Skip to content

Conversation

leynos
Copy link
Owner

@leynos leynos commented Aug 30, 2025

Summary

  • expand push queue builder docs with a complete example covering capacities, rate limits, and dead-letter queue behaviour
  • document rate and DLQ setters, noting that None disables throttling and frames are dropped when the DLQ is absent or full
  • clarify lint expectations in connection actor fixtures and validate builder rates with a dedicated is_invalid_rate predicate
  • refine deprecated constructors' error messages and mark PushError as non-exhaustive
  • deduplicate deprecated constructors via a shared build_via_builder helper
  • reserve queue slots before rate limiting and throttle DLQ logging with per-handle counters
  • test that rate(None) disables throttling and share builder fixtures across push policy tests
  • consolidate test queue construction with fixtures to reduce repetition
  • replace spaced hyphens with em dashes, mark docs no_run, disable throttling in more tests, remove #[tokio::test] from doctests, and downgrade DLQ loss logs to warnings
  • adopt Oxford “-ize” spelling across documentation and swap unchecked unwrap calls for expect in push handle examples

Testing

  • make fmt
  • make lint
  • make test
  • make markdownlint
  • make nixie (fails: KeyboardInterrupt)

https://chatgpt.com/codex/tasks/task_e_68aeba8d630c8322bcab55de80b2ef06

Summary by Sourcery

Replace PushQueues’ legacy constructors with a flexible PushQueuesBuilder API and enforce robust rate‐limit and dead‐letter queue behavior across code, tests, and documentation

New Features:

  • Introduce PushQueuesBuilder for fluent configuration of high/low capacities, rate limits, and optional DLQ
  • Add dead‐letter queue support and make rate limiting optional via None

Bug Fixes:

  • Fix builder to reject invalid rates with a dedicated is_invalid_rate predicate

Enhancements:

  • Enforce and validate allowed push rates (reject zero or above MAX_PUSH_RATE, accept None for unlimited)
  • Reserve queue slots before applying rate limiting and throttle DLQ logging with per‐handle counters
  • Deprecate old constructors in favor of builder and mark PushError and PushConfigError as non‐exhaustive
  • Downgrade DLQ loss logs to warnings

Documentation:

  • Expand PushQueues documentation with example covering capacities, rate limits, and DLQ behavior and mark code blocks no_run
  • Adopt Oxford “-ize” spelling, replace spaced hyphens with em dashes, and replace unwraps with expect in examples

Tests:

  • Add tests for invalid builder rates, unlimited mode, and capacity validations
  • Unify and deduplicate push queue fixtures and share builder setup across push and policy tests

Chores:

  • Remove #[tokio::test] from doctests, apply fmt/lint/markdownlint fixes

Copy link
Contributor

sourcery-ai bot commented Aug 30, 2025

Reviewer's Guide

This pull request refactors the PushQueues API into a fluent builder pattern with centralized validation (including invalid-rate checks), enhances dead-letter queue handling and log throttling, and overhauls tests and documentation to adopt the new builder interface, share fixtures, and improve examples and formatting.

Sequence diagram for frame push with dead-letter queue and rate limiting

sequenceDiagram
    participant Producer
    participant PushHandle
    participant RateLimiter
    participant PushQueues
    participant DLQ
    Producer->>PushHandle: push_high_priority(frame)
    PushHandle->>PushQueues: reserve queue slot
    alt Rate limiting enabled
        PushHandle->>RateLimiter: acquire token
        RateLimiter-->>PushHandle: token granted
    end
    alt Queue full
        PushHandle->>DLQ: try_send(frame)
        alt DLQ full or absent
            PushHandle->>PushHandle: log warning (throttled)
        end
    else Queue available
        PushHandle->>PushQueues: send frame
    end
Loading

File-Level Changes

Change Details Files
Introduce builder API for configuring PushQueues and centralize configuration/validation
  • Add PushQueuesBuilder with capacity, rate and DLQ configuration methods
  • Implement is_invalid_rate predicate and build_via_builder helper for deprecated constructors
  • Remove legacy bounded_* constructors in favor of builder.build()
src/push/queues/builder.rs
src/push/queues/mod.rs
src/push/mod.rs
Refactor tests to use shared builder fixtures and validate rate behavior
  • Add rstest fixtures for queues and builder across test modules
  • Replace direct PushQueues::bounded calls with builder.build()
  • Add tests for invalid rate rejection and None-rate acceptance
tests/push.rs
tests/push_policies.rs
tests/connection_actor.rs
Enhance dead-letter queue handling and logging throttling
  • Throttle DLQ error logs using per-handle counters and timed intervals
  • Reserve queue slots before rate limiting to avoid deadlock on closed queues
  • Downgrade DLQ loss messages to warnings under WarnAndDrop policy
src/push/queues/handle.rs
Update documentation and examples for the builder API and formatting
  • Add comprehensive builder examples with no_run annotations
  • Swap unwrap() calls for expect() in code samples
  • Replace spaced hyphens with em dashes and adopt Oxford “-ize” spelling
README.md
docs/efficiency-report.md
docs/hardening-wireframe-a-guide-to-production-resilience.md

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
Contributor

coderabbitai bot commented Aug 30, 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.

Note

Reviews paused

Use the following commands to manage reviews:

  • @coderabbitai resume to resume automatic reviews.
  • @coderabbitai review to trigger a single review.

Summary by CodeRabbit

  • New Features

    • Introduced a builder-based API for push queues with configurable high/low capacities, optional rate limiting (including unlimited), and optional dead-letter queue with logging.
    • Exposed PushHandle and refined error reporting, including a QueueFull variant.
  • Refactor

    • Reworked push-queue internals and deprecated direct constructors in favour of the builder flow.
  • Documentation

    • Added and updated “Push Queues” guidance and examples to the builder API; corrected spelling and improved formatting across docs.
  • Tests

    • Migrated tests to the builder API and added validations for capacities, rate limits, and DLQ behaviours.

Walkthrough

Replace the legacy monolithic push implementation with a modular, builder-based push-queue subsystem; add builder, handle, errors and queues submodules; remove the old src/push.rs; update docs, examples and tests to the new builder API and rename one PushError variant.

Changes

Cohort / File(s) Summary
Push queues core (new modular API)
src/push/mod.rs, src/push/queues/mod.rs, src/push/queues/builder.rs, src/push/queues/handle.rs, src/push/queues/errors.rs
Add modular push-queue implementation: PushQueuesBuilder, PushQueues, PushHandle, PushPriority, PushPolicy, PushError, PushConfigError, MAX_PUSH_RATE, rate limiting, DLQ support, recv/close, validation and builder-based construction; provide deprecated bounded constructors that delegate to builder.
Legacy module removal
src/push.rs
Remove previous monolithic push queue implementation and its public items (traits, types, constants, methods).
Public re-export shim
src/push/mod.rs
Re-export new push API (builder, handle, errors, constants) under wireframe::push.
Documentation updates (design and guides)
README.md, docs/asynchronous-outbound-messaging-design.md, docs/efficiency-report.md, docs/hardening-wireframe-a-guide-to-production-resilience.md, docs/multi-packet-and-streaming-responses-design.md
Update API examples and prose to the builder pattern; document Push Queues builder API; record decode optimisation wording change (freeze().to_vec()); spelling adjustments (optimised → optimized); note duplicate README section introduced.
Source doc/comment adjustments
src/connection.rs, src/session.rs, src/response.rs
Update in-code examples to use PushQueues::<T>::builder()...build().expect(...), switch code fences to no_run where applicable, and correct doc spelling.
Tests: builder adoption, fixtures and assertions
tests/* (many files: advanced, async_stream, connection_actor, correlation_id, push, push_policies, session_registry, stream_end, wireframe_protocol, world, support, server, etc.)
Replace PushQueues::bounded(...) usages with PushQueues::<T>::builder()...build().expect(...) or shared builder fixtures; add tests for builder validation (invalid rate, invalid capacities), DLQ behaviours and renamed error variant PushError::QueueFull; add tests/support.rs builder helper and other fixtures; adjust some rstest lint attributes.
Server test minor robustness
tests/server.rs
Replace unwrap() with expect("failed to bind existing listener") in binding test.

Sequence Diagram(s)

sequenceDiagram
  autonumber
  actor App as Application
  participant PB as PushQueues::<F>::builder()
  participant B as PushQueuesBuilder<F>
  participant Q as PushQueues<F>
  participant H as PushHandle<F>

  App->>PB: builder()
  PB-->>App: PushQueuesBuilder<F>
  App->>B: high_capacity(...), low_capacity(...), rate(...), dlq(...)
  App->>B: build()
  B-->>App: Result<(Q, H)>
  note over Q,H #DDEBF7: Pair returned on success (or Err on invalid config)
Loading
sequenceDiagram
  autonumber
  actor Prod as Producer
  participant H as PushHandle<F>
  participant HP as high_prio_tx
  participant LP as low_prio_tx
  participant RL as RateLimiter (opt)
  participant DLQ as DLQ Sender (opt)

  alt push_high_priority
    Prod->>H: push_high_priority(frame)
    H->>HP: reserve/send (async)
  else push_low_priority
    Prod->>H: push_low_priority(frame)
    H->>LP: reserve/send (async)
  end
  opt rate limiting enabled
    H->>RL: throttle/reserve
  end
  alt try_push (non-blocking)
    Prod->>H: try_push(frame, priority, policy)
    H->>HP: try_send / full?
    H->>LP: try_send / full?
    alt Full + Drop policy
      H->>DLQ: try_send(frame)
      note right of H #FFF2CC: Log warn periodically on DLQ drops
    else Full + ReturnError
      H-->>Prod: Err(QueueFull)
    end
  end
Loading
sequenceDiagram
  autonumber
  participant Q as PushQueues<F>
  participant HR as high_priority_rx
  participant LR as low_priority_rx
  participant Conn as Connection Actor

  loop recv loop
    Conn->>Q: recv().await
    alt high priority available
      Q->>HR: recv()
      HR-->>Q: Some(F)
      Q-->>Conn: (High, F)
    else low priority available
      Q->>LR: recv()
      LR-->>Q: Some(F)
      Q-->>Conn: (Low, F)
    else both closed/empty
      Q-->>Conn: None
    end
  end
Loading

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~60 minutes

Poem

Queues rebuilt with fluent grace,
High and low now take their place.
A builder whispers: rate or none—
DLQ waits for drops undone.
Handles clone, the frames all flow,
Tests align, green lights aglow.

✨ Finishing Touches
🧪 Generate unit tests
  • Create PR with unit tests
  • Post copyable unit tests in a comment
  • Commit unit tests in branch codex/introduce-pushqueuesbuilder-with-deprecation-225o2i

🪧 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.
    • 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.
  • 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 the files in the src/scheduler package and generate a class diagram using mermaid and a README in the markdown format.

Support

Need help? Create a ticket on our support page for assistance with any issues or questions.

CodeRabbit Commands (Invoked using PR/Issue comments)

Type @coderabbitai help to get the list of available commands.

Other keywords and placeholders

  • Add @coderabbitai ignore or @coderabbit 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

Status, Documentation and Community

  • Visit our Status Page to check the current availability of CodeRabbit.
  • 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.

codescene-delta-analysis[bot]

This comment was marked as outdated.

sourcery-ai[bot]

This comment was marked as resolved.

chatgpt-codex-connector[bot]

This comment was marked as resolved.

codescene-delta-analysis[bot]

This comment was marked as outdated.

@leynos
Copy link
Owner Author

leynos commented Aug 30, 2025

@coderabbitai Have the following now been resolved?

  • Add a test case for rate = MAX_PUSH_RATE to verify that the builder accepts the upper boundary as valid.
  • There’s a lot of repeated builder boilerplate in the tests—consider extracting a shared helper or fixture for default queue construction to reduce duplication.
  • Consider adding a convenience builder method like unlimited() that wraps .rate(None) to make the no-rate-limiting scenario more ergonomic.

This comment was marked as resolved.

codescene-delta-analysis[bot]

This comment was marked as outdated.

@leynos
Copy link
Owner Author

leynos commented Aug 30, 2025

@coderabbitai Please suggest a fix for this issue and supply a prompt for an AI coding agent to enable it to apply the fix:

Excess Number of Function Arguments
src/push/queues/mod.rs: PushQueues.build_with_rate_dlq

What lead to degradation?

PushQueues.build_with_rate_dlq has 6 arguments, threshold = 4
Why does this problem occur?

Functions with many arguments indicate either a) low cohesion where the function has too many responsibilities, or b) a missing abstraction that encapsulates those arguments.

The threshold for the Rust language is 4 function arguments.
How to fix it?

Start by investigating the responsibilities of the function. Make sure it doesn't do too many things, in which case it should be split into smaller and more cohesive functions. Consider the refactoring INTRODUCE PARAMETER OBJECT to encapsulate arguments that refer to the same logical concept.

@leynos
Copy link
Owner Author

leynos commented Aug 30, 2025

@coderabbitai review

Copy link
Contributor

coderabbitai bot commented Aug 30, 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.

This comment was marked as resolved.

Copy link

@coderabbitai review

Copy link
Contributor

coderabbitai bot commented Aug 30, 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

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

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (10)
tests/wireframe_protocol.rs (1)

66-79: Avoid explicit drop; ignore the unused binding in the pattern.

Destructure to _queues instead of calling drop.

-    let (queues, handle) = queues;
+    let (_queues, handle) = queues;
     hooks.on_connection_setup(handle, &mut ConnectionContext);
-    drop(queues); // silence unused warnings
tests/connection_actor.rs (2)

1-554: Split this test module; it exceeds the 400-line limit.

Extract fairness tests, shutdown/abort tests, and error propagation tests into separate files to meet the size guideline and improve focus.

I can draft a patch that introduces tests/connection_actor_fairness.rs, tests/connection_actor_shutdown.rs, and tests/connection_actor_errors.rs, moving the respective test groups and shared fixtures.


397-410: Deflake the blocking assertion.

The 50 ms timeout can be flaky under load. Increase the bound or switch to a non-blocking try_push_high_priority if available.

-    let blocked = timeout(Duration::from_millis(50), handle.push_high_priority(2)).await;
+    let blocked = timeout(Duration::from_millis(200), handle.push_high_priority(2)).await;
docs/hardening-wireframe-a-guide-to-production-resilience.md (2)

354-366: Downgrade DLQ loss log from error to warning.

Reflect the change to warning severity for DLQ loss events.

-                tracing::error!("Push queue and DLQ are both full. Frame lost.");
+                tracing::warn!("Push queue and DLQ are both full. Frame lost.");

Add a brief note that DLQ loss logging is throttled per handle.


336-341: Use Oxford -ize spelling in prose (“recognize”).

Keep documentation spelling consistent.

-This explicit marker lets clients recognise that the logical stream has ended and
+This explicit marker lets clients recognize that the logical stream has ended and
tests/push_policies.rs (1)

68-71: Eliminate flakiness from timing-based assertion

Avoid real-time timeouts in tests. Check queue emptiness without sleeping.

-assert!(
-    timeout(Duration::from_millis(20), queues.recv())
-        .await
-        .is_err()
-);
+assert!(queues.try_recv().is_err(), "queue should be empty");
tests/push.rs (3)

157-176: Fix deadlock: timeout with paused time never elapses

Using time::timeout under time::pause causes a hang; neither the timeout nor the rate-limited push completes. Assert pending without time instead, then advance virtual time to unblock.

@@
-    let attempt = match priority {
-        PushPriority::High => {
-            time::timeout(Duration::from_millis(10), handle.push_high_priority(2u8)).await
-        }
-        PushPriority::Low => {
-            time::timeout(Duration::from_millis(10), handle.push_low_priority(2u8)).await
-        }
-    };
-
-    assert!(attempt.is_err(), "second push should block");
+    use futures::FutureExt;
+    let fut = match priority {
+        PushPriority::High => handle.push_high_priority(2u8),
+        PushPriority::Low => handle.push_low_priority(2u8),
+    };
+    tokio::pin!(fut);
+    tokio::task::yield_now().await; // register w/ scheduler
+    assert!(
+        fut.as_mut().now_or_never().is_none(),
+        "second push should be pending under rate limit"
+    );

Add import near the top:

 use tokio::time::{self, Duration};
+use futures::FutureExt;

206-213: Fix deadlock: shared limiter test also uses timeout under paused time

Apply the same pending-assertion approach here.

-    let attempt = time::timeout(Duration::from_millis(10), handle.push_low_priority(2u8)).await;
-    assert!(attempt.is_err(), "second push should block across queues");
+    use futures::FutureExt;
+    let mut fut = handle.push_low_priority(2u8);
+    tokio::pin!(fut);
+    tokio::task::yield_now().await;
+    assert!(
+        fut.as_mut().now_or_never().is_none(),
+        "second push should be pending across queues"
+    );

258-263: Fix deadlock: burst-limit test uses timeout under paused time

Avoid timeout + paused time; assert pending then advance.

-    let res = time::timeout(Duration::from_millis(10), handle.push_high_priority(99)).await;
-    assert!(
-        res.is_err(),
-        "Push exceeding burst capacity should be rate limited"
-    );
+    use futures::FutureExt;
+    let mut fut = handle.push_high_priority(99);
+    tokio::pin!(fut);
+    tokio::task::yield_now().await;
+    assert!(
+        fut.as_mut().now_or_never().is_none(),
+        "push exceeding burst capacity should be pending"
+    );
docs/asynchronous-outbound-messaging-design.md (1)

19-19: Standardise on en-GB Oxford -ize spelling in docs

Adopt -ize uniformly per project style (retain -our). Fix mixed -ise/-ize usages.

- required extra synchronisation
+ required extra synchronization
- ### 3.1 Prioritised Message Queues
+ ### 3.1 Prioritized Message Queues
- The prioritised write loop
+ The prioritized write loop
- The flow diagram below summarises the fairness logic.
+ The flow diagram below summarizes the fairness logic.
- clean, organised, and extensible configuration API
+ clean, organized, and extensible configuration API

Also applies to: 63-66, 81-86, 158-162, 514-517

♻️ Duplicate comments (1)
src/push/queues/mod.rs (1)

77-84: Collapse long parameter list with a parameter object for DLQ logging.

Reduce argument count and improve cohesion by bundling DLQ logging knobs into a small struct. This also addresses the CodeScene warning on “Excess Number of Function Arguments.”

@@
+#[derive(Clone, Copy, Debug)]
+pub(super) struct DlqLogPolicy {
+    pub every_n: usize,
+    pub interval: Duration,
+}
@@
-        dlq_log_every_n: usize,
-        dlq_log_interval: Duration,
+        dlq_log: DlqLogPolicy,
     ) -> Result<(Self, PushHandle<F>), PushConfigError> {
@@
-            dlq_last_log: Mutex::new(
-                Instant::now()
-                    .checked_sub(dlq_log_interval)
-                    .unwrap_or_else(Instant::now),
-            ),
-            dlq_log_every_n,
-            dlq_log_interval,
+            dlq_last_log: Mutex::new(
+                Instant::now()
+                    .checked_sub(dlq_log.interval)
+                    .unwrap_or_else(Instant::now),
+            ),
+            dlq_log_every_n: dlq_log.every_n,
+            dlq_log_interval: dlq_log.interval,
         };
@@
-        Self::build_with_rate_dlq(
-            high_capacity,
-            low_capacity,
-            rate,
-            dlq,
-            100,
-            Duration::from_secs(10),
-        )
+        Self::build_with_rate_dlq(
+            high_capacity,
+            low_capacity,
+            rate,
+            dlq,
+            DlqLogPolicy { every_n: 100, interval: Duration::from_secs(10) },
+        )
AI coding-agent prompt:
Refactor src/push/queues/mod.rs to introduce `DlqLogPolicy` as shown in the diff and update all call sites. Then run `make lint` and `make test`. If other internal helpers call `build_with_rate_dlq`, update them similarly. Ensure docs mention the new parameter object only for internal use (deprecated constructors remain unchanged externally). 

Also applies to: 206-214, 113-120

📜 Review details

Configuration used: CodeRabbit UI

Review profile: ASSERTIVE

Plan: Pro

💡 Knowledge Base configuration:

  • Jira integration is disabled

You can enable these sources in your CodeRabbit configuration.

📥 Commits

Reviewing files that changed from the base of the PR and between 4bcade6 and b7f9fa2.

📒 Files selected for processing (27)
  • README.md (1 hunks)
  • docs/asynchronous-outbound-messaging-design.md (1 hunks)
  • docs/efficiency-report.md (3 hunks)
  • docs/hardening-wireframe-a-guide-to-production-resilience.md (1 hunks)
  • docs/multi-packet-and-streaming-responses-design.md (2 hunks)
  • src/connection.rs (2 hunks)
  • src/push.rs (0 hunks)
  • src/push/mod.rs (1 hunks)
  • src/push/queues/builder.rs (1 hunks)
  • src/push/queues/errors.rs (1 hunks)
  • src/push/queues/handle.rs (1 hunks)
  • src/push/queues/mod.rs (1 hunks)
  • src/response.rs (1 hunks)
  • src/session.rs (6 hunks)
  • tests/advanced/concurrency_loom.rs (1 hunks)
  • tests/advanced/interaction_fuzz.rs (1 hunks)
  • tests/async_stream.rs (1 hunks)
  • tests/connection_actor.rs (3 hunks)
  • tests/correlation_id.rs (1 hunks)
  • tests/push.rs (8 hunks)
  • tests/push_policies.rs (8 hunks)
  • tests/server.rs (1 hunks)
  • tests/session_registry.rs (1 hunks)
  • tests/stream_end.rs (3 hunks)
  • tests/support.rs (1 hunks)
  • tests/wireframe_protocol.rs (6 hunks)
  • tests/world.rs (3 hunks)
💤 Files with no reviewable changes (1)
  • src/push.rs
🧰 Additional context used
📓 Path-based instructions (2)
**/*.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.
  • Where code is only used by specific features, it must be conditionally compiled or a conditional expectation for unused_code applied.

  • 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.
  • Environment access (env::set_var and env::remove_var) are always unsafe in Rust 2024 and MUST be marked as such

    • For testing of functionality depending upon environment variables, dependency injection and the mockable crate are the preferred option.
    • If mockable cannot be used, env mutations in tests ...

Files:

  • tests/server.rs
  • src/response.rs
  • src/push/queues/errors.rs
  • src/session.rs
  • tests/world.rs
  • src/connection.rs
  • tests/support.rs
  • src/push/mod.rs
  • tests/advanced/concurrency_loom.rs
  • tests/wireframe_protocol.rs
  • tests/stream_end.rs
  • tests/async_stream.rs
  • tests/session_registry.rs
  • src/push/queues/handle.rs
  • tests/connection_actor.rs
  • tests/push_policies.rs
  • src/push/queues/builder.rs
  • tests/correlation_id.rs
  • tests/advanced/interaction_fuzz.rs
  • tests/push.rs
  • src/push/queues/mod.rs
**/*.md

⚙️ CodeRabbit configuration file

**/*.md: * Avoid 2nd person or 1st person pronouns ("I", "you", "we")

  • Use en-GB-oxendict (-ize / -our) spelling and grammar
  • Headings must not be wrapped.
  • Documents must start with a level 1 heading
  • Headings must correctly increase or decrease by no more than one level at a time
  • Use GitHub-flavoured Markdown style for footnotes and endnotes.
  • Numbered footnotes must be numbered by order of appearance in the document.

Files:

  • docs/multi-packet-and-streaming-responses-design.md
  • docs/asynchronous-outbound-messaging-design.md
  • README.md
  • docs/hardening-wireframe-a-guide-to-production-resilience.md
  • docs/efficiency-report.md
🪛 LanguageTool
docs/efficiency-report.md

[style] ~98-~98: Using four (or more) nouns in a row may decrease readability.
Context: ... Connection Handling - Bottleneck: Connection actor event loop and fairness tracking - **Critical Path...

(FOUR_NN)


[style] ~99-~99: Using four (or more) nouns in a row may decrease readability.
Context: ... Critical Path: tokio::select! in connection actor - Optimization Priority: Medium—affects per-connection perfor...

(FOUR_NN)

🔍 Remote MCP

Here are a few concrete details from the diff that merit attention during review:

• The core constructor function PushQueues::build_with_rate_dlq now takes six parameters—
(high_capacity: usize, low_capacity: usize, rate: Option<usize>, dlq: Option<Sender<F>>, dlq_log_every_n: usize, dlq_log_interval: Duration)
and the deprecated helpers (bounded_with_rate_dlq) call into it with two hard‐coded logging defaults (100, 10 s). This long parameter list suggests a refactor opportunity to bundle related settings into a PushQueueConfig struct rather than passing six separate args (github.com).

• The PushQueuesBuilder now offers a convenience method unlimited() that is simply shorthand for .rate(None), making it clearer when rate limiting is disabled (github.com).

• A dedicated shared fixture (tests/support.rs) now provides a builder() function returning a PushQueuesBuilder with unit capacities, avoiding repetition across tests (github.com).

• There is a new test builder_accepts_max_rate verifying that Some(MAX_PUSH_RATE) is accepted by the builder’s validation logic, closing the boundary‐case gap (github.com).

• The PushHandle send path has been tightened: after reserving capacity, the code now checks if permit.send(frame) returns a closed‐channel indicator and propagates Err(PushError::Closed) rather than silently dropping the frame (github.com).

🔇 Additional comments (14)
src/response.rs (1)

47-47: Standardize spelling to -ize; OK.

The docstring uses “optimized”, which matches the en-GB Oxford -ize style. No behavioural change.

docs/efficiency-report.md (1)

14-16: Optimisation verified: LengthPrefixedProcessor::decode uses src.split_to(len).freeze().to_vec() at line 75 in src/frame/processor.rs, matching the efficiency report.

tests/server.rs (1)

46-46: Replace unwrap with expect; OK.

The panic message improves failure diagnostics while preserving behaviour.

src/connection.rs (2)

101-106: Docs: switch to builder-based construction; OK.

Example reflects the new API and uses no_run appropriately.


132-145: Docs: update new() example to builder; OK.

Matches the public API and house style.

tests/async_stream.rs (1)

26-31: LGTM: builder migration is correct.

The builder initialisation and error handling read cleanly; the test semantics remain unchanged.

docs/hardening-wireframe-a-guide-to-production-resilience.md (1)

256-280: Fix ordering in example: reserve capacity before rate limiting.

The PR states “Reserve queue slots before rate limiting”. Update the snippet to match the implementation behaviour.

 async fn push(&self, frame: Frame) -> Result<(), PushError> {
-    // If a limiter is configured, wait for a token before queuing the frame.
-    if let Some(ref limiter) = self.limiter {
-        limiter.acquire(1).await;
-    }
-
-    self.tx.send(frame).await.map_err(|_| /*...*/)
+    // Reserve capacity before waiting on the limiter.
+    let permit = self.tx.reserve().await.map_err(|_| /*...*/)?;
+    if let Some(ref limiter) = self.limiter {
+        limiter.acquire(1).await;
+    }
+    permit.send(frame).map_err(|_| /*...*/)
 }
tests/push_policies.rs (1)

185-193: LGTM: DLQ warning assertion

The warning-level log assertion for DLQ failures matches the updated semantics.

tests/push.rs (1)

61-79: Keep: test correctly proves bursts succeed when unlimited

The burst test is sound and will not hang because pushes complete immediately with unlimited rate.

src/push/queues/handle.rs (2)

67-75: Propagate closed error after send attempt

Returned sender being closed implies the frame was not delivered. The check and error propagation look correct.

Add an async test that closes queues after reserving capacity but before send to ensure PushError::Closed is returned.


157-169: Fix compile error and division-by-zero in DLQ logging

is_multiple_of is not in scope and will not compile; modulo by a zero log_every_n would panic. Gate the count path and fall back to interval-based logging when n == 0.

-                    if dropped.is_multiple_of(log_every_n)
-                        || now.duration_since(*last) > log_interval
-                    {
+                    let by_count = log_every_n > 0 && dropped % log_every_n == 0;
+                    let by_interval = now.duration_since(*last) > log_interval;
+                    if by_count || by_interval {

Likely an incorrect or invalid review comment.

src/push/queues/builder.rs (1)

20-37: LGTM: Builder docs clearly state validation happens at build time

Docs align with guidelines and examples compile as no_run snippets.

docs/asynchronous-outbound-messaging-design.md (1)

356-365: LGTM: Public API diagrams match the builder-based surface

Diagrams and method lists reflect PushQueues::builder() and PushQueuesBuilder.

Also applies to: 368-373

src/push/queues/mod.rs (1)

97-107: LGTM: channel wiring and rate-limiter construction.

Channel setup and optional limiter initialisation look correct and side-effect free. Returning (PushQueues, PushHandle) via a shared inner is clean.

Also applies to: 121-128

codescene-delta-analysis[bot]

This comment was marked as outdated.

Copy link
Contributor

coderabbitai bot commented Aug 30, 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.

@leynos
Copy link
Owner Author

leynos commented Aug 30, 2025

@coderabbitai pause

coderabbitai[bot]

This comment was marked as resolved.

Copy link
Contributor

coderabbitai bot commented Aug 30, 2025

✅ Actions performed

Reviews paused.

codescene-delta-analysis[bot]

This comment was marked as outdated.

codescene-delta-analysis[bot]

This comment was marked as outdated.

codescene-delta-analysis[bot]

This comment was marked as outdated.

Repository owner deleted a comment from coderabbitai bot Aug 31, 2025
codescene-delta-analysis[bot]

This comment was marked as outdated.

codescene-delta-analysis[bot]

This comment was marked as outdated.

Repository owner deleted a comment from coderabbitai bot Aug 31, 2025
Repository owner deleted a comment from chatgpt-codex-connector bot Aug 31, 2025
Repository owner deleted a comment from chatgpt-codex-connector bot Aug 31, 2025
Repository owner deleted a comment from coderabbitai bot Aug 31, 2025
codescene-delta-analysis[bot]

This comment was marked as outdated.

@leynos leynos force-pushed the codex/introduce-pushqueuesbuilder-with-deprecation-225o2i branch from 6e0a0d8 to cc1a2c6 Compare August 31, 2025 19:16
codescene-delta-analysis[bot]

This comment was marked as outdated.

Payton McIntosh added 2 commits September 1, 2025 00:32
…Q logging

- Avoid reserving tokens for probe-only futures by replacing
   with non-blocking  loop plus short sleeps.
- Use  macros in push handle so  captures warnings.
- Log every DLQ drop by default to make tests deterministic.
- Update docs to describe configurable DLQ logging cadence.
…eplace tracing macros with log across server/app/connection.\n- Emit both log and tracing panic events to satisfy tests.\n- Add regression test to guard rate limiter token reservation.\n- Keep DLQ logging default verbose for test determinism.
@leynos leynos merged commit 3195dfb into main Aug 31, 2025
5 checks passed
@leynos leynos deleted the codex/introduce-pushqueuesbuilder-with-deprecation-225o2i branch August 31, 2025 23:48
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.

1 participant