Skip to content

prefetcher: ERROR on admit saturation#122

Draft
nclack wants to merge 1 commit into
worktree-prefetchfrom
prefetcher-saturation-errors
Draft

prefetcher: ERROR on admit saturation#122
nclack wants to merge 1 commit into
worktree-prefetchfrom
prefetcher-saturation-errors

Conversation

@nclack
Copy link
Copy Markdown
Owner

@nclack nclack commented May 23, 2026

What was broken

admit_locked in src/prefetch/prefetcher.c had two silent-drop paths when
admission couldn't proceed: when batch_get_or_create_locked returned NULL
(all batch_capacity entries in use) and when prefetch_cache_request
returned an invalid handle (e.g., array_meta cache eviction blocked). Both
paths freed popped->uri, bumped errored, and discarded the sample with
no observable signal. A caller pushing many distinct batches faster than
they drain would see batches silently vanish instead of getting a clean
saturation report.

The fix

admit_locked now treats both failure modes as terminal PREFETCHER_ERROR
slots carrying uri/aabb/batch_id from the popped sample and
err_code = DAMACY_OOM. The slot follows the same lifecycle as a
successful admission: the caller observes it through
prefetcher_pop_ready / prefetcher_pop_ready_for_batch, releases the
URI via prefetcher_ready_free, and (for the cache-failure case where a
batch entry was acquired) optionally calls prefetcher_release_batch to
reclaim the gate.

Routing the synthetic ERROR into the free slot the worker already found
keeps the change small — no new overflow queue, no change to worker_fn.
emit_error_slot_locked is the only new helper. admit_locked keeps a
single Drop fall-through label as a CHECK_SILENT guard against the
hypothetical NULL-slot case (worker_fn never reaches that path today).

Key change: src/prefetch/prefetcher.c::admit_locked (~line 312).

How the user observes saturation

prefetcher_drain(p);
struct prefetcher_ready r = { 0 };
while (prefetcher_pop_ready(p, &r)) {
    if (r.state == PREFETCHER_ERROR && r.err_code == DAMACY_OOM) {
        // batch_id, uri tell the caller which sample was rejected
    }
    prefetcher_ready_free(&r);
}

test_batch_capacity_saturation_surfaces_error in tests/test_prefetcher.c
walks that loop end-to-end. The existing test_admit_fail_releases_batch_entry
was updated to pop the ERROR slot and call release_batch before asserting
the gate is gone — the entry lifetime now matches the successful-admission
contract.

@codecov
Copy link
Copy Markdown

codecov Bot commented May 23, 2026

Codecov Report

❌ Patch coverage is 93.33333% with 1 line in your changes missing coverage. Please review.
✅ Project coverage is 58.22%. Comparing base (23d95f0) to head (14dcf83).

Files with missing lines Patch % Lines
src/prefetch/prefetcher.c 93.33% 1 Missing ⚠️
Additional details and impacted files

Impacted file tree graph

@@                Coverage Diff                 @@
##           worktree-prefetch     #122   +/-   ##
==================================================
  Coverage              58.21%   58.22%           
==================================================
  Files                     56       56           
  Lines                   7948     7956    +8     
  Branches                1396     1396           
==================================================
+ Hits                    4627     4632    +5     
- Misses                  2746     2753    +7     
+ Partials                 575      571    -4     
Flag Coverage Δ
unittests 58.22% <93.33%> (+<0.01%) ⬆️

Flags with carried forward coverage won't be shown. Click here to find out more.

Files with missing lines Coverage Δ
src/prefetch/prefetcher.c 78.90% <93.33%> (+1.09%) ⬆️

... and 8 files with indirect coverage changes

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.

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