mirror of
https://github.com/trustgraph-ai/trustgraph.git
synced 2026-05-12 16:52:37 +02:00
Per-flow librarian clients and per-workspace response queues (#865)
Replace singleton LibrarianClient with per-flow instances via the new LibrarianSpec, giving each flow its own librarian tied to the workspace-scoped request/response queues from the blueprint. Move all workspace-scoped services (config, flow, librarian, knowledge) from a single base-queue response producer to per-workspace response producers created alongside the existing per-workspace request consumers. Update the gateway dispatcher and bootstrapper flow client to subscribe to the matching workspace-scoped response queues. Fix WorkspaceInit to register workspaces through the IAM create-workspace API so they appear in __workspaces__ and are visible to the gateway. Simplify the bootstrapper gate to only check config-svc reachability. Updated tests accordingly.
This commit is contained in:
parent
01bf1d89d5
commit
03cc5ac80f
30 changed files with 405 additions and 735 deletions
|
|
@ -177,8 +177,7 @@ class TestRecursiveChunkerSimple(IsolatedAsyncioTestCase):
|
|||
|
||||
processor = Processor(**config)
|
||||
|
||||
# Mock save_child_document to avoid waiting for librarian response
|
||||
processor.librarian.save_child_document = AsyncMock(return_value="mock-doc-id")
|
||||
# Mock save_child_document on flow to avoid waiting for librarian response
|
||||
|
||||
# Mock message with TextDocument
|
||||
mock_message = MagicMock()
|
||||
|
|
@ -204,6 +203,7 @@ class TestRecursiveChunkerSimple(IsolatedAsyncioTestCase):
|
|||
"output": mock_producer,
|
||||
"triples": mock_triples_producer,
|
||||
}.get(key)
|
||||
mock_flow.librarian.save_child_document = AsyncMock(return_value="mock-doc-id")
|
||||
|
||||
# Act
|
||||
await processor.on_message(mock_message, mock_consumer, mock_flow)
|
||||
|
|
|
|||
|
|
@ -177,8 +177,7 @@ class TestTokenChunkerSimple(IsolatedAsyncioTestCase):
|
|||
|
||||
processor = Processor(**config)
|
||||
|
||||
# Mock save_child_document to avoid librarian producer interactions
|
||||
processor.librarian.save_child_document = AsyncMock(return_value="chunk-id")
|
||||
# Mock save_child_document on flow to avoid librarian producer interactions
|
||||
|
||||
# Mock message with TextDocument
|
||||
mock_message = MagicMock()
|
||||
|
|
@ -204,6 +203,7 @@ class TestTokenChunkerSimple(IsolatedAsyncioTestCase):
|
|||
"output": mock_producer,
|
||||
"triples": mock_triples_producer,
|
||||
}.get(key)
|
||||
mock_flow.librarian.save_child_document = AsyncMock(return_value="chunk-id")
|
||||
|
||||
# Act
|
||||
await processor.on_message(mock_message, mock_consumer, mock_flow)
|
||||
|
|
|
|||
|
|
@ -156,6 +156,7 @@ class TestMistralOcrProcessor(IsolatedAsyncioTestCase):
|
|||
"output": mock_output_flow,
|
||||
"triples": mock_triples_flow,
|
||||
}.get(name))
|
||||
mock_flow.librarian.save_child_document = AsyncMock(return_value="mock-doc-id")
|
||||
|
||||
config = {
|
||||
'id': 'test-mistral-ocr',
|
||||
|
|
@ -171,9 +172,6 @@ class TestMistralOcrProcessor(IsolatedAsyncioTestCase):
|
|||
("# Page 2\nMore content", 2),
|
||||
]
|
||||
|
||||
# Mock save_child_document
|
||||
processor.librarian.save_child_document = AsyncMock(return_value="mock-doc-id")
|
||||
|
||||
with patch.object(processor, 'ocr', return_value=ocr_result):
|
||||
await processor.on_message(mock_msg, None, mock_flow)
|
||||
|
||||
|
|
@ -227,8 +225,7 @@ class TestMistralOcrProcessor(IsolatedAsyncioTestCase):
|
|||
Processor.add_args(mock_parser)
|
||||
|
||||
mock_parent_add_args.assert_called_once_with(mock_parser)
|
||||
assert mock_parser.add_argument.call_count == 3
|
||||
# Check the API key arg is among them
|
||||
assert mock_parser.add_argument.call_count == 1
|
||||
call_args_list = [c[0] for c in mock_parser.add_argument.call_args_list]
|
||||
assert ('-k', '--api-key') in call_args_list
|
||||
|
||||
|
|
|
|||
|
|
@ -72,6 +72,7 @@ class TestPdfDecoderProcessor(IsolatedAsyncioTestCase):
|
|||
"output": mock_output_flow,
|
||||
"triples": mock_triples_flow,
|
||||
}.get(name))
|
||||
mock_flow.librarian.save_child_document = AsyncMock(return_value="mock-doc-id")
|
||||
|
||||
config = {
|
||||
'id': 'test-pdf-decoder',
|
||||
|
|
@ -80,9 +81,6 @@ class TestPdfDecoderProcessor(IsolatedAsyncioTestCase):
|
|||
|
||||
processor = Processor(**config)
|
||||
|
||||
# Mock save_child_document to avoid waiting for librarian response
|
||||
processor.librarian.save_child_document = AsyncMock(return_value="mock-doc-id")
|
||||
|
||||
await processor.on_message(mock_msg, None, mock_flow)
|
||||
|
||||
# Verify output was sent for each page
|
||||
|
|
@ -148,6 +146,7 @@ class TestPdfDecoderProcessor(IsolatedAsyncioTestCase):
|
|||
"output": mock_output_flow,
|
||||
"triples": mock_triples_flow,
|
||||
}.get(name))
|
||||
mock_flow.librarian.save_child_document = AsyncMock(return_value="mock-doc-id")
|
||||
|
||||
config = {
|
||||
'id': 'test-pdf-decoder',
|
||||
|
|
@ -156,9 +155,6 @@ class TestPdfDecoderProcessor(IsolatedAsyncioTestCase):
|
|||
|
||||
processor = Processor(**config)
|
||||
|
||||
# Mock save_child_document to avoid waiting for librarian response
|
||||
processor.librarian.save_child_document = AsyncMock(return_value="mock-doc-id")
|
||||
|
||||
await processor.on_message(mock_msg, None, mock_flow)
|
||||
|
||||
mock_output_flow.send.assert_called_once()
|
||||
|
|
|
|||
|
|
@ -254,8 +254,7 @@ class TestUniversalProcessor(IsolatedAsyncioTestCase):
|
|||
"triples": mock_triples_flow,
|
||||
}.get(name))
|
||||
|
||||
# Mock save_child_document and magic
|
||||
processor.librarian.save_child_document = AsyncMock(return_value="mock-id")
|
||||
mock_flow.librarian.save_child_document = AsyncMock(return_value="mock-id")
|
||||
|
||||
with patch('trustgraph.decoding.universal.processor.magic') as mock_magic:
|
||||
mock_magic.from_buffer.return_value = "text/markdown"
|
||||
|
|
@ -310,7 +309,7 @@ class TestUniversalProcessor(IsolatedAsyncioTestCase):
|
|||
"triples": mock_triples_flow,
|
||||
}.get(name))
|
||||
|
||||
processor.librarian.save_child_document = AsyncMock(return_value="mock-id")
|
||||
mock_flow.librarian.save_child_document = AsyncMock(return_value="mock-id")
|
||||
|
||||
with patch('trustgraph.decoding.universal.processor.magic') as mock_magic:
|
||||
mock_magic.from_buffer.return_value = "application/pdf"
|
||||
|
|
@ -361,7 +360,7 @@ class TestUniversalProcessor(IsolatedAsyncioTestCase):
|
|||
"triples": mock_triples_flow,
|
||||
}.get(name))
|
||||
|
||||
processor.librarian.save_child_document = AsyncMock(return_value="mock-id")
|
||||
mock_flow.librarian.save_child_document = AsyncMock(return_value="mock-id")
|
||||
|
||||
with patch('trustgraph.decoding.universal.processor.magic') as mock_magic:
|
||||
mock_magic.from_buffer.return_value = "application/pdf"
|
||||
|
|
@ -374,7 +373,7 @@ class TestUniversalProcessor(IsolatedAsyncioTestCase):
|
|||
assert mock_triples_flow.send.call_count == 2
|
||||
|
||||
# save_child_document called twice (page + image)
|
||||
assert processor.librarian.save_child_document.call_count == 2
|
||||
assert mock_flow.librarian.save_child_document.call_count == 2
|
||||
|
||||
@patch('trustgraph.base.flow_processor.FlowProcessor.add_args')
|
||||
def test_add_args(self, mock_parent_add_args):
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue