Say what the sandbox's connection lock guards
The lock claimed to serialize a whole read, while `_documents` resolves the owners under it and then reads through them outside. That is right: resolving the owners is an operation on the shared connection, reading through them is not, and each owner is a session of its own. Holding the lock across a read per database would serialize them against the capability's searches to guard state none of them touch.
This commit is contained in:
parent
b6bc54c69e
commit
18c22f1ddb
1 changed files with 10 additions and 4 deletions
|
|
@ -225,13 +225,17 @@ class Sandbox:
|
||||||
async def _connection(
|
async def _connection(
|
||||||
self, owner: "HaikuRAG | None" = None
|
self, owner: "HaikuRAG | None" = None
|
||||||
) -> "AsyncIterator[HaikuRAG]":
|
) -> "AsyncIterator[HaikuRAG]":
|
||||||
"""Yield the shared connection (serialized by the lock), or an ephemeral
|
"""Yield the shared connection, or an ephemeral read-only one.
|
||||||
read-only one. The lock guards the whole block so a read's awaits cannot
|
|
||||||
interleave with another task's operation on the same connection.
|
The lock, where there is one, is held for the block: what a caller does
|
||||||
|
to the shared connection is serialized against the capability's own tool
|
||||||
|
calls, since both hold that client. It guards that connection and not
|
||||||
|
the databases underneath, which have their own locks.
|
||||||
|
|
||||||
`owner` is the client holding one document, for the reads addressed to a
|
`owner` is the client holding one document, for the reads addressed to a
|
||||||
single document. The shared connection covers a set of databases and has
|
single document. The shared connection covers a set of databases and has
|
||||||
no repositories of its own, so those reads have to name their owner.
|
no repositories of its own, so those reads have to name their owner. An
|
||||||
|
owner is a session of its own, so it is yielded unserialized.
|
||||||
"""
|
"""
|
||||||
connection = owner if owner is not None else self._rag
|
connection = owner if owner is not None else self._rag
|
||||||
if connection is not None:
|
if connection is not None:
|
||||||
|
|
@ -272,6 +276,8 @@ class Sandbox:
|
||||||
docs = await rag.list_documents(filter=self._context.filter)
|
docs = await rag.list_documents(filter=self._context.filter)
|
||||||
return docs, {}
|
return docs, {}
|
||||||
owners = await rag.clients_covering(self._context.sources)
|
owners = await rag.clients_covering(self._context.sources)
|
||||||
|
# Resolve owners under the shared-client lock; owner sessions perform
|
||||||
|
# reads independently.
|
||||||
groups = await asyncio.gather(
|
groups = await asyncio.gather(
|
||||||
*(owner.list_documents(filter=self._context.filter) for owner in owners)
|
*(owner.list_documents(filter=self._context.filter) for owner in owners)
|
||||||
)
|
)
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue