Skip to content

deps: update dependency flagsmith/sdk-spec to v0.7.0 - #64

Open
renovate[bot] wants to merge 2 commits into
mainfrom
renovate/sdk-spec
Open

renovate[bot] wants to merge 2 commits into
mainfrom
renovate/sdk-spec

Conversation

@renovate

@renovate renovate Bot commented Oct 21, 2026 •

Copy link
Copy Markdown

This PR contains the following updates:

Package Type Update Change
Flagsmith/sdk-spec minor v0.3.0 → v0.7.0
Flagsmith/sdk-spec workflow minor v0.3.0 → v0.7.0

Release Notes

Flagsmith/sdk-spec

v0.7.0

Compare Source

What's Changed
New Contributors

Full Changelog: Flagsmith/sdk-spec@v0.6.0...v0.7.0

v0.6.0

Compare Source

What's Changed
New Contributors

Full Changelog: Flagsmith/sdk-spec@v0.5.1...v0.6.0

v0.5.1

Compare Source

What's Changed
  • ci: Run the JS client and iOS against main in the compatibility matrix by @​khvn26 in #​12
  • feat: Optionally treat steps an SDK does not implement as expected failures by @​khvn26 in #​11
  • feat: Add a testChange SDK step by @​khvn26 in #​14

Full Changelog: Flagsmith/sdk-spec@v0.5.0...v0.5.1

v0.5.0

Compare Source

What's Changed

Full Changelog: Flagsmith/sdk-spec@v0.4.0...v0.5.0

v0.4.0

Compare Source

What's Changed
New Contributors

Full Changelog: Flagsmith/sdk-spec@v0.3.0...v0.4.0


Configuration

📅 Schedule: (UTC)

  • Branch creation
    • At any time (no schedule defined)
  • Automerge
    • At any time (no schedule defined)

🚦 Automerge: Disabled by config. Please merge this manually once you are satisfied.

♻ Rebasing: Whenever PR becomes conflicted, or you tick the rebase/retry checkbox.

🔕 Ignore: Close this PR and you won't be reminded about these updates again.


  • If you want to rebase/retry this PR, check this box

This PR was generated by Mend Renovate. View the repository job log.

@renovate
renovate Bot requested a review from a team as a code owner October 21, 2026 16:52
@renovate renovate Bot added the sdk-spec Bumps of the Flagsmith SDK behavioural spec label Oct 21, 2026
@renovate
renovate Bot requested review from emyller and removed request for a team October 21, 2026 16:52
@khvn26 khvn26 added the openhands For the OpenHands agent to pick up label Oct 21, 2026
@khvn26 khvn26 changed the title deps: update dependency flagsmith/sdk-spec to v0.5.0 deps: update dependency flagsmith/sdk-spec to v0.5.1 Oct 21, 2026
@renovate renovate Bot changed the title deps: update dependency flagsmith/sdk-spec to v0.5.1 deps: update dependency flagsmith/sdk-spec to v0.6.0 Oct 29, 2026
@renovate
renovate Bot force-pushed the renovate/sdk-spec branch from f9e4c74 to 1853c7f Compare October 29, 2026 10:32
@coderabbitai

coderabbitai Bot commented Oct 29, 2026 •

Copy link
Copy Markdown

Review in Change Stack →

Important

Review skipped

Bot user detected.

To trigger a single review, invoke the @coderabbitai review command.

Run configuration
  • Source mode: Auto
  • Repository: Unavailable
  • Branch: Unavailable
  • File: No configuration file from this repository applied
  • Commit: Unavailable
  • Layers: Organization UI
  • Review profile: ASSERTIVE
  • Plan: Advanced
  • Run ID: c644f4f0-feee-41a8-908e-2ed85ee10720

You can disable this status message by setting the reviews.review_status to false in the CodeRabbit configuration file.

Use the checkbox below for a quick retry:

  • 🔍 Trigger review
Walkthrough

The SDK adds configuration for event collection and support for retrieving experiment flags, tracking events, and recording exposures. A supervised processor buffers events and sends batches. Feature-state and flag schemas now include experiment and variant data. The SDK spec workflow moves to version v0.6.0; documentation and tests cover the new options and APIs.

Priority: Normal

Estimated code review effort: 4 (Complex) | ~45 minutes

Merge Risk: Moderate · previous review 85410

With events enabled, an outage or slowness in the events API can make the event processor repeatedly block on failing requests once its buffer fills, and can make explicit flush calls exit with a timeout. Fix the buffer-full retry behaviour and the flush call timeout before merging. Event collection is opt-in, which limits the exposure.

- [ ] Autofix · Keep fixing CodeRabbit findings and required CI, and resolving merge conflicts

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@flagsmithsmith

Copy link
Copy Markdown

Spec v0.6.0 adds the @events capability (experiment flags, tracked events and exposures). This SDK had none of it, so 5 of the 7 scenarios failed with "The SDK does not implement the step". 8541003 implements it in the SDK:

  • Flagsmith.Client.get_experiment_flag/4 gets an identity's flag through the identities API and records which variant the identity was exposed to. It sends a $flag_exposure event, valued with the variant served, only when the flag is enabled and the identity is enrolled in a running experiment (metadata.experiment.in_experiment). In any other case it logs the reason at debug level and sends nothing.
  • Flagsmith.Client.track_event/3 and track_exposure_event/3 send events to Flagsmith's events API (POST <events_api_url>v1/events). Event names starting with $ are reserved, and an exposure needs an identifier.
  • Events processor: events are buffered per environment key under Flagsmith.Supervisor and sent in batches: on an interval, when 1,000 events are buffered, and on shutdown. If a batch fails, its events are kept and sent again on the next flush. A repeated exposure (same feature, identifier and variant) inside one flush interval is sent once.
  • Flags from the identities API now carry variant and experiment.
  • New options, documented in HEXDOCS.md: enable_events (default false), events_api_url and events_flush_interval_milliseconds.
  • sdk-spec/steps.exs maps the three new When steps and Create the SDK client with events enabled to these SDK calls. The client step starts Flagsmith.Supervisor, as an application using events must.

Tests: added test/flagsmith_events_test.exs and extended the configuration tests. mix format --check-formatted, mix test (182 tests) and mix dialyzer pass locally. I also ran spec v0.6.0 locally against its compose stack: 7/7 scenarios passed.

One existing test, poller init and refresh the refresh works accordingly, fails now and then because it waits only 15 ms. It does the same on main without this change.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 3


Review info
Run configuration
  • Source mode: Auto
  • Repository: Unavailable
  • Branch: Unavailable
  • File: No configuration file from this repository applied
  • Commit: Unavailable
  • Layers: Organization UI
  • Review profile: ASSERTIVE
  • Plan: Advanced
  • Run ID: 267d49f8-a62e-4ca3-b57f-cbd2fe5887ea
Commits

Reviewing files that changed from the base of the PR and between 77b5e9a and 8541003.

Files selected for processing: 14
  • .github/workflows/sdk-spec.yml
  • HEXDOCS.md
  • lib/configuration/flagsmith_configuration.ex
  • lib/flagsmith_client.ex
  • lib/flagsmith_client_events_processor.ex
  • lib/flagsmith_supervisor.ex
  • lib/schemas/experiment.ex
  • lib/schemas/features/feature_state.ex
  • lib/schemas/features/feature_state_metadata.ex
  • lib/schemas/flag.ex
  • lib/supervisors/events_processor_supervisor.ex
  • sdk-spec/steps.exs
  • test/flagsmith_configuration_test.exs
  • test/flagsmith_events_test.exs

Included review availability: This review used your included allowance. Your plan provides up to 1 included review per hour; 0 remain after this review.

Comment on lines +66 to +70
def flush(environment_key) do
case whereis(environment_key) do
pid when is_pid(pid) -> GenServer.call(pid, :flush)
:undefined -> :noop
end

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Minor · Stability & Availability · Quick win

flush/1 can exit the caller when the HTTP request is slow.

GenServer.call(pid, :flush) uses the default 5000 ms timeout. The processor runs the HTTP request inside this call. request_timeout_milliseconds is at least 5000 and retries can multiply the wait. A slow or failing events API can therefore make the caller exit with :timeout. The processor also keeps the late reply.

Use a longer call timeout, or :infinity, because the HTTP client already bounds the request.

Proposed fix
-      pid when is_pid(pid) -> GenServer.call(pid, :flush)
+      pid when is_pid(pid) -> GenServer.call(pid, :flush, :infinity)
Committable suggestion

IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
def flush(environment_key) do
case whereis(environment_key) do
pid when is_pid(pid) -> GenServer.call(pid, :flush)
:undefined -> :noop
end
def flush(environment_key) do
case whereis(environment_key) do
pid when is_pid(pid) -> GenServer.call(pid, :flush, :infinity)
:undefined -> :noop
end

Comment on lines +165 to +168
case length(data.buffer) >= @max_buffered_events do
true -> elem(do_flush(data), 1)
false -> data
end

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Major · Stability & Availability · Quick win

A full buffer triggers a blocking HTTP request for every new event while the events API is failing.

buffer/2 calls do_flush/1 whenever length(data.buffer) >= @max_buffered_events. On failure, do_flush/1 keeps Enum.take(buffer, 1000), so the buffer stays at 1000 events. The next {:track, event} cast makes it 1001, which is still >= 1000, so the processor sends another batch. The result is as follows:

  • Each tracked event causes one synchronous POST to the failing endpoint inside the GenServer. The POST can block up to request_timeout_milliseconds (and longer with retries).
  • The mailbox grows without bound while the calls block.
  • Calls to flush/1 time out.

The retry design says failed batches are retried on the next flush. It does not say that every cast must retry.

Flush from buffer/2 only when the size reaches the limit. When the buffer is already full after a failure, drop the oldest event and wait for the scheduled flush. length/1 is also O(n) on every event, so keep a size counter in the state.

Proposed fix
   defstruct [
     :configuration,
     buffer: [],
+    buffer_size: 0,
     exposure_keys: MapSet.new()
   ]
   defp buffer(%__MODULE__{buffer: buffer, buffer_size: size} = data, event) do
-    data = %{data | buffer: [event | buffer]}
-
-    case length(data.buffer) >= @max_buffered_events do
-      true -> elem(do_flush(data), 1)
-      false -> data
-    end
+    case size + 1 do
+      n when n < @max_buffered_events ->
+        %{data | buffer: [event | buffer], buffer_size: n}
+
+      @max_buffered_events ->
+        elem(do_flush(%{data | buffer: [event | buffer], buffer_size: @max_buffered_events}), 1)
+
+      _ ->
+        # A previous flush failed and the buffer is full: drop the oldest event
+        # and wait for the scheduled flush instead of retrying on every event.
+        %{data | buffer: Enum.take([event | buffer], @max_buffered_events)}
+    end
   end

Also set buffer_size: 0 in the success branch of do_flush/1. Keep buffer_size equal to @max_buffered_events after a failed flush.

Comment on lines +399 to +425
test "events Flagsmith fails to receive are sent again on the next flush", %{
config: config,
receive_events: receive_events
} do
# Given
expect(Tesla.Adapter.Mock, :call, fn _tesla_env, _options ->
{:ok, %Tesla.Env{status: 503, body: "unavailable"}}
end)

expect(Tesla.Adapter.Mock, :call, receive_events)
:ok = Client.track_event(config, "checkout_completed", identifier: "user_123")

# When
log =
capture_log(fn ->
assert {:error, "unavailable"} = Processor.flush(config.environment_key)
end)

:ok = Client.track_event(config, "signed_out", identifier: "user_123")
:ok = Processor.flush(config.environment_key)

# Then
assert log =~ "Failed to send events to Flagsmith, keeping them to retry"

assert_receive {:events_request, _tesla_env, %{"events" => events}}
assert ["checkout_completed", "signed_out"] = Enum.map(events, & &1["event"])
end

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Trivial · Maintainability & Code Quality · Quick win

Add a test for retrying at full buffer capacity.

The failure test covers a small buffer only. It does not cover the case where the buffer is full and the events API keeps failing. Add a test that tracks more than 1000 events while the adapter returns 503. The test must assert that the adapter does not receive a request for every extra event. It would have caught the retry-per-event behaviour in Flagsmith.Client.Events.Processor.buffer/2.

@renovate
renovate Bot force-pushed the renovate/sdk-spec branch from 8541003 to ed91bc8 Compare October 29, 2026 19:54
@renovate renovate Bot changed the title deps: update dependency flagsmith/sdk-spec to v0.6.0 deps: update dependency flagsmith/sdk-spec to v0.7.0 Oct 29, 2026
Implements SDK spec v0.6.0's `@events` capability:

- `Flagsmith.Client.get_experiment_flag/4` gets an identity's flag and,
  when the identity is enrolled in a running experiment on an enabled
  feature, sends a `$flag_exposure` event valued with the variant served.
- `Flagsmith.Client.track_event/3` and `track_exposure_event/3` send
  events to Flagsmith's events API.
- Events are buffered per environment key by a supervised processor and
  sent in batches on an interval, when the buffer fills, and on shutdown;
  failed batches are kept and retried.
- Flags from the identities API now carry their `variant` and
  `experiment` metadata.
- New options: `enable_events`, `events_api_url` and
  `events_flush_interval_milliseconds`.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
(cherry picked from commit 8541003)
@renovate

renovate Bot commented Oct 29, 2026

Copy link
Copy Markdown
Author

Edited/Blocked Notification

Renovate will not automatically rebase this PR, because it does not recognize the last commit author and assumes somebody else may have edited the PR.

You can manually request rebase by checking the rebase/retry box above.

⚠️ Warning: custom changes will be lost.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

openhands For the OpenHands agent to pick up sdk-spec Bumps of the Flagsmith SDK behavioural spec

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant