Explicit, dark PostgreSQL edge writer for the scoped unique-index cutover.
This module never builds or removes indexes. A fleet write barrier and index
swap are operator work; a single connection cannot establish fleet state.
ScopedEdgeIndexNotReady
Bases: RuntimeError
The resolved edge table cannot safely serve scoped conflict writes.
ScopedEdgeWriteConflict
Bases: RuntimeError
A different unique constraint rejected the edge write.
require_scoped_edge_index
async
require_scoped_edge_index(conn: Any) -> None
Check the exact table resolved by the writer on this connection.
Source code in src/symfonic/memory/backends/postgres_edge_scoped_writer.py
| async def require_scoped_edge_index(conn: Any) -> None:
"""Check the exact table resolved by the writer on this connection."""
try:
indexes = await conn.fetch(_INDEX_SQL)
if (
not indexes or indexes[0]["relkind"] != "r"
or indexes[0]["identity_collations_deterministic"] is not True
):
raise ScopedEdgeIndexNotReady("scoped edge index is not ready")
for index in indexes:
keys = index["keys"]
if index["name"] == OLD_INDEX or (
index["unique"] and index["key_count"] == 4
and tuple(keys) == _KEYS
):
raise ScopedEdgeIndexNotReady("tenant-wide edge index is still present")
if (
index["name"] != NEW_INDEX and index["unique"]
and index["key_count"] == 5 and tuple(keys[:4]) == _KEYS
):
# ON CONFLICT may infer every matching unique index. An extra
# expression index can arbitrate with a different collation.
raise ScopedEdgeIndexNotReady("another scoped edge arbiter is present")
matches = [index for index in indexes if index["name"] == NEW_INDEX]
if len(matches) != 1:
raise ScopedEdgeIndexNotReady("scoped edge index is not ready")
index = matches[0]
keys = index["keys"]
if not (
index["unique"] and index["valid"] and index["ready"]
and index["live"] and index["nonpartial"]
and index["key_collations_deterministic"] is True
and index["key_opclasses_default"] is True
and index["method"] == "btree"
and index["key_count"] == index["total_count"] == 5
and len(keys) == 5 and tuple(keys[:4]) == _KEYS
and _canonical_expression(keys[4]) in _EXPRESSIONS
):
raise ScopedEdgeIndexNotReady("scoped edge index is not ready")
except ScopedEdgeIndexNotReady:
raise
except Exception:
# Driver errors can contain SQL values. Keep refusal independent of them.
raise ScopedEdgeIndexNotReady("scoped edge index verification failed") from None
|
upsert_scoped_edge
async
upsert_scoped_edge(conn: Any, scope: TenantScope, edge: MemoryEdge) -> Any
Verify then write through one connection; preserve the existing contract.
Source code in src/symfonic/memory/backends/postgres_edge_scoped_writer.py
| async def upsert_scoped_edge(conn: Any, scope: TenantScope, edge: MemoryEdge) -> Any:
"""Verify then write through one connection; preserve the existing contract."""
native = _is_native_scope(scope)
async with conn.transaction() if native else nullcontext():
if native:
from symfonic.memory.backends.postgres_native_edge_write import lock_native_endpoints
await lock_native_endpoints(conn, scope, edge)
return await _upsert_scoped_edge(conn, scope, edge)
|