Skip to content

feat: Schedule FDv2 recovery after the FDv1 fallback TTL elapses - #1875

Draft
joker23 wants to merge 1 commit into
skz/sdk-2617/fdv1-fallback-fixfrom
skz/SDK-2912/fdv2-recovery-orchestration
Draft

feat: Schedule FDv2 recovery after the FDv1 fallback TTL elapses#1875
joker23 wants to merge 1 commit into
skz/sdk-2617/fdv1-fallback-fixfrom
skz/SDK-2912/fdv2-recovery-orchestration

Conversation

@joker23

@joker23 joker23 commented Aug 21, 2026

Copy link
Copy Markdown
Contributor

Summary

Wires the recovery half of the FDv1 fallback directive: once the SDK has fallen back to FDv1, it now schedules an unconditional, elapsed-time attempt to return to FDv2 once the fallback TTL elapses, using the fdv2Recovery() / isCurrentSynchronizerFDv1Fallback primitives added in #1856.

Also corrects fallbackDirective.ts's TTL handling to match the spec: an absent, unparseable, negative, or out-of-range TTL (including 0, previously treated as indefinite fallback) now clamps to a jittered 1-hour default instead. A server-supplied in-range TTL is used as-is. Directed fallback is therefore never indefinite.

FDv2RecoveryTimer is a new standalone primitive holding that single deadline; it is not modeled as a Condition since getConditions() produces nothing when the SDK has one or zero available synchronizers, which is exactly the state a directed fallback creates. In FDv2DataSource, the deadline races the active synchronizer loop, and if every synchronizer slot is blocked before the deadline fires, a background continuation takes over responsibility for the timer and restarts FDv2 sources on its own once it elapses -- without holding up the in-flight start()/identify() call.

This is what #1858's contract-test entity wiring exercises.

A directed FDv1 fallback now always carries a concrete deadline for
returning to FDv2. An absent, unparseable, or out-of-range fallback TTL is
replaced with a 1-hour default, jittered down by up to half so a fleet
that fell back together does not retry in lockstep; a server-supplied
in-range TTL is used as given. Fallback is therefore never indefinite.

FDv2RecoveryTimer holds that single deadline. It outlives individual
synchronizer runs, so the orchestrator races it alongside the active
synchronizer and, when every slot is blocked, hands it to a background
continuation that restarts the FDv2 sources once the deadline elapses.
@github-actions

Copy link
Copy Markdown
Contributor

@launchdarkly/js-sdk-common size report
This is the brotli compressed size of the ESM build.
Compressed size: 26360 bytes
Compressed size limit: 29000
Uncompressed size: 129188 bytes

@github-actions

Copy link
Copy Markdown
Contributor

@launchdarkly/js-client-sdk size report
This is the brotli compressed size of the ESM build.
Compressed size: 32876 bytes
Compressed size limit: 34000
Uncompressed size: 117490 bytes

@github-actions

Copy link
Copy Markdown
Contributor

@launchdarkly/browser size report
This is the brotli compressed size of the ESM build.
Compressed size: 180522 bytes
Compressed size limit: 200000
Uncompressed size: 834659 bytes

@github-actions

Copy link
Copy Markdown
Contributor

@launchdarkly/js-client-sdk-common size report
This is the brotli compressed size of the ESM build.
Compressed size: 43315 bytes
Compressed size limit: 44000
Uncompressed size: 233109 bytes

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

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant