Skip to content

Conversation

@datagutt
Copy link
Member

@datagutt datagutt commented Nov 12, 2025

…rove connection selection logic

  • Updated README to include detailed descriptions of core and enhanced modes, including new features like exponential NAK decay, NAK burst detection, and RTT-aware selection.
  • Adjusted congestion control logic to ensure window growth behavior matches classic mode while maintaining quality scoring in connection selection.
  • Introduced a minimum time threshold between connection switches to prevent rapid thrashing and improve load distribution.
  • Enhanced connection selection logic to incorporate smarter exploration based on connection quality patterns, allowing for better adaptation to network conditions.
  • Updated tests to validate new features and ensure expected behavior across different connection scenarios.

Summary by CodeRabbit

  • Documentation

    • Expanded README with runtime toggles, monitoring/debugging, expected behavior, troubleshooting, and performance tuning guidance.
  • New Features

    • Enhanced default mode: exponential NAK decay, burst detection, RTT-aware quality scoring, minimal hysteresis, optional smart exploration, and a Classic mode toggle.
    • Per-packet timing-aware switch dampening and last-switch tracking for smoother routing and load distribution.
    • Runtime toggles and status/debug commands (no restart required).
  • Refactor

    • Connection selection and congestion strategies reorganized into distinct, pluggable modules.
  • Tests

    • Added/updated tests covering modes, selection, exploration, recovery, timing, and quality scoring.
  • Chores

    • Test helpers enabled under an internal feature; package version bumped.

…rove connection selection logic

- Updated README to include detailed descriptions of core and enhanced modes, including new features like exponential NAK decay, NAK burst detection, and RTT-aware selection.
- Adjusted congestion control logic to ensure window growth behavior matches classic mode while maintaining quality scoring in connection selection.
- Introduced a minimum time threshold between connection switches to prevent rapid thrashing and improve load distribution.
- Enhanced connection selection logic to incorporate smarter exploration based on connection quality patterns, allowing for better adaptation to network conditions.
- Updated tests to validate new features and ensure expected behavior across different connection scenarios.
…ection selection logic

- Removed the old congestion control implementation and replaced it with a modular structure featuring classic and enhanced modes.
- Introduced separate modules for classic and enhanced congestion control, ensuring clear delineation of logic and improved maintainability.
- Updated connection selection to support both classic and enhanced strategies, incorporating quality-aware scoring and exploration features.
- Added tests for new modules to validate functionality and ensure expected behavior across different connection scenarios.
@coderabbitai
Copy link

coderabbitai bot commented Nov 12, 2025

Caution

Review failed

The pull request is closed.

Note

Other AI code review bot(s) detected

CodeRabbit has detected other AI code review bot(s) in this pull request and will avoid duplicating their findings in the review comments. This may lead to a less comprehensive review.

Walkthrough

Modularizes congestion and sender selection into classic/enhanced strategies (plus quality/exploration), removes previous monoliths, threads last_switch_time_ms through packet handling and forwarding, updates README/tests, and exposes test helpers via a test-internals feature flag.

Changes

Cohort / File(s) Summary
Documentation
README.md
Expanded mode descriptions (Enhanced/Classic), exploration, quality scoring, NAK-burst rules, runtime toggles, monitoring, tuning, examples, and expected behavior.
Removed congestion monolith
src/connection/congestion.rs
Deleted previous single-file congestion control implementation (NAK tracking, fast recovery, window logic).
Congestion modules & facade
src/connection/congestion/mod.rs, src/connection/congestion/classic.rs, src/connection/congestion/enhanced.rs
Added modular congestion subsystem: mod.rs exposes CongestionControl facade and constants; classic.rs implements classic ACK growth; enhanced.rs implements enhanced ACK handling, NAK/burst tracking and time-based recovery.
Removed selection monolith
src/sender/selection.rs
Deleted prior monolithic selection and quality logic.
Selection modularization
src/sender/selection/mod.rs, src/sender/selection/classic.rs, src/sender/selection/enhanced.rs, src/sender/selection/quality.rs, src/sender/selection/exploration.rs
New selection subsystem: classic (capacity-based), enhanced (quality multipliers, hysteresis, time dampening), quality (exponential NAK decay + RTT bonus), exploration (degradation/recovery and periodic fallback); mod.rs re-exports quality and provides facade and MIN_SWITCH_INTERVAL_MS.
Selection facade & tests
src/sender/selection/mod.rs, src/tests/sender_tests.rs
Added select_connection_idx facade delegating to classic/enhanced; tests updated for expanded signature and new timing/exploration behaviours.
Sender switch tracking
src/sender/mod.rs, src/sender/packet_handler.rs
Added last_switch_time_ms local tracking and threaded it through handle_srt_packet, select_connection_idx, and forward_via_connection; updates timestamp on connection switch.
Connection tests updated
src/tests/connection_tests.rs
Adjusted enhanced vs classic ACK handling test sequences and expectations to match new modular behavior.
Test helpers visibility
src/lib.rs, src/main.rs, src/test_helpers.rs
Made test_helpers compile under #[cfg(any(test, feature = "test-internals"))] and added #![allow(dead_code)] in helpers.
Version bump
Cargo.toml
Crate version bumped from 2.6.1 to 2.7.0.

Sequence Diagram(s)

sequenceDiagram
  autonumber
  participant Sender
  participant Selection as Selection (mod)
  participant Congestion as CongestionControl (mod)
  participant Connection

  Sender->>Selection: select_connection_idx(conns, last_idx, last_switch_time_ms, current_time_ms, enable_quality, enable_explore, classic)
  Note right of Selection `#D6EAF8`: enhanced -> quality & exploration\nclassic -> pure capacity score
  Selection-->>Sender: chosen_idx

  Sender->>Congestion: handle_srtla_ack_* / handle_nak(window, seq, ...)
  Note right of Congestion `#FDEBD0`: tracks NAKs, bursts (>=5), fast-recovery,\nand time-based progressive recovery
  Congestion-->>Sender: updated window / flags

  Sender->>Connection: forward packet to chosen_idx
  alt connection switched
    Sender->>Sender: update last_switch_time_ms = now_ms()
  end
Loading

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~45 minutes

  • Focus review attention on:
    • Behavioral parity between removed monoliths and new classic/enhanced implementations.
    • Correct propagation and update of last_switch_time_ms across selection and forwarding paths.
    • Correctness of quality multiplier math (exponential decay, burst penalty, RTT bonus) and constants.
    • Time-based recovery and fast-recovery transitions in enhanced congestion module.
    • Tests updated to match new signatures and semantics (exploration/timing parameters).

Possibly related PRs

  • feat(README, congestion, sender): enhance SRTLA functionality and imp… #8 — Directly related refactor: replaces old congestion and selection monoliths with congestion/{classic,enhanced} and selection/{classic,enhanced,quality,exploration}, and threads last_switch_time_ms.
  • Major rewrite #5 — Overlaps selection and toggle APIs and test-internals exposure; likely touches similar selection/congestion modularization.
  • Test suite #1 — Adds shared now_ms utility and test-internals feature; relates to time utilities and test helper visibility used here.

Poem

🐰
I hop through code with whiskers bright,
I split the monolith into modes tonight,
Classic keeps calm, Enhanced seeks more,
I time the switches, count the booms before,
Tests applaud while I tidy the floor.

Pre-merge checks and finishing touches

✅ Passed checks (3 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title references key aspects of the PR (README, congestion, sender) and mentions enhanced SRTLA functionality, but is truncated and does not fully convey the comprehensive refactoring and new features introduced.
Docstring Coverage ✅ Passed Docstring coverage is 100.00% which is sufficient. The required threshold is 80.00%.

📜 Recent review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 71164f8 and d5b002c.

⛔ Files ignored due to path filters (1)
  • Cargo.lock is excluded by !**/*.lock
📒 Files selected for processing (1)
  • Cargo.toml (1 hunks)

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.

Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 2

📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 1157a2c and 6f0c1d0.

📒 Files selected for processing (15)
  • README.md (3 hunks)
  • src/connection/congestion.rs (0 hunks)
  • src/connection/congestion/classic.rs (1 hunks)
  • src/connection/congestion/enhanced.rs (1 hunks)
  • src/connection/congestion/mod.rs (1 hunks)
  • src/sender/mod.rs (3 hunks)
  • src/sender/packet_handler.rs (6 hunks)
  • src/sender/selection.rs (0 hunks)
  • src/sender/selection/classic.rs (1 hunks)
  • src/sender/selection/enhanced.rs (1 hunks)
  • src/sender/selection/exploration.rs (1 hunks)
  • src/sender/selection/mod.rs (1 hunks)
  • src/sender/selection/quality.rs (1 hunks)
  • src/tests/connection_tests.rs (1 hunks)
  • src/tests/sender_tests.rs (6 hunks)
💤 Files with no reviewable changes (2)
  • src/sender/selection.rs
  • src/connection/congestion.rs
🧰 Additional context used
📓 Path-based instructions (3)
**/*.rs

📄 CodeRabbit inference engine (AGENTS.md)

**/*.rs: All Rust code must pass cargo fmt --all -- --check
All Rust code must pass clippy with -D warnings (no warnings allowed)
Use anyhow::Result for error propagation
Group imports as std → external → crate with module-level granularity (imports_granularity = "Module", group_imports = "StdExternalCrate")
Follow naming conventions: constants SCREAMING_SNAKE_CASE
Follow naming conventions: structs PascalCase
Follow naming conventions: functions snake_case
Follow naming conventions: modules snake_case (file/module names)
Use tracing macros (debug!, info!, warn!, etc.) for logging
Use Tokio for async runtime (net, time, io, signal) and async operations
Keep code self-documenting; add doc comments for public API when necessary

Files:

  • src/sender/selection/classic.rs
  • src/sender/selection/enhanced.rs
  • src/sender/selection/exploration.rs
  • src/connection/congestion/classic.rs
  • src/sender/selection/quality.rs
  • src/connection/congestion/enhanced.rs
  • src/sender/selection/mod.rs
  • src/sender/mod.rs
  • src/sender/packet_handler.rs
  • src/tests/sender_tests.rs
  • src/tests/connection_tests.rs
  • src/connection/congestion/mod.rs
src/**/*.rs

📄 CodeRabbit inference engine (AGENTS.md)

Expose internal fields for testing only behind #[cfg(feature = "test-internals")]

Files:

  • src/sender/selection/classic.rs
  • src/sender/selection/enhanced.rs
  • src/sender/selection/exploration.rs
  • src/connection/congestion/classic.rs
  • src/sender/selection/quality.rs
  • src/connection/congestion/enhanced.rs
  • src/sender/selection/mod.rs
  • src/sender/mod.rs
  • src/sender/packet_handler.rs
  • src/tests/sender_tests.rs
  • src/tests/connection_tests.rs
  • src/connection/congestion/mod.rs
src/tests/**/*.rs

📄 CodeRabbit inference engine (AGENTS.md)

Place integration, end-to-end, and protocol tests under src/tests/

Files:

  • src/tests/sender_tests.rs
  • src/tests/connection_tests.rs
🧬 Code graph analysis (9)
src/sender/selection/classic.rs (1)
src/sender/selection/enhanced.rs (1)
  • select_connection (33-128)
src/sender/selection/enhanced.rs (5)
src/sender/selection/exploration.rs (1)
  • should_explore_now (18-59)
src/sender/selection/quality.rs (1)
  • calculate_quality_multiplier (15-65)
src/utils.rs (1)
  • now_ms (15-20)
src/connection/mod.rs (2)
  • total_nak_count (525-527)
  • nak_burst_count (529-531)
src/connection/congestion/mod.rs (1)
  • time_since_last_nak_ms (161-167)
src/sender/selection/exploration.rs (1)
src/utils.rs (1)
  • elapsed_ms (24-26)
src/sender/selection/quality.rs (1)
src/utils.rs (1)
  • now_ms (15-20)
src/connection/congestion/enhanced.rs (2)
src/utils.rs (1)
  • now_ms (15-20)
src/connection/congestion/mod.rs (1)
  • perform_window_recovery (147-158)
src/sender/selection/mod.rs (3)
src/sender/selection/quality.rs (1)
  • calculate_quality_multiplier (15-65)
src/sender/selection/classic.rs (1)
  • select_connection (21-37)
src/sender/selection/enhanced.rs (1)
  • select_connection (33-128)
src/sender/packet_handler.rs (1)
src/utils.rs (1)
  • now_ms (15-20)
src/tests/sender_tests.rs (3)
src/sender/selection/mod.rs (1)
  • select_connection_idx (41-56)
src/utils.rs (1)
  • now_ms (15-20)
src/sender/selection/quality.rs (1)
  • calculate_quality_multiplier (15-65)
src/connection/congestion/mod.rs (4)
src/utils.rs (1)
  • now_ms (15-20)
src/connection/mod.rs (1)
  • nak_burst_count (529-531)
src/connection/congestion/classic.rs (1)
  • handle_srtla_ack_specific (16-29)
src/connection/congestion/enhanced.rs (2)
  • handle_srtla_ack (25-60)
  • perform_window_recovery (70-153)
🪛 LanguageTool
README.md

[grammar] ~40-~40: Ensure spelling is correct
Context: ...riodic Fallback**: Every 30 seconds for 300ms as a safety net - Smart Switching: ...

(QB_NEW_EN_ORTHOGRAPHY_ERROR_IDS_1)


[grammar] ~348-~348: Use a hyphen to join words.
Context: ...se - HALF_LIFE_MS: Currently 2000ms (2 second NAK decay) - adjust recovery spee...

(QB_NEW_EN_HYPHEN)

…ment

- Add MIN_SWITCH_INTERVAL_MS constant (500ms) to prevent rapid thrashing
- Enhanced mode now enforces time-based switch dampening in addition to score-based hysteresis
- Prevents connection switches within 500ms cooldown period when current connection is still valid
- Also blocks exploration-triggered switches during cooldown period
- Classic mode remains unchanged (no dampening, matches original C implementation)
- Wire last_switch_time_ms and current_time_ms through selection functions
- Update all tests to pass new current_time_ms parameter

This addresses flip-flopping under bursty scores while maintaining SRTLA's natural per-packet load distribution mechanism. The time-based dampening works in combination with the existing 2% score-based hysteresis for stable connection selection.
…suppression

Remove .max(1.0) clamp in enhanced mode that was forcing saturated
connections (base score = 0) to have a minimum score of 1.0. This
prevented the core SRTLA capacity-based selection from working correctly
when connections were saturated.

The clamp was defeating both:
- Zero-capacity link suppression (window full, base = 0)
- Quality penalty effectiveness for low-capacity connections

This fix ensures that:
- Saturated links stay at score 0 until window recovers
- Quality penalties properly reduce scores for degraded connections
- Enhanced mode with quality_mult = 1.0 matches classic mode behavior
Add 5 new tests covering per-packet routing behavior with time-based dampening:

1. test_time_based_switch_dampening_blocks_within_cooldown
   - Verifies all packets continue routing via current connection during 500ms cooldown
   - Prevents rapid thrashing between connections under bursty score changes

2. test_time_based_switch_dampening_allows_after_cooldown
   - Verifies per-packet routing switches to better connection after cooldown expires
   - Demonstrates that subsequent packets flow through the newly selected connection

3. test_time_based_switch_dampening_allows_if_current_invalid
   - Verifies cooldown is bypassed when current connection times out
   - Ensures packets immediately route via valid connection

4. test_exploration_blocked_during_cooldown
   - Verifies exploration-triggered routing changes are blocked during cooldown
   - Prevents exploration from causing rapid per-packet routing instability

5. test_classic_mode_ignores_time_dampening
   - Verifies classic mode per-packet selection always picks highest score
   - Confirms no dampening or hysteresis (matches original C implementation)

Enhanced test comments to clarify SRTLA's per-packet selection model:
- Selection happens for EACH incoming SRT packet
- Dampening prevents changing routing decision too frequently
- All packets flow through the selected connection (not round-robin)
- Natural load distribution occurs as scores change dynamically

Also added detailed documentation to enhanced::select_connection explaining
the per-packet routing model to prevent confusion about "switching" behavior.
Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 1

📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 6f0c1d0 and 43f82b2.

📒 Files selected for processing (5)
  • src/sender/packet_handler.rs (6 hunks)
  • src/sender/selection/classic.rs (1 hunks)
  • src/sender/selection/enhanced.rs (1 hunks)
  • src/sender/selection/mod.rs (1 hunks)
  • src/tests/sender_tests.rs (6 hunks)
🧰 Additional context used
📓 Path-based instructions (3)
**/*.rs

📄 CodeRabbit inference engine (AGENTS.md)

**/*.rs: All Rust code must pass cargo fmt --all -- --check
All Rust code must pass clippy with -D warnings (no warnings allowed)
Use anyhow::Result for error propagation
Group imports as std → external → crate with module-level granularity (imports_granularity = "Module", group_imports = "StdExternalCrate")
Follow naming conventions: constants SCREAMING_SNAKE_CASE
Follow naming conventions: structs PascalCase
Follow naming conventions: functions snake_case
Follow naming conventions: modules snake_case (file/module names)
Use tracing macros (debug!, info!, warn!, etc.) for logging
Use Tokio for async runtime (net, time, io, signal) and async operations
Keep code self-documenting; add doc comments for public API when necessary

Files:

  • src/sender/selection/mod.rs
  • src/sender/selection/classic.rs
  • src/sender/packet_handler.rs
  • src/sender/selection/enhanced.rs
  • src/tests/sender_tests.rs
src/**/*.rs

📄 CodeRabbit inference engine (AGENTS.md)

Expose internal fields for testing only behind #[cfg(feature = "test-internals")]

Files:

  • src/sender/selection/mod.rs
  • src/sender/selection/classic.rs
  • src/sender/packet_handler.rs
  • src/sender/selection/enhanced.rs
  • src/tests/sender_tests.rs
src/tests/**/*.rs

📄 CodeRabbit inference engine (AGENTS.md)

Place integration, end-to-end, and protocol tests under src/tests/

Files:

  • src/tests/sender_tests.rs
🧬 Code graph analysis (5)
src/sender/selection/mod.rs (4)
src/sender/selection/quality.rs (1)
  • calculate_quality_multiplier (15-65)
src/sender/selection/enhanced.rs (1)
  • select_connection (43-171)
src/sender/selection/classic.rs (1)
  • select_connection (22-38)
src/tests/sender_tests.rs (1)
  • test_select_connection_idx_classic (18-29)
src/sender/selection/classic.rs (1)
src/sender/selection/enhanced.rs (1)
  • select_connection (43-171)
src/sender/packet_handler.rs (2)
src/utils.rs (1)
  • now_ms (15-20)
src/sender/selection/mod.rs (1)
  • select_connection_idx (48-71)
src/sender/selection/enhanced.rs (5)
src/sender/selection/exploration.rs (1)
  • should_explore_now (18-59)
src/sender/selection/quality.rs (1)
  • calculate_quality_multiplier (15-65)
src/sender/selection/classic.rs (1)
  • select_connection (22-38)
src/connection/mod.rs (2)
  • total_nak_count (525-527)
  • nak_burst_count (529-531)
src/connection/congestion/mod.rs (1)
  • time_since_last_nak_ms (161-167)
src/tests/sender_tests.rs (4)
src/sender/selection/mod.rs (1)
  • select_connection_idx (48-71)
src/test_helpers.rs (1)
  • create_test_connections (50-89)
src/utils.rs (1)
  • now_ms (15-20)
src/sender/selection/quality.rs (1)
  • calculate_quality_multiplier (15-65)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (2)
  • GitHub Check: Test
  • GitHub Check: Test (Windows)

Replace empty placeholder tests in selection/mod.rs with proper assertions:

- test_select_connection_idx_classic: Verifies classic mode always picks highest
  score connection, ignoring time-based dampening (matches original C impl)

- test_select_connection_idx_enhanced: Verifies enhanced mode enforces cooldown
  dampening (stays with current connection within 500ms) and allows switching
  after cooldown expires

These tests verify the wrapper correctly delegates to classic vs enhanced
selection strategies and that each mode has the expected behavior.

Fixes false sense of test coverage from placeholder stubs.
Copy link
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

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

Pull Request Overview

This PR refactors the SRTLA sender to introduce modular congestion control and connection selection strategies, adding enhanced mode features while preserving the classic C implementation behavior as an option.

Key Changes:

  • Introduced exponential NAK decay for smooth quality recovery over ~8 seconds (replacing step-function penalties)
  • Added time-based switch dampening (500ms cooldown) to prevent rapid connection thrashing
  • Refactored code into modular classic/enhanced strategies for maintainability
  • Enhanced quality scoring with RTT-aware bonuses and NAK burst detection

Reviewed Changes

Copilot reviewed 18 out of 18 changed files in this pull request and generated 4 comments.

Show a summary per file
File Description
src/tests/sender_tests.rs Updated test signatures to include time-based dampening parameters; added new tests for cooldown behavior, classic mode bypass, and invalid connection handling; updated quality multiplier tests for exponential decay
src/tests/connection_tests.rs Revised enhanced mode ACK test to verify identical window growth behavior to classic mode
src/sender/selection/quality.rs New module implementing exponential NAK decay, burst penalties, and RTT-aware quality scoring with 30-second startup grace period
src/sender/selection/mod.rs New module entry point providing unified interface for classic/enhanced selection with time-based dampening constant
src/sender/selection/exploration.rs New module implementing smart exploration logic based on connection degradation patterns and periodic fallback
src/sender/selection/enhanced.rs New module implementing enhanced selection with quality scoring, hysteresis (2%), cooldown enforcement, and optional exploration
src/sender/selection/classic.rs New module implementing original C algorithm for capacity-based selection without quality awareness
src/sender/packet_handler.rs Added last_switch_time_ms parameter tracking to enable time-based dampening in connection selection
src/sender/mod.rs Added last_switch_time_ms state variable initialization and threading through packet handling
src/connection/congestion/mod.rs New module entry point with common NAK handling logic and dispatching to classic/enhanced implementations
src/connection/congestion/enhanced.rs New module implementing enhanced ACK handling with identical window growth to classic but supporting fast recovery mode
src/connection/congestion/classic.rs New module implementing original C ACK handling logic exactly as reference implementation
README.md Expanded documentation with detailed feature descriptions, mode comparisons, troubleshooting guide, and performance tuning section

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

datagutt and others added 3 commits November 13, 2025 17:04
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 1

♻️ Duplicate comments (1)
README.md (1)

361-361: Clarify MAX_RTT_BONUS constant status.

Past reviews flagged that MAX_RTT_BONUS doesn't exist as a named constant in the codebase—it's hardcoded as 1.03 in calculate_rtt_bonus() in quality.rs. Either remove this line or update it to reflect the actual implementation (e.g., "RTT bonus: Currently hardcoded as 1.03 in src/sender/selection/quality.rs line 87").

- `MAX_RTT_BONUS`: 1.03 (3% max bonus) - maximum RTT bonus multiplier
+ RTT bonus: Currently hardcoded as 1.03 (3% max) in `src/sender/selection/quality.rs` – requires code edit to adjust
📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 84aa500 and f262394.

📒 Files selected for processing (2)
  • README.md (4 hunks)
  • src/sender/selection/quality.rs (1 hunks)
🚧 Files skipped from review as they are similar to previous changes (1)
  • src/sender/selection/quality.rs
🧰 Additional context used
🪛 LanguageTool
README.md

[grammar] ~40-~40: Ensure spelling is correct
Context: ...riodic Fallback**: Every 30 seconds for 300ms as a safety net - Smart Switching: ...

(QB_NEW_EN_ORTHOGRAPHY_ERROR_IDS_1)

⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (1)
  • GitHub Check: Test
🔇 Additional comments (1)
README.md (1)

232-232: Verify past review correction was successfully applied.

The burst NAK description now correctly states "Additional 30% penalty (0.7x multiplier)" instead of the previous misleading "double punishment" language. This aligns with the earlier feedback.

@datagutt datagutt requested a review from Copilot November 13, 2025 17:32
@datagutt
Copy link
Member Author

@coderabbitai review

@coderabbitai
Copy link

coderabbitai bot commented Nov 13, 2025

✅ Actions performed

Review triggered.

Note: CodeRabbit is an incremental review system and does not re-review already reviewed commits. This command is applicable only when automatic reviews are paused.

Copy link
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

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

Pull Request Overview

Copilot reviewed 18 out of 18 changed files in this pull request and generated 7 comments.


💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 1

🧹 Nitpick comments (3)
src/tests/connection_tests.rs (1)

335-336: Clarify the expected window increase amount.

Per the past review comment, the assertion uses WINDOW_INCR - 1 which matches the C implementation's classic mode behavior. The comment should specify the exact expected increase for clarity.

Apply this diff:

-        assert_eq!(conn.window, 5000 + WINDOW_INCR - 1); // Should increase by WINDOW_INCR - 1
+        assert_eq!(conn.window, 5000 + WINDOW_INCR - 1); // Should increase by WINDOW_INCR - 1 (matches classic C implementation)
README.md (1)

232-232: Clarify the NAK burst penalty description.

The phrase "Additional 30% penalty (0.7x multiplier)" could be clearer. A 0.7x multiplier reduces the score TO 70% of its original value (a 30% reduction), not a penalty added on top. Per past review feedback, consider using more precise language.

Apply this diff:

-**Quality-Based Scoring** (`quality`): Punishes connections with recent NAKs. More recent NAKs = more punishment. **Additional 30% penalty (0.7x multiplier) for NAK bursts** (≥5 NAKs in short time).
+**Quality-Based Scoring** (`quality`): Punishes connections with recent NAKs. More recent NAKs = more punishment. **Additional 0.7x multiplier for NAK bursts** (≥5 NAKs in short time, reducing score to 70% or a 30% reduction).
src/sender/selection/quality.rs (1)

29-30: Use consistent penalty terminology.

Line 29-30 describes the burst penalty as "30% extra penalty" while Line 46 more accurately describes it as "30% reduction." For consistency and clarity, align the comment with the doc comment's phrasing.

Apply this diff:

-/// Additional multiplier penalty for NAK bursts (0.7 = 30% extra penalty)
+/// Additional multiplier for NAK bursts (0.7 = reduces score to 70%, a 30% reduction)
📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between f262394 and c8b2574.

📒 Files selected for processing (5)
  • README.md (4 hunks)
  • src/connection/congestion/mod.rs (1 hunks)
  • src/sender/selection/quality.rs (1 hunks)
  • src/tests/connection_tests.rs (1 hunks)
  • src/tests/sender_tests.rs (6 hunks)
🚧 Files skipped from review as they are similar to previous changes (1)
  • src/connection/congestion/mod.rs
🧰 Additional context used
📓 Path-based instructions (3)
**/*.rs

📄 CodeRabbit inference engine (AGENTS.md)

**/*.rs: All Rust code must pass cargo fmt --all -- --check
All Rust code must pass clippy with -D warnings (no warnings allowed)
Use anyhow::Result for error propagation
Group imports as std → external → crate with module-level granularity (imports_granularity = "Module", group_imports = "StdExternalCrate")
Follow naming conventions: constants SCREAMING_SNAKE_CASE
Follow naming conventions: structs PascalCase
Follow naming conventions: functions snake_case
Follow naming conventions: modules snake_case (file/module names)
Use tracing macros (debug!, info!, warn!, etc.) for logging
Use Tokio for async runtime (net, time, io, signal) and async operations
Keep code self-documenting; add doc comments for public API when necessary

Files:

  • src/tests/connection_tests.rs
  • src/sender/selection/quality.rs
  • src/tests/sender_tests.rs
src/**/*.rs

📄 CodeRabbit inference engine (AGENTS.md)

Expose internal fields for testing only behind #[cfg(feature = "test-internals")]

Files:

  • src/tests/connection_tests.rs
  • src/sender/selection/quality.rs
  • src/tests/sender_tests.rs
src/tests/**/*.rs

📄 CodeRabbit inference engine (AGENTS.md)

Place integration, end-to-end, and protocol tests under src/tests/

Files:

  • src/tests/connection_tests.rs
  • src/tests/sender_tests.rs
🧬 Code graph analysis (2)
src/sender/selection/quality.rs (1)
src/utils.rs (1)
  • now_ms (15-20)
src/tests/sender_tests.rs (4)
src/sender/selection/mod.rs (1)
  • select_connection_idx (48-71)
src/test_helpers.rs (1)
  • create_test_connections (51-90)
src/utils.rs (1)
  • now_ms (15-20)
src/sender/selection/quality.rs (1)
  • calculate_quality_multiplier (48-95)
🪛 LanguageTool
README.md

[grammar] ~40-~40: Ensure spelling is correct
Context: ...riodic Fallback**: Every 30 seconds for 300ms as a safety net - Smart Switching: ...

(QB_NEW_EN_ORTHOGRAPHY_ERROR_IDS_1)

⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (1)
  • GitHub Check: Test
🔇 Additional comments (8)
README.md (2)

271-271: Good clarity on burst penalty description.

This description correctly explains the 0.7x multiplier as a "30% reduction," which is clearer than the similar text on Line 232.


345-365: LGTM! Constants documentation is accurate.

The documentation correctly references the modular structure under src/sender/selection/ and includes the MAX_RTT_BONUS constant (defined at Line 39 of quality.rs), addressing previous review concerns.

src/sender/selection/quality.rs (2)

63-75: LGTM! Exponential decay implementation and documentation are correct.

The mathematical formula and comments accurately describe the exponential decay behavior. Verified calculations:

  • 0ms → 0.5x multiplier ✓
  • 2000ms → 0.816x multiplier ✓
  • 4000ms → 0.932x multiplier ✓
  • 8000ms+ → 0.991x multiplier ✓

This addresses the past review concern about incorrect values.


101-120: LGTM! RTT bonus logic is correct.

The RTT bonus calculation properly:

  • Guards against missing data (returns 1.0)
  • Provides small bonuses for low-latency connections (max 3%)
  • Never applies penalties (.max(1.0) ensures bonuses only)
  • Won't resurrect zero-capacity links since it's a multiplier on the quality factor, not the base score
src/tests/sender_tests.rs (4)

74-103: LGTM! Well-documented test for cooldown dampening.

This test correctly verifies that connection switching is blocked during the cooldown period, preventing rapid thrashing. The comments clearly explain the per-packet routing behavior.


136-170: LGTM! Critical safety test for bypassing cooldown.

This test correctly verifies that cooldown dampening is bypassed when the current connection becomes invalid/timed out, ensuring traffic can immediately route through valid connections.


473-543: LGTM! Comprehensive and mathematically correct quality multiplier tests.

The test thoroughly validates:

  • Startup grace period behavior
  • Exponential decay at multiple time intervals (verified calculations match expected values)
  • Perfect connection bonus
  • NAK burst penalty interaction

All expected values are mathematically accurate based on the exponential decay formula.


206-237: LGTM! Important test for classic mode purity.

This test correctly verifies that classic mode ignores enhanced mode features like time-based dampening, maintaining compatibility with the original C implementation's immediate per-packet selection behavior.

@datagutt datagutt merged commit 59c6481 into main Nov 16, 2025
5 of 6 checks passed
@datagutt datagutt deleted the feat/rethink-enhanced-mode branch November 19, 2025 17:10
@coderabbitai coderabbitai bot mentioned this pull request Jan 7, 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.

2 participants