fix(event_executor): update provider status before invoking API-level handlers#494
Conversation
… handlers triggerEvent dispatched API-level (global) handlers before calling states.Store, so a global handler that queries client state observed the stale status. Client-scoped handlers were fine — states.Store ran just before those. This violated OpenFeature spec requirement 5.3.5: > If the provider emits an event, the value of the client's provider > status MUST be updated to the status associated with that event > BEFORE the SDK invokes any event handlers for that event. Collect the domain writes first (for every named domain matching this provider, plus defaultDomain if the handler is the default provider), call states.Store for each, then dispatch API-level, named-domain, and default-domain handlers in the same order as before. No change to handler ordering, just the state-write ordering. Closes open-feature/go-sdk issue 493. Signed-off-by: SAY-5 <say.apm35@gmail.com>
There was a problem hiding this comment.
Code Review
This pull request refactors the triggerEvent function in openfeature/event_executor.go to comply with OpenFeature specification 5.3.5, ensuring provider status is updated before any event handlers are executed. Feedback suggests optimizing the implementation by hoisting redundant function calls, such as newProviderRef and stateFromEvent, out of loops to reduce memory pressure and improve performance.
Codecov Report✅ All modified and coverable lines are covered by tests. Additional details and impacted files@@ Coverage Diff @@
## main #494 +/- ##
==========================================
+ Coverage 84.07% 84.12% +0.04%
==========================================
Files 27 27
Lines 2079 2085 +6
==========================================
+ Hits 1748 1754 +6
Misses 292 292
Partials 39 39
Flags with carried forward coverage won't be shown. Click here to find out more. ☔ View full report in Codecov by Sentry. 🚀 New features to boost your workflow:
|
|
@SAY-5 Can you add an explicit test for this? |
Adds TestEventHandler_StateUpdatedBeforeHandlersRun with three subtests: - API handler observes ReadyState when ProviderReady fires for default provider - client handler observes ErrorState when ProviderError fires for named provider - on stale->ready, handler observes ReadyState (not the previous StaleState) All three fail against the prior ordering (state written after API handlers ran) and pass with the fix in this PR. Signed-off-by: SAY-5 <say.apm35@gmail.com>
|
@toddbaert added |
|
@SAY-5 I think this is close! Please consider the remaining comments/issues. |
Per @toddbaert / @erka / @sahidvelji / Gemini reviews: - Hoist `newProviderRef(handler)` out of the loop (it's loop-invariant) and cache `stateFromEvent(event)` in `newState` so we don't re-allocate the reflection-based ref + channel on every iteration. - Drop the eager-preallocation `make([]string, 0)` for `namedDomains` in favour of `var namedDomains []string` — the realistic case is one provider, so paying for an allocation up front isn't worth it. - Trim the spec-5.3.5 rationale comment to two lines. No behaviour change. `make test` clean (open-feature/go-sdk package: 53.5% coverage, full suite green).
|
Round-2 in 29086ca:
On the use mock providers nudge from @erka — kept the embedded
|
Per @toddbaert / @erka / @sahidvelji / Gemini reviews: - Hoist `newProviderRef(handler)` out of the loop (it's loop-invariant) and cache `stateFromEvent(event)` in `newState` so we don't re-allocate the reflection-based ref + channel on every iteration. - Drop the eager-preallocation `make([]string, 0)` for `namedDomains` in favour of `var namedDomains []string` — the realistic case is one provider, so paying for an allocation up front isn't worth it. - Trim the spec-5.3.5 rationale comment to two lines. No behaviour change. `make test` clean (open-feature/go-sdk package: 53.5% coverage, full suite green). Signed-off-by: SAY-5 <say.apm35@gmail.com>
29086ca to
37db71d
Compare
toddbaert
left a comment
There was a problem hiding this comment.
LGTM - will wait for a review from @erka or @sahidvelji as well.
Signed-off-by: Roman Dmytrenko <rdmytrenko@gmail.com>
Fixes #493.
Per OpenFeature spec requirement 5.3.5:
triggerEventpreviously dispatched API-level (global) handlers before callingstates.Store, so a global handler that queried client state observed the stale status. Client-scoped handlers were fine —states.Storeran just before those.Fix
Collect the domain writes first (every named domain matching this provider, plus
defaultDomainif the handler is the default provider), callstates.Storefor each, then dispatch API-level → named-domain → default-domain handlers in the same order as before. No change to handler ordering, just the state-write ordering.Test
go test -tags testtools ./openfeature/...clean.