Skip to content

Cap the typed-structure dictionary in RecordEncoder (maxOwnStructures) - #1145

Merged
kriszyp merged 1 commit into
mainfrom
kris/maxownstructures-cap
Jun 9, 2026
Merged

Cap the typed-structure dictionary in RecordEncoder (maxOwnStructures)#1145
kriszyp merged 1 commit into
mainfrom
kris/maxownstructures-cap

Conversation

@kriszyp

@kriszyp kriszyp commented Jun 5, 2026

Copy link
Copy Markdown
Member

Summary

Defaults maxOwnStructures to 256 in RecordEncoder and bumps structon to ^1.0.6 (which adds the cap). Bounds the per-encoder typed-structure dictionary that was growing unbounded and OOM-ing under shape-heterogeneous data.

Purpose

structon's random-access typed-struct dictionary (typedStructs + transition trie) is append-only and pinned on the long-lived primary-store encoder/decoder. The encoder branches per field on the value's numeric width (num8/num32/num64, float32/float64) and string kind, so a wide/sparse schema (~hundreds of distinct key-sets) explodes into tens of thousands of structures — and per-table-per-peer dictionaries, multiplied across worker isolates, OOM-crash-looped a production cluster during replication catch-up of a bulk-loaded table.

structon@1.0.6 adds an opt-in maxOwnStructures cap (uncapped by default; see HarperFast/structon#4). This wires it on: once the cap is hit, novel shapes fall back to plain msgpack encoding; the read path is untouched so existing/persisted structs stay decodable. 256 is caller-overridable (a table/DBI option can raise it).

Where to look

  • One-line change in resources/RecordEncoder.ts (options.maxOwnStructures ??= 256 before super(options)), plus the structon dep bump. RecordEncoder extends structon's createStructon(Encoder).

Validation

  • Builds clean (tsc); unitTests/resources suite passes (687 passing, 0 failing). The cap logic itself is covered by structon's 94-test suite (structon#4), which exercises exactly this createStructon(msgpackr-v2) + maxOwnStructures usage. Change is a one-line option default, so no dedicated harper unit test added (RecordEncoder isn't standalone-instantiable; the behavior is upstream-tested).
  • Companion: the deployed 5.0.x line (msgpackr v1, no structon) gets the equivalent change on the v5.0 branch + msgpackr 1.11.13.

🤖 Generated by Claude (Opus 4.7).

@gemini-code-assist

Copy link
Copy Markdown
Contributor

Warning

You have reached your daily quota limit. Please wait up to 24 hours and I will start processing your requests again!

@claude

claude Bot commented Jun 5, 2026

Copy link
Copy Markdown
Contributor

Reviewed; no blockers found.

@socket-security

socket-security Bot commented Jun 5, 2026

Copy link
Copy Markdown

Review the following changes in direct dependencies. Learn more about Socket for GitHub.

Diff Package Supply Chain
Security
Vulnerability Quality Maintenance License
Updatedstructon@​1.0.5 ⏵ 1.0.677 +1100100 +193100

View full report

The per-encoder typedStructs dictionary (structon's random-access typed structs)
is append-only and pinned on the long-lived primary store. A wide/sparse schema
whose records vary by per-field value width mints a distinct structure per
shape×width combination and grows the dictionary unbounded, exhausting memory
(observed on a bulk-loaded table under replication catch-up).

Default maxOwnStructures to 256 (caller-overridable), bounding each dictionary.
Bumps structon to ^1.0.6, which adds the cap (uncapped by default).

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
@kriszyp
kriszyp force-pushed the kris/maxownstructures-cap branch from 3607b98 to 52c192c Compare June 9, 2026 12:24
@kriszyp
kriszyp marked this pull request as ready for review June 9, 2026 12:25
@kriszyp
kriszyp merged commit c93a726 into main Jun 9, 2026
38 checks passed
@kriszyp
kriszyp deleted the kris/maxownstructures-cap branch June 9, 2026 21:50
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.

2 participants