Erase every node at scope or below it, with its edges.
Atomic by construction: the whole sweep runs in one synchronous span
with no await in it, so no concurrent write on this loop can land
in a scope between its discovery and its deletion.
Source code in src/symfonic/memory/backends/in_memory_deletion.py
| def delete_subtree(store: Any, scope: TenantScope) -> int:
"""Erase every node at ``scope`` or below it, with its edges.
Atomic by construction: the whole sweep runs in one synchronous span
with no ``await`` in it, so no concurrent write on this loop can land
in a scope between its discovery and its deletion.
"""
root = materialise_scope_path(scope)
tenant_nodes = store._nodes.get(scope.tenant_id, {})
doomed = [
node_id
for node_id, node in tenant_nodes.items()
if is_in_subtree(stored_scope_path(node.properties, node.tenant_id), root)
]
tenant_edges = store._edges.get(scope.tenant_id, {})
doomed_set = set(doomed)
for edge_id in [
eid
for eid, edge in tenant_edges.items()
if str(edge.source) in doomed_set or str(edge.target) in doomed_set
]:
del tenant_edges[edge_id]
for node_id in doomed:
del tenant_nodes[node_id]
for key in tuple(store._workset_cursors):
if is_in_subtree(key[0], root):
del store._workset_cursors[key]
return len(doomed)
|