Skip to content

feat: add polling and cache sources for FDv2#261

Draft
kinyoklion wants to merge 2 commits intomainfrom
rlamb/sdk-2184/fdv2-polling-cache-sources
Draft

feat: add polling and cache sources for FDv2#261
kinyoklion wants to merge 2 commits intomainfrom
rlamb/sdk-2184/fdv2-polling-cache-sources

Conversation

@kinyoklion
Copy link
Copy Markdown
Member

Implements the four building blocks Phase 3 needs from Stream A:

  • calculate_poll_delay.dart: pure helper. Given freshness and interval, returns the time remaining in the interval; zero when overdue; full interval when there's no prior freshness or the freshness is in the future (clock skew clamp).
  • polling_initializer.dart: one-shot Initializer. Calls the injected PollFunction up to 3 times. ChangeSetResult and terminal status results return immediately. Interrupted results retry after a 1s delay. After 3 interrupted attempts the last is escalated to terminalError so the orchestrator stops retrying at this layer. close() interrupts a pending retry delay and yields shutdown.
  • polling_synchronizer.dart: long-lived Synchronizer. Single- subscription StreamController that polls immediately on subscribe, then schedules subsequent polls via calculatePollDelay over the freshness of the most recent successful result. Interrupted results pass through but do not advance freshness, so a transient failure does not delay the catch-up poll. Injected TimerFactory and now() for deterministic tests.
  • cache_initializer.dart: Initializer that reads the persistence cache via an injected CachedFlagsReader. Cache hit emits a full ChangeSetResult with persist=false and an empty selector (the cache does not track server-side selector state). Cache miss or reader exception emits a none-type ChangeSetResult so the initializer chain advances. The reader typedef leaves the actual persistence wiring to the orchestrator (Phase C1).

PollFunction, DelayFunction, TimerFactory, and CachedFlagsReader are typedefs rather than concrete dependencies so the orchestrator can wire real implementations and tests can inject scripted ones, mirroring the abstraction style established in SDK-2183.

Requirements

  • I have added test coverage for new or changed functionality
  • I have followed the repository's pull request submission guidelines
  • I have validated my changes against all supported platform versions

Related issues

Provide links to any issues in this repository or elsewhere relating to this pull request.

Describe the solution you've provided

Provide a clear and concise description of what you expect to happen.

Describe alternatives you've considered

Provide a clear and concise description of any alternative solutions or features you've considered.

Additional context

Add any other context about the pull request here.

Implements the four building blocks Phase 3 needs from Stream A:

- calculate_poll_delay.dart: pure helper. Given freshness and
  interval, returns the time remaining in the interval; zero when
  overdue; full interval when there's no prior freshness or the
  freshness is in the future (clock skew clamp).
- polling_initializer.dart: one-shot Initializer. Calls the injected
  PollFunction up to 3 times. ChangeSetResult and terminal status
  results return immediately. Interrupted results retry after a 1s
  delay. After 3 interrupted attempts the last is escalated to
  terminalError so the orchestrator stops retrying at this layer.
  close() interrupts a pending retry delay and yields shutdown.
- polling_synchronizer.dart: long-lived Synchronizer. Single-
  subscription StreamController that polls immediately on subscribe,
  then schedules subsequent polls via calculatePollDelay over the
  freshness of the most recent successful result. Interrupted
  results pass through but do not advance freshness, so a transient
  failure does not delay the catch-up poll. Injected TimerFactory
  and now() for deterministic tests.
- cache_initializer.dart: Initializer that reads the persistence
  cache via an injected CachedFlagsReader. Cache hit emits a full
  ChangeSetResult with persist=false and an empty selector (the
  cache does not track server-side selector state). Cache miss or
  reader exception emits a none-type ChangeSetResult so the
  initializer chain advances. The reader typedef leaves the actual
  persistence wiring to the orchestrator (Phase C1).

PollFunction, DelayFunction, TimerFactory, and CachedFlagsReader are
typedefs rather than concrete dependencies so the orchestrator can
wire real implementations and tests can inject scripted ones,
mirroring the abstraction style established in SDK-2183.
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