Skip to content

Tolerant typed decode: skip interleaved non-schema records (#30)#36

Merged
tbeason merged 8 commits into
mainfrom
tolerant-typed-decode
Jun 10, 2026
Merged

Tolerant typed decode: skip interleaved non-schema records (#30)#36
tbeason merged 8 commits into
mainfrom
tolerant-typed-decode

Conversation

@tbeason

@tbeason tbeason commented Jun 10, 2026

Copy link
Copy Markdown
Owner

Summary

Stacked on #35 (which is stacked on #34) — merge in order; this PR auto-retargets as base branches are deleted.

The typed get_range/foreach_record path called DBN''s _foreach_record_impl, which throws Expected ... but got rtype=... on the first record that isn''t the schema''s type. But historical responses can legitimately interleave gateway ErrorMsg (e.g. partial continuous-symbol resolution), SystemMsg, and SymbolMappingMsg records with the data — so real-world pulls forced typed=false, losing the ~10× fast path and the error record''s explanation.

New private _foreach_typed_tolerant(f, decoder, ::Type{T}) in src/store.jl, used by both the buffered (get_range) and streaming (foreach_record) typed paths. It keeps the zero-allocation hot path (peek header → read into a reused Ref{T}) and handles everything else by category:

Implemented DatabentoAPI-side using existing DBN primitives (read_record_header, _read_typed_record_stream, read_record_dispatch) — same precedent as the live typed reader. DBN''s exported foreach_record_with_control was considered but rejected: it silently drops mismatched data records and carries file-closing finally semantics this layer doesn''t own.

Behavior note (in CHANGELOG): an explicitly wrong record_type override on foreach_record now yields zero callbacks + summary warning instead of throwing.

Tests

Full offline suite passes (1847 tests, Julia 1.12.6). New coverage: mixed trades+ErrorMsg+SystemMsg payloads through both get_range and foreach_record, unknown-rtype skip with summary warn, wrong record_type override, and a no-warnings regression test on pure streams.

Fixes #30

🤖 Generated with Claude Code

tbeason and others added 3 commits June 9, 2026 21:25
The Historical guide showed `foreach_record(client, DBN.TradeMsg; ...)`,
a method that does not exist — the call raises a MethodError. The record
type is inferred from `schema` (overridable via the `record_type` kwarg).
Corrected the example and the surrounding prose.

Fixes #32

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Long-range get_range queries spend well over 100s in server-side
assembly before the first byte streams, so the old 100s default killed
every multi-year pull. Read timeouts are deterministic for a given query
shape, so they are no longer retried; HTTP.jl TimeoutError is mapped to
a new BentoTimeoutError whose message names the remedy.

Fixes #31

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Historical responses can legitimately interleave gateway ErrorMsg,
SystemMsg, and SymbolMappingMsg records with the data; the typed decode
path threw on the first one, forcing callers back to typed=false. The
new _foreach_typed_tolerant loop keeps the zero-allocation typed hot
path, @Warns ErrorMsg contents (they explain missing data), quietly
skips other control records, and skips mismatched/unknown rtypes with
one summary warning.

Fixes #30

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
tbeason and others added 4 commits June 10, 2026 07:13
The guide only imports DatabentoAPI and Dates, so the record_type
override examples referenced an undefined DBN name (review feedback).

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
If the foreach_record callback itself throws HTTP.Exceptions.TimeoutError
(e.g. it makes its own HTTP request), open_stream unconditionally mapped
it to BentoTimeoutError, blaming the Databento stream and reporting the
wrong timeout value (review feedback). Track the exact exception object
that escapes the consumer and map only stream-originated timeouts; a
mid-body stall of our own stream still maps correctly because HTTP.jl
raises the TimeoutError from the HTTP.open frame, a different object
than whatever escaped the consumer.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
@tbeason tbeason changed the base branch from raise-read-timeout to main June 10, 2026 12:30
@tbeason tbeason merged commit 089c182 into main Jun 10, 2026
7 checks passed
@tbeason tbeason deleted the tolerant-typed-decode branch June 10, 2026 12:33
tbeason added a commit that referenced this pull request Jun 10, 2026
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.

Typed get_range/foreach_record throw on interleaved non-schema records (gateway ErrorMsg/SystemMsg)

1 participant