Skip to content

[codex] Recover live graph refresh after DB contention#40

Merged
rabii-chaarani merged 2 commits into
mainfrom
codex/fix-live-graph-refresh-lock-recovery
Jun 23, 2026
Merged

[codex] Recover live graph refresh after DB contention#40
rabii-chaarani merged 2 commits into
mainfrom
codex/fix-live-graph-refresh-lock-recovery

Conversation

@rabii-chaarani

Copy link
Copy Markdown
Owner

Summary

Make live graph refresh resilient when Ladybug DB contention or partial writes occur. DB lock conflicts are now treated as recoverable refresh contention instead of fatal watcher failures.

Root Cause

The MCP refresh loop and standalone codebase-graph watch propagated refresh write failures out of their watcher loops. A transient Ladybug lock conflict could therefore terminate live refresh, leaving the MCP session stale until the server was restarted.

Changes

  • Added a shared graph DB access layer for Ladybug opens, transient DB error classification, retry/backoff, and a repo-local write-intent guard under .codebaseGraph/.
  • Kept MCP auto-refresh alive after transient and non-transient materialization errors, recording retry/error status instead of ending the loop.
  • Extended refresh status with backward-compatible last_error_count and last_retry_unix_ms fields.
  • Made incremental writes idempotent by deleting incoming node/edge rows before copying staged replacements, while preserving retained shared rows.
  • Aligned standalone codebase-graph watch retry behavior with MCP refresh and kept --max-iterations tied to successful refreshes.

Validation

  • cargo fmt -- --check
  • cargo clippy --all-targets -- -D warnings
  • cargo test
  • ./target/debug/codebase-graph check-health --repo-root .
  • cargo build --release
  • codebase-graph reinstall --repo-root . --mode full --mcp-client codex --instructions-target skip --json
  • MCP live-refresh probe: added and deleted a temporary Rust source file, confirmed graph health changed with last_rebuilt=1 and then last_deleted=1, and verified exact deleted path query returned 0.

Treat Ladybug lock conflicts as expected refresh contention instead of fatal watcher failures. The graph access path now shares transient-error classification, bounded retry, and a repo-local write-intent marker. Incremental writes delete incoming row IDs before COPY so retries and manifest/DB drift do not trip duplicate primary keys.

Constraint: Ladybug enforces its own DB lock and can reject concurrent readers or writers during refresh

Rejected: Add an external file-lock dependency | stdlib write-intent marker and Ladybug retry handling are sufficient for this recovery path

Confidence: high

Scope-risk: moderate

Directive: Keep MCP refresh loops supervising after recoverable write failures; do not reintroduce fatal propagation from refresh_batch

Tested: cargo fmt -- --check; cargo clippy --all-targets -- -D warnings; cargo test; targeted cargo test watch/mcp/graph/db_writer filters; target debug check-health

Not-tested: Live restarted MCP daemon under an externally held Ladybug lock
Windows cargo test fell back to building Ladybug from source after the upstream prebuilt Windows archive returned 404, and the debug C++ build exceeds MSVC library/object limits before Rust tests can run. Keep Linux and macOS on the normal debug cargo test path, but run the Windows test leg in release profile, matching the already-passing Windows package build path while still executing the Rust test suite.

Constraint: Upstream Ladybug 0.17.1 Windows static archive URL currently returns 404 in CI

Rejected: Disable Windows tests | would remove platform coverage instead of preserving the test suite

Rejected: Add a new file-lock or build dependency | unnecessary for a CI-only upstream C++ debug-link limit

Confidence: medium

Scope-risk: narrow

Directive: Revisit this once upstream publishes a usable Windows prebuilt lbug archive or the source build no longer exceeds MSVC debug-link limits

Tested: cargo run -p xtask -- release-gate

Tested: cargo fmt -- --check

Tested: cargo test --workspace --locked --release
@rabii-chaarani rabii-chaarani marked this pull request as ready for review June 23, 2026 01:04
@rabii-chaarani rabii-chaarani merged commit ee1754b into main Jun 23, 2026
22 checks passed
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.

1 participant