Skip to content

symfonic.memory.backends.postgres_erase_create

postgres_erase_create

Creating a durable native erase job under the sweep's locks (CORE-199).

PostgresNativeEraser.start calls these inside its first transaction, after the tenant's lifecycle lock and the EXCLUSIVE graph lock.

create async

create(conn: Any, jobs: str, scope: Any, *, vectors: bool = False) -> tuple[EraseStep, bool]

Under both locks: erase content, and record a job only if more remains.

Content over one transaction's budget is not erased here at all: the job is recorded in phase edges with the subtree's erase generation, and from that commit every read hides the subtree and every write refuses under it; chunks erase the content (postgres_erase_content). The flag says whether the job was recorded that way.

Source code in src/symfonic/memory/backends/postgres_erase_create.py
async def create(
    conn: Any, jobs: str, scope: Any, *, vectors: bool = False
) -> tuple[EraseStep, bool]:
    """Under both locks: erase content, and record a job only if more remains.

    Content over one transaction's budget is not erased here at all: the job
    is recorded in phase ``edges`` with the subtree's erase generation, and
    from that commit every read hides the subtree and every write refuses
    under it; chunks erase the content (``postgres_erase_content``). The flag
    says whether the job was recorded that way.
    """
    from symfonic.memory.backends import postgres_erase_content as content
    from symfonic.memory.backends.postgres_memory_generation import advance
    from symfonic.memory.backends.postgres_native_subtree import delete_graph_ids
    from symfonic.memory.backends.postgres_pending_claims import erase_subtree, over_budget

    if await content.over_budget(conn, scope):
        if not await content.content_ready(conn, jobs):
            raise MemoryContractError(content.CONTENT_EXCEEDED)
        job_id = await _record(conn, jobs, scope, "edges", vectors=vectors)
        await advance(conn, scope)
        return EraseStep(job_id, False), True
    large = await over_budget(conn, scope)
    doomed = await delete_graph_ids(conn, scope)
    if not large:
        if vectors:
            return EraseStep(
                await _record(conn, jobs, scope, None, vectors=True), False, doomed
            ), False
        await erase_subtree(conn, scope)
        return EraseStep(None, True, doomed), False
    return EraseStep(await _record(conn, jobs, scope, None, vectors=vectors), False, doomed), False