Skip to content

feat: add server FDv2 data system orchestrator#529

Draft
beekld wants to merge 2 commits intomainfrom
beeklimt/SDK-2098
Draft

feat: add server FDv2 data system orchestrator#529
beekld wants to merge 2 commits intomainfrom
beeklimt/SDK-2098

Conversation

@beekld
Copy link
Copy Markdown
Contributor

@beekld beekld commented May 5, 2026

Add FDv2DataSystem orchestrator

Orchestrates FDv2 initializers and synchronizers; applies changesets and reports data-source status.

What's implemented

  • FDv2DataSystemIDataSystem impl. Runs initializers, then a synchronizer; applies changesets; tracks the selector; emits status (kInitializingkValid on first apply / kInterrupted on errors → kOff on destruction). Offline (no factories) goes straight to kValid.
  • IFDv2InitializerFactory, IFDv2SynchronizerFactory — build a fresh source per call.
  • ITransactionalDestination — extends IDestination with Apply(ChangeSet); implemented by MemoryStore and ChangeNotifier.
  • ChangeNotifier::Apply — diffs against the current store, updates the dependency tracker, applies to the sink, emits change events. Full diffs per-kind and version-aware; Partial notifies unconditionally per item.

Design decisions

  • No shared_ptr<State> for orchestrator-level async safety. Other FDv2 components keep async state in a shared_ptr<State> so callbacks can outlive the public object. This one captures this directly — safe because ~ClientImpl does ioc_.stop() and run_thread_.join() before destroying the data system. The destructor's precondition (caller drains the executor first) is documented on the class.
  • New ITransactionalDestination rather than adding Apply to IDestination. Leaves the FDv1 persistent-store path untouched.
  • DataSourceStatusManager is non-owning. ClientImpl (shared with FDv1) is its sole owner; the data system only borrows it. Declaration order in ClientImpl guarantees the manager outlives the data system.

Test plan

11 cases in libs/server-sdk/tests/fdv2_data_system_test.cpp cover lifecycle, initializer phase (basis received, basis-skips-remaining, Interrupted advances, ChangeSet without selector continues), and synchronizer phase (apply, Interrupted loops, Goodbye/TerminalError advances, selector forwarding). Mocks resolve futures synchronously; tests run the io_context to drain orchestration before assertions.

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