Repository navigation
fix(graph): stop the embedding miner from failing silently - #84
Merged
Merged
Conversation
`miner_embedding` wrapped embedding, quantization and bit conversion in one
`try/except Exception` that returned `{"edges": 0}` and logged nothing. The
comment claimed it covered "no numpy/model" — both wrong. `embed_texts` does
not raise when no model is available (it falls back to hash vectors, see
`_compute_missing_embeddings`) and `embed_to_binary` has its own numpy-less
path, so the only exceptions reaching that handler were real failures: an
unreachable or slow embedding service above all.
What it cost: `semantic_overlap` stood still for six days — 18294 edges from
30.09 to 04.10 — while every other relation kept growing (`co_mentions`
8840 → 9626, `topic_overlap` +14), and `memory.log` said nothing. A frozen
number reads as saturation, so the outage was first explained as the gate
working as intended.
`graph_enrich` already knew how to report a failed miner: `{"edges": -1}` plus
a `logger.warning`, added after an audit that had found a silently failed
miner. That branch was unreachable, because the swallow sits inside the miner.
The exception is now allowed to escape, which reaches it. A test pins both
halves: the miner raises, and the pass records -1 with the reason.
Second, the pass logs every miner's edge count on one line:
`miner edges: layer=user tags=42 tokens=...`. `-1` still means failure, and
the reason is on the warning line above. The phase timings from fa6c3e5 say
which miner ran and for how long; they could not say that a miner ran and
produced nothing, which is exactly what the outage looked like — a `0 ms`
phase next to a `0` that was indistinguishable from "no work to do".
Third, `_remote_embed` posted the whole text list in one request under a fixed
30 s timeout. A ~6k-text layer measured 24.4 s, about 20 % of headroom, so the
timeout was a ceiling on layer size. It now asks in batches of 500
(`_CACHE_LOOKUP_CHUNK`, the convention already used for round trips), keeping
a request near 2 s, and vectors still come back in input order. A list smaller
than one batch still costs exactly one POST.
Tests: four on batching (split into bounded requests, order preserved across
batches, single request when small, no request when empty), one that a
backend failure escapes `miner_embedding`, one that a failed miner is reported
as -1 with its reason, one that per-miner counts reach the log.
Full suite: 2085 passed.
|
Important
This repository does not receive automatic reviews because it has fewer than 10 stars. ⚙️ Run configuration
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
The bug
miner_embeddingwrapped embedding, quantization and bit conversion in onetry/except Exceptionthat returned{"edges": 0}and logged nothing:The comment is wrong twice.
embed_textsdoes not raise when no model is available — it falls back to hash vectors (_compute_missing_embeddings) — andembed_to_binaryhas its own numpy-less path. So the only exceptions reaching that handler were real failures, an unreachable or slow embedding service above all.What it cost
semantic_overlapstood still for six days while every other relation kept growing:By edge
created_at, the two passes of 03.10 and 05.10 producedco_mentionsedges and exactly zerosemantic_overlap— so the passes ran and this one miner was dead.memory.logsaid nothing, and a frozen number reads as saturation: the outage was first explained as the gate working as intended.The fix that was already there
graph_enrichhad known how to report a failed miner since an audit that found a silently failed miner:That branch was unreachable, because the swallow sits inside the miner, below it. The exception is now allowed to escape, which reaches it. Two tests pin both halves: the miner raises, and the pass records
-1with the reason.Per-miner edge counts in the log
-1still means failure, with the reason on the warning line above. The phase timings fromfa6c3e5say which miner ran and for how long; they could not say that a miner ran and produced nothing — which is exactly what the outage looked like, a0 msphase beside a0indistinguishable from "no work to do".The 30 s ceiling
_remote_embedposted the whole text list in one request under a fixedtimeout=30. A ~6k-text layer measured 24.4 s — about 20 % of headroom — so the timeout was a ceiling on layer size, and the swallowed timeout is the likeliest trigger.It now asks in batches of 500 (
_REMOTE_BATCH_SIZE, matching the existing_CACHE_LOOKUP_CHUNKconvention), keeping a single request near ~2 s and giving room for much larger layers. Vectors still come back in input order, and a list smaller than one batch still costs exactly one POST.Tests
Four on batching (split into bounded requests, order preserved across batches, one request when small, no request when empty), one that a backend failure escapes
miner_embedding, one that a failed miner is reported as-1with its reason, one that per-miner counts reach the log.Full suite: 2085 passed.
Note on a test-isolation trap
The new test file initially broke
test_shared.py::test_archived_memoriesin the full suite: its fixture left a connection inconnection_manager._connspointing at a deletedtmp_path, and that neighbouring test is not isolated — it takes its connection from the same cache. Fixed with a fixture that clears_connson teardown, and documented in the file, because the trap is in the neighbour, not the new test.The one pre-existing failure this exposed is unrelated and was confirmed by stashing:
test_archived_memoriesfails on a cleanmastertoo when run alone, onno such table: archived_memories.