Repository navigation
feat: Retry event delivery and flush on close - #129
Conversation
Its entry in Flagsmith/sdk-spec's compatibility matrix at v0.9.0: `core events local-evaluation`.
|
Important Review skippedBot user detected. To trigger a single review, invoke the
|
Implement SDK spec v0.9.0: - Send a batch of events up to 3 times, one batch at a time, backing off from 1 second with full jitter, with a 3 second request timeout. Keep a batch whose last attempt failed transiently for the next flush, unless that attempt got a 500; drop a batch the events API rejects; stop event tracking when it refuses the environment key (401/403). A full buffer drops its oldest event. - Add `Client#flush_events`, which returns once the tracked events are delivered, dropped or kept, and `Client#close(timeout_seconds:)`, which stops background work and sends the buffered events within the timeout. - Record exposures under local evaluation: carry the environment document's `metadata.experiment` and multivariate option keys through to identity flags' `experiment` and `variant`. - Wire the new spec steps in sdk-spec/steps.rb. Co-Authored-By: Claude Opus 5.5 <[email protected]>
|
Implemented SDK spec v0.9.0 in 4b281a4. CI had failed because the SDK was missing 4 steps: the local evaluation + events client, flushing events, closing the client, and tracking a numbered range of events. Behind those steps were 2 missing SDK features. Event delivery (
Client
Exposures under local evaluation
Tests and steps
Unrelated to this change, possibly a bug: under local evaluation, identity overrides get priority |
Zaimwa9
left a comment
There was a problem hiding this comment.
Requesting changes. Spec passes and the threading is sound, but once a kept batch fills the buffer, every track restarts a retry cycle. Please also make close terminal.
…minal - While the buffer holds a batch whose attempts all failed, a full buffer waits for the next flush instead of starting another round of attempts on every tracked event. - Once the processor is stopping, tracking and flushing do nothing, and it does not start again. - A flush now only skips events a batch taken after it was requested already sent, so a flush resends a kept batch even when no event was tracked since. Co-Authored-By: Claude Opus 5.5 <[email protected]>
Both are fixed in 6aa2ec4; details are in the inline replies.
That change also fixes a related bug: a flush with no events tracked since a kept batch failed used to send nothing. It now resends the kept batch. Locally, rspec (456 examples, 6 consecutive runs) and rubocop pass. |
A flush requested while a full-buffer flush was sending a batch counted no batch taken since, so it sent the kept batch again once that batch's attempts failed. Count settled batches instead: one in flight at the request settles after it, and covers the events tracked up to it. Co-Authored-By: Claude Opus 5.5 <[email protected]>
|
A follow-up to 6aa2ec4, in daead64. In CI, the spec run on 6aa2ec4 failed "A full buffer drops its oldest event": The cause was in 6aa2ec4's new rule for when a flush skips events another flush already sent. It counted batches taken. If the full-buffer flush had already taken the batch when the application called It now counts batches settled. A batch in flight when a flush is requested settles after the request, so the flush skips the events it covered. The new spec "does not send again a batch in flight when the flush was requested" fails on 6aa2ec4 and passes now. All checks are green on daead64. |
|
@themis-blindfold review |
⚖️ Themis review: 🟠 Fix before mergeThe retry policy does not match the requested delivery contract, and shutdown can still start a send after its deadline. Retained exposure events can also be duplicated in the buffer. The SDK specification and Ruby CI checks passed, but they do not cover these cases. Ruby was unavailable for local execution.
🟠 Majors
📝 Walkthrough
🧪 How to verify
Product take: Reliable event delivery and shutdown materially improve experiment data quality, provided failures and deadlines follow the shared SDK contract. 🧭 Assumptions & unverified claimsNo unverified assumptions or claims. May the last batch leave on time · reviewed at daead64 |
- A send queued behind the in-flight batch, such as the final flush when close times out, no longer takes a batch once the processor is closed. - Keeping a failed batch rebuilds the buffered exposure keys, dropping exposures equal to one already buffered, so a kept exposure tracked again is sent once. Co-Authored-By: Claude Opus 5.5 <[email protected]>
I have gone through the Themis review of daead64 and replied to each finding inline:
The new specs for the two fixes fail on daead64 and pass now. Locally, rubocop and rspec pass (460 examples). The only failures were in |
Contributes to Flagsmith/sdk-spec#23