perf: offload the video-detail lookup off the event loop - #1392
Conversation
`GET /api/v1/videos/{video_id}` called `data_service.get_video_detail`
directly on the event loop. That helper runs an uncached recursive
`rglob` over the enhanced-analysis tree, stats every match, then opens
and reads a metadata file and the full markdown body. All of it is
blocking I/O whose cost grows with the corpus, so a single request
stalled every other request sharing the loop.
Dispatch the lookup to a worker thread with `asyncio.to_thread`.
The thread pool is a shared, and small, resource: `asyncio.to_thread`
uses the loop's default `ThreadPoolExecutor`, sized
`min(32, (os.cpu_count() or 1) + 4)`, so as few as 5 workers. The
learning-log endpoint already gates its walk at 4. Giving this endpoint
its own gate of 4 would be locally correct but globally wrong, because
the two gates could between them occupy all 5 workers and starve the
executor. So the existing gate is generalised into one shared
filesystem-walk budget that both endpoints draw from, which always
leaves at least one worker free. The trade-off is head-of-line blocking
between the two endpoints, which is acceptable because they do the same
class of work over the same tree.
Adds `TestVideoDetailOffloading` (8 tests) covering thread identity,
argument forwarding, timing-relative loop responsiveness, hop count,
the 404 and 500 contracts, the concurrency cap, and the shared budget.
Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
|
The latest updates on your projects. Learn more about Vercel for GitHub.
|
|
Important Review skippedAuto reviews are limited based on label configuration. 🏷️ Required labels (at least one) (1)
Please check the settings in the CodeRabbit UI or the ⚙️ Run configurationConfiguration used: Repository YAML (base), Repository UI (inherited), Organization UI (inherited) Review profile: ASSERTIVE Plan: Pro Plus Run ID: You can disable this status message by setting the Use the checkbox below for a quick retry:
📝 WalkthroughSummary by CodeRabbit
WalkthroughThe router adds a shared per-event-loop semaphore that limits filesystem walks to four concurrent operations. Video detail retrieval moves to a worker thread, and learning-log retrieval uses the shared semaphore. ChangesFilesystem concurrency control
Estimated code review effort: 3 (Moderate) | ~20 minutes Sequence Diagram(s)sequenceDiagram
participant Client
participant VideoDetailEndpoint
participant FilesystemGate
participant WorkerThread
participant DataService
Client->>VideoDetailEndpoint: request video details
VideoDetailEndpoint->>FilesystemGate: acquire semaphore
FilesystemGate->>WorkerThread: run filesystem work
WorkerThread->>DataService: get_video_detail(video_id)
DataService-->>WorkerThread: return video detail
WorkerThread-->>VideoDetailEndpoint: return result
VideoDetailEndpoint-->>Client: response
Possibly related issues
Possibly related PRs
Suggested labels: Suggested reviewers: Poem
🚥 Pre-merge checks | ✅ 3 | ❌ 4❌ Failed checks (4 inconclusive)
✅ Passed checks (3 passed)
✨ Finishing Touches📝 Generate docstrings
🧪 Generate unit tests (beta)
✨ Simplify code
Warning Review ran into problems🔥 ProblemsThese MCP integrations need to be re-authenticated in the Integrations settings: Sentry Linked repositories: Public OSS repositories can only analyze public repositories installed in this organization. No linked repositories were analyzed; skipped Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
Dependency Review✅ No vulnerabilities or license issues or OpenSSF Scorecard issues found.Snapshot WarningsEnsure that dependencies are being submitted on PR branches and consider enabling retry-on-snapshot-warnings. See the documentation for more information and troubleshooting advice. Scanned FilesNone |
Agent Completion Truth Gate: NOT_APPLICABLEEvidence agrees. Machine-readable verdict{
"details": {},
"reasons": [],
"verdict": "not_applicable"
} |
|
@linear-code @coderabbitai review Context, and the specific judgement call I would most like a second opinion on. A note on the canonical issue. #1389 was auto-closed as The design decision. The obvious implementation was to give this endpoint its own gate of 4. I deliberately did not do that. Two independent gates of 4 each reason locally about a shared resource, and could between them occupy all 5 workers — starving the executor for everything else in the process, which is the exact failure the original gate was introduced to prevent. Instead the existing gate is generalised into one shared filesystem-walk budget both endpoints draw from, so at least one worker is always free. The cost is real and I want it on the record: the two endpoints now head-of-line block each other. Four in-flight learning-log walks will make a video-detail request wait. I judged that acceptable because both do the same class of work (recursive walk plus file reads) over the same tree, so one budget matches one underlying cost. If per-endpoint fairness is ever needed, I believe the right answer is a shared total budget with per-endpoint sub-limits — not two independent gates. Please push back if you disagree, because this is the kind of trade-off that is much cheaper to change now than after it ships. Why I trust the test that enforces it. I ran a three-rung negative-control ladder, each mutation applied with a guarded replacement and then restored byte-exact:
NC-3 is the one that earns its keep. It is a complete, plausible, locally-correct implementation — it even passes its own per-endpoint concurrency-cap test. It fails only Two earlier NC-3 attempts are not in that table because they were not valid controls: the first tripped its Two smaller things worth your attention:
Deliberately not fixed here: the dead duplicate |
🧩 Analysis chain🏁 Script executed: #!/bin/bash
set -euo pipefail
echo '--- changed files ---'
git diff --name-status origin/main...HEAD
echo '--- diff ---'
git diff --unified=80 origin/main...HEAD
echo '--- candidate source files ---'
fd -t f 'router\.py|test_v1_router_extended\.py|data_service\.py' . | sort
echo '--- outlines ---'
for f in $(fd -t f 'router\.py|test_v1_router_extended\.py' .); do
echo "### $f"
ast-grep outline "$f" --items all --type function,class --view expanded || true
doneLength of output: 43003 🏁 Script executed: #!/bin/bash
set -euo pipefail
router='src/youtube_extension/backend/api/v1/router.py'
service='src/youtube_extension/backend/services/data_service.py'
tests='tests/unit/test_v1_router_extended.py'
echo '--- router imports and shared gate ---'
sed -n '1,135p' "$router"
sed -n '970,1080p' "$router"
echo '--- synchronous helper implementations ---'
rg -n -A80 -B10 '^\s*def (get_video_detail|get_learning_log)\s*\(' "$service"
echo '--- all router asyncio.to_thread call sites ---'
rg -n -A4 -B4 'asyncio\.to_thread\s*\(' "$router"
echo '--- gate tests and module state references ---'
rg -n -A20 -B10 '_fs_walk_gates|_get_fs_walk_gate|_FS_WALK_MAX_CONCURRENCY' "$tests" "$router"
echo '--- default executor configuration ---'
rg -n -i -A3 -B3 'set_default_executor|ThreadPoolExecutor|default.executor' \
-g '*.py' -g 'Dockerfile' -g 'docker-compose*.yml' .Length of output: 29025 🏁 Script executed: #!/bin/bash
set -euo pipefail
echo '--- Docker configuration candidates ---'
fd -t f -i '^(dockerfile|docker-compose.*\.(yml|yaml))$' . -x sh -c '
echo "### $1"
sed -n "1,240p" "$1"
' sh {}
echo '--- executor configuration candidates ---'
rg -n -i -A3 -B3 'set_default_executor|ThreadPoolExecutor|default[_ -]?executor' \
-g '*.py' -g 'Dockerfile' -g 'docker-compose*.yml' -g 'docker-compose*.yaml' . || true
echo '--- Uvicorn launch configuration ---'
rg -n -i -A3 -B3 '\buvicorn\b|--workers\b' \
-g 'Dockerfile' -g '*.py' -g '*.sh' -g '*.yml' -g '*.yaml' . || true
echo '--- current diff summary ---'
git diff --check origin/main...HEAD
git diff --stat origin/main...HEADLength of output: 42180
Issue The shared The head-of-line blocking is an acceptable trade-off here. Both endpoints use the same expensive resource class. If fairness becomes necessary, retain this shared total limit and add per-endpoint limits beneath it. The Docker launch uses one Uvicorn worker. The repository does not configure a custom default executor. The executor sizing assumption is valid for this deployment. One non-blocking correction: after contention,
✅ Action performedReview finished.
|
There was a problem hiding this comment.
Pull request overview
Offloads video-detail filesystem work from the event loop and shares concurrency limits with learning-log processing.
Changes:
- Adds worker-thread dispatch for video-detail lookup.
- Generalizes the filesystem-walk concurrency gate.
- Adds offloading, contract, and concurrency tests.
Reviewed changes
Copilot reviewed 2 out of 2 changed files in this pull request and generated 2 comments.
| File | Description |
|---|---|
src/youtube_extension/backend/api/v1/router.py |
Adds shared gated thread offloading. |
tests/unit/test_v1_router_extended.py |
Tests offloading and shared concurrency. |
| # Maps a running event loop -> the ``asyncio.Semaphore`` bound to that loop. | ||
| _fs_walk_gates: weakref.WeakKeyDictionary = weakref.WeakKeyDictionary() | ||
| _fs_walk_gates_lock = threading.Lock() | ||
|
|
||
|
|
||
| def _get_fs_walk_gate() -> asyncio.Semaphore: | ||
| """Return the filesystem-walk concurrency gate bound to the running loop.""" | ||
| loop = asyncio.get_running_loop() | ||
| with _fs_walk_gates_lock: | ||
| gate = _fs_walk_gates.get(loop) | ||
| if gate is None: | ||
| gate = asyncio.Semaphore(_FS_WALK_MAX_CONCURRENCY) | ||
| _fs_walk_gates[loop] = gate | ||
| return gate |
| video_id="dQw4w9WgXcQ", data_service=svc | ||
| ) | ||
|
|
||
| result = asyncio.run(_run()) | ||
|
|
||
| assert result == self.PAYLOAD | ||
| svc.get_video_detail.assert_called_once_with("dQw4w9WgXcQ") |
groupthinking
left a comment
There was a problem hiding this comment.
Reviewed on request. Independently verified the diff at 8af194b — the change is correct and the design reasoning holds up.
Verified locally
- Read the full
get_video_detail_v1body: the offload sits inside thetry, theexcept HTTPException: raisere-raise is intact, and theif not video_detail → 404check runs after theasync withreleases the gate. Both error contracts are preserved. - Ran
tests/unit/test_v1_router_extended.py→ 141 passed (133 pre-existing + 8 new), matching the PR's claim. The 8TestVideoDetailOffloadingtests each carry a real anti-vacuity assertion, andtest_budget_is_shared_with_the_learning_log_walkis the one that actually pins the design decision (a per-endpoint gate would givepeak == 2 * limit). - Confirmed the per-loop-
WeakKeyDictionarysemaphore rationale:Semaphore.acquirereturns on the fast path before_get_loop(), so a module-level semaphore is a latent cross-loop landmine. The per-loop keying is the right fix.
Endorse the shared-budget call. Gating exactly the two uncached rglob endpoints (get_video_detail, get_learning_log) against one budget of 4 — rather than one gate each — is the correct reading of the shared ThreadPoolExecutor as the real resource. I verified in data_service.py that these two are the uncached (rglob, no _get_all_files_cached) walks, so the boundary you drew is principled, not arbitrary.
One non-blocking observation (does not block merge): the stated invariant "at least one worker is always free" is slightly weaker than absolute, because list_videos_v1 → _collect_videos_page also dispatches a walk via asyncio.to_thread outside this gate. It's normally behind the 60s TTL cache, so on a cache hit it does no walk — which is exactly why leaving it ungated is defensible. But _get_all_files_cached() holds no lock (per its own docstring), so a burst that lands on an expired/cold cache can have several list_videos requests each rebuild the cache concurrently on the executor, none of them drawing on _FS_WALK_MAX_CONCURRENCY. Under that specific window the shared budget isn't the only claimant on the ~5 workers. Not a regression this PR introduces, and arguably out of scope (cache-miss walks are ≤ ~once/60s in the common case) — flagging it only because if the goal is a hard executor bound, folding the cache-refresh path into the same budget (or serialising the refresh) would close the last gap. Fine to track separately.
No changes requested. This is merge-ready from a review standpoint; leaving the actual merge to you.
Generated by Claude Code
Addresses CodeRabbit's non-blocking finding on #1392: the rationale comment claimed each loop's semaphore "is collected along with the loop it belongs to". That is only true for a gate that is never contended. WeakKeyDictionary holds its keys weakly but its *values* strongly, and asyncio's _LoopBoundMixin._get_loop() stores the loop on the semaphore -- reached only on the waiting path. So once a gate is contended the chain module global -> data dict -> semaphore -> loop keeps the weak key reachable and the removal callback never fires. Measured directly (WeakKeyDictionary[loop] -> Semaphore, entries retained after the loop is closed and gc.collect() runs): uncontended: 0 retained (sem._loop is None -> True) contended: 1 retained (sem._loop is None -> False) So the very fast-path asymmetry the comment correctly identifies as the latent landmine is also what defeats the weak collection it then claims. Two changes: - Rewrite the comment to state this accurately rather than overclaim. - Add _discard_closed_fs_walk_gates() and call it from _get_fs_walk_gate() on the gate-creation path only, so the retention is actually bounded and not merely documented. Creation is rare (once per loop), so this adds no per-request cost. Deletions are applied after the comprehension completes because a WeakKeyDictionary must not change size during iteration. Rejected alternative: storing the gate as an attribute on the loop object, which would form a self-contained collectable cycle. uvloop.Loop is a C extension type and setattr would raise AttributeError in production. Adds test_closed_loops_are_discarded_from_the_gate_registry, which asserts both halves: that a contended gate really does pin its closed loop (anti-vacuity -- without it the test would pass against a registry that never needed pruning), and that a later gate build reclaims it. Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
|
@coderabbitai — your The claim, and why it was wrongThe comment said each loop's semaphore "is collected along with the loop it belongs to". I measured it directly — a
The mechanism is the same fast-path asymmetry the comment already describes two paragraphs earlier:
So after the first genuine contention the chain What changed
I could have left this as a comment-only fix, since production is one Uvicorn worker and one long-lived loop — a single entry either way. I didn't, because "it doesn't matter in production" is exactly the reasoning that produced the bug you flagged in the first place. Rejected alternativeStoring the gate as an attribute on the loop object would form a self-contained collectable cycle and need no registry at all. Rejected: Test
Negative control, with the It fails at the third assertion and not the second — i.e. the retention it is asserting is real, and the test isolates the prune rather than the registry design. Whole file: 142 passed (was 141). Lint parity against the previous branch commit on the same two paths: 26 findings vs 26, identical set; Thanks for the catch, and for actually running the shell checks on the shared-gate question rather than pattern-matching it — the executor-sizing verification in particular was the part I most wanted a second opinion on. |
|
Tip For best results, initiate chat on the files or code changes. 🧩 Analysis chain🏁 Script executed: #!/bin/bash
set -euo pipefail
router='src/youtube_extension/backend/api/v1/router.py'
tests='tests/unit/test_v1_router_extended.py'
echo '--- current commit and fix commit ---'
git log --oneline -8
git show --stat --oneline 8e3beae9e
echo '--- router shared gate declarations and implementations ---'
ast-grep outline "$router" --items all --type function --match 'fs_walk|gate' --view expanded || true
rg -n -A70 -B15 \
'(_FS_WALK_MAX_CONCURRENCY|_fs_walk_gates|_discard_closed_fs_walk_gates|_get_fs_walk_gate)' \
"$router"
echo '--- regression test ---'
rg -n -A110 -B15 \
'test_closed_loops_are_discarded_from_the_gate_registry' \
"$tests"
echo '--- fix commit patch ---'
git show --format=fuller --find-renames --find-copies --unified=60 8e3beae9e -- "$router" "$tests"
echo '--- whitespace validation ---'
git diff --check origin/main...HEADLength of output: 11107 🏁 Script executed: #!/bin/bash
set -euo pipefail
echo '--- files changed by the fix commit ---'
git show --format='' --name-only 8e3beae9e
echo '--- locate the regression test ---'
fd -t f -a '.*v1.*router.*extended.*\.py$|.*router.*\.py$' . \
| while IFS= read -r f; do
if rg -n -q 'test_closed_loops_are_discarded_from_the_gate_registry' "$f"; then
echo "### $f"
rg -n -A110 -B20 \
'test_closed_loops_are_discarded_from_the_gate_registry' "$f"
fi
done
echo '--- precise fix patch ---'
git show --format=fuller --unified=80 8e3beae9e -- \
src/youtube_extension/backend/api/v1/router.py
git show --format=fuller --unified=100 8e3beae9e -- \
"$(git show --format='' --name-only 8e3beae9e | rg 'test.*\.py$')"
echo '--- whitespace validation ---'
git diff --check origin/main...HEADLength of output: 22018
The cleanup runs only when The regression test is strong. It forces the semaphore waiting path, verifies that the closed first loop remains pinned before pruning, then verifies that creation on a second loop removes the first entry. The test would fail if the cleanup call were removed.
The comment now describes the actual ownership chain and collection behavior. No further finding. 🐇 ✅ ✏️ Learnings added
If you found this review helpful, would you consider giving us a shout-out on X? Thank you for using CodeRabbit! You are interacting with an AI system. |
Independent review - red-team of the diff on top of CodeRabbit's reviewI re-reviewed this change adversarially after CodeRabbit signed off, on the exact SHA that is pushed ( 1. The one non-blocking finding, and why CodeRabbit was rightCodeRabbit's only correction was that the original rationale comment claimed the gate entry would be "collected along with the loop it belongs to". I did not take that on trust in either direction - I wrote a standalone reproduction:
The mechanism, confirmed against CPython source:
The bitter irony is that the same lazy-binding asymmetry the comment correctly identified as the reason the gate must be loop-scoped is also precisely what defeats weak collection. The comment was self-inconsistent, and CodeRabbit caught it. This is now the second time in this PR series that a CodeRabbit documentation-accuracy finding was correct on verification (the first was the CPython Fix applied in 2. Rejected alternative, and whyThe obvious "simpler" fix is to store the gate as an attribute on the loop object itself, which sidesteps the registry entirely. Rejected: production runs 3. Negative-control ladder - four rungs, each failing a strictly smaller setA regression test that cannot fail is decoration. I mutated the source four ways and confirmed the suite catches each one, with a shrinking blast radius:
NC-3 is the one I care about most. It is not a strawman - it is the design a reasonable reviewer would have asked for, and the suite rejects it for the right reason with the right number. Two of these rungs initially failed to apply cleanly (NC-2 silently matched nothing and printed a deceptive "8 passed"; NC-3's first attempt raised 4. Fresh RED -> GREEN proof in a detached worktreeRun against the pushed SHA, not my working tree:
The whole-file RED (10) is broader than NC-1's 5 because it additionally catches the four 5. Neutrality and hygiene
I predicted the full-suite pass count as 8288 (the 8287 from the previous run plus the one new prune test) before starting it, and that is exactly what it returned. Predicting the number first is the only way to notice a silent collection change. Lint parity was measured with leading whitespace stripped before sorting, because ruff right-aligns its 6. What I looked for and did not find
7. Accepted cost, stated plainlyOne shared budget means head-of-line blocking between endpoints: four concurrent learning-log walks will make a video-detail request wait. That is deliberate. Two independent budgets of 4 could occupy every worker in the pool and starve unrelated 8. Deliberately not fixed here
Four pre-existing failures remain on VerdictThe change is bounded, tested against four independent mutations, neutral on lint, verified RED -> GREEN on the pushed SHA in an isolated worktree, and CodeRabbit's single correction has been fixed and re-reviewed to "no further finding". Merging. |
Canonical issue
Closes #1389
GET /api/v1/videos/{video_id}callsdata_service.get_video_detail(video_id)directly on the event loop. That helper is not a cheap lookup — it is a recursive filesystem walk plus two file reads:data_service.pyrglob("*")over the enhanced-analysis tree.stat()on every matchglobfor the metadata sibling.exists()probejson.loadof the metadata fileNone of this is behind the
_get_all_files_cached()TTL cache (_file_cache_ttl = 60, L48) that other call sites use. Every request re-walks the tree. While that runs, the event loop is stalled for all clients in the process, not just the caller.Outcome
The lookup is dispatched to a worker thread with
asyncio.to_thread, so the event loop stays free to service other requests while the walk and the reads proceed.The judgement call worth reviewing — one shared budget, not one gate per endpoint.
asyncio.to_threadhands work to the loop's defaultThreadPoolExecutor, sizedmin(32, (os.cpu_count() or 1) + 4)— as few as 5 workers. The learning-log endpoint (merged in #1388) already gates its walk at 4.The obvious move was to give this endpoint its own gate of 4. That is locally correct and globally wrong: two independent gates each reasoning about a shared resource could between them occupy all 5 workers and starve the executor — exactly the failure the gate was introduced to prevent. Anything else needing a thread would queue behind them.
So this PR generalises the existing learning-log gate into a single filesystem-walk budget that both endpoints draw from:
_LEARNING_LOG_MAX_CONCURRENCY→_FS_WALK_MAX_CONCURRENCY(still 4)_get_learning_log_gate()→_get_fs_walk_gate()With one shared budget of 4 against a floor of 5 workers, at least one worker is always free.
The trade-off, stated plainly: the two endpoints now head-of-line block each other. Four in-flight learning-log walks will make a video-detail request wait. I consider that acceptable because both endpoints do the same class of work (recursive walk + read) over the same tree, so a shared budget matches the shared cost. If a future change needs per-endpoint fairness, the correct fix is a shared total budget with per-endpoint sub-limits — not two independent gates, which would reintroduce the starvation. That reasoning is now enforced by a test, not left to a comment.
The rename is behaviour-neutral: the whole test file was 133 passed before and 133 passed after the rename, with no other change applied.
Risk
data_service.get_video_detailis untouched.asyncio.Semaphorecreated at import time binds to whichever loop first contends on it, and then raises at runtime from any other loop. This is subtle —Semaphore.acquirereturns on the fast path before_get_loop()is ever reached:weakref.WeakKeyDictionary, guarded by a plainthreading.Lock(not anasyncio.Lock, which would itself be loop-bound).Verification
Negative-control ladder. Every rung was applied to the merged source with a guarded replacement (
assert s.count(old) == 1), run, then restored from a byte-exact backup and confirmed withdiff -q.git checkout origin/main -- router.py(revert the whole fix)async with _get_fs_walk_gate():, keep the offloadtest_budget_is_shared_with_the_learning_log_walk, withcombined peak of 8 across both walk endpoints with a shared cap of 4— i.e.assert 8 == 4, precisely2 × limit.NC-3 is the control that matters: without that one test, the globally-wrong implementation passes everything else, including its own per-endpoint cap test. Two earlier attempts at NC-3 were discarded rather than reported — the first failed its
assert s.count(old) == 1guard (wrong indentation) and never mutated the file; the second raisedNameErrorat collection. Neither is a valid control, since a collection error demonstrates nothing about test discrimination.Tests added —
TestVideoDetailOffloading, 8 tests:test_lookup_runs_on_a_worker_threadtest_video_id_is_forwarded_to_the_servicetest_event_loop_stays_responsive_while_lookup_is_in_flighttest_lookup_uses_exactly_one_to_thread_hoptest_missing_video_still_returns_404except HTTPException: raisere-raise being swallowed into a 500test_error_contract_is_unchangedtest_concurrent_lookups_are_capped_by_the_gatepeak == limit, not<=, so an absent or oversized cap failstest_budget_is_shared_with_the_learning_log_walkpeak == 2 * limitOn the responsiveness test: the inherited pattern in this file asserts a raw tick count while the mock blocks, which passes even against a fully inline implementation. This test instead records
time.monotonic()per tick and compares against the walk's finish time, so it fails if the work is not actually offloaded. (The pre-existing weakness inTestListVideosOffloadingis tracked separately in #1390 and deliberately not touched here.)Runs:
TestVideoDetailOffloadingtests/unit/test_v1_router_extended.py(whole file)Lint parity — absolute counts are meaningless here, so this is a stash contrast over the same two paths:
ruff checkfindingsruff format --difflinesIdentical rule-and-file sets (25 router, 1 test) on both sides. This branch introduces zero new findings and zero format drift; the 26 are pre-existing and deliberately not "fixed" here.
Production evidence
Not applicable — no production surface changes.
This PR changes only where an existing synchronous call runs: on a worker thread instead of on the event loop. The route, its path parameter, the response body, and both error contracts are byte-identical, and
data_service.get_video_detailitself is untouched. There is no migration, no feature flag, no configuration change, and nothing to observe in a production dashboard beyond reduced event-loop stalling under concurrent load.Two deployment facts make the per-loop gate the right unit here. The
Dockerfileruns Uvicorn without--workers, so there is one event loop per process and a per-loop semaphore is effectively a per-process limit. And no custom default-executor is configured anywhere in the repo, so themin(32, cpu_count + 4)sizing above is the real bound in production, not a theoretical one. The default rate limit is 60/minute per client and explicitly permits bursts, with no endpoint-specific override — so a burst of concurrent walks is a reachable state, not a hypothetical.