symfonic.capabilities.memory.publish¶
publish ¶
How a cycle becomes durable, and what happens when it may not.
Split from :mod:symfonic.capabilities.memory.consolidation along the seam
the design actually has: that module runs a roster, this one decides whether
what the roster produced is allowed to land. The two questions have different
readers -- a phase author needs the first, a reviewer of the atomicity contract
needs the second -- and keeping them in one file made the runtime the longest
module in the capability.
Everything here answers to :mod:.commit, which owns the rule that a cycle
commits in exactly one transaction domain or is refused before it starts.
publish_cycle
async
¶
publish_cycle(scope: MemoryScope, state: ConsolidationState, journal: CycleJournal, fence: Fence | None, domain: Any = None, writes: Any = None) -> tuple[str, ...]
Make this cycle's work durable -- all of it, or none of it.
Both halves go together: the graph mutations the phases made through the journal, and the records they staged through the write coordinator. Publishing them separately is the split this mechanism exists to close -- the runtime used to withhold the staged half on a failure while the direct half was already in the store, so a cycle that half-failed left a visible half.
A cycle that failed, was abandoned, or lost its lease discards the journal instead. What it did is then not merely unpublished, it never happened: the next clean cycle starts from the state this one found.
Source code in src/symfonic/capabilities/memory/publish.py
still_ours
async
¶
Ask the fence once more, whatever the phases did or did not write.
Not redundant with the per-mutation checks: a cycle whose phases all
read and none wrote reaches the end having never asked the fence
anything, and reporting clean for a cycle that had no authority
would tell a scheduler the scope was consolidated when another worker
was in the middle of consolidating it.