The reviewable plan of a CORE-171 positional row migration.
plan_rows classifies every candidate row of one tenant inside a backend
session and binds the result to a digest; it changes no row. Apply re-runs
it in its write session and refuses unless the digest still matches.
A plan is a public frozen value, so a caller can build or edit one, and its
digest is a public function of its rows: it proves no planner ran.
bound_plan refuses anything but exact builtin values whose rows hash to
the digest; apply then executes only the rows it re-reads. Rollback has no
re-read to lean on, so restorable_plan admits only quarantined rows,
whose key records the owner they came from.
PlannedRow
dataclass
PlannedRow(kind: str, row_id: str, source: str | bool | int | float | None, target: str | None, disposition: RowDisposition, reason: str)
One row's audited move; owner keys only, never memory content.
PositionalMigrationPlan
dataclass
PositionalMigrationPlan(tenant_id: str, rows: tuple[PlannedRow, ...], digest: str)
A reviewable migration of one tenant, bound to the rows it read.
counts
counts() -> dict[str, int]
Rows per disposition, for an operator's review.
Source code in src/symfonic/capabilities/memory/positional_plan.py
| def counts(self) -> dict[str, int]:
"""Rows per disposition, for an operator's review."""
return dict(Counter(row.disposition.value for row in self.rows))
|
moved
moved() -> tuple[PlannedRow, ...]
The rows apply re-keys and rollback restores.
Source code in src/symfonic/capabilities/memory/positional_plan.py
| def moved(self) -> tuple[PlannedRow, ...]:
"""The rows apply re-keys and rollback restores."""
return tuple(row for row in self.rows if row.disposition is not RowDisposition.UNTOUCHED)
|
bound_plan
bound_plan(plan: PositionalMigrationPlan) -> PositionalMigrationPlan
plan when it holds exact values whose rows hash to its digest, or refuse.
Source code in src/symfonic/capabilities/memory/positional_plan.py
| def bound_plan(plan: PositionalMigrationPlan) -> PositionalMigrationPlan:
"""``plan`` when it holds exact values whose rows hash to its digest, or refuse."""
rows = plan.rows
if (type(plan.tenant_id) is not str or type(plan.digest) is not str
or type(rows) is not tuple or not all(_exact(row) for row in rows)):
raise MemoryContractError(PLAN_UNBOUND)
if _digest(plan.tenant_id, rows) != plan.digest:
raise MemoryContractError(PLAN_UNBOUND)
return plan
|
restorable_plan
restorable_plan(plan: PositionalMigrationPlan) -> tuple[PlannedRow, ...]
The quarantined rows rollback restores, or refuse before any read.
A row moved to a native owner refuses (ROLLBACK_UNPROVABLE): nothing
the store or the audit port keeps tells it from a row written there since.
Source code in src/symfonic/capabilities/memory/positional_plan.py
| def restorable_plan(plan: PositionalMigrationPlan) -> tuple[PlannedRow, ...]:
"""The quarantined rows rollback restores, or refuse before any read.
A row moved to a native owner refuses (``ROLLBACK_UNPROVABLE``): nothing
the store or the audit port keeps tells it from a row written there since.
"""
moved = bound_plan(plan).moved()
if any(row.disposition is RowDisposition.MIGRATE for row in moved):
raise MemoryContractError(ROLLBACK_UNPROVABLE)
if len({(row.kind, row.row_id) for row in moved}) != len(moved) or not all(
_restorable(row) for row in moved
):
raise MemoryContractError(NOT_RESTORABLE)
return moved
|