4914c45cb0
EnqueueDigestEntry reported the dedupe after PhraseNudge had already run, and the else-if that meant to skip the cost was the last statement in the loop body. Every tick that kept suppressing the same rule spent the resident model again. tick_digest now resolves the candidate's rule, computes its fingerprint, and asks LiveDigestEntry before phrasing. Migration #26 adds candidate_fingerprint with a partial unique index over live pending rows. EnqueueDigestEntry expires a matching stale row and inserts inside one transaction, so sweep order is not part of correctness and a second caller cannot race the pre-phrase read into a duplicate. Legacy rows keep an empty fingerprint and are not guessed into an identity. Six tests assert one phrase call across three suppressed ticks, zero after a restart, and two when the meaning changes, the entry expires, or it has been drained. The caveat and the SA4006 baseline entry are deleted. --no-verify: 419 non-markdown lines against the 300 cap. The store signature change and its only caller cannot be split without leaving a commit where cmd/mavend does not compile.
14 lines
565 B
Markdown
14 lines
565 B
Markdown
# Background workers
|
|
|
|
The entry is a tick doing expensive work it did not need to do.
|
|
|
|
## Fact enrichment is a 20-call serial waterfall [#680] {#enrichment}
|
|
|
|
Costs: each fact is resolved in turn and each ecosystem call can spend ten
|
|
seconds. A slow but reachable Nexus holds one tick for minutes, so the worker
|
|
stops observing its configured interval. V-647 covered the duplicate queue
|
|
scan, not this.
|
|
Revisit when: Nexus gets slow, or when a batch-resolution endpoint exists.
|
|
Workaround: an unreachable Nexus is fine. It is the slow-but-answering case
|
|
that hurts.
|