relay(stats): fix TOML stats config silently clobbered by clap update_from#1491
Conversation
a5c57c3 to
33399d6
Compare
|
Warning Review limit reached
Your plan includes 4 reviews of capacity. Refill in 7 minutes and 13 seconds. Your organization has run out of usage credits. Purchase more in the billing tab. ⌛ How to resolve this issue?After more review capacity refills, a review can be triggered using the We recommend that you space out your commits to avoid hitting the rate limit. 🚦 How do rate limits work?CodeRabbit enforces hourly rate limits for each developer per organization. Our paid plans have higher rate limits than trial, open-source, and free plans. In all cases, review capacity refills continuously over time. Please see our FAQ for further information. ℹ️ Review info⚙️ Run configurationConfiguration used: Organization UI Review profile: CHILL Plan: Pro Run ID: ⛔ Files ignored due to path filters (1)
📒 Files selected for processing (6)
WalkthroughThis PR fixes a clap/TOML config interaction bug where CLI argument re-parsing clobbered TOML boolean values. The solution extracts config loading into a 🚥 Pre-merge checks | ✅ 5✅ Passed checks (5 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. ✨ Finishing Touches✨ Simplify code
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
…e-parse.
Config::load did: parse CLI -> deserialize TOML -> update_from(cli_args).
That re-runs the clap parser onto the TOML-derived config. For a bare bool
with no --flag on the CLI, clap writes Default::default() (false) over the
TOML value, silently disabling any stats config that was set only in TOML.
(Option<T> fields survive because update_from leaves them untouched.)
Type StatsConfig.enabled as Option<bool> with unwrap_or(false) at the
call site, mirroring how IrohEndpointConfig.enabled handles the same
class of merge.
Split Config::load into the public entry point and a pure
parse_and_merge(args) so tests can drive it with synthetic args (no
std::env::args, no log init). Add two regression tests:
- cli_does_not_clobber_toml_stats_enabled: TOML enables stats with
no overriding CLI flag, expects Some(true). This is the test that
would have caught the original bug.
- cli_flag_overrides_toml_stats_enabled: belt-and-suspenders that
explicit --stats-enabled=false still wins.
Add a "Config flags + TOML merge (clap pitfall)" note to CLAUDE.md so
future config knobs follow the Option<T> pattern.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Switch localhost's --stats-node from "localhost" to "local/host" and
add matching [stats] sections to leaf0/leaf1 ("local/leaf0", "local/leaf1"),
so the demo exercises the multi-segment node path that real cluster
deployments use (sjc/1, sjc/2, etc.).
Also includes the configVersion = 0 line that newer bun adds to
bun.lock on first install.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
33399d6 to
a28fdb5
Compare
There was a problem hiding this comment.
Actionable comments posted: 2
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Inline comments:
In `@rs/moq-relay/src/config.rs`:
- Around line 113-119: The tests cli_does_not_clobber_toml_stats_enabled and
cli_flag_overrides_toml_stats_enabled mutate the process-global
MOQ_STATS_ENABLED via unsafe { std::env::remove_var("MOQ_STATS_ENABLED") } while
clap reads that same env, which can race when tests run concurrently; serialize
the mutation by adding a shared test-level lock (e.g., a static Mutex/OnceGuard)
or use a test-serialization helper (serial_test attribute or temp-env crate) so
only one test touches MOQ_STATS_ENABLED at a time, update the tests to acquire
that lock before calling std::env::remove_var("MOQ_STATS_ENABLED") and release
after, and remove the incorrect comment about single-threaded guarantees.
- Around line 69-74: The docstring for the pure loader incorrectly mentions a
`--file` flag; update the merge-order wording to reference the positional TOML
path (Config::file / the `file` positional argument) instead of `--file` so it
reads: "CLI args (`config.file` and any flags) → TOML file (if `file` is set) →
CLI args re-applied..." — edit the comment near the pure `Self::load` (the
function that explains merge order) to replace `--file` with
`file`/`Config::file`.
🪄 Autofix (Beta)
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: Organization UI
Review profile: CHILL
Plan: Pro
Run ID: 3cba33f5-fdd2-4819-856e-3b4fa4e5c199
⛔ Files ignored due to path filters (1)
bun.lockis excluded by!**/*.lock
📒 Files selected for processing (6)
CLAUDE.mddemo/relay/leaf0.tomldemo/relay/leaf1.tomldemo/relay/localhost.tomlrs/moq-relay/src/config.rsrs/moq-relay/src/stats.rs
- Serialize MOQ_STATS_ENABLED env mutation across tests with a Mutex. `cargo test` parallelizes tests within a binary; the previous single-threaded assumption in the SAFETY comment was wrong, and the unsafe env mutations could race with each other (and with clap's internal env reads). - Fix two docstrings that referenced a `--file` flag; the path is the positional `file` argument, not a flag. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Summary
Config::loaddid: parse CLI → deserialize TOML →update_from(cli_args). That re-runs the clap parser onto the TOML-derived config. For a bareboolfield with no--flagon the CLI, clap writesDefault::default()(false) over the TOML value, silently disabling any setting that was configured only via TOML.Option<T>fields survive becauseupdate_fromleaves them untouched when the arg is absent.This was hitting
StatsConfig.enabledin particular: a relay launched withlocalhost.toml(which has[stats] enabled = true) booted with stats publishing disabled, no warning, no log line. The dashboard's stats subscriber would just sit there forever waiting for announces that never came.What's in this PR
The fix (
rs/moq-relay/src/stats.rs):pub enabled: bool→pub enabled: Option<bool>,unwrap_or(false)at the call site. Mirrors howIrohEndpointConfig.enabledalready handles the same merge.Testable
Config::load(rs/moq-relay/src/config.rs): split into the public entry point and a pureparse_and_merge(args)so tests can drive it with synthetic args (nostd::env::args, nolog.init()).Two regression tests in
rs/moq-relay/src/config.rs::tests:cli_does_not_clobber_toml_stats_enabled— TOML enables stats, no overriding CLI flag, expectsSome(true). This is the test that would have caught the original bug. As a bonus, reverting the field to bareboolmakes theassert_eq!(..., Some(true))line stop compiling, so type-level regressions get caught at build time.cli_flag_overrides_toml_stats_enabled— belt-and-suspenders that explicit--stats-enabled=falsestill wins.CLAUDE.md note — a new "Config flags + TOML merge (clap pitfall)" bullet under Rust Conventions so future config knobs reach for
Option<T>by default and add a parallel test.Demo configs — enable
[stats]onleaf0.toml/leaf1.toml, switchlocalhost.tomlfrom--stats-node "localhost"to"local/host", so the demo exercises the multi-segment node path that real cluster deployments use. Also picks up theconfigVersion = 0lockfile bump from newer bun.Verification
cargo test -p moq-relay --lib→ 77 passed, 0 failed (2 new tests included).cargo run --bin moq-relay -- localhost.toml(no flags, no env) now logsstats publishing enabled prefix=".stats" levels=3 node=Some(Path("local/host"))on startup. Before the fix, this log line never appeared.Test plan
cargo test,cargo fmt,cargo clippy).just demoand confirm stats announces appear on the dashboard's broadcasts page when scoped toanon.🤖 Generated with Claude Code