-
Notifications
You must be signed in to change notification settings - Fork 10
fix(rfc64): settle SWM only after VM commit #2040
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: codex/rfc64-m1-edge-periodic-scope-plan
Are you sure you want to change the base?
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -68,19 +68,16 @@ interface SharedMemorySyncContext { | |
| }>; | ||
| ensureContextGraph: (contextGraphId: string) => Promise<void>; | ||
| storeInsert: (quads: Quad[]) => Promise<void>; | ||
| /** Store adapter for verified public SWM snapshots. */ | ||
| snapshotMaterializer?: SharedMemorySnapshotMaterializer; | ||
| /** | ||
| * Everything needed to MATERIALIZE verified public SWM snapshots into the | ||
| * triple store, as ONE cohesive dependency — the contract (and the | ||
| * production implementation) live in `swm-snapshot-materializer.ts`. | ||
| * | ||
| * Why it exists at all: contentScopeVersion-2 KAs carry no dkg:rootEntity, | ||
| * so the aggregate data phase legitimately returns 0 data quads for them — | ||
| * their content travels as immutable snapshots. The catch-up lane fetched | ||
| * and VERIFIED those snapshots and then never wrote them, so a node that | ||
| * missed the live gossip stayed empty forever ("0 data + N meta triples"). | ||
| * Absent entirely => materialization is skipped (never half-applied). | ||
| * Post-commit policy for a materialized snapshot. It runs only after the | ||
| * verified metadata insert succeeds and outside the per-KA write lock. | ||
| */ | ||
| snapshotMaterializer?: SharedMemorySnapshotMaterializer; | ||
| settleGraphScopedSnapshot?: ( | ||
| contextGraphId: string, | ||
| descriptor: GraphScopedSwmRecoveryDescriptor, | ||
| ) => Promise<void>; | ||
| publicSnapshotStore?: WorkspacePublicSnapshotStore; | ||
| getRegisteredSubGraphNames?: (contextGraphId: string) => Promise<readonly string[]>; | ||
| getExcludedSubGraphNames?: (contextGraphId: string) => Promise<readonly string[]>; | ||
|
|
@@ -119,6 +116,7 @@ export async function runSharedMemorySync(context: SharedMemorySyncContext): Pro | |
| ensureContextGraph, | ||
| storeInsert, | ||
| snapshotMaterializer, | ||
| settleGraphScopedSnapshot, | ||
| publicSnapshotStore, | ||
| getRegisteredSubGraphNames, | ||
| getExcludedSubGraphNames, | ||
|
|
@@ -468,15 +466,15 @@ export async function runSharedMemorySync(context: SharedMemorySyncContext): Pro | |
| summary.insertedTriples += processed.verifiedMeta.length; | ||
| summary.insertedMetaTriples += processed.verifiedMeta.length; | ||
| } | ||
| // Deliberately outside the per-KA snapshot lock above: the finalizer | ||
| // acquires the same lock before stamping the local retirement marker. | ||
| // Running settlement inside the materializer critical section would | ||
| // deadlock. The handoff remains part of the ONE required materializer | ||
| // contract, so production cannot wire materialization without it. | ||
| await snapshotMaterializer?.settleCommittedSnapshots( | ||
| pid, | ||
| [...settledDescriptors.values()], | ||
| ); | ||
| // Deliberately after the verified metadata insert and outside the per-KA | ||
| // snapshot lock above: the finalizer acquires that same lock before | ||
| // stamping the local retirement marker. A failed insert therefore keeps | ||
| // the recovery snapshot visible and cannot deadlock settlement. | ||
| if (settleGraphScopedSnapshot) { | ||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 🟡 Issue: Snapshot materialization can now be wired without its required settlement step What's wrong Example Suggested direction For Agents |
||
| for (const descriptor of settledDescriptors.values()) { | ||
| await settleGraphScopedSnapshot(pid, descriptor); | ||
| } | ||
| } | ||
| recordPhaseOutcome(wsMetaResult); | ||
| recordPhaseOutcome(wsDataResult); | ||
| if ((wsMetaResult.timedOut || wsDataResult.timedOut) && shouldStopAfterBackoffWorthyFailure(pid, 'phase timeout')) { | ||
|
|
||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🟡 Issue: The split settlement dependency is not verified against the half-configured case
What's wrong
This change moves post-commit settlement out of SharedMemorySnapshotMaterializer, but the new callback is optional and the coordinator no-ops when it is missing. The added tests validate the desired ordering only in harnesses that provide the callback, so they would not fail if a production or future caller materialized verified public SWM snapshots without retiring the finalized recovery copy.
Example
A caller supplies snapshotMaterializer and publicSnapshotStore so a verified graph-scoped snapshot is materialized, but omits settleGraphScopedSnapshot. runSharedMemorySync still inserts metadata, records phase completion, and never calls retireSyncedGraphScopedSwmIfFinalized, so the missing post-commit retirement is not caught by the current tests.
Suggested direction
Either make settlement a required dependency whenever snapshot materialization is enabled, or add a focused test proving that omitting it fails or leaves the phase incomplete instead of silently checkpointing.
Confidence note
I did not run the test suite in the read-only sandbox, but the diff and surrounding tests show the coordinator only exercises settlement when a callback is provided.
For Agents
Look at runSharedMemorySync in packages/agent/src/sync/requester/shared-memory-sync.ts and its snapshot materialization tests. Preserve the new ordering where settlement runs after verified metadata insertion and outside the KA lock, but add a regression test or contract check for the half-configured case: materializer present with settled descriptors but no settleGraphScopedSnapshot should not silently complete as successful materialization.