Skip to content

ops fixes for v0.2.5: Pebble level sizing knobs, lift the write deadline through the middleware, tolerate tar rc 1 in snapshot.sh, compact phase liveness, Go runtime memory metrics - #50

Merged
andreimarinescu merged 5 commits into
mainfrom
andrei/v0.2.5-ops-fixes
Sep 12, 2026

Conversation

@andreimarinescu

Copy link
Copy Markdown
Collaborator

Five small operational fixes from the 2026-09-11/12 maintenance window on the production box (17M docs, 83M vectors,
560 GB Pebble store). One commit per fix.

  1. Pebble level sizing (env-gated, defaults untouched). COSIFT_PEBBLE_TARGET_FILE_MB (L0 target file size, doubling
    per level up to L6), COSIFT_PEBBLE_LBASE_MB, COSIFT_PEBBLE_L0_COMPACTION_FILES, COSIFT_PEBBLE_L0_STOP_WRITES. Unset
    leaves pebble.Options exactly as before (verified against EnsureDefaults). One log line at open when any is set.
    Background: with Pebble's 2 MiB target_file_size a full graph persist left 132k L0 files; the following range
    compaction rewrote 259 GiB over 10.5 h and a plain restart wedged on L0StopWritesThreshold (12). Documented in
    docs/ENV.md.
  2. Write deadline actually lifted. statusCapturingWriter and recordingWriter gain Unwrap() http.ResponseWriter,
    so http.NewResponseController(w).SetWriteDeadline reaches the connection through the middleware chain. The five call
    sites use a shared liftWriteDeadline that logs the error once instead of discarding it. Symptom fixed: a 4m31s
    /admin/checkpoint returned curl: (52) Empty reply and the snapshot service failed. Test: httptest server with
    WriteTimeout 200 ms and the real middleware; a handler that lifts the deadline and sleeps 500 ms delivers its body.
    Note: /answer SSE streams are no longer cut at 60 s by the server (the edge still bounds them).
  3. snapshot.sh tolerates tar rc 1. --warning=no-file-changed; rc 1 ("file changed as we read it", harmless on a
    hard-linked checkpoint) continues, rc ≥ 2 aborts. scripts/snapshot-test.sh reproduces both with stubbed
    curl/gcloud/pigz.
  4. Compact liveness. Steps 3 (URL-index rebuild) and 4 (entry-point scan) of compactLocked log start/end with
    elapsed time and report compact:url-index / compact:entry-point through the existing progress hook, so
    /stats.hnsw_compact.phase no longer sits on compact for minutes with no signal. Locking unchanged.
  5. Go runtime memory metrics. /stats gains runtime (heap_objects_bytes, heap_live_bytes, heap_goal_bytes,
    mem_limit_bytes (−1 when unset), mem_total_bytes, gc_cycles, goroutines) and /metrics gains the matching
    cosift_go_* series, read via runtime/metrics (no stop-the-world). The GC wall of 2026-09-06 (heap pinned at the
    GOMEMLIMIT goal, p50 150 ms → 4 s) is visible as heap_goal − heap_live → 0.

Deploy notes: the Pebble knobs ship as a separate systemd drop-in and are enabled on a maintenance restart only; existing
SSTs are rewritten as compactions touch them.

@codecov

codecov Bot commented Sep 12, 2026

Copy link
Copy Markdown

Codecov Report

❌ Patch coverage is 98.11321% with 2 lines in your changes missing coverage. Please review.

Files with missing lines Patch % Lines
cmd/cosift/serve_admin.go 66.66% 1 Missing ⚠️
cmd/cosift/serve_crawl.go 0.00% 1 Missing ⚠️

📢 Thoughts on this report? Let us know!

…esholds)

COSIFT_PEBBLE_TARGET_FILE_MB, COSIFT_PEBBLE_LBASE_MB,
COSIFT_PEBBLE_L0_COMPACTION_FILES and COSIFT_PEBBLE_L0_STOP_WRITES set the
matching pebble.Options fields only when present; unset leaves the options
byte-identical to before. With the 2 MiB default a full graph persist left
132k L0 files on the production store, the follow-up range compaction ran
10.5 h and a plain restart wedged on the L0 stop-writes threshold.
statusCapturingWriter and recordingWriter lacked Unwrap(), so
http.NewResponseController(w).SetWriteDeadline returned ErrNotSupported
at every call site and the 60 s WriteTimeout stayed in force for
/admin/checkpoint, /admin/eval-quick, /admin/hnsw-compact?wait,
/admin/frontier-clear and the /answer SSE stream (a 4m31s checkpoint
returned an empty reply and failed the snapshot job). Both wrappers now
unwrap and a shared liftWriteDeadline logs a failure once instead of
discarding it.
A serve restart during the 40-minute tar made tar exit 1 under set -e and
aborted the snapshot. Checkpoint SSTs are hard-linked and immutable, so
rc 1 is harmless; rc >= 2 still aborts. snapshot-test.sh reproduces both
with stubbed curl, gcloud and pigz.
… compact

Steps 3 and 4 of compactLocked ran silently under the write lock; on the
production graph the URL-index rebuild alone took ~5 minutes while
/stats.hnsw_compact.phase stayed on "compact". Both steps now log start
and end with elapsed time and report compact:url-index and
compact:entry-point through the existing progress hook. Locking is
unchanged.
runtime/metrics samples (no stop-the-world) exposed as a runtime object on
/stats and as cosift_go_* series on /metrics: heap objects, heap live,
heap goal, memory limit (-1 when unset), total mapped memory, GC cycles,
goroutines. The 2026-09-06 GC wall (heap pinned at the GOMEMLIMIT goal,
/search p50 150 ms -> 4 s) reads as heap_goal - heap_live -> 0.
@andreimarinescu
andreimarinescu merged commit 5437ab0 into main Sep 12, 2026
4 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