Skip to content

fix(groupalgo): in-memory compute-once memo guard for group Pass-4 (bounds persist-failure recompute spin)#5908

Merged
cajasmota merged 1 commit into
mainfrom
worktree-agent-ab4db5138bbe8a671
Jul 22, 2026
Merged

fix(groupalgo): in-memory compute-once memo guard for group Pass-4 (bounds persist-failure recompute spin)#5908
cajasmota merged 1 commit into
mainfrom
worktree-agent-ab4db5138bbe8a671

Conversation

@cajasmota

Copy link
Copy Markdown
Owner

Recovered from an abandoned prior-session branch (verified genuinely unmerged, not subsumed by the existing disk-overlay guard). Refs #5850.

The failure mode it fixes: main's group Pass-4 recompute-avoidance is entirely disk-overlay-gated (readOverlayUnconditional/OverlayNeedsRecompute, keyed on InputHash). When the overlay can't persist — read-only ~/.grafel/groups, disk-full, EPERM (the "sidecars=0" symptom) — the overlay never lands, so every trigger falls through to a full graph.RunAlgorithms (O(V·E) betweenness over the ~32k-node group union). This adds an in-memory memo (memoMu) layered below the disk-overlay skip: it fires only when the disk skip did not, closing that recompute spin. It's the group-scope analog of the already-merged per-repo in-memory guard.

Reviewed (independent, mutation-proven):

  • Strict parity — keyed on CommunityInputHash (full node set + weighted edges); stores the literal *AlgorithmResults; deep-equal-verified. A structural change invalidates the key (mutation confirmed).
  • Exactly-once recompute on version change; persist-failure bounds recompute to once (store-before-overlay-write; mutation confirmed).
  • Concurrency clean: -race -count=20 → 60 pass; memoMu sole lock, no lock-order cycle; map bounded to one entry per group (replaced on version change), no leak.
  • Composition correct (disk skip first); default subprocess path unaffected (memo cold, discarded per fork).

Process-local by design → helps the in-process path (GRAFEL_SUBPROCESS_INDEXER=0); the default subprocess path retains nothing. Bounded per-group retention on that path is the deliberate CPU-spin-vs-RAM tradeoff (possible follow-up: free the memo entry after a successful overlay write).

🤖 Generated with Claude Code

https://claude.ai/code/session_017quGgaqK7NRoxGT6BTqV2o

…ss-4

The group-scope Pass-4 sweep (Louvain + PageRank + O(V*E) betweenness over
the assembled ~32k-node group union) reused results only via the on-disk
<group>-algo.json overlay. When that overlay could not be persisted
(read-only ~/.grafel/groups, disk-full, EPERM) the disk-skip path could
never engage, so RunGroupAlgorithmsIncremental re-ran the full sweep on
EVERY trigger, pinning the daemon at sustained high CPU with spikes on a
large multi-repo group -- the group-scope analog of the per-repo #50
compute->evict spin.

Add a process-local guard keyed on the group-version (community input
hash): the heavy pass now runs at most once per version regardless of
whether the overlay reached disk. The result is recorded BEFORE the
caller's overlay write, so a persist failure cannot reopen the spin. A
real re-index bumps the input hash -> exactly one recompute (correctness
preserved). Guard access is mutex-protected; the cached result is treated
read-only, mirroring the overlay reconstitution contract.

Tests (>=2-repo group, exercising the combined union path):
- compute-once-per-version across repeated loads with no persist
- persist failure (read-only overlay dir) does not recompute forever
- structural re-index bumps the version -> one recompute, then reuse
@cajasmota
cajasmota merged commit 4d02ab7 into main Jul 22, 2026
1 of 2 checks passed
@cajasmota
cajasmota deleted the worktree-agent-ab4db5138bbe8a671 branch July 22, 2026 05:52
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants