feat(openfeature): DatadogOfflineOpenFeatureProvider [PR3] (FFL-2689, FFL-2690)#1332
Draft
btthomas wants to merge 3 commits into
Draft
feat(openfeature): DatadogOfflineOpenFeatureProvider [PR3] (FFL-2689, FFL-2690)#1332btthomas wants to merge 3 commits into
btthomas wants to merge 3 commits into
Conversation
…FL-2690) A never-fetch OpenFeature provider for offline initialization. It behaves like DatadogOpenFeatureProvider — same evaluation and exposure/RUM tracking — except initialize/onContextChange use FlagsClient.setEvaluationContextWithoutFetching instead of the fetching setEvaluationContext, so it never hits the CDN. It exposes setConfiguration (delegating to the FlagsClient) and emits provider events from the configuration outcome: first config -> READY, subsequent -> CONFIGURATION_CHANGED, mismatch/invalid -> ERROR. - Core: setConfiguration and setEvaluationContextWithoutFetching now return a ConfigurationStatus so the provider can map outcome -> event; export configurationFromString/configurationToString, ParsedFlagsConfiguration, and ConfigurationStatus. - react-native-openfeature: make flagsClient protected and export toDdContext so the offline provider can reuse the base; export DatadogOfflineOpenFeatureProvider and re-export configurationFromString; README offline-init section. No native changes — the offline path uses existing native enable + trackEvaluation and skips native setEvaluationContext; evaluation is all JS. Tests: provider never calls the fetching path, delegates setConfiguration, emits the right events, and resolves through the client. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Both the online and offline providers now extend a shared, internal (un-exported) DatadogCoreOpenFeatureProvider that owns the FlagsClient, event emitter, and resolveX evaluation. DatadogOpenFeatureProvider keeps its fetch-on-context initialize/onContextChange, and DatadogOfflineOpenFeatureProvider extends the base directly instead of the online provider, so it no longer inherits the online fetch/promise-chain machinery. Public API and online behavior are unchanged and the base is not exported. Matches the Portable RFC's CoreProvider. Adds a provider test locking the online provider's fetch-on-initialize behavior. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
… exports)
Two-agent review follow-ups on the offline provider:
- C1 (critical): the offline provider no longer stamps an empty OpenFeature
context in initialize/onContextChange, so OpenFeature's initialize({}) on
setProviderAndWait can't defeat the configuration's embedded context (which
previously caused a spurious mismatch -> PROVIDER_ERROR for every real config).
- H1/M1 (events): the provider now emits CONFIGURATION_CHANGED on a successful
load (OpenFeature already emits READY when initialize resolves) and emits READY
only to clear a prior error state, removing the premature/duplicate READY and
fixing error recovery.
- M2/L5: keep ConfigurationStatus internal (dropped from the public core export;
the provider derives it via ReturnType) and document it may widen for rules.
- L4: move toDdContext (and a new isEmptyContext) into mappers.ts so the base
module no longer carries an exported free helper.
- L3: fix the offline provider's stale TSDoc link.
Tests: add a real-FlagsClient integration test that would have caught C1
(initialize({}) then setConfiguration serves; explicit mismatch errors), and
update the unit tests for the empty-context and event behavior. Also lock the
online provider's fetch-on-initialize behavior.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
5a7a06e to
8cce4b5
Compare
2ee5c00 to
38a7e7a
Compare
There was a problem hiding this comment.
Pull request overview
This PR adds an offline OpenFeature provider for the React Native Datadog SDK, enabling feature-flag evaluation from a precomputed configuration supplied by the app (no network fetch), while keeping evaluation + exposure/RUM tracking aligned with the existing online provider.
Changes:
- Introduces
DatadogOfflineOpenFeatureProviderand refactors shared logic intoDatadogCoreOpenFeatureProvider. - Adds offline configuration plumbing/events (context set without fetch; emit
ConfigurationChanged/Error/Readyas appropriate). - Publicly exports offline configuration helpers/types from core (
configurationFromString,configurationToString,ParsedFlagsConfiguration) and re-exportsconfigurationFromStringfrom the OpenFeature package; updates docs + adds tests.
Reviewed changes
Copilot reviewed 11 out of 11 changed files in this pull request and generated 2 comments.
Show a summary per file
| File | Description |
|---|---|
| packages/react-native-openfeature/src/provider.ts | Refactors online provider to extend shared core provider; keeps fetch-on-context behavior. |
| packages/react-native-openfeature/src/offlineProvider.ts | Adds offline provider that never fetches; supports setConfiguration + event mapping. |
| packages/react-native-openfeature/src/mappers.ts | Extracts OF → Datadog context conversion + empty-context detection helper. |
| packages/react-native-openfeature/src/index.ts | Exports offline provider and re-exports configurationFromString. |
| packages/react-native-openfeature/src/coreProvider.ts | Adds shared base provider owning FlagsClient, event emitter, and evaluations. |
| packages/react-native-openfeature/src/tests/provider.test.ts | Adds unit coverage for online provider behavior after refactor. |
| packages/react-native-openfeature/src/tests/offlineProvider.test.ts | Adds unit coverage for offline provider no-fetch behavior + events. |
| packages/react-native-openfeature/src/tests/offlineProvider.integration.test.ts | Adds integration coverage using real FlagsClient for offline flow edge cases. |
| packages/react-native-openfeature/README.md | Documents offline initialization flow and usage. |
| packages/core/src/index.tsx | Exposes configuration parse/serialize utilities and parsed config type publicly. |
| packages/core/src/flags/FlagsClient.ts | Returns configuration outcome status from offline context/config APIs for provider event mapping. |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
Comment on lines
+51
to
+59
| constructor(options: DatadogOpenFeatureProviderOptions = {}) { | ||
| if (!options.clientName) { | ||
| options.clientName = 'default'; | ||
| } | ||
|
|
||
| this.options = options; | ||
|
|
||
| this.flagsClient = DdFlags.getClient(this.options.clientName); | ||
| } |
Comment on lines
+34
to
+40
| * Whether an OpenFeature evaluation context carries no information (no targeting key and no | ||
| * attributes). Used by the offline provider to avoid overwriting a configuration's embedded | ||
| * context with an empty context stamped by the OpenFeature lifecycle. | ||
| */ | ||
| export const isEmptyContext = (context: OFEvaluationContext): boolean => { | ||
| return Object.keys(context).length === 0; | ||
| }; |
4 tasks
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Offline feature flags — related PRs
FlagsClient.setConfiguration): feat(flags): FlagsClient.setConfiguration + context matching [PR2] (FFL-2688) #1331Summary
Adds
DatadogOfflineOpenFeatureProvider— a never-fetch OpenFeature provider for offline initialization — and the public exports for the offline API.The offline provider evaluates flags and reports exposures/RUM exactly like
DatadogOpenFeatureProvider, but never fetches configuration from the network:initialize/onContextChangeset the evaluation context without a request, and the configuration is supplied viasetConfiguration. A precomputed configuration carries the context it was computed for, so no separateOpenFeature.setContextcall is needed.DatadogCoreOpenFeatureProviderbase that owns the flag client, event emitter, and flag evaluation; only the context-sourcing (initialize/onContextChange) differs.PROVIDER_CONFIGURATION_CHANGED; an unusable or context-mismatched configuration emitsPROVIDER_ERROR.configurationFromString,configurationToString,ParsedFlagsConfiguration. OpenFeature:DatadogOfflineOpenFeatureProviderand a re-exportedconfigurationFromString. The README documents offline usage.No native changes: the offline path uses the existing native
enable+ exposure tracking and skips the native fetch; evaluation is all JS.Tests
react-native-openfeature(13 tests) covers both providers — the offline provider never fetches, honors the configuration's context, emits the right events, and (via a real-FlagsClientintegration test) serves flags end to end; the online provider still fetches on context. The coreflags/suite (53 tests) passes. Lint andtscare clean on both packages.Example App
iOS
Android