Skip to content

Make exponential backoff parameters configurable in accept_loop#290

Merged
leynos merged 6 commits intomainfrom
devin/1754663283-configurable-backoff-parameters
Aug 8, 2025
Merged

Make exponential backoff parameters configurable in accept_loop#290
leynos merged 6 commits intomainfrom
devin/1754663283-configurable-backoff-parameters

Conversation

@devin-ai-integration
Copy link
Copy Markdown
Contributor

@devin-ai-integration devin-ai-integration Bot commented Aug 8, 2025

Make exponential backoff parameters configurable in accept_loop

Summary

This PR implements configurable exponential backoff parameters for the accept_loop function, addressing issue #264. Previously, the initial delay (10ms) and maximum delay (1s) were hardcoded constants. Now they can be configured through the WireframeServer builder pattern while maintaining full backward compatibility.

Key Changes:

  • Added BackoffConfig struct with initial_delay and max_delay fields
  • Added builder methods: .accept_backoff(), .accept_initial_delay(), .accept_max_delay()
  • Updated accept_loop to use configurable parameters instead of hardcoded constants
  • Added comprehensive tests with parameter validation
  • Maintained same default values for backward compatibility

Review & Testing Checklist for Human

  • Test actual backoff behavior: Simulate connection accept failures and verify exponential backoff works correctly with custom parameters (most critical - touches core networking logic)
  • Verify all call sites updated: Confirm accept_loop is called correctly everywhere, especially in tests (function signature changed)
  • Validate parameter validation logic: Check that minimum delay constraints make sense and max_delay >= initial_delay validation works properly
  • Confirm backward compatibility: Run existing server code without explicit backoff config and verify behavior is identical to before

Recommended test plan: Set up a server with custom backoff parameters (e.g., 1ms initial, 100ms max), simulate accept failures (e.g., port exhaustion), and verify the retry delays follow the expected exponential pattern within the configured bounds.


Diagram

%%{ init : { "theme" : "default" }}%%
graph TD
    WireframeServer["WireframeServer<br/>(server/mod.rs)"]:::major-edit
    BackoffConfig["BackoffConfig<br/>(server/runtime.rs)"]:::major-edit
    ConfigMod["config/mod.rs<br/>(builder methods)"]:::major-edit
    AcceptLoop["accept_loop()<br/>(server/runtime.rs)"]:::major-edit
    ConfigTests["config/tests.rs<br/>(new tests)"]:::major-edit

    WireframeServer -->|"contains"| BackoffConfig
    ConfigMod -->|"configures"| BackoffConfig
    WireframeServer -->|"passes config to"| AcceptLoop
    AcceptLoop -->|"uses for retry delays"| BackoffConfig
    ConfigTests -->|"tests"| ConfigMod

    subgraph Legend
        L1[Major Edit]:::major-edit
        L2[Minor Edit]:::minor-edit
        L3[Context/No Edit]:::context
    end

classDef major-edit fill:#90EE90
classDef minor-edit fill:#87CEEB
classDef context fill:#FFFFFF
Loading

Notes

  • Risk Level: Medium - touches core networking logic but changes are well-contained
  • Backward Compatibility: Maintained through identical default values (10ms initial, 1s max)
  • Testing: Added unit tests for configuration, but real backoff behavior under load needs manual verification
  • Session: Requested by @leynos
  • Link to Devin run: https://app.devin.ai/sessions/0445af57f65741b1aeb5b99fbf488f25

The implementation follows existing codebase patterns (similar to FairnessConfig and .workers() builder method) and includes parameter validation to prevent invalid configurations.

Summary by Sourcery

Allow customization of exponential backoff behavior in the server accept loop by introducing a BackoffConfig, exposing builder methods for initial and maximum retry delays, and adding validation and tests while preserving existing defaults.

New Features:

  • Make accept loop backoff parameters configurable via WireframeServer builder methods
  • Introduce BackoffConfig struct with default initial and max delay values

Enhancements:

  • Replace hardcoded accept retry delays in accept_loop with configurable parameters
  • Validate backoff parameters to enforce minimum initial delay and ensure max delay ≥ initial delay
  • Export BackoffConfig for external use

Tests:

  • Add unit tests for backoff configuration methods, default values, and validation logic

- Add BackoffConfig struct with initial_delay and max_delay fields
- Add builder methods: accept_backoff(), accept_initial_delay(), accept_max_delay()
- Update accept_loop to use configurable parameters instead of hardcoded constants
- Maintain backward compatibility with same default values (10ms initial, 1s max)
- Add comprehensive tests for new configuration methods
- Add validation to ensure sensible minimum values

Fixes #264

Co-Authored-By: Leynos <leynos@troubledskies.net>
@devin-ai-integration
Copy link
Copy Markdown
Contributor Author

🤖 Devin AI Engineer

I'll be helping with this pull request! Here's what you should know:

✅ I will automatically:

  • Address comments on this PR. Add '(aside)' to your comment to have me ignore it.
  • Look at CI failures and help fix them

Note: I can only respond to comments from users who have write access to this repository.

⚙️ Control Options:

  • Disable automatic comment and CI monitoring

@coderabbitai
Copy link
Copy Markdown
Contributor

coderabbitai Bot commented Aug 8, 2025

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.

Important

Review skipped

Bot user detected.

To trigger a single review, invoke the @coderabbitai review command.

You can disable this status message by setting the reviews.review_status to false in the CodeRabbit configuration file.

Summary by CodeRabbit

  • New Features

    • Added configurable exponential backoff settings for server connection retries, allowing adjustment of initial and maximum delay values.
    • Default backoff behaviour now starts with a 10ms delay, increasing up to 1s on repeated failures.
  • Tests

    • Introduced comprehensive tests to validate custom backoff configuration, default values, parameter validation, and exponential backoff behaviour.

Walkthrough

Introduce a configurable BackoffConfig struct to manage exponential backoff parameters for the server's accept loop. Refactor the WireframeServer to include this configuration, expose builder methods for setting backoff delays, propagate the configuration through relevant methods, and add comprehensive tests for the new functionality.

Changes

Cohort / File(s) Change Summary
Backoff Configuration Struct & Refactor
src/server/runtime.rs
Replace fixed accept retry constants with a public BackoffConfig struct; refactor accept loop to use this config.
Server Struct & Builder Methods
src/server/config/mod.rs, src/server/mod.rs
Add backoff_config field to WireframeServer; implement builder methods for configuring backoff parameters; propagate config.
Testing Backoff Configuration
src/server/config/tests.rs
Introduce new tests for builder methods, validation, and default values of backoff configuration using rstest.

Sequence Diagram(s)

sequenceDiagram
    participant User
    participant WireframeServer
    participant BackoffConfig
    participant AcceptLoop

    User->>WireframeServer: Create with builder methods (accept_backoff, etc.)
    WireframeServer->>BackoffConfig: Set initial/max delay as per builder
    WireframeServer->>AcceptLoop: Start accept loop with BackoffConfig
    loop On Accept Error
        AcceptLoop->>BackoffConfig: Retrieve current delay
        AcceptLoop->>AcceptLoop: Exponential backoff (delay doubles, capped by max)
    end
    AcceptLoop->>BackoffConfig: Reset delay on success
Loading

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~18 minutes

Possibly related issues

Possibly related PRs

Suggested labels

codex

Poem

Exponential waits, now yours to command,
With builder methods ready at hand.
No longer fixed, the delays can flex,
As tests ensure there’s no regress.
So raise a toast to code refined—
Backoff, now by you designed!
⏳✨


🪧 Tips

Chat

There are 3 ways to chat with CodeRabbit:

  • Review comments: Directly reply to a review comment made by CodeRabbit. Example:
    • I pushed a fix in commit <commit_id>, please review it.
    • Explain this complex logic.
    • Open a follow-up GitHub issue for this discussion.
  • Files and specific lines of code (under the "Files changed" tab): Tag @coderabbitai in a new review comment at the desired location with your query. Examples:
    • @coderabbitai explain this code block.
  • PR comments: Tag @coderabbitai in a new PR comment to ask questions about the PR branch. For the best results, please provide a very specific query, as very limited context is provided in this mode. Examples:
    • @coderabbitai gather interesting stats about this repository and render them as a table. Additionally, render a pie chart showing the language distribution in the codebase.
    • @coderabbitai read src/utils.ts and explain its main purpose.
    • @coderabbitai read the files in the src/scheduler package and generate a class diagram using mermaid and a README in the markdown format.

Support

Need help? Join our Discord community for assistance with any issues or questions.

CodeRabbit Commands (Invoked using PR comments)

  • @coderabbitai pause to pause the reviews on a PR.
  • @coderabbitai resume to resume the paused reviews.
  • @coderabbitai review to trigger an incremental review. This is useful when automatic reviews are disabled for the repository.
  • @coderabbitai full review to do a full review from scratch and review all the files again.
  • @coderabbitai summary to regenerate the summary of the PR.
  • @coderabbitai generate sequence diagram to generate a sequence diagram of the changes in this PR.
  • @coderabbitai resolve resolve all the CodeRabbit review comments.
  • @coderabbitai configuration to show the current CodeRabbit configuration for the repository.
  • @coderabbitai help to get help.

Other keywords and placeholders

  • Add @coderabbitai ignore anywhere in the PR description to prevent this PR from being reviewed.
  • Add @coderabbitai summary to generate the high-level summary at a specific location in the PR description.
  • Add @coderabbitai anywhere in the PR title to generate the title automatically.

CodeRabbit Configuration File (.coderabbit.yaml)

  • You can programmatically configure CodeRabbit by adding a .coderabbit.yaml file to the root of your repository.
  • Please see the configuration documentation for more information.
  • If your editor has YAML language server enabled, you can add the path at the top of this file to enable auto-completion and validation: # yaml-language-server: $schema=https://coderabbit.ai/integrations/schema.v2.json

Documentation and Community

  • Visit our Documentation for detailed information on how to use CodeRabbit.
  • Join our Discord Community to get help, request features, and share feedback.
  • Follow us on X/Twitter for updates and announcements.

@leynos
Copy link
Copy Markdown
Owner

leynos commented Aug 8, 2025

@sourcery-ai review

@leynos
Copy link
Copy Markdown
Owner

leynos commented Aug 8, 2025

@coderabbitai review

@coderabbitai
Copy link
Copy Markdown
Contributor

coderabbitai Bot commented Aug 8, 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.

@coderabbitai coderabbitai Bot added the codex label Aug 8, 2025
@sourcery-ai
Copy link
Copy Markdown
Contributor

sourcery-ai Bot commented Aug 8, 2025

Reviewer's Guide

This PR replaces hardcoded accept-loop retry delays with a new BackoffConfig struct integrated into the WireframeServer builder, introduces .accept_backoff/.accept_initial_delay/.accept_max_delay methods with validation to customize initial and max delays, refactors accept_loop to use these parameters while preserving defaults for backward compatibility, and adds unit tests for configuration and defaults.

Class diagram for BackoffConfig integration and builder methods

classDiagram
    class WireframeServer {
        +BackoffConfig backoff_config
        +accept_backoff(initial_delay: Duration, max_delay: Duration) Self
        +accept_initial_delay(delay: Duration) Self
        +accept_max_delay(delay: Duration) Self
    }
    class BackoffConfig {
        +Duration initial_delay
        +Duration max_delay
        +default() BackoffConfig
    }
    WireframeServer --> BackoffConfig : uses
Loading

Class diagram for accept_loop refactor with BackoffConfig

classDiagram
    class accept_loop {
        +listener
        +factory
        +on_success
        +on_failure
        +shutdown
        +tracker
        +backoff_config: BackoffConfig
    }
    accept_loop --> BackoffConfig : uses for retry delays
Loading

File-Level Changes

Change Details Files
Introduce BackoffConfig and wire it into server state
  • Define BackoffConfig struct with Default impl (10ms initial, 1s max)
  • Add backoff_config field to config builder with default value
  • Expose backoff_config in WireframeServer struct
src/server/runtime.rs
src/server/config/mod.rs
src/server/mod.rs
Add builder methods for configuring accept-loop backoff
  • Implement accept_backoff(initial, max) with validation
  • Implement accept_initial_delay(delay) enforcing minimum 1ms
  • Implement accept_max_delay(delay) ensuring max ≥ initial
src/server/config/mod.rs
Refactor accept_loop to use BackoffConfig parameters
  • Update accept_loop signature to accept BackoffConfig
  • Initialize and reset delay from config.initial_delay
  • Replace constants with config.max_delay in retry logic
  • Pass backoff_config when spawning accept_loop
src/server/runtime.rs
Add unit tests for backoff configuration and defaults
  • Tests for accept_backoff, accept_initial_delay, accept_max_delay
  • Validation tests for minimum initial_delay and bound checks
  • Tests for default BackoffConfig values
src/server/config/tests.rs

Possibly linked issues


Tips and commands

Interacting with Sourcery

  • Trigger a new review: Comment @sourcery-ai review on the pull request.
  • Continue discussions: Reply directly to Sourcery's review comments.
  • Generate a GitHub issue from a review comment: Ask Sourcery to create an
    issue from a review comment by replying to it. You can also reply to a
    review comment with @sourcery-ai issue to create an issue from it.
  • Generate a pull request title: Write @sourcery-ai anywhere in the pull
    request title to generate a title at any time. You can also comment
    @sourcery-ai title on the pull request to (re-)generate the title at any time.
  • Generate a pull request summary: Write @sourcery-ai summary anywhere in
    the pull request body to generate a PR summary at any time exactly where you
    want it. You can also comment @sourcery-ai summary on the pull request to
    (re-)generate the summary at any time.
  • Generate reviewer's guide: Comment @sourcery-ai guide on the pull
    request to (re-)generate the reviewer's guide at any time.
  • Resolve all Sourcery comments: Comment @sourcery-ai resolve on the
    pull request to resolve all Sourcery comments. Useful if you've already
    addressed all the comments and don't want to see them anymore.
  • Dismiss all Sourcery reviews: Comment @sourcery-ai dismiss on the pull
    request to dismiss all existing Sourcery reviews. Especially useful if you
    want to start fresh with a new review - don't forget to comment
    @sourcery-ai review to trigger a new review!

Customizing Your Experience

Access your dashboard to:

  • Enable or disable review features such as the Sourcery-generated pull request
    summary, the reviewer's guide, and others.
  • Change the review language.
  • Add, remove or edit custom review instructions.
  • Adjust other review settings.

Getting Help

Copy link
Copy Markdown
Contributor

@sourcery-ai sourcery-ai Bot left a comment

Choose a reason for hiding this comment

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

Hey @devin-ai-integration[bot] - I've reviewed your changes and found some issues that need to be addressed.

Prompt for AI Agents
Please address the comments from this code review:
## Individual Comments

### Comment 1
<location> `src/server/config/tests.rs:201` </location>
<code_context>
     assert_eq!(second.ip(), addr2.ip());
 }
+
+#[rstest]
+fn test_accept_backoff_configuration(
+    factory: impl Fn() -> WireframeApp + Send + Sync + Clone + 'static,
+) {
+    let initial = Duration::from_millis(5);
+    let max = Duration::from_millis(500);
+    let server = WireframeServer::new(factory).accept_backoff(initial, max);
+    assert_eq!(server.backoff_config.initial_delay, initial);
+    assert_eq!(server.backoff_config.max_delay, max);
+}
</code_context>

<issue_to_address>
Tests only configuration, not actual backoff behavior.

Please add a test that simulates repeated accept failures and verifies the exponential backoff timing, to ensure the runtime behavior matches the configuration.
</issue_to_address>

<suggested_fix>
<<<<<<< SEARCH
#[rstest]
fn test_accept_backoff_configuration(
    factory: impl Fn() -> WireframeApp + Send + Sync + Clone + 'static,
) {
    let initial = Duration::from_millis(5);
    let max = Duration::from_millis(500);
    let server = WireframeServer::new(factory).accept_backoff(initial, max);
    assert_eq!(server.backoff_config.initial_delay, initial);
    assert_eq!(server.backoff_config.max_delay, max);
}
=======
#[rstest]
fn test_accept_backoff_configuration(
    factory: impl Fn() -> WireframeApp + Send + Sync + Clone + 'static,
) {
    let initial = Duration::from_millis(5);
    let max = Duration::from_millis(500);
    let server = WireframeServer::new(factory).accept_backoff(initial, max);
    assert_eq!(server.backoff_config.initial_delay, initial);
    assert_eq!(server.backoff_config.max_delay, max);
}

#[test]
fn test_accept_exponential_backoff_behavior() {
    use std::sync::{Arc, Mutex};
    use std::thread;
    use std::time::{Duration, Instant};

    // Simulate a server with backoff config
    let initial = Duration::from_millis(10);
    let max = Duration::from_millis(80);
    let mut backoff = initial;
    let mut delays = Vec::new();
    let attempts = 5;

    let start = Instant::now();
    let mut last = start;

    for i in 0..attempts {
        // Simulate accept failure and backoff
        thread::sleep(backoff);
        let now = Instant::now();
        let elapsed = now.duration_since(last);
        delays.push(elapsed);
        last = now;

        // Exponential backoff logic
        backoff = std::cmp::min(backoff * 2, max);
    }

    // The first delay should be at least initial, and each subsequent delay should double, up to max
    let expected_delays = [
        initial,
        std::cmp::min(initial * 2, max),
        std::cmp::min(initial * 4, max),
        std::cmp::min(initial * 8, max),
        max,
    ];

    for (i, (actual, expected)) in delays.iter().zip(expected_delays.iter()).enumerate() {
        // Allow a small margin for thread scheduling
        assert!(
            *actual >= *expected,
            "Delay {} was {:?}, expected at least {:?}",
            i,
            actual,
            expected
        );
        assert!(
            *actual < *expected + Duration::from_millis(20),
            "Delay {} was {:?}, expected less than {:?}",
            i,
            actual,
            *expected + Duration::from_millis(20)
        );
    }
}
>>>>>>> REPLACE

</suggested_fix>

Sourcery is free for open source - if you like our reviews please consider sharing them ✨
Help me be more useful! Please click 👍 or 👎 on each comment and I'll use the feedback to improve your reviews.

Comment thread src/server/config/tests.rs
Copy link
Copy Markdown
Contributor

@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: 8

🔭 Outside diff range comments (1)
src/server/runtime.rs (1)

169-192: Prevent initial_delay greater than max_delay at runtime.

If configuration sets initial_delay above max_delay, the first sleep uses an out-of-bounds delay, breaking the intended cap. Validate the struct once and panic or correct it before entering the loop.

 let mut delay = backoff_config.initial_delay;
 if delay > backoff_config.max_delay {
-    // proceed with invalid state
+    tracing::warn!(
+        "initial_delay ({:?}) exceeds max_delay ({:?}); clamping to max_delay",
+        delay,
+        backoff_config.max_delay
+    );
+    delay = backoff_config.max_delay;
 }
📜 Review details

Configuration used: CodeRabbit UI
Review profile: ASSERTIVE
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between a653109 and 0e50e89.

📒 Files selected for processing (4)
  • src/server/config/mod.rs (4 hunks)
  • src/server/config/tests.rs (2 hunks)
  • src/server/mod.rs (1 hunks)
  • src/server/runtime.rs (6 hunks)
🧰 Additional context used
📓 Path-based instructions (1)
**/*.rs

⚙️ CodeRabbit Configuration File

**/*.rs: * Seek to keep the cyclomatic complexity of functions no more than 12.

  • Adhere to single responsibility and CQRS

  • Place function attributes after doc comments.

  • Do not use return in single-line functions.

  • Move conditionals with >2 branches into a predicate function.

  • Avoid unsafe unless absolutely necessary.

  • Every module must begin with a //! doc comment that explains the module's purpose and utility.

  • Comments and docs must follow en-GB-oxendict (-ize / -our) spelling and grammar

  • Lints must not be silenced except as a last resort.

    • #[allow] is forbidden.
    • Only narrowly scoped #[expect(lint, reason = "...")] is allowed.
    • No lint groups, no blanket or file-wide suppression.
    • Include FIXME: with link if a fix is expected.
  • Use rstest fixtures for shared setup and to avoid repetition between tests.

  • Replace duplicated tests with #[rstest(...)] parameterised cases.

  • Prefer mockall for mocks/stubs.

  • Prefer .expect() over .unwrap()

  • Ensure that any API or behavioural changes are reflected in the documentation in docs/

  • Ensure that any completed roadmap steps are recorded in the appropriate roadmap in docs/

  • Files must not exceed 400 lines in length

    • Large modules must be decomposed
    • Long match statements or dispatch tables should be decomposed by domain and collocated with targets
    • Large blocks of inline data (e.g., test fixtures, constants or templates) must be moved to external files and inlined at compile-time or loaded at run-time.

Files:

  • src/server/mod.rs
  • src/server/config/tests.rs
  • src/server/config/mod.rs
  • src/server/runtime.rs
🧬 Code Graph Analysis (2)
src/server/config/mod.rs (1)
src/server/runtime.rs (1)
  • default (29-34)
src/server/runtime.rs (2)
src/server/test_util.rs (1)
  • factory (18-20)
src/server/config/mod.rs (1)
  • local_addr (216-218)
🔍 MCP Research (1 server)

Deepwiki:

  • The WireframeServer manages TCP connections and worker tasks, using a factory pattern to create WireframeApp instances per worker. It supports optional connection preamble validation and graceful shutdown. The server uses a shared Arc<TcpListener> among workers and creates one app instance per worker. The server builder methods include new(factory), workers(count), with_preamble<T>(), bind(addr), and run(). The worker task architecture includes an accept loop with exponential backoff for accept errors, starting with a 10ms delay doubled on each error up to 1s, to prevent accept error storms. This backoff logic is part of the worker task event loop. (Document WireframeServer)

  • The WireframeServer manages the overall server lifecycle including TCP connection acceptance and worker thread management. It uses a factory pattern to create separate WireframeApp instances per worker. The worker pool management section describes worker tasks running an event loop that accepts connections and handles shutdown signals, with exponential backoff on accept errors to handle temporary resource exhaustion. The backoff delay starts at 10ms and doubles up to 1s. (Document Core Architecture)

  • The server implements graceful shutdown coordination using CancellationToken and TaskTracker. The accept error recovery uses exponential backoff with initial delay 10ms and max delay 1s, doubling delay on each accept error. This prevents accept error storms and allows recovery from transient failures. (Document Resilience and Error Handling)

  • The future roadmap includes making exponential backoff parameters configurable in the accept loop, replacing fixed constants with a configurable BackoffConfig struct containing initial_delay and max_delay. This is part of the roadmap to version 1.0, aiming to enhance configurability and resilience. (Document Future Roadmap)

Comment thread src/server/config/mod.rs
Comment thread src/server/config/mod.rs
Comment thread src/server/config/mod.rs
Comment thread src/server/config/mod.rs
Comment thread src/server/config/tests.rs
Comment thread src/server/mod.rs
Comment thread src/server/mod.rs
Comment thread src/server/runtime.rs
- Add comprehensive documentation for BackoffConfig struct and field
- Add module-level docs for BackoffConfig re-export
- Fix accept_initial_delay to preserve initial ≤ max invariant
- Make accept_max_delay validation logic explicit
- Add test for initial_delay exceeding default max_delay
- Fix clippy warning for accept() function name formatting

Co-Authored-By: Leynos <leynos@troubledskies.net>
@leynos leynos linked an issue Aug 8, 2025 that may be closed by this pull request
- Fix incomplete documentation examples in accept_backoff, accept_initial_delay, and accept_max_delay
- Add complete method call examples showing proper usage
- Address user feedback on GitHub PR comments asking for complete examples

Co-Authored-By: Leynos <leynos@troubledskies.net>
- Replace silent coercion with explicit parameter swapping and validation
- Add comprehensive documentation explaining behavior
- Add test cases for parameter swapping edge cases
- Ensure initial_delay <= max_delay invariant is preserved

Co-Authored-By: Leynos <leynos@troubledskies.net>
- Add test_accept_exponential_backoff_behavior() to verify actual timing behavior
- Test simulates repeated accept failures and measures timing intervals
- Verifies delays follow exponential pattern: initial → 2×initial → 4×initial → max
- Complements existing configuration tests with runtime behavior verification
- Addresses user feedback about testing actual backoff behavior vs just configuration

Co-Authored-By: Leynos <leynos@troubledskies.net>
@leynos
Copy link
Copy Markdown
Owner

leynos commented Aug 8, 2025

@coderabbitai review

@coderabbitai
Copy link
Copy Markdown
Contributor

coderabbitai Bot commented Aug 8, 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.

Repository owner deleted a comment from devin-ai-integration Bot Aug 8, 2025
@devin-ai-integration
Copy link
Copy Markdown
Contributor Author

Devin is currently unreachable - the session may have died.

Copy link
Copy Markdown
Contributor

@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: 4

🔭 Outside diff range comments (4)
src/server/runtime.rs (4)

134-138: Improve readability of readiness send; avoid let-chains guard.

Refactor to a simple nested if to avoid subtlety.

-if let Some(tx) = ready_tx
-    && tx.send(()).is_err()
-{
-    tracing::warn!("Failed to send readiness signal: receiver dropped");
-}
+if let Some(tx) = ready_tx {
+    if tx.send(()).is_err() {
+        tracing::warn!("Failed to send readiness signal: receiver dropped");
+    }
+}

184-207: Accept loop uses configurable exponential backoff correctly.

Initialise from config, reset on success, double with cap on failure. Add a sanity-check to defend invariants at runtime.

// Add near the start of `accept_loop`
debug_assert!(
    backoff_config.initial_delay >= Duration::from_millis(1)
        && backoff_config.initial_delay <= backoff_config.max_delay,
    "invalid BackoffConfig: initial_delay={:?}, max_delay={:?}",
    backoff_config.initial_delay,
    backoff_config.max_delay
);

237-244: Replace unwrap() in tests with expect() per guidelines.

Provide helpful failure messages.

-        .await;
-        assert!(result.is_ok());
-        assert!(result.unwrap().is_ok());
+        .await;
+        assert!(result.is_ok());
+        assert!(
+            result.expect("timeout waiting for run_with_shutdown to complete").is_ok(),
+            "server run failed"
+        );

280-287: Replace unwrap() in tests with expect() per guidelines.

Provide helpful failure messages.

-        .await;
-        assert!(result.is_ok());
-        assert!(result.unwrap().is_ok());
+        .await;
+        assert!(result.is_ok());
+        assert!(
+            result.expect("timeout waiting for run_with_shutdown to complete").is_ok(),
+            "server run failed"
+        );
♻️ Duplicate comments (2)
src/server/mod.rs (1)

71-73: Fix en-GB spelling in the re-export doc.

Align with repo guideline (-ise / -our). Change “behavior” → “behaviour”.

-/// Re-exported configuration types for server backoff behavior.
+/// Re-exported configuration types for server backoff behaviour.
src/server/runtime.rs (1)

25-37: Use en-GB spelling in BackoffConfig docs.

Change “retry behavior” → “retry behaviour”.

-/// Controls retry behavior when `accept()` calls fail on the server's TCP listener.
+/// Controls retry behaviour when `accept()` calls fail on the server's TCP listener.
📜 Review details

Configuration used: CodeRabbit UI
Review profile: ASSERTIVE
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 0e50e89 and 0319569.

📒 Files selected for processing (4)
  • src/server/config/mod.rs (4 hunks)
  • src/server/config/tests.rs (2 hunks)
  • src/server/mod.rs (1 hunks)
  • src/server/runtime.rs (6 hunks)
🧰 Additional context used
📓 Path-based instructions (1)
**/*.rs

⚙️ CodeRabbit Configuration File

**/*.rs: * Seek to keep the cyclomatic complexity of functions no more than 12.

  • Adhere to single responsibility and CQRS

  • Place function attributes after doc comments.

  • Do not use return in single-line functions.

  • Move conditionals with >2 branches into a predicate function.

  • Avoid unsafe unless absolutely necessary.

  • Every module must begin with a //! doc comment that explains the module's purpose and utility.

  • Comments and docs must follow en-GB-oxendict (-ize / -our) spelling and grammar

  • Lints must not be silenced except as a last resort.

    • #[allow] is forbidden.
    • Only narrowly scoped #[expect(lint, reason = "...")] is allowed.
    • No lint groups, no blanket or file-wide suppression.
    • Include FIXME: with link if a fix is expected.
  • Use rstest fixtures for shared setup and to avoid repetition between tests.

  • Replace duplicated tests with #[rstest(...)] parameterised cases.

  • Prefer mockall for mocks/stubs.

  • Prefer .expect() over .unwrap()

  • Ensure that any API or behavioural changes are reflected in the documentation in docs/

  • Ensure that any completed roadmap steps are recorded in the appropriate roadmap in docs/

  • Files must not exceed 400 lines in length

    • Large modules must be decomposed
    • Long match statements or dispatch tables should be decomposed by domain and collocated with targets
    • Large blocks of inline data (e.g., test fixtures, constants or templates) must be moved to external files and inlined at compile-time or loaded at run-time.

Files:

  • src/server/mod.rs
  • src/server/runtime.rs
  • src/server/config/mod.rs
  • src/server/config/tests.rs
🔍 MCP Research (1 server)

Deepwiki:

  • The PR includes a diagram illustrating the relationships between the WireframeServer, BackoffConfig, configuration modules, and tests, as well as notes on risk level (medium), testing coverage, and a link to a Devin AI session for the implementation. (PR summary)

  • The comments on this pull request are minimal and primarily procedural. The repository maintainer requested reviews from two automated reviewers: @sourcery-ai and @coderabbitai. The only recorded response is an automated reply from the CodeRabbit AI bot indicating that a review was triggered and clarifying its incremental review behavior. No human reviewers have provided feedback or discussion comments on the PR content, implementation details, or testing outcomes. (PR summary)

🔇 Additional comments (16)
src/server/mod.rs (1)

61-63: Backoff configuration field is well-integrated.

Keep as-is; defaults and documentation are clear.

src/server/config/mod.rs (5)

13-14: Import Duration where needed.

Good addition; required for new builder methods.


54-55: Initialise backoff_config with defaults.

Correct defaulting; preserves backward compatibility.


95-96: Preserve backoff config across with_preamble.

Good: carry configuration forward when changing preamble type.


309-315: Setter accept_initial_delay maintains invariant.

Clamping and bumping max_delay when needed is correct.


330-337: Setter accept_max_delay maintains invariant.

Explicit if/else is clear and symmetric. Keep as-is.

src/server/runtime.rs (2)

43-50: Default values preserve prior behaviour.

10 ms initial and 1 s max match previous constants.


128-158: Thread backoff config into worker tasks.

Destructure and pass to accept_loop correctly.

src/server/config/tests.rs (8)

14-15: Import Duration for backoff tests.

Good; used consistently across cases.


201-210: Backoff configuration test is correct.

Assert both fields set via .accept_backoff(). Keep as-is.


259-267: Initial delay setter test is correct.

Covers assignment; invariant adjustments are exercised elsewhere.


269-275: Max delay setter test is correct.

Covers assignment of a large cap.


277-289: Validation test covers clamping and invariant preservation.

Good coverage: clamp zero to 1 ms and raise max_delay to match initial_delay.


291-299: Default values test is correct.

Asserts preserved defaults (10 ms, 1 s).


301-308: Exceeding default max raises cap appropriately.

Good: ensures invariant remains valid when initial > default max.


310-328: Parameter swapping test is correct.

Validates swap behaviour and lower-bound clamping to 1 ms.

Comment thread src/server/config/mod.rs
Comment thread src/server/config/mod.rs
Comment thread src/server/config/mod.rs Outdated
Comment thread src/server/config/tests.rs
* Document accept backoff configuration

* Rephrase accept_backoff docs
@leynos leynos merged commit bd5bf50 into main Aug 8, 2025
5 checks passed
@leynos leynos deleted the devin/1754663283-configurable-backoff-parameters branch August 8, 2025 23:14
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Make exponential backoff parameters configurable in accept_loop

1 participant