Skip to content

symfonic.memory.backends.postgres_memory_generation_witness

postgres_memory_generation_witness

The memory erase generation table's install witness and restore seal (CORE-171).

The forward row trigger carries two arguments: the installing transaction's pg_current_xact_id() and the cluster's system_identifier. The trigger row's xmin is that transaction's 32-bit form; a reader rebuilds its 64-bit value as the newest transaction ID at or below its own snapshot's xmax that shares those 32 bits, and requires it to equal the first argument, and the second to equal its own cluster's. A copy of the trigger -- a dump restored into this cluster, another cluster or by pg_upgrade -- is written by a later transaction or another cluster, so it never binds, whatever its 32 bits. The cost is a horizon: past 2^32 transactions after the install even the original no longer binds, and readers refuse until the script is re-run, which it accepts only while the witness still binds.

A turn's token binds the witness and the server it was captured on (the postmaster's start time): a physical restore, a promoted replica or a restart always starts a new postmaster, so a turn captured before one refuses.

A sealed table carries ('sealed', <export digest>) instead (postgres_memory_restore): no reader binds it, and the forward function refuses every write to it. The install refuses to re-mint over a table whose two-argument witness does not bind -- copied, sealed, expired or tampered --: only the restore procedure's validation re-mints it. Every mint also marks the table v2 (MARKER, its comment): the previous release's script keeps the table and its comment while it swaps in a no-argument trigger, and a dump carries the comment, so once marked, a witness that does not bind refuses whatever its argument count. An unmarked table with a 0/1-argument trigger -- an earlier release, or a pre-v2 backup -- is still re-minted: telling those apart needs proof kept outside the database. "Readers" here are the generation-table readers: turn admission and the erase gates.

bound_witness async

bound_witness(conn: Any, table: str, relation: int, rows: Any) -> tuple[int, int]

(witness, server) of relation, once rows and the name are proved its own.

Source code in src/symfonic/memory/backends/postgres_memory_generation_witness.py
async def bound_witness(conn: Any, table: str, relation: int, rows: Any) -> tuple[int, int]:
    """``(witness, server)`` of ``relation``, once ``rows`` and the name are proved its own."""
    if any(row["tableoid"] != relation for row in rows):
        raise MemoryContractError(REBOUND)
    same, witness, server = await conn.fetchval(_BOUND, table, relation)
    if not same:
        raise MemoryContractError(REBOUND)
    if witness is None:
        raise MemoryContractError(UNWITNESSED)
    return int(witness), int(server)

mint async

mint(conn: Any) -> int

Re-mint the witness on the table in conn's search path; the new witness.

Source code in src/symfonic/memory/backends/postgres_memory_generation_witness.py
async def mint(conn: Any) -> int:
    """Re-mint the witness on the table in ``conn``'s search path; the new witness."""
    await conn.execute(MINT)
    witness = await conn.fetchval(f"SELECT {witness_sql(_TABLE)}")
    if witness is None:  # inside a savepoint: the trigger row is the subtransaction's
        raise MemoryContractError(UNWITNESSED)
    return int(witness)

witness_sql

witness_sql(relation: str) -> str

The row trigger's witness on relation as text, or NULL unless bound.

Nested CASE: SQL does not short-circuit AND, so the cast runs only on digits.

Source code in src/symfonic/memory/backends/postgres_memory_generation_witness.py
def witness_sql(relation: str) -> str:
    """The row trigger's witness on ``relation`` as text, or NULL unless bound.

    Nested CASE: SQL does not short-circuit AND, so the cast runs only on digits.
    """
    return (
        f"(SELECT CASE WHEN {_ARG1} ~ '^[1-9][0-9]{{0,18}}$' THEN CASE WHEN "
        f"{_ARG2} = {_SYSTEM} AND {_ARG1}::numeric = {_XMIN64} THEN {_ARG1} END END "
        f"FROM pg_trigger t WHERE t.tgrelid={relation} AND t.tgname='{FORWARD}_rows' "
        "AND NOT t.tgisinternal AND t.tgnargs=2)"
    )