fix(config): bound message size, watchdog, and ring size at load time#826
Merged
Conversation
Three configuration knobs accepted out-of-range values that the loader then propagated into the engine as oversized memory commitments or arithmetic that wrapped under the operator's stated tuning. `[grpc] max_message_size_mb` was multiplied by `1024 * 1024` straight from TOML with no range check, so an absurd value overflowed the byte conversion into a tiny garbage cap and a `0` silently uncapped the inbound decode budget. The override is now rejected by name unless it sits in `[1, 64]` MB, and the conversion uses `checked_mul` so an out-of-range input always surfaces as a range error. `data_watchdog_ms` had no `bounds::` range and no `validate` clause, unlike every sibling streaming knob. It is a wall-clock backstop above the read timeout, so an enabled value must sit in `[100, 3_600_000]` ms and at or above `timeout_ms`; `0` continues to disable it. Both invariants are now enforced. `check_ring_size` capped nothing above the power-of-two minimum, so `ring_size = 2^40` passed validation and the engine would pre-allocate an absurd ring. A `2^24` ceiling bounds the up-front allocation while leaving generous headroom above the shipped 131,072-slot default. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Three configuration knobs accepted out-of-range values that the loader then propagated into the engine as oversized memory commitments or arithmetic that wrapped under the operator's stated tuning. Each is now bounded at load/validate time and reported by name so a misconfiguration fails fast instead of running a silently-corrupted budget.
[grpc] max_message_size_mbThe MB override was multiplied by
1024 * 1024straight from TOML with no range check. An absurd value overflowed the byte conversion (debug panic / release wrap into a tiny garbage cap) and a0silently uncapped the inbound decode budget. The override is now rejected unless it sits in[1, 64]MB — the production default is 4 MB and 64 MB leaves generous headroom for the largest bulk historical chunk — and the conversion useschecked_mulso an out-of-range input always surfaces as a range error.streaming.data_watchdog_msThis knob had no
bounds::range and no clause invalidate, unlike every sibling streaming knob. It is a wall-clock backstop above the read timeout, so an enabled value must sit in[100, 3_600_000]ms (one-hour ceiling) and at or abovetimeout_ms, otherwise the backstop would fire before the read timeout it is meant to backstop.0continues to disable it. Both invariants are now enforced.ring_sizeupper boundcheck_ring_sizeenforced power-of-two and a64-slot minimum but capped nothing above it, soring_size = 2^40passed and the engine would attempt to pre-allocate terabytes up front. The ring is allocated in full at construction, so the size is a memory commitment, not a load-driven ceiling. A2^24(16,777,216-slot) maximum bounds that commitment while leaving generous headroom above the shipped 131,072-slot default.Tests
grpc_max_message_size_mb_at_ceiling_is_accepted/_above_ceiling_is_rejected/_zero_is_rejected/_absurd_value_does_not_panic_or_wrapvalidate_accepts_disabled_data_watchdog/validate_accepts_in_range_data_watchdog/validate_rejects_data_watchdog_below_read_timeout/validate_rejects_data_watchdog_above_maximumaccepts_maximum/rejects_above_maximum/error_message_names_maximum_on_too_large/shipped_default_is_under_maximumcargo fmt --all -- --check,cargo test -p thetadatadx --lib --features config-file(853 passed), andcargo clippy -p thetadatadx --features config-file --lib -- -D warningsall pass.🤖 Generated with Claude Code