Point the limit comments at the right limits

_session_limits still called the session budget the backstop for code that
computes, which stopped being true when the pool gained a request_timeout in the
same commit. The watchdog kills such a call at code_timeout, so it can never
spend a budget of code_timeout * max_executions. The docstring now names the two
per-call limits and claims neither.

The crash test said the discard prevents a RuntimeError escaping execute(). The
handler catches RuntimeError too, so without the discard every later call
returns a failed result instead.

Name MemoryFile's missing write hook as the reason metadata.json takes a reader
and a deny pair. Drop the clause in the CHANGELOG that narrated how the old
overrun accumulated.
This commit is contained in:
Yiorgis Gozadinos 2026-07-28 19:09:04 +03:00
parent 221c90af72
commit d1ad14f44b
No known key found for this signature in database
3 changed files with 7 additions and 7 deletions

View file

@ -21,7 +21,7 @@
- `evaluations run` opens the database read-only outside the population phase, so an embedder identity differing from the stored one warns instead of aborting the run. - `evaluations run` opens the database read-only outside the population phase, so an embedder identity differing from the stored one warns instead of aborting the run.
- `docs/installation.md` documents the `jina`, `s3` and `ingester` extras, names the extras the full package actually pulls, drops the removed MixedBread AI reranker, and no longer lists Anthropic as a built-in provider. - `docs/installation.md` documents the `jina`, `s3` and `ingester` extras, names the extras the full package actually pulls, drops the removed MixedBread AI reranker, and no longer lists Anthropic as a built-in provider.
- `docs/tuning.md` no longer points at the removed `claim_timeout_s` setting. - `docs/tuning.md` no longer points at the removed `claim_timeout_s` setting.
- `analysis.code_timeout` is checked before each document read; code that reads in a loop no longer overruns it by the duration of the outstanding reads. - `analysis.code_timeout` is enforced before each document read, bounding a call that reads in a loop.
- `metadata.json` in the document VFS rejects writes, matching `content.txt`, `items.jsonl` and `toc.json`. - `metadata.json` in the document VFS rejects writes, matching `content.txt`, `items.jsonl` and `toc.json`.
### Removed ### Removed

View file

@ -415,8 +415,8 @@ class Sandbox:
ensure_ascii=False, ensure_ascii=False,
) )
# A MemoryFile accepts writes, so mount metadata.json through the # MemoryFile has no write hook, so metadata.json goes through the
# same read and deny pair as the rest. The content is already built. # same read and deny pair as the rest. Its content is already built.
files.append( files.append(
CallbackFile( CallbackFile(
f"{doc_dir}/metadata.json", f"{doc_dir}/metadata.json",
@ -472,9 +472,9 @@ class Sandbox:
Monty spends ``max_duration_secs`` across the session's whole life, and Monty spends ``max_duration_secs`` across the session's whole life, and
the session is reused so variables persist between calls. Budget it for the session is reused so variables persist between calls. Budget it for
the run rather than for one call, or the first slow call starves every the run rather than for one call, or the first slow call starves every
later one. ``code_timeout`` is enforced per call by the read deadline in later one. ``code_timeout`` is enforced per call elsewhere: the read
``_run_on_loop``. This is the backstop for code that computes without deadline in ``_run_on_loop`` bounds a call that reads, and the pool's
reading, and one such call can spend all of it. ``request_timeout`` bounds one that computes.
""" """
analysis = self._config.analysis analysis = self._config.analysis
return {"max_duration_secs": analysis.code_timeout * analysis.max_executions} return {"max_duration_secs": analysis.code_timeout * analysis.max_executions}

View file

@ -894,7 +894,7 @@ class TestSandboxWorkerCrash:
assert crashed.success is False assert crashed.success is False
assert "restarted" in crashed.stderr assert "restarted" in crashed.stderr
# Without the discard this raises RuntimeError out of execute(). # Without the discard every later call fails on the dead session.
recovered = await sb.execute("print(3)") recovered = await sb.execute("print(3)")
assert recovered.success, recovered.stderr assert recovered.success, recovered.stderr
assert "3" in recovered.stdout assert "3" in recovered.stdout