Skip to content

Page get_result by stored byte range without reading the whole stash (#540) - #550

Merged
zackbart merged 1 commit into
mainfrom
fix/540-get-result-paging-cost
Sep 17, 2026
Merged

zackbart merged 1 commit into
mainfrom
fix/540-get-result-paging-cost

Conversation

@zackbart

Copy link
Copy Markdown
Owner

Closes #540.

#546 already removed the per-page full encode the issue describes: get_result decodes only the page's base64 range. What remained was the storage read. The whole envelope lived under one key, so every page fetched the full stored value (about 1.33 million characters per 1 KB page of a 1 MB result), which documentation/meta-tools.md admitted in as many words.

What changes

  • A stashed result is stored as base64 chunks, one key each: 48 KiB of result text per chunk, widening past roughly 1.5 MB so a result never occupies more than 33 keys. get_result reads only the chunks a page covers.
  • Measured after: about 131 thousand storage characters per page regardless of total size.
  • Trailing chunks are written first, so a write that fails midway leaves no readable header, and expiry reclaims every backing key. An envelope is still one stash entry charged its total ASCII length.
  • Offsets, nextOffset, totalBytes, and UTF-8 boundary alignment are unchanged. Entries stashed in the v1 single-key format and as pre-v1 raw text stay readable for the rest of their 15-minute TTL.

Trade-off

One stash write becomes up to 33. fileStorage rewrites its file per write and already reads from memory, so Node deployments pay more per stash and gain nothing on reads; Workers KV is where the read saving lands. The chunk width and key cap (RESULT_CHUNK_BYTES, RESULT_MAX_CHUNKS) are the dials.

Tests

In test/meta-tools-call.test.ts: a structural read-count test (same page against a 300 KB and a 1.2 MB result reads the same amount, within a 33-key bound), byte-exact reassembly across chunk boundaries at a page size coprime with the chunk width, and both pre-chunk formats still paging.

npm run check passes: 120 files, 3274 tests passed, 37 skipped.

🤖 Generated with Claude Code

…540)

A stashed result is stored as base64 chunks under one key each — 48 KiB of
result text per chunk, widening past roughly 1.5 MB so a result never occupies
more than 33 keys — and get_result reads and decodes only the chunks a page
covers plus a few bytes of UTF-8 boundary lookaround. Paging cost now tracks
the page rather than the total: a 1.2 MB result and a 300 KB one cost the same
per page. Offsets, nextOffset, totalBytes, and character-boundary alignment are
unchanged, an envelope is still one stash entry charged its total ASCII length,
and entries stashed in the two earlier formats stay readable for the rest of
their 15-minute TTL.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
@zackbart
zackbart merged commit ca7f4c1 into main Sep 17, 2026
2 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.

Page get_result by byte offset without re-encoding the whole stash

1 participant