phase 2 progress
This commit is contained in:
@@ -6,25 +6,31 @@ Phase 1 established the subsystem vocabulary and moved the runtime path behind c
|
||||
|
||||
## Status
|
||||
|
||||
- Phase 2 design package: proposed.
|
||||
- Phase 2 implementation: not started.
|
||||
- Phase 2 design package: accepted.
|
||||
- Phase 2 implementation: substantially complete for the coordination substrate.
|
||||
- Current alignment: the typed event substrate, app-owned dispatcher, coalesced app pump, reload bridge events, production bridges, and event behavior tests are in place. Remaining items are narrow follow-ups rather than foundation work.
|
||||
|
||||
The current repo already has useful footholds:
|
||||
The current repo now has concrete Phase 2 implementation footholds:
|
||||
|
||||
- `ControlServices` owns OSC/web/file-watch ingress and queues service-side work.
|
||||
- `RuntimeCoordinator` owns mutation validation, classification, and coordinator result policy.
|
||||
- `RuntimeUpdateController` applies coordinator outcomes and bridges toward render, shader builds, broadcasts, and backend state.
|
||||
- `RuntimeSnapshotProvider` publishes render-facing snapshots.
|
||||
- `HealthTelemetry` owns status/timing snapshots.
|
||||
- `RuntimeEventType`, typed payload structs, `RuntimeEvent`, `RuntimeEventQueue`, `RuntimeEventDispatcher`, and `RuntimeEventCoalescingQueue` define the event substrate.
|
||||
- `OpenGLComposite` owns one app-level `RuntimeEventDispatcher` and passes it into `RuntimeServices`, `RuntimeCoordinator`, `RuntimeUpdateController`, `RuntimeSnapshotProvider`, `ShaderBuildQueue`, and `VideoBackend`.
|
||||
- `ControlServices` publishes typed OSC and runtime-state broadcast events and uses condition-variable wakeups with a fallback compatibility timer.
|
||||
- `RuntimeCoordinator` publishes accepted, rejected, state-changed, persistence, reload, shader-build, and compile-status follow-up events.
|
||||
- `RuntimeUpdateController` subscribes to event families for broadcast, shader build, compile status, render reset, and dispatcher health observations.
|
||||
- `RuntimeSnapshotProvider` publishes render snapshot request/published events.
|
||||
- `ShaderBuildQueue` and `RuntimeUpdateController` publish shader build lifecycle events with generation matching.
|
||||
- `VideoBackend` publishes backend observation events and timing samples.
|
||||
- `HealthTelemetry` receives dispatcher metrics directly and the event vocabulary now includes health observation events.
|
||||
- Tests cover event type stability, payload mapping, FIFO dispatch, coalescing infrastructure, app-level coalesced broadcast/build behavior, handler failures, mutation follow-up behavior, reload bridge behavior, and shader-build generation behavior.
|
||||
|
||||
Those are good boundaries. The Phase 2 job is to stop using "poll, drain, then interpret side effects" as the main coordination style between them.
|
||||
The implementation is now established in the repo. The remaining Phase 2 follow-up work is small: add completion/failure observations where useful and keep the runtime-store poll fallback explicitly transitional until a later file-watch implementation replaces it.
|
||||
|
||||
## Why Phase 2 Exists
|
||||
|
||||
The resilience review calls out three timing and ownership problems that an event model can directly improve:
|
||||
The resilience review originally called out three timing and ownership problems that an event model could directly improve:
|
||||
|
||||
- background service timing still relies on coarse sleeps and polling
|
||||
- control, reload, persistence, and render-update work still travel through mixed shared state and result queues
|
||||
- background service timing relied on coarse sleeps and polling
|
||||
- control, reload, persistence, and render-update work traveled through mixed shared state and result queues
|
||||
- later render/backend refactors need a stable coordination model before they move more work across threads
|
||||
|
||||
The goal is not to make the app fully asynchronous in one pass. It is to introduce typed internal events so each subsystem can publish what happened without knowing who will react or how many downstream effects are needed.
|
||||
@@ -56,15 +62,24 @@ Those are later phases. Phase 2 provides the coordination substrate they can bui
|
||||
|
||||
## Current Coordination Shape
|
||||
|
||||
The current runtime is much cleaner than before Phase 1, but coordination is still mostly pull-based:
|
||||
The current runtime is much cleaner than before Phase 1, and Phase 2 has moved the main coordination model toward typed publication and app-owned dispatch:
|
||||
|
||||
- `ControlServices::PollLoop(...)` drains pending OSC commits, polls runtime file changes, queues `RuntimeCoordinatorResult` objects, then sleeps.
|
||||
- `RuntimeUpdateController::ProcessRuntimeWork()` consumes queued coordinator results, applies them, and then checks whether a prepared shader build is ready.
|
||||
- `RuntimeCoordinatorResult` carries many downstream effects: shader build request, compile status update, transient OSC clear, runtime-state broadcast, committed-state mode, render reset scope.
|
||||
- shader-build readiness is polled from the app update path.
|
||||
- runtime-state broadcasts are requested by direct calls rather than by an event publication contract.
|
||||
- `ControlServices` publishes OSC value, OSC commit, and runtime-state broadcast events.
|
||||
- `ControlServices::PollLoop(...)` is wakeup-driven for queued OSC commit work, with a bounded fallback timer for compatibility polling.
|
||||
- `RuntimeCoordinator` still returns `RuntimeCoordinatorResult` for synchronous callers, but also publishes accepted/rejected/follow-up events.
|
||||
- `RuntimeUpdateController` subscribes to event families and applies many effects from events rather than only from drained result objects.
|
||||
- shader-build request, readiness, failure, and application are represented by typed events.
|
||||
- render snapshot publication and backend observations are represented by typed events.
|
||||
- dispatcher queue metrics and handler failures feed telemetry and health observation events.
|
||||
|
||||
This works, but it keeps timing behavior implicit. Phase 2 should make those transitions visible as typed events.
|
||||
There is still transitional bridge-state:
|
||||
|
||||
- `ControlServices` still exposes completed OSC commit notifications for render overlay settlement.
|
||||
- `RuntimeEventCoalescingQueue` is now wired into the app-owned dispatcher for latest-value event types.
|
||||
- `FileChangeDetected` and `ManualReloadRequested` are now published as reload ingress bridge events before coordinator reload follow-ups.
|
||||
- runtime-state broadcast completion/failure events are still a target, not current behavior.
|
||||
|
||||
That means Phase 2 is complete enough as the coordination substrate for later phases. The remaining items are refinement work and should not block moving to render ownership, live-state layering, or persistence work.
|
||||
|
||||
## Event Model Principles
|
||||
|
||||
@@ -289,23 +304,24 @@ Phase 2 does not need a large framework. A small app-owned dispatcher is enough.
|
||||
|
||||
Suggested components:
|
||||
|
||||
- `RuntimeEventBus`
|
||||
- `RuntimeEventDispatcher`
|
||||
- owns queues
|
||||
- assigns sequence numbers
|
||||
- exposes `Publish(...)`
|
||||
- exposes `Drain(...)` or `DispatchPending(...)`
|
||||
- `RuntimeEventHandler`
|
||||
- exposes `DispatchPending(...)`
|
||||
- event handlers
|
||||
- narrow handler interface or function callback
|
||||
- registered by subsystem/composition root
|
||||
- `RuntimeEventQueue`
|
||||
- bounded FIFO for ordinary events
|
||||
- coalesced map for latest-value events such as high-rate OSC
|
||||
- `RuntimeEventMetrics`
|
||||
- `RuntimeEventCoalescingQueue`
|
||||
- bounded keyed latest-value queue for flows such as high-rate OSC, broadcast requests, file/reload bursts, and queue-depth telemetry
|
||||
- queue and dispatch metrics
|
||||
- queue depth
|
||||
- oldest event age
|
||||
- dropped/coalesced counts
|
||||
|
||||
Initial implementation can be single-process and mostly single-dispatch-thread. The important part is that event publication and event handling become explicit.
|
||||
Initial implementation is single-process and mostly single-dispatch-thread. The important part is that event publication and event handling are explicit.
|
||||
|
||||
### Dispatcher Ownership Decision
|
||||
|
||||
@@ -320,6 +336,7 @@ References:
|
||||
- `RuntimeServices` receives the dispatcher and passes it to `ControlServices`.
|
||||
- `RuntimeCoordinator` receives the dispatcher so coordinator outcomes can become explicit events.
|
||||
- `RuntimeUpdateController` receives the dispatcher so it can become the first effect/apply handler.
|
||||
- `RuntimeSnapshotProvider`, `ShaderBuildQueue`, and `VideoBackend` receive the dispatcher so snapshot, shader lifecycle, and backend observation events are visible.
|
||||
|
||||
This is intentionally a composition-root dependency, not a new subsystem dependency. Subsystems should not construct their own dispatchers, and future tests should use `RuntimeEventTestHarness` rather than creating ad hoc event plumbing.
|
||||
|
||||
@@ -372,27 +389,27 @@ This section is the implementation rulebook for converting existing direct calls
|
||||
| `coalesced-latest` | only the latest value per key matters | bounded coalescing queue | handler consumes the latest event and telemetry records collapsed count |
|
||||
| `sync-command-with-event` | caller needs an immediate success/error result | direct owner call plus follow-up event publication | handler must not be required for the caller's response |
|
||||
| `observation-only` | event is telemetry/diagnostic and must not drive core behavior | FIFO or coalesced depending on rate | handler failure must never block app behavior |
|
||||
| `compatibility-poll` | source cannot yet publish an event directly | temporary poll adapter publishes typed events | poll interval should shrink or become wakeup-driven over Phase 2 |
|
||||
| `compatibility-poll` | source cannot yet publish an event directly | temporary poll adapter publishes typed events | poll interval is wakeup-driven with a fallback timer until a later file-watch implementation replaces it |
|
||||
|
||||
### Current Bridge Decisions
|
||||
|
||||
| Current flow | First Phase 2 bridge | Event(s) | Queue policy |
|
||||
| Current flow | Phase 2 bridge | Event(s) | Current status |
|
||||
| --- | --- | --- | --- |
|
||||
| OSC latest-value updates | `ControlServices` ingress bridge | `OscValueReceived`, optional `OscValueCoalesced` | `coalesced-latest` by route key |
|
||||
| OSC commit after settle | `ControlServices -> RuntimeCoordinator` bridge | `OscCommitRequested`, then `RuntimeMutationAccepted` or `RuntimeMutationRejected` | commit request `coalesced-latest` by route key; mutation result `fifo-fact` |
|
||||
| HTTP/UI mutation needing response | direct call into `RuntimeCoordinator` | `RuntimeMutationAccepted` or `RuntimeMutationRejected` after the synchronous response path | `sync-command-with-event` |
|
||||
| runtime-state broadcast request | presentation/broadcast bridge | `RuntimeStatePresentationChanged`, `RuntimeStateBroadcastRequested` | `coalesced-latest` by event type or reason family |
|
||||
| manual reload button | control ingress bridge | `ManualReloadRequested`, then `RuntimeReloadRequested` | `fifo-fact` for manual request; reload execution may coalesce |
|
||||
| file watcher changes | file-watch bridge | `FileChangeDetected`, then `RuntimeReloadRequested` | `coalesced-latest` by path, then coalesced reload request |
|
||||
| runtime store poll fallback | compatibility poll adapter | `ShaderPackagesChanged`, `RuntimeReloadRequested`, or warning event | `compatibility-poll` until file events fully replace polling |
|
||||
| shader build request | runtime/render bridge | `ShaderBuildRequested` | `coalesced-latest` by input dimensions and preserve-feedback flag |
|
||||
| shader build ready/failure/apply | shader build lifecycle bridge | `ShaderBuildPrepared`, `ShaderBuildFailed`, `ShaderBuildApplied`, `CompileStatusChanged` | `fifo-fact` |
|
||||
| render snapshot publication | snapshot bridge | `RenderSnapshotPublishRequested`, `RenderSnapshotPublished` | request may coalesce by output dimensions; published event is `fifo-fact` |
|
||||
| render reset request/application | render bridge | `RenderResetRequested`, `RenderResetApplied` | `fifo-fact` |
|
||||
| input signal changes | backend observation bridge | `InputSignalChanged` | `coalesced-latest` by signal lane |
|
||||
| output late/dropped/completed frames | backend timing bridge | `OutputFrameCompleted`, `OutputLateFrameDetected`, `OutputDroppedFrameDetected` | late/dropped `fifo-fact`; high-rate completed frames may become `observation-only` coalesced metrics |
|
||||
| warnings and recovery | telemetry bridge | `SubsystemWarningRaised`, `SubsystemWarningCleared`, `SubsystemRecovered` | `fifo-fact` for lifecycle transitions |
|
||||
| queue depth/timing samples | telemetry metrics bridge | `QueueDepthChanged`, `TimingSampleRecorded` | `coalesced-latest` by metric key |
|
||||
| OSC latest-value updates | `ControlServices` ingress bridge | `OscValueReceived`, optional `OscValueCoalesced` | Event publication exists; source-side pending map and app-level dispatcher coalescing both provide latest-value behavior. |
|
||||
| OSC commit after settle | `ControlServices -> RuntimeCoordinator` bridge | `OscCommitRequested`, then `RuntimeMutationAccepted` or `RuntimeMutationRejected` | Event publication exists. Coordinator follow-up work now reaches the app path through events rather than a service-result queue. |
|
||||
| HTTP/UI mutation needing response | direct call into `RuntimeCoordinator` | `RuntimeMutationAccepted` or `RuntimeMutationRejected` after the synchronous response path | Implemented as `sync-command-with-event`; synchronous response remains supported. |
|
||||
| runtime-state broadcast request | presentation/broadcast bridge | `RuntimeStatePresentationChanged`, `RuntimeStateBroadcastRequested` | Request event exists, is handled, and is coalesced by the app dispatcher. Completion/failure events remain follow-ups. |
|
||||
| manual reload button | control ingress bridge | `ManualReloadRequested`, then `RuntimeReloadRequested` | Ingress and follow-up events exist and are covered by tests. |
|
||||
| file watcher changes | file-watch bridge | `FileChangeDetected`, then `RuntimeReloadRequested` | Poll fallback remains, but detected changes now publish ingress and follow-up events and are covered by tests. |
|
||||
| runtime store poll fallback | compatibility poll adapter | `FileChangeDetected`, `RuntimeReloadRequested`, or warning/compile-status event | Still present by design as a transitional bridge with a condition-variable fallback timer. Detected changes publish ingress and follow-up events. |
|
||||
| shader build request | runtime/render bridge | `ShaderBuildRequested` | Event publication, handler, and app dispatcher coalescing exist. |
|
||||
| shader build ready/failure/apply | shader build lifecycle bridge | `ShaderBuildPrepared`, `ShaderBuildFailed`, `ShaderBuildApplied`, `CompileStatusChanged` | Implemented with generation matching. |
|
||||
| render snapshot publication | snapshot bridge | `RenderSnapshotPublishRequested`, `RenderSnapshotPublished` | Implemented. Publish requests are coalesced by output dimensions in the app dispatcher. |
|
||||
| render reset request/application | render bridge | `RenderResetRequested`, `RenderResetApplied` | Request handling exists; applied event coverage can be expanded in later render work. |
|
||||
| input signal changes | backend observation bridge | `InputSignalChanged` | Implemented as backend observation publication. |
|
||||
| output late/dropped/completed frames | backend timing bridge | `OutputFrameCompleted`, `OutputLateFrameDetected`, `OutputDroppedFrameDetected` | Implemented at the vocabulary and backend publication level. High-rate policy may be refined during backend lifecycle work. |
|
||||
| warnings and recovery | telemetry bridge | `SubsystemWarningRaised`, `SubsystemWarningCleared`, `SubsystemRecovered` | Vocabulary exists; direct telemetry writes still coexist with event observations. |
|
||||
| queue depth/timing samples | telemetry metrics bridge | `QueueDepthChanged`, `TimingSampleRecorded` | Implemented for dispatcher/backend observations and coalesced by metric key in the app dispatcher. |
|
||||
|
||||
### Bridge Rules
|
||||
|
||||
@@ -456,6 +473,8 @@ After that, the next bridge should be `ShaderBuildRequested`, because it already
|
||||
|
||||
### Step 1. Add Event Types And A Minimal Dispatcher
|
||||
|
||||
Status: complete.
|
||||
|
||||
Introduce:
|
||||
|
||||
- `RuntimeEvent`
|
||||
@@ -472,6 +491,8 @@ Start with events that do not change behavior:
|
||||
|
||||
### Step 2. Convert `RuntimeUpdateController` Into An Event Handler
|
||||
|
||||
Status: complete for the Phase 2 target, with synchronous API helpers retained.
|
||||
|
||||
`RuntimeUpdateController` is already close to an event effect applier. Phase 2 should narrow it into a handler for:
|
||||
|
||||
- coordinator outcome events
|
||||
@@ -481,8 +502,12 @@ Start with events that do not change behavior:
|
||||
|
||||
The class should stop being the place that polls every source of work.
|
||||
|
||||
Current note: `RuntimeUpdateController` now subscribes to the dispatcher and handles broadcast, reload, shader build, compile status, render reset, and health observation paths. It still accepts synchronous `RuntimeCoordinatorResult` values for UI/API calls that need immediate success or error responses.
|
||||
|
||||
### Step 3. Replace `ControlServices::PollLoop` Sleep With Wakeups
|
||||
|
||||
Status: complete for OSC commit wakeups; runtime-store compatibility polling remains explicitly transitional.
|
||||
|
||||
Keep coalescing, but replace the fixed `25 x Sleep(10)` cadence with:
|
||||
|
||||
- a condition variable or waitable event
|
||||
@@ -492,8 +517,12 @@ Keep coalescing, but replace the fixed `25 x Sleep(10)` cadence with:
|
||||
|
||||
This is the most direct Phase 2 timing win.
|
||||
|
||||
Current note: `ControlServices` now uses a condition variable and fallback timer. The fallback exists for runtime-store polling until a later file-watch implementation can replace scanning as the change source. Detected reload/file changes publish typed ingress and follow-up events.
|
||||
|
||||
### Step 4. Route Shader Build Lifecycle Through Events
|
||||
|
||||
Status: mostly complete.
|
||||
|
||||
Turn the current request/apply/failure/success path into explicit events:
|
||||
|
||||
- `ShaderBuildRequested`
|
||||
@@ -504,8 +533,12 @@ Turn the current request/apply/failure/success path into explicit events:
|
||||
|
||||
This should preserve the current off-frame-path compile behavior while making readiness visible.
|
||||
|
||||
Current note: request, prepared, failed, applied, and compile-status events exist. Generation-aware consumption is covered by tests. Request events are coalesced by build dimensions and preserve-feedback policy in the app dispatcher.
|
||||
|
||||
### Step 5. Route Runtime Broadcasts Through Events
|
||||
|
||||
Status: partially complete.
|
||||
|
||||
Replace direct "broadcast now" decisions with:
|
||||
|
||||
- `RuntimeStatePresentationChanged`
|
||||
@@ -515,8 +548,12 @@ Replace direct "broadcast now" decisions with:
|
||||
|
||||
This keeps UI delivery in `ControlServices` while keeping presentation ownership in the runtime presentation layer.
|
||||
|
||||
Current note: `RuntimeStateBroadcastRequested` exists, is coalesced by the app dispatcher, and is handled. Broadcast completion/failure events have not been added yet.
|
||||
|
||||
### Step 6. Add Event Metrics
|
||||
|
||||
Status: mostly complete for dispatcher metrics; broader health-event observation continues.
|
||||
|
||||
Before using the event system for hotter paths, add metrics:
|
||||
|
||||
- event queue depth
|
||||
@@ -528,6 +565,8 @@ Before using the event system for hotter paths, add metrics:
|
||||
|
||||
These should feed `HealthTelemetry`.
|
||||
|
||||
Current note: queue depth, oldest-event age, dispatch duration, dropped count, coalesced count, and handler failure counts feed telemetry. Queue/timing events are also published and coalesced by metric key.
|
||||
|
||||
## Dependency Rules
|
||||
|
||||
Allowed:
|
||||
@@ -551,39 +590,61 @@ The dispatcher is coordination infrastructure, not a new domain owner.
|
||||
|
||||
Phase 2 should add tests that do not require GL, DeckLink, or network sockets.
|
||||
|
||||
Recommended tests:
|
||||
Implemented tests:
|
||||
|
||||
- FIFO events dispatch in sequence order
|
||||
- coalesced events keep the latest payload and count collapsed updates
|
||||
- rejected mutations publish rejection events without downstream snapshot/build events
|
||||
- accepted parameter mutations publish the expected follow-up event set
|
||||
- file reload bursts collapse into one reload request
|
||||
- handler failures are reported as health/log events
|
||||
- queue depth and oldest-event-age metrics update predictably
|
||||
- typed payload mapping covers persistence, render snapshot, backend, timing, queue-depth, and late/dropped output-frame events
|
||||
- shader build generation matching applies only the expected prepared build
|
||||
|
||||
The existing runtime subsystem tests are a good home for the first pure event model tests, or a new `RuntimeEventTests.cpp` target can be added if the event layer grows enough.
|
||||
Remaining useful tests before deeper file-watch work:
|
||||
|
||||
- file reload bursts collapse into one reload request across a real poll burst
|
||||
- broadcast completion/failure events are observable once those payloads exist
|
||||
|
||||
The existing `RuntimeEventTypeTests` target is now the main pure event behavior harness. `RuntimeEventTestHarness` should remain the shared test helper so future lanes do not invent their own dispatcher plumbing.
|
||||
|
||||
## Phase 2 Exit Criteria
|
||||
|
||||
Phase 2 can be considered complete once the project can say:
|
||||
|
||||
- there is a typed internal event envelope and dispatcher
|
||||
- `ControlServices` emits typed events for OSC commits, broadcast requests, and reload/file-change work
|
||||
- `RuntimeCoordinator` publishes explicit accepted/rejected/follow-up events instead of callers interpreting broad result objects everywhere
|
||||
- `RuntimeUpdateController` handles events rather than polling all runtime work sources directly
|
||||
- shader build request/readiness/failure/application is represented as events
|
||||
- runtime-state broadcasts are event-driven and coalesced
|
||||
- event queues expose depth, age, coalescing, and failure metrics
|
||||
- coarse sleep polling is no longer the default coordination model for service work
|
||||
- [x] there is a typed internal event envelope and dispatcher
|
||||
- [x] `OpenGLComposite` owns the dispatcher as the current composition root
|
||||
- [x] `ControlServices` emits typed events for OSC commits and broadcast requests
|
||||
- [x] reload/file-change work publishes typed ingress and follow-up events
|
||||
- [x] `RuntimeCoordinator` publishes explicit accepted/rejected/follow-up events
|
||||
- [x] callers no longer need broad compatibility result queues for normal runtime side effects
|
||||
- [x] `RuntimeUpdateController` handles event-driven broadcast, shader build, compile status, render reset, and health observation paths
|
||||
- [x] `RuntimeUpdateController` no longer needs compatibility result draining for ordinary service work
|
||||
- [x] shader build request/readiness/failure/application is represented as events
|
||||
- [x] shader build requests are coalesced by dimensions and preserve-feedback policy in the app path
|
||||
- [x] render snapshot publication is represented as request/published events
|
||||
- [x] render snapshot publish requests are coalesced in the app path where needed
|
||||
- [x] backend observations publish typed events
|
||||
- [x] event queues expose depth, age, dropped, coalescing, and failure metrics
|
||||
- [x] production event paths use coalescing for broadcast requests, shader-build requests, and high-rate metrics
|
||||
- [x] coarse sleep polling is no longer the default coordination model for OSC commit service work
|
||||
- [x] runtime-store/file-change compatibility polling is explicitly contained and publishes event-first reload bridge events when changes are detected
|
||||
|
||||
Phase 2 closure note:
|
||||
|
||||
- The checklist above is complete for the internal event model substrate.
|
||||
- Broadcast completion/failure events and real file-watch burst tests are useful follow-ups, but they are no longer foundation blockers.
|
||||
- `RuntimeCoordinatorResult` may remain as a synchronous return type for command APIs; the Phase 2 requirement is that accepted/rejected/follow-up behavior is also published as typed events, which is now true.
|
||||
|
||||
## Open Questions For Implementation
|
||||
|
||||
- Should the first dispatcher be single-threaded and pumped by the app loop, or should `ControlServices` own a dedicated service event thread?
|
||||
- Should high-rate OSC transient overlay events go through the same bus, or should only commit/settle events enter the bus initially?
|
||||
- Should event payloads use `std::variant`, type-erased handlers, or separate strongly typed queues per family?
|
||||
- How much of `RuntimeCoordinatorResult` should survive as an internal helper versus being replaced by explicit events?
|
||||
- Should persistence requests be represented in Phase 2 even though the background writer lands later?
|
||||
- Should backend callback events be introduced now as observation-only events, or wait until the backend state-machine phase?
|
||||
- Resolved: the first dispatcher is single-process, app-owned, and pumped through the current app/update path.
|
||||
- Resolved: event payloads use typed structs carried by `std::variant`.
|
||||
- Resolved: persistence requests are represented in Phase 2 even though background persistence lands later.
|
||||
- Resolved: backend callback events are introduced now as observation-only events.
|
||||
- Still open: should high-rate OSC transient overlay events enter the app dispatcher, or should they remain source-local until the live-state layering phase?
|
||||
- Resolved for Phase 2: `RuntimeCoordinatorResult` can survive as a synchronous helper for command APIs, as long as event publication remains the coordination path for downstream effects.
|
||||
- Resolved: app-level coalescing lives inside `RuntimeEventDispatcher`; source-specific bridges can still coalesce before publication when they own useful domain-specific collapse policy.
|
||||
|
||||
## Short Version
|
||||
|
||||
|
||||
Reference in New Issue
Block a user