Skip to content

feat(json): default delta_ratio to 8, count only delta bytes#1765

Merged
kixelated merged 1 commit into
mainfrom
claude/vigorous-hypatia-1f9399
Jun 16, 2026
Merged

feat(json): default delta_ratio to 8, count only delta bytes#1765
kixelated merged 1 commit into
mainfrom
claude/vigorous-hypatia-1f9399

Conversation

@kixelated

Copy link
Copy Markdown
Collaborator

Summary

Make the snapshot/delta JSON producer (rs/moq-json and @moq/json) emit deltas by default instead of requiring an explicit opt-in, and fix the budget so it counts only the delta bytes.

  • delta_ratio default is now 8 (was disabled). The config changes from Option<f64> / number | undefined (default disabled) to a plain number defaulting to 8, where 0 now means disabled. Rust uses u32 (the ratio is a coarse knob with no need for fractional precision); JS keeps number. Deltas are never even encoded when the ratio is 0.
  • Budget counts only the deltas, not the snapshot frame. The check is now accumulated_delta_bytes + new_delta > ratio × snapshot_size. Previously the snapshot counted toward the budget, which made a ratio of 1 behave identically to 0 (the snapshot alone filled the budget, so no delta ever fit). Now 1 means "deltas may total up to one snapshot before rolling", genuinely distinct from disabled.
  • Catalog producers pin delta_ratio: 0 for now (rs/moq-mux/src/catalog/producer.rs and js/publish/src/broadcast.ts) to stay byte-compatible with consumers that only read snapshots. Turning deltas on for the catalog is a follow-up.

Semantics

With default 8: a group keeps appending deltas until they total more than 8× the current snapshot size, then it rolls a fresh snapshot. A late joiner reads the snapshot at frame 0 plus the deltas (still also bounded by the existing 256-frame cap).

Public API

  • moq_json::Config::delta_ratio: Option<f64>u32 (breaking, but moq-json has no external consumers yet).
  • @moq/json Config.deltaRatio: still number?, semantics changed (0 disables, default 8).

Tests

  • Added deltas_stay_within_ratio_times_snapshot (Rust) / "deltas stay within ratio times snapshot" (JS) documenting the exact byte-budget threshold: with 7-byte frames, ratio 8 admits 8 deltas on top of the snapshot (group 0 = 9 frames) before the 9th delta rolls.
  • Updated tight_ratio_rolls_snapshots to show ratio 1 now lands one delta per group then rolls (distinct from 0), and the deltas-off tests to pass 0 explicitly.

Test plan

  • cargo test -p moq-json (23 pass)
  • cargo build -p moq-mux, clippy + fmt clean (via nix)
  • bun test in js/json (37 pass), biome clean

(Written by Claude)

Make the snapshot/delta JSON producer emit deltas by default instead of
requiring an explicit opt-in. The delta_ratio config goes from
Option<f64>/number-or-undefined (default disabled) to a plain number
defaulting to 8, where 0 now means disabled. Rust uses u32 since the
ratio is a coarse knob with no need for fractional precision; JS keeps
number.

The budget now measures only the accumulated delta bytes against
ratio x snapshot size, excluding the snapshot frame. Previously the
snapshot counted toward the budget, which made a ratio of 1 behave
identically to 0 (the snapshot alone filled the budget, so no delta
ever fit). Now ratio 1 means "deltas may total up to one snapshot
before rolling", genuinely distinct from disabled.

The catalog producers (rs/moq-mux and js/publish) explicitly pass 0 for
now to stay byte-compatible with consumers that only read snapshots; the
delta rollout is a follow-up.

Adds tests documenting the byte-budget threshold on both sides.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
@coderabbitai

coderabbitai Bot commented Jun 16, 2026

Copy link
Copy Markdown
Contributor

Review Change Stack

Walkthrough

The delta ratio configuration for JSON producers is changed in both the Rust (rs/moq-json) and TypeScript (js/json) implementations. Config::delta_ratio / Config.deltaRatio is converted from an optional float to a plain integer (u32 in Rust, number in TypeScript) where 0 explicitly disables deltas and any positive value sets the budget multiplier. The default shifts from "disabled" (via None / undefined) to 8. Internal budget tracking migrates from a total group-byte counter to a delta-only byte counter (delta_bytes / #deltaBytes) that is reset on each new snapshot and excluded from the snapshot frame size. Two catalog call sites (Broadcast.catalog in TypeScript, the hang catalog track in rs/moq-mux) are updated to pass delta_ratio: 0 explicitly. Tests across both implementations are updated to the new integer configuration form.

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Title check ✅ Passed The title accurately summarizes the main changes: setting a default delta_ratio to 8 and correcting the budget calculation to count only delta bytes.
Description check ✅ Passed The description is comprehensive and directly related to the changeset, clearly explaining the rationale, implementation details, and impact of the changes across all affected files.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
✨ Simplify code
  • Create PR with simplified code
  • Commit simplified code in branch claude/vigorous-hypatia-1f9399

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.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

🤖 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-json/src/lib.rs`:
- Around line 56-75: The Config struct is public and allows direct construction
by consumers using struct-literal syntax. To make future field additions
non-breaking, add the `#[non_exhaustive]` attribute to the Config struct before
the existing `#[derive(Debug, Clone)]` attribute. This ensures that adding new
optional fields to Config in the future will not break existing code that
constructs it, since callers will be required to use the Default implementation
or an explicit constructor rather than direct struct literals.
🪄 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: 58f15f08-5811-438b-9aba-3b21dd1ac850

📥 Commits

Reviewing files that changed from the base of the PR and between 52b9bc0 and 2b79e45.

📒 Files selected for processing (5)
  • js/json/src/json.test.ts
  • js/json/src/producer.ts
  • js/publish/src/broadcast.ts
  • rs/moq-json/src/lib.rs
  • rs/moq-mux/src/catalog/producer.rs

Comment thread rs/moq-json/src/lib.rs
Comment on lines +56 to 75
#[derive(Debug, Clone)]
pub struct Config {
/// Controls whether the producer emits deltas (merge patches) instead of full snapshots.
/// Controls how aggressively the producer emits deltas (merge patches) instead of full snapshots.
///
/// `None` disables deltas: every change is published as a new snapshot group.
/// A ratio of `0` disables deltas: every change is published as a new snapshot group.
///
/// `Some(ratio)` enables deltas. A delta is appended to the current group as long as the
/// group's total size stays within `ratio` times the size of a fresh snapshot; otherwise a
/// new snapshot group is started. A larger ratio tolerates bigger groups before snapshotting.
pub delta_ratio: Option<f64>,
/// A positive ratio enables deltas. A delta is appended to the current group as long as the
/// accumulated deltas (excluding the snapshot frame) stay within `ratio` times the size of a
/// fresh snapshot; otherwise a new snapshot group is started. So `1` allows deltas totalling up
/// to one snapshot before rolling, and a larger ratio tolerates more deltas per snapshot.
///
/// Defaults to `8`.
pub delta_ratio: u32,
}

impl Default for Config {
fn default() -> Self {
Self { delta_ratio: 8 }
}
}

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🛠️ Refactor suggestion | 🟠 Major | ⚡ Quick win

Add #[non_exhaustive] to the Config struct.

The Config struct is public and constructed by consumers. Without #[non_exhaustive], adding new optional fields later becomes a breaking change for callers using struct-literal syntax.

Proposed fix
 /// Configuration for a [`Producer`].
+#[non_exhaustive]
 #[derive(Debug, Clone)]
 pub struct Config {

Based on coding guidelines: "Add #[non_exhaustive] to config structs that consumers construct, and provide a Default or constructor so new optional fields stay additive".

📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
#[derive(Debug, Clone)]
pub struct Config {
/// Controls whether the producer emits deltas (merge patches) instead of full snapshots.
/// Controls how aggressively the producer emits deltas (merge patches) instead of full snapshots.
///
/// `None` disables deltas: every change is published as a new snapshot group.
/// A ratio of `0` disables deltas: every change is published as a new snapshot group.
///
/// `Some(ratio)` enables deltas. A delta is appended to the current group as long as the
/// group's total size stays within `ratio` times the size of a fresh snapshot; otherwise a
/// new snapshot group is started. A larger ratio tolerates bigger groups before snapshotting.
pub delta_ratio: Option<f64>,
/// A positive ratio enables deltas. A delta is appended to the current group as long as the
/// accumulated deltas (excluding the snapshot frame) stay within `ratio` times the size of a
/// fresh snapshot; otherwise a new snapshot group is started. So `1` allows deltas totalling up
/// to one snapshot before rolling, and a larger ratio tolerates more deltas per snapshot.
///
/// Defaults to `8`.
pub delta_ratio: u32,
}
impl Default for Config {
fn default() -> Self {
Self { delta_ratio: 8 }
}
}
#[non_exhaustive]
#[derive(Debug, Clone)]
pub struct Config {
/// Controls how aggressively the producer emits deltas (merge patches) instead of full snapshots.
///
/// A ratio of `0` disables deltas: every change is published as a new snapshot group.
///
/// A positive ratio enables deltas. A delta is appended to the current group as long as the
/// accumulated deltas (excluding the snapshot frame) stay within `ratio` times the size of a
/// fresh snapshot; otherwise a new snapshot group is started. So `1` allows deltas totalling up
/// to one snapshot before rolling, and a larger ratio tolerates more deltas per snapshot.
///
/// Defaults to `8`.
pub delta_ratio: u32,
}
impl Default for Config {
fn default() -> Self {
Self { delta_ratio: 8 }
}
}
🤖 Prompt for 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.

In `@rs/moq-json/src/lib.rs` around lines 56 - 75, The Config struct is public and
allows direct construction by consumers using struct-literal syntax. To make
future field additions non-breaking, add the `#[non_exhaustive]` attribute to
the Config struct before the existing `#[derive(Debug, Clone)]` attribute. This
ensures that adding new optional fields to Config in the future will not break
existing code that constructs it, since callers will be required to use the
Default implementation or an explicit constructor rather than direct struct
literals.

Source: Coding guidelines

@kixelated
kixelated enabled auto-merge (squash) June 16, 2026 18:24
@kixelated
kixelated merged commit c9401a2 into main Jun 16, 2026
1 check passed
@kixelated
kixelated deleted the claude/vigorous-hypatia-1f9399 branch June 16, 2026 18:39
This was referenced Jun 16, 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.

1 participant