Skip to content

symfonic.memory.backends.mongo_positional_rows

mongo_positional_rows

Mongo rows for the CORE-171 positional migration, read and re-keyed.

One session is one snapshot transaction of the guarded session domain, opened through its tenant guard: the $inc on the tenant's guard document is the transaction's first write. Every cooperating writer, publication and native forget of that tenant takes the same document, so they and a migration serialize as write conflicts, and an abort -- a refusal, an unmatched row, a lost conflict -- rolls every re-keyed document back. Writers constructed outside the domain are outside this fence, as they are for every guarded operation.

Every session, planning (write=False) included, opens through that guard, so planning writes once: the $inc of the tenant's guard revision, a serialization counter that is metadata only. No row, owner copy or lease changes unless a writing session re-keys or deletes.

A migrated row is reached by the public Mongo v1 forget (capabilities.memory.mongo_native_forget), which erases a native scope and its descendants unless its inventory refuses. A row whose target that forget already erased is quarantined, not moved: the session reads the forget's erase documents (mongo_native_erased) in the same guarded transaction. Apply refuses, before any re-key, when that forget's inventory caps or owner checks would refuse the tenant afterwards (mongo_positional_forget_admission). Rollback refuses on Mongo (RESTORE_UNPROVABLE): the erase documents record native forgets only, so nothing proves a quarantined row's v0 origin was not forgotten since apply. The pending-marker check a rollback would take in the same guarded transaction is kept, and tested, for when one is.

Every owner copy moves together: a node's top-level scope_path and its properties.scope_path, an edge's scope_path, and a vector's scope_path and metadata.scope_path. Mongo v1 forget inventories and erases vectors, so a migrated vector copy stays erasable. A copy absent before stays absent. A NULL or missing owner is restored as null, which every Mongo read treats as the same pre-v8 owner.

MongoPositionalRows

MongoPositionalRows(domain: Any)

Sessions over one exact guarded Mongo session domain.

Source code in src/symfonic/memory/backends/mongo_positional_rows.py
def __init__(self, domain: Any) -> None:
    self._domain = domain

admit classmethod

admit(store: Any) -> MongoPositionalRows | None

The guarded domain behind store, or None when it is not exact.

Source code in src/symfonic/memory/backends/mongo_positional_rows.py
@classmethod
def admit(cls, store: Any) -> MongoPositionalRows | None:
    """The guarded domain behind ``store``, or None when it is not exact."""
    from symfonic.memory.backends.mongo_tenant_guard import _Backend, _TenantGuardDomain
    from symfonic.memory.backends.mongodb import MongoGraphBackend, MongoVectorBackend

    graph = store.graph
    domain = getattr(graph, "_domain", None) if isinstance(graph, _Backend) else None
    if (not isinstance(domain, _TenantGuardDomain) or domain.graph is not graph
            or type(graph._backend) is not MongoGraphBackend  # noqa: SLF001
            or type(domain.vector._backend) is not MongoVectorBackend  # noqa: SLF001
            or any(vector is not domain.vector
                   for vector in store.transaction_participants[1:])):
        return None
    return cls(domain)

refuse_caller_transaction

refuse_caller_transaction() -> None

No refusal: the guarded session domain refuses a nested or concurrent transaction, so no forget can join one around apply or rollback.

Source code in src/symfonic/memory/backends/mongo_positional_rows.py
def refuse_caller_transaction(self) -> None:
    """No refusal: the guarded session domain refuses a nested or concurrent
    transaction, so no forget can join one around apply or rollback."""