Step 4
This commit is contained in:
@@ -241,6 +241,7 @@ void ControlServices::PollLoop(RuntimeCoordinator& runtimeCoordinator)
|
||||
completedCommit.generation = entry.second.generation;
|
||||
std::lock_guard<std::mutex> lock(mCompletedOscCommitMutex);
|
||||
mCompletedOscCommits.push_back(std::move(completedCommit));
|
||||
PublishOscOverlaySettled(entry.second);
|
||||
}
|
||||
else if (!result.errorMessage.empty())
|
||||
{
|
||||
@@ -321,3 +322,22 @@ void ControlServices::PublishOscCommitRequested(const PendingOscCommit& commit)
|
||||
OutputDebugStringA("OscCommitRequested event publish threw.\n");
|
||||
}
|
||||
}
|
||||
|
||||
void ControlServices::PublishOscOverlaySettled(const PendingOscCommit& commit)
|
||||
{
|
||||
try
|
||||
{
|
||||
OscOverlayEvent event;
|
||||
event.routeKey = commit.routeKey;
|
||||
event.layerKey = commit.layerKey;
|
||||
event.parameterKey = commit.parameterKey;
|
||||
event.generation = commit.generation;
|
||||
event.settled = true;
|
||||
if (!mRuntimeEventDispatcher.PublishPayload(event, "ControlServices"))
|
||||
OutputDebugStringA("OscOverlaySettled event publish failed.\n");
|
||||
}
|
||||
catch (...)
|
||||
{
|
||||
OutputDebugStringA("OscOverlaySettled event publish threw.\n");
|
||||
}
|
||||
}
|
||||
|
||||
@@ -76,6 +76,7 @@ private:
|
||||
void PublishRuntimeStateBroadcastRequested(const std::string& reason);
|
||||
void PublishOscValueReceived(const PendingOscUpdate& update, const std::string& routeKey);
|
||||
void PublishOscCommitRequested(const PendingOscCommit& commit);
|
||||
void PublishOscOverlaySettled(const PendingOscCommit& commit);
|
||||
|
||||
std::unique_ptr<ControlServer> mControlServer;
|
||||
std::unique_ptr<OscServer> mOscServer;
|
||||
|
||||
@@ -178,9 +178,14 @@ RuntimeCoordinatorResult RuntimeCoordinator::UpdateLayerParameterByControlKey(co
|
||||
RuntimeCoordinatorResult RuntimeCoordinator::CommitOscParameterByControlKey(const std::string& layerKey, const std::string& parameterKey, const JsonValue& newValue)
|
||||
{
|
||||
std::lock_guard<std::mutex> lock(mMutex);
|
||||
constexpr RuntimeCoordinatorOscCommitPersistence kDefaultOscCommitPersistence =
|
||||
RuntimeCoordinatorOscCommitPersistence::SessionOnly;
|
||||
constexpr bool kPersistSettledOscCommits =
|
||||
kDefaultOscCommitPersistence == RuntimeCoordinatorOscCommitPersistence::Persistent;
|
||||
|
||||
std::string error;
|
||||
ResolvedParameterMutation mutation;
|
||||
if (!BuildParameterMutationByControlKey(layerKey, parameterKey, newValue, true, mutation, error))
|
||||
if (!BuildParameterMutationByControlKey(layerKey, parameterKey, newValue, kPersistSettledOscCommits, mutation, error))
|
||||
{
|
||||
RuntimeCoordinatorResult result = ApplyStoreMutation(false, error, false, false, false);
|
||||
PublishCoordinatorResult("CommitOscParameterByControlKey", result);
|
||||
|
||||
@@ -32,6 +32,12 @@ enum class RuntimeCoordinatorTransientOscInvalidation
|
||||
All
|
||||
};
|
||||
|
||||
enum class RuntimeCoordinatorOscCommitPersistence
|
||||
{
|
||||
SessionOnly,
|
||||
Persistent
|
||||
};
|
||||
|
||||
struct RuntimeCoordinatorResult
|
||||
{
|
||||
bool accepted = false;
|
||||
|
||||
@@ -7,8 +7,8 @@ Phase 1 named the subsystems. Phase 2 added the typed event substrate. Phase 3 m
|
||||
## Status
|
||||
|
||||
- Phase 5 design package: proposed.
|
||||
- Phase 5 implementation: Step 3 complete.
|
||||
- Current alignment: Phase 3 introduced the first pure composition boundary and transient OSC overlay owner. Phase 5 now has a small `RuntimeStateLayerModel` inventory that names the current state categories, `RenderStateComposer` consumes a `LayeredRenderStateInput` whose fields make base persisted, committed live, and transient automation inputs explicit, and `RuntimeLiveState` owns transient-overlay invalidation against current layer/parameter compatibility. Committed runtime values are still physically stored through `RuntimeStore`/`LayerStackStore`.
|
||||
- Phase 5 implementation: Step 4 complete.
|
||||
- Current alignment: Phase 3 introduced the first pure composition boundary and transient OSC overlay owner. Phase 5 now has a small `RuntimeStateLayerModel` inventory that names the current state categories, `RenderStateComposer` consumes a `LayeredRenderStateInput` whose fields make base persisted, committed live, and transient automation inputs explicit, `RuntimeLiveState` owns transient-overlay invalidation against current layer/parameter compatibility, and settled OSC commits have an explicit session-only persistence policy. Committed runtime values are still physically stored through `RuntimeStore`/`LayerStackStore`.
|
||||
|
||||
Current live-state footholds:
|
||||
|
||||
@@ -20,6 +20,7 @@ Current live-state footholds:
|
||||
- `RuntimeServiceLiveBridge` drains OSC ingress/completion queues and applies them to render live state during frame preparation.
|
||||
- `RuntimeStateLayerModel` names the Phase 5 state categories and classifies current fields as base persisted, committed live, transient automation, render-local, or health/config state.
|
||||
- `RuntimeCoordinator` can request layer-scoped transient OSC invalidation, while `RuntimeLiveState` prunes overlays that no longer map to the current render-facing layer/parameter definitions.
|
||||
- `RuntimeCoordinator::CommitOscParameterByControlKey(...)` commits settled OSC values into session state without requesting persistence by default.
|
||||
|
||||
## Why Phase 5 Exists
|
||||
|
||||
@@ -287,13 +288,22 @@ Make the transient-to-committed path explicit.
|
||||
|
||||
Initial target:
|
||||
|
||||
- document and test whether settled OSC commits persist
|
||||
- ensure stale generation completions are ignored
|
||||
- ensure one settled route does not clear unrelated overlay state
|
||||
- publish or preserve useful events for accepted overlay commits
|
||||
- [x] document and test whether settled OSC commits persist
|
||||
- [x] ensure stale generation completions are ignored
|
||||
- [x] ensure one settled route does not clear unrelated overlay state
|
||||
- [x] publish or preserve useful events for accepted overlay commits
|
||||
|
||||
Current Phase 3 behavior is a good base; Phase 5 should make the policy easier to reason about from the code.
|
||||
|
||||
Current policy:
|
||||
|
||||
- settled OSC commits are `RuntimeCoordinatorOscCommitPersistence::SessionOnly` by default
|
||||
- accepted settled OSC commits update the committed session value through `RuntimeStore::SetStoredParameterValue(..., persistState = false, ...)`
|
||||
- accepted settled OSC commits publish runtime mutation/state-change observations, but no `RuntimePersistenceRequested` event
|
||||
- accepted service-side commit completions publish `OscOverlaySettled`
|
||||
- stale generation completions are ignored by `RuntimeLiveState::ApplyOscCommitCompletions(...)`
|
||||
- unrelated routes remain untouched when a different route settles or completes
|
||||
|
||||
### Step 5. Separate Committed-Live Concept From Durable Storage
|
||||
|
||||
Decide whether to physically split committed-live state now or introduce a read/model boundary first.
|
||||
@@ -377,7 +387,7 @@ Phase 5 can be considered complete once the project can say:
|
||||
- [x] final render-value precedence is explicit and covered by tests
|
||||
- [x] `RenderStateComposer` or its replacement consumes a layered input contract
|
||||
- [x] reset/reload/preset behavior for transient overlays is centralized or clearly delegated
|
||||
- [ ] OSC overlay settle/commit behavior is explicit, including persistence policy
|
||||
- [x] OSC overlay settle/commit behavior is explicit, including persistence policy
|
||||
- [ ] `RuntimeStore` remains durable-state focused and does not absorb transient automation policy
|
||||
- [ ] render-local temporal/feedback state remains separate from live parameter layering
|
||||
- [ ] subsystem docs and the architecture review reflect the final ownership model
|
||||
|
||||
@@ -272,6 +272,8 @@ For OSC specifically, the coordinator should eventually decide:
|
||||
- whether it should later commit into committed live state
|
||||
- what reset/reload actions invalidate it
|
||||
|
||||
Phase 5 sets the default settled OSC policy to session-only. `CommitOscParameterByControlKey(...)` updates committed session state through the store with persistence disabled, publishes ordinary mutation/state-change observations, and does not request a persistence write unless a future explicit policy opts into durable OSC commits.
|
||||
|
||||
### Health and timing state
|
||||
|
||||
The coordinator may emit events like:
|
||||
|
||||
@@ -311,8 +311,18 @@ void TestRuntimeCoordinatorPersistenceEvents()
|
||||
Expect(countEvents(overlayEvents, RuntimeEventType::OscOverlayApplied) == 1, "transient OSC overlay is observable");
|
||||
Expect(countEvents(overlayEvents, RuntimeEventType::RuntimePersistenceRequested) == 0, "transient OSC overlay does not request persistence");
|
||||
|
||||
expectAcceptedPersistence(coordinator.CommitOscParameterByControlKey("alpha", "gain", JsonValue(0.2)), "CommitOscParameterByControlKey",
|
||||
"accepted OSC commit is persistent");
|
||||
RuntimeCoordinatorResult oscCommitResult = coordinator.CommitOscParameterByControlKey("alpha", "gain", JsonValue(0.2));
|
||||
std::vector<RuntimeEvent> oscCommitEvents = dispatchAndClear();
|
||||
Expect(oscCommitResult.accepted, "accepted OSC commit updates committed session state");
|
||||
Expect(!oscCommitResult.persistenceRequested, "settled OSC commit does not request persistence by default");
|
||||
Expect(countEvents(oscCommitEvents, RuntimeEventType::RuntimeMutationAccepted) == 1, "settled OSC commit publishes accepted fact");
|
||||
Expect(countEvents(oscCommitEvents, RuntimeEventType::RuntimeStateChanged) == 1, "settled OSC commit publishes state change");
|
||||
Expect(countEvents(oscCommitEvents, RuntimeEventType::RuntimePersistenceRequested) == 0, "settled OSC commit publishes no persistence request");
|
||||
RuntimeStore::StoredParameterSnapshot oscCommitSnapshot;
|
||||
Expect(store.TryGetStoredParameterByControlKey("alpha", "gain", oscCommitSnapshot, error), "settled OSC commit can be read back");
|
||||
Expect(!oscCommitSnapshot.currentValue.numberValues.empty() &&
|
||||
oscCommitSnapshot.currentValue.numberValues[0] == 0.2,
|
||||
"settled OSC commit updates the committed session value");
|
||||
}
|
||||
|
||||
std::filesystem::remove_all(root);
|
||||
|
||||
Reference in New Issue
Block a user