Conversation
Reviewer's GuideThis PR enhances the asynchronous-outbound-messaging design doc by standardizing the requirements table formatting and embedding a set of Mermaid diagrams (class and sequence) to illustrate the ConnectionActor architecture and its various push flows (client‐initiated, application tasks, WebSocket heartbeats, MQTT fan‐out). Sequence diagram for client-initiated push flowsequenceDiagram
participant Client
participant ConnectionActor
participant Queue as Outbox
participant Socket
Client->>ConnectionActor: Initiate connection/request
ConnectionActor->>Queue: enqueue outbound frame
Note over ConnectionActor,Queue: Manages high/low priority queues
ConnectionActor->>Socket: Write outbound frame (from queue)
Socket-->>Client: Delivers outbound message
Sequence diagram for application task push flowsequenceDiagram
participant AppTask as Application Task
participant SessionRegistry
participant ConnectionActor
participant Socket
AppTask->>SessionRegistry: get PushHandle for session
AppTask->>ConnectionActor: push(OK packet or LOCAL INFILE)
ConnectionActor->>ConnectionActor: queue frame in outbox
ConnectionActor->>Socket: write frame (when idle or after command completes)
Sequence diagram for WebSocket heart-beat push flowsequenceDiagram
participant Timer as Heart-beat Timer
participant ConnectionActor
participant Socket
Timer->>ConnectionActor: push_high_priority(Ping frame)
ConnectionActor->>ConnectionActor: enqueue Ping in high-priority queue
ConnectionActor->>Socket: write Ping frame (even during response stream)
Sequence diagram for MQTT broker fan-out push flowsequenceDiagram
participant Broker as MQTT Broker
participant SessionRegistry
participant ConnectionActor as Client ConnectionActor
participant Socket
Broker->>SessionRegistry: get PushHandle for subscriber
Broker->>ConnectionActor: try_push(PUBLISH frame)
alt Queue not full
ConnectionActor->>Socket: write PUBLISH frame
else Queue full
ConnectionActor->>ConnectionActor: drop frame
end
Class diagram for ConnectionActor, PushHandle, and SessionRegistryclassDiagram
class ConnectionActor {
- context: ConnectionContext
- high_priority_queue: mpsc::Receiver<Frame>
- low_priority_queue: mpsc::Receiver<Frame>
- response_stream: Stream<Response>
- shutdown_signal: CancellationToken
+ run()
+ handle_push()
+ handle_response()
}
class PushHandle {
+ push(frame: Frame)
+ try_push(frame: Frame)
+ push_with_policy(frame: Frame, policy: PushPolicy)
}
class SessionRegistry {
- sessions: DashMap<SessionId, Weak<ConnectionActor>>
+ register(session_id, actor)
+ get_handle(session_id): Option<PushHandle>
}
ConnectionActor o-- PushHandle : exposes
SessionRegistry o-- PushHandle : provides
PushHandle ..> ConnectionActor : queues frames
File-Level Changes
Tips and commandsInteracting with Sourcery
Customizing Your ExperienceAccess your dashboard to:
Getting Help
|
Summary by CodeRabbit
Summary by CodeRabbit
WalkthroughThis update enhances the documentation for asynchronous outbound messaging by standardising table formatting and adding multiple Mermaid diagrams. New sections introduce class and sequence diagrams for the connection actor architecture, as well as additional diagrams illustrating specific asynchronous push use cases for MySQL, WebSocket, and MQTT protocols. No code or API changes are included. Changes
Sequence Diagram(s)sequenceDiagram
participant Client
participant ConnectionActor
participant Socket
Client->>ConnectionActor: Initiate connection
ConnectionActor->>ConnectionActor: Enqueue outbound message
ConnectionActor->>Socket: Deliver frame
Socket-->>Client: Frame delivered
sequenceDiagram
participant AppTask
participant SessionRegistry
participant ConnectionActor
participant Socket
AppTask->>SessionRegistry: Request push (e.g. MySQL packet)
SessionRegistry->>ConnectionActor: Forward push
ConnectionActor->>Socket: Send outbound message
Socket-->>AppTask: Delivery acknowledgement
sequenceDiagram
participant Timer
participant ConnectionActor
participant Socket
Timer->>ConnectionActor: Trigger heart-beat ping
ConnectionActor->>Socket: Send ping frame
Socket-->>Timer: Ping delivered
sequenceDiagram
participant Broker
participant ConnectionActor
participant Socket
Broker->>ConnectionActor: Send MQTT PUBLISH frame
ConnectionActor->>Socket: Deliver frame
Socket-->>Broker: Confirm delivery or drop
Possibly related PRs
Poem
✨ Finishing Touches🧪 Generate Unit Tests
🪧 TipsChatThere are 3 ways to chat with CodeRabbit:
SupportNeed help? Create a ticket on our support page for assistance with any issues or questions. Note: Be mindful of the bot's finite context window. It's strongly recommended to break down tasks such as reading entire modules into smaller chunks. For a focused discussion, use review comments to chat about specific files and their changes, instead of using the PR comments. CodeRabbit Commands (Invoked using PR comments)
Other keywords and placeholders
CodeRabbit Configuration File (
|
There was a problem hiding this comment.
Actionable comments posted: 3
📜 Review details
Configuration used: CodeRabbit UI
Review profile: ASSERTIVE
Plan: Pro
📒 Files selected for processing (1)
docs/asynchronous-outbound-messaging-design.md(3 hunks)
⏰ Context from checks skipped due to timeout of 90000ms (1)
- GitHub Check: build-test
🔇 Additional comments (1)
docs/asynchronous-outbound-messaging-design.md (1)
40-46: Table header looks good – consistent and m-linter friendly.
Switching to a pipe-delimited header row aligns with Markdown conventions and satisfies most linters/parsers.
|
@coderabbitai review |
✅ Actions performedReview triggered.
|
There was a problem hiding this comment.
Actionable comments posted: 3
📜 Review details
Configuration used: CodeRabbit UI
Review profile: ASSERTIVE
Plan: Pro
📒 Files selected for processing (1)
docs/asynchronous-outbound-messaging-design.md(5 hunks)
🧰 Additional context used
🪛 LanguageTool
docs/asynchronous-outbound-messaging-design.md
[style] ~79-~79: Would you like to use the Oxford spelling “Prioritized”? The spelling ‘Prioritised’ is also correct.
Context: ...l space becomes available. ### 3.2 The Prioritised Write Loop The connection actor's writ...
(OXFORD_SPELLING_Z_NOT_S)
[grammar] ~81-~81: An apostrophe ‘s’ denotes possession. Did you mean to use the plural form of the noun (no apostrophe)?
Context: ... Prioritised Write Loop The connection actor's write logic will be implemented within ...
(NOUN_APOSTROPHE_S_VERB)
🔇 Additional comments (1)
docs/asynchronous-outbound-messaging-design.md (1)
40-46: Table re-alignment reads well
The new Markdown pipe syntax renders cleanly and the fixed width makes the requirements list far easier to scan. Nice touch.
|
@coderabbitai review |
|
@sourcery-ai review |
✅ Actions performedReview triggered.
|
There was a problem hiding this comment.
Actionable comments posted: 1
🔭 Outside diff range comments (2)
docs/asynchronous-outbound-messaging-design.md (2)
50-53: Undefined foot-note markers1and2remainNumbers
1and2read as superscript foot-notes but no matching definitions exist at the bottom of the document. Either convert them into normal prose (delete the markers) or add proper foot-note definitions to avoid the same confusion we previously fixed for8,16, etc.Example fix (delete the stray markers):
-...managed by a dedicated, isolated asynchronous task. ¹ This approach serialises all I/O for a given connection, eliminating the need for -complex locking and simplifying reasoning about concurrency. ² +...managed by a dedicated, isolated asynchronous task. This approach serialises all I/O for a given connection, eliminating the need for +complex locking and simplifying reasoning about concurrency.
100-104: Stray “Rust” heading disrupts Markdown flowThe standalone
Rustline sits between body text and the fenced code block without heading markup, rendering as plain paragraph text. Convert it to a proper heading or drop it.-Rust - -```rust +```rust
📜 Review details
Configuration used: CodeRabbit UI
Review profile: ASSERTIVE
Plan: Pro
📒 Files selected for processing (1)
docs/asynchronous-outbound-messaging-design.md(5 hunks)
🧰 Additional context used
🪛 LanguageTool
docs/asynchronous-outbound-messaging-design.md
[style] ~79-~79: Would you like to use the Oxford spelling “Prioritized”? The spelling ‘Prioritised’ is also correct.
Context: ...l space becomes available. ### 3.2 The Prioritised Write Loop The connection actor's writ...
(OXFORD_SPELLING_Z_NOT_S)
[grammar] ~81-~81: An apostrophe ‘s’ denotes possession. Did you mean to use the plural form of the noun (no apostrophe)?
Context: ... Prioritised Write Loop The connection actor's write logic will be implemented within ...
(NOUN_APOSTROPHE_S_VERB)
| - sessions: DashMap<SessionId, Weak<ConnectionActor>> | ||
| + register(session_id, actor) | ||
| + get_handle(session_id): Option<PushHandle> | ||
| } |
There was a problem hiding this comment.
🛠️ Refactor suggestion
Inconsistent identifier: SessionId vs ConnectionId
The class diagram shows SessionRegistry storing DashMap<SessionId, …>, whereas the Rust sample later implements SessionRegistry<F>(DashMap<ConnectionId, …>). Pick one term and use it consistently across both diagram and code to prevent readers from assuming two distinct concepts.
- class SessionRegistry {
- - sessions: DashMap<SessionId, Weak<ConnectionActor>>
+ class SessionRegistry {
+ - sessions: DashMap<ConnectionId, Weak<ConnectionActor>>and/or
-pub struct SessionRegistry<F>(DashMap<ConnectionId, Weak<PushHandleInner<F>>>);
+pub struct SessionRegistry<F>(DashMap<SessionId, Weak<PushHandleInner<F>>>);Also applies to: 302-306
🤖 Prompt for AI Agents
In docs/asynchronous-outbound-messaging-design.md around lines 156 to 159 and
also lines 302 to 306, the identifiers `SessionId` and `ConnectionId` are used
inconsistently between the class diagram and Rust sample code. Choose either
`SessionId` or `ConnectionId` and update all occurrences in both the diagram and
code snippets to use the same term consistently, ensuring readers do not confuse
them as different concepts.
|
@coderabbitai review |
✅ Actions performedReview triggered.
|
|
@coderabbitai review |
✅ Actions performedReview triggered.
|
There was a problem hiding this comment.
Actionable comments posted: 1
♻️ Duplicate comments (3)
docs/asynchronous-outbound-messaging-design.md (3)
165-174: Self-message still reads like a re-entrant call (previously flagged)
ConnectionActor ->> ConnectionActor: enqueue outbound framegives the impression of a recursive invocation rather than an internal queue operation. The earlier review suggested using anote overor a dedicatedQueueparticipant; the same guidance applies here.
436-444: Same self-message issue in WebSocket heart-beat diagram
ConnectionActor ->> ConnectionActor: enqueue Ping in high-priority queuerepeats the self-arrow pattern that was previously identified as potentially misleading.
452-464: Same self-message issue in MQTT fan-out diagram
ConnectionActor ->> ConnectionActor: drop frameagain uses a self-arrow. Replacing it with a note or explicitHighPriorityQueue / LowPriorityQueueparticipant would improve readability.
📜 Review details
Configuration used: CodeRabbit UI
Review profile: ASSERTIVE
Plan: Pro
📒 Files selected for processing (1)
docs/asynchronous-outbound-messaging-design.md(5 hunks)
🧰 Additional context used
🧠 Learnings (1)
docs/asynchronous-outbound-messaging-design.md (10)
Learnt from: CR
PR: leynos/wireframe#0
File: docs/asynchronous-outbound-messaging-design.md:0-0
Timestamp: 2025-06-24T16:40:33.344Z
Learning: In the wireframe Rust framework, asynchronous outbound messaging is implemented using a stateful actor-per-connection model, where each connection is managed by a dedicated async task that serializes all I/O for that connection. This eliminates the need for complex locking and simplifies concurrency.
Learnt from: CR
PR: leynos/wireframe#0
File: docs/asynchronous-outbound-messaging-design.md:0-0
Timestamp: 2025-06-24T16:40:33.344Z
Learning: Each connection actor manages two distinct, bounded tokio::mpsc channels for outbound frames: one for high-priority (urgent) messages and one for low-priority (background) messages. The bounded nature of these channels provides robust back-pressure, suspending writers when buffers are full.
Learnt from: CR
PR: leynos/wireframe#0
File: docs/asynchronous-outbound-messaging-design.md:0-0
Timestamp: 2025-06-24T16:40:33.344Z
Learning: The actor's write loop should use a tokio::select! loop with the biased keyword to enforce strict polling order: (1) shutdown signal, (2) high-priority push channel, (3) low-priority push channel, (4) handler response stream. This ensures critical messages are never starved by bulk data.
Learnt from: CR
PR: leynos/wireframe#0
File: docs/multi-packet-and-streaming-responses-design.md:0-0
Timestamp: 2025-06-24T16:41:50.533Z
Learning: The connection actor's prioritized write loop should always poll for urgent, out-of-band push messages before polling the response stream, ensuring that high-priority messages are not starved by long-running streams.
Learnt from: CR
PR: leynos/wireframe#0
File: docs/asynchronous-outbound-messaging-design.md:0-0
Timestamp: 2025-06-24T16:40:33.344Z
Learning: The prioritised write loop naturally interleaves pushed messages and streaming responses, ensuring urgent pushes can interrupt long-running streams, and operates at the logical frame level, with fragmentation handled transparently by lower layers.
Learnt from: CR
PR: leynos/wireframe#0
File: docs/multi-packet-and-streaming-responses-design.md:0-0
Timestamp: 2025-06-24T16:41:50.533Z
Learning: In Rust-based protocol frameworks (such as wireframe), handlers should return a declarative Response enum that supports single-frame, multi-frame (Vec), and streaming (Stream) responses, enabling both simple and complex reply patterns without changing the handler signature.
Learnt from: CR
PR: leynos/wireframe#0
File: docs/asynchronous-outbound-messaging-design.md:0-0
Timestamp: 2025-06-24T16:40:33.344Z
Learning: For critical messages that must not be dropped, the framework supports an optional Dead Letter Queue (DLQ): frames that would be dropped due to full queues can be redirected to a user-provided mpsc::Sender for inspection, logging, or retry.
Learnt from: CR
PR: leynos/wireframe#0
File: docs/observability-operability-and-maturity.md:0-0
Timestamp: 2025-06-24T16:41:59.381Z
Learning: Support optional Dead Letter Queues (DLQ) for resilient messaging: if the primary push queue is full, route frames to a DLQ instead of dropping them, ensuring no critical messages are lost if the DLQ consumer can keep up.
Learnt from: CR
PR: leynos/wireframe#0
File: docs/hardening-wireframe-a-guide-to-production-resilience.md:0-0
Timestamp: 2025-06-24T16:41:00.450Z
Learning: Support optional Dead Letter Queues (DLQ) in push mechanisms to guarantee message delivery under high load; route undeliverable messages to a DLQ for later inspection and reprocessing instead of dropping them.
Learnt from: CR
PR: leynos/wireframe#0
File: docs/multi-layered-testing-strategy.md:0-0
Timestamp: 2025-06-24T16:41:40.729Z
Learning: For high-volume message handling in wireframe, PushHandle must be able to push large numbers of frames (e.g., 10,000) without deadlocks or frame loss, and all frames must be received in order by the connection actor. Tests should complete within a tight time budget (e.g., <500ms on CI).
🪛 LanguageTool
docs/asynchronous-outbound-messaging-design.md
[style] ~52-~52: Would you like to use the Oxford spelling “serializes”? The spelling ‘serialises’ is also correct.
Context: ...olated asynchronous task. This approach serialises all I/O for a given connection, elimina...
(OXFORD_SPELLING_Z_NOT_S)
[style] ~79-~79: Would you like to use the Oxford spelling “Prioritized”? The spelling ‘Prioritised’ is also correct.
Context: ...l space becomes available. ### 3.2 The Prioritised Write Loop The connection actor's writ...
(OXFORD_SPELLING_Z_NOT_S)
[grammar] ~81-~81: An apostrophe ‘s’ denotes possession. Did you mean to use the plural form of the noun (no apostrophe)?
Context: ... Prioritised Write Loop The connection actor's write logic will be implemented within ...
(NOUN_APOSTROPHE_S_VERB)
🔇 Additional comments (1)
docs/asynchronous-outbound-messaging-design.md (1)
40-47: Table header re-alignment looks spot-onThe Markdown table now uses a canonical header row (
| --- |) which renders correctly across GitHub, mdBook and most PDF pipelines.
No further action required.
There was a problem hiding this comment.
Actionable comments posted: 2
♻️ Duplicate comments (1)
docs/asynchronous-outbound-messaging-design.md (1)
168-172: Self-arrow still risks misinterpretation – previous concern remainsThe
ConnectionActor ->> ConnectionActorline is rendered as a re-entrant call, not an internal queueing action. Replacing it with either anote overor an anonymous “Queue” participant would convey intent without confusion.
📜 Review details
Configuration used: CodeRabbit UI
Review profile: ASSERTIVE
Plan: Pro
📒 Files selected for processing (1)
docs/asynchronous-outbound-messaging-design.md(5 hunks)
🧰 Additional context used
📓 Path-based instructions (2)
`docs/**/*.md`: Use the markdown files within the `docs/` directory as a knowledge base and source of truth for project requirements, dependency choices, and architectural decision...
docs/**/*.md: Use the markdown files within thedocs/directory as a knowledge base and source of truth for project requirements, dependency choices, and architectural decisions.
Proactively update the relevant file(s) in thedocs/directory to reflect the latest state when new decisions are made, requirements change, libraries are added/removed, or architectural patterns evolve.
Documentation in thedocs/directory must use en-GB-oxendict spelling and grammar, except for the word 'license'.
docs/asynchronous-outbound-messaging-design.md
`**/*.md`: Validate Markdown files using `markdownlint *.md **/*.md`. Run `mdformat-all` after any documentation changes to format all Markdown files and fix table markup. Validate...
**/*.md: Validate Markdown files usingmarkdownlint *.md **/*.md.
Runmdformat-allafter any documentation changes to format all Markdown files and fix table markup.
Validate Markdown Mermaid diagrams using thenixieCLI by runningnixie *.md **/*.md.
Markdown paragraphs and bullet points must be wrapped at 80 columns.
Code blocks in Markdown files must be wrapped at 120 columns.
Tables and headings in Markdown files must not be wrapped.
docs/asynchronous-outbound-messaging-design.md
🧠 Learnings (1)
docs/asynchronous-outbound-messaging-design.md (14)
Learnt from: CR
PR: leynos/wireframe#0
File: docs/asynchronous-outbound-messaging-design.md:0-0
Timestamp: 2025-06-24T16:40:33.385Z
Learning: In the wireframe Rust framework, asynchronous outbound messaging is implemented using a stateful actor-per-connection model, where each connection is managed by a dedicated async task that serializes all I/O for that connection. This eliminates the need for complex locking and simplifies concurrency.
Learnt from: CR
PR: leynos/wireframe#0
File: docs/the-road-to-wireframe-1-0-feature-set-philosophy-and-capability-maturity.md:0-0
Timestamp: 2025-06-24T16:43:37.907Z
Learning: The actor-per-connection model is recommended for managing TCP connections in asynchronous Rust servers. Each connection is handled by a dedicated async task, serializing all I/O and simplifying resource management.
Learnt from: CR
PR: leynos/wireframe#0
File: docs/asynchronous-outbound-messaging-design.md:0-0
Timestamp: 2025-06-24T16:40:33.385Z
Learning: Each connection actor manages two distinct, bounded tokio::mpsc channels for outbound frames: one for high-priority (urgent) messages and one for low-priority (background) messages. The bounded nature of these channels provides robust back-pressure, suspending writers when buffers are full.
Learnt from: CR
PR: leynos/wireframe#0
File: docs/asynchronous-outbound-messaging-design.md:0-0
Timestamp: 2025-06-24T16:40:33.385Z
Learning: The actor's write loop should use a tokio::select! loop with the biased keyword to enforce strict polling order: (1) shutdown signal, (2) high-priority push channel, (3) low-priority push channel, (4) handler response stream. This ensures critical messages are never starved by bulk data.
Learnt from: CR
PR: leynos/wireframe#0
File: docs/wireframe-1-0-detailed-development-roadmap.md:0-0
Timestamp: 2025-06-24T16:43:46.789Z
Learning: When implementing a connection actor in Rust (e.g., for duplex communication), use a biased select! loop to prioritize shutdown signals, high/low priority pushes, and handler response streams in a strict order. This ensures predictable and robust processing of events.
Learnt from: CR
PR: leynos/wireframe#0
File: docs/the-road-to-wireframe-1-0-feature-set-philosophy-and-capability-maturity.md:0-0
Timestamp: 2025-06-24T16:43:37.907Z
Learning: When multiplexing multiple sources of outbound frames in a connection actor, use tokio::select!(biased;) to prioritize critical events such as graceful shutdown signals and high-priority push channels over standard handler responses. This ensures timely handling of control messages.
Learnt from: CR
PR: leynos/wireframe#0
File: docs/multi-packet-and-streaming-responses-design.md:0-0
Timestamp: 2025-06-24T16:41:50.561Z
Learning: The connection actor's prioritized write loop should always poll for urgent, out-of-band push messages before polling the response stream, ensuring that high-priority messages are not starved by long-running streams.
Learnt from: CR
PR: leynos/wireframe#0
File: docs/asynchronous-outbound-messaging-design.md:0-0
Timestamp: 2025-06-24T16:40:33.385Z
Learning: The prioritised write loop naturally interleaves pushed messages and streaming responses, ensuring urgent pushes can interrupt long-running streams, and operates at the logical frame level, with fragmentation handled transparently by lower layers.
Learnt from: CR
PR: leynos/wireframe#0
File: docs/multi-packet-and-streaming-responses-design.md:0-0
Timestamp: 2025-06-24T16:41:50.561Z
Learning: In Rust-based protocol frameworks (such as wireframe), handlers should return a declarative Response enum that supports single-frame, multi-frame (Vec), and streaming (Stream) responses, enabling both simple and complex reply patterns without changing the handler signature.
Learnt from: CR
PR: leynos/wireframe#0
File: docs/asynchronous-outbound-messaging-design.md:0-0
Timestamp: 2025-06-24T16:40:33.385Z
Learning: For critical messages that must not be dropped, the framework supports an optional Dead Letter Queue (DLQ): frames that would be dropped due to full queues can be redirected to a user-provided mpsc::Sender for inspection, logging, or retry.
Learnt from: CR
PR: leynos/wireframe#0
File: docs/observability-operability-and-maturity.md:0-0
Timestamp: 2025-06-24T16:41:59.419Z
Learning: Support optional Dead Letter Queues (DLQ) for resilient messaging: if the primary push queue is full, route frames to a DLQ instead of dropping them, ensuring no critical messages are lost if the DLQ consumer can keep up.
Learnt from: CR
PR: leynos/wireframe#0
File: docs/the-road-to-wireframe-1-0-feature-set-philosophy-and-capability-maturity.md:0-0
Timestamp: 2025-06-24T16:43:37.907Z
Learning: For reliability, implement an optional Dead Letter Queue (DLQ) pattern for push mechanisms. If a push fails due to a full queue, route the frame to a separate channel for later inspection or reprocessing.
Learnt from: CR
PR: leynos/wireframe#0
File: docs/hardening-wireframe-a-guide-to-production-resilience.md:0-0
Timestamp: 2025-06-24T16:41:00.477Z
Learning: Support optional Dead Letter Queues (DLQ) in push mechanisms to guarantee message delivery under high load; route undeliverable messages to a DLQ for later inspection and reprocessing instead of dropping them.
Learnt from: CR
PR: leynos/wireframe#0
File: docs/multi-layered-testing-strategy.md:0-0
Timestamp: 2025-06-24T16:41:40.768Z
Learning: For high-volume message handling in wireframe, PushHandle must be able to push large numbers of frames (e.g., 10,000) without deadlocks or frame loss, and all frames must be received in order by the connection actor. Tests should complete within a tight time budget (e.g., <500ms on CI).
🪛 LanguageTool
docs/asynchronous-outbound-messaging-design.md
[style] ~52-~52: Would you like to use the Oxford spelling “serializes”? The spelling ‘serialises’ is also correct.
Context: ...olated asynchronous task. This approach serialises all I/O for a given connection, elimina...
(OXFORD_SPELLING_Z_NOT_S)
[style] ~79-~79: Would you like to use the Oxford spelling “Prioritized”? The spelling ‘Prioritised’ is also correct.
Context: ...l space becomes available. ### 3.2 The Prioritised Write Loop The connection actor's writ...
(OXFORD_SPELLING_Z_NOT_S)
[grammar] ~81-~81: An apostrophe ‘s’ denotes possession. Did you mean to use the plural form of the noun (no apostrophe)?
Context: ... Prioritised Write Loop The connection actor's write logic will be implemented within ...
(NOUN_APOSTROPHE_S_VERB)
aa2d33e to
d4d3337
Compare
There was a problem hiding this comment.
Actionable comments posted: 5
♻️ Duplicate comments (1)
docs/asynchronous-outbound-messaging-design.md (1)
135-156: Unescaped closing ‘>’ still breaks Mermaid renderingThe second
>in theWeakgeneric is raw, so GitHub’s Mermaid parser drops everything after it.- - sessions: DashMap<ConnectionId, Weak<ConnectionActor>> + - sessions: DashMap<ConnectionId, Weak<ConnectionActor>>Escape all closing brackets when you expand this pattern elsewhere to avoid recurrent rendering regressions.
📜 Review details
Configuration used: CodeRabbit UI
Review profile: ASSERTIVE
Plan: Pro
📒 Files selected for processing (1)
docs/asynchronous-outbound-messaging-design.md(5 hunks)
🧰 Additional context used
📓 Path-based instructions (2)
`docs/**/*.md`: Use the markdown files within the `docs/` directory as a knowledge base and source of truth for project requirements, dependency choices, and architectural decision...
docs/**/*.md: Use the markdown files within thedocs/directory as a knowledge base and source of truth for project requirements, dependency choices, and architectural decisions.
Proactively update the relevant file(s) in thedocs/directory to reflect the latest state when new decisions are made, requirements change, libraries are added/removed, or architectural patterns evolve.
Documentation in thedocs/directory must use en-GB-oxendict spelling and grammar, except for the word 'license'.
docs/asynchronous-outbound-messaging-design.md
`**/*.md`: Validate Markdown files using `markdownlint *.md **/*.md`. Run `mdformat-all` after any documentation changes to format all Markdown files and fix table markup. Validate...
**/*.md: Validate Markdown files usingmarkdownlint *.md **/*.md.
Runmdformat-allafter any documentation changes to format all Markdown files and fix table markup.
Validate Markdown Mermaid diagrams using thenixieCLI by runningnixie *.md **/*.md.
Markdown paragraphs and bullet points must be wrapped at 80 columns.
Code blocks in Markdown files must be wrapped at 120 columns.
Tables and headings in Markdown files must not be wrapped.
docs/asynchronous-outbound-messaging-design.md
🧠 Learnings (1)
docs/asynchronous-outbound-messaging-design.md (13)
Learnt from: CR
PR: leynos/wireframe#0
File: docs/the-road-to-wireframe-1-0-feature-set-philosophy-and-capability-maturity.md:0-0
Timestamp: 2025-06-24T16:43:37.907Z
Learning: The actor-per-connection model is recommended for managing TCP connections in asynchronous Rust servers. Each connection is handled by a dedicated async task, serializing all I/O and simplifying resource management.
Learnt from: CR
PR: leynos/wireframe#0
File: docs/rust-binary-router-library-design.md:0-0
Timestamp: 2025-06-24T16:42:41.685Z
Learning: Automating connection lifecycle management (accepting connections, spawning per-connection tasks, handling disconnections) and abstracting away network boilerplate allows developers to focus on protocol logic rather than low-level networking details.
Learnt from: CR
PR: leynos/wireframe#0
File: docs/asynchronous-outbound-messaging-design.md:0-0
Timestamp: 2025-06-24T16:40:33.385Z
Learning: The actor's write loop should use a tokio::select! loop with the biased keyword to enforce strict polling order: (1) shutdown signal, (2) high-priority push channel, (3) low-priority push channel, (4) handler response stream. This ensures critical messages are never starved by bulk data.
Learnt from: CR
PR: leynos/wireframe#0
File: docs/wireframe-1-0-detailed-development-roadmap.md:0-0
Timestamp: 2025-06-24T16:43:46.789Z
Learning: When implementing a connection actor in Rust (e.g., for duplex communication), use a biased select! loop to prioritize shutdown signals, high/low priority pushes, and handler response streams in a strict order. This ensures predictable and robust processing of events.
Learnt from: CR
PR: leynos/wireframe#0
File: docs/asynchronous-outbound-messaging-design.md:0-0
Timestamp: 2025-06-24T16:40:33.385Z
Learning: Each connection actor manages two distinct, bounded tokio::mpsc channels for outbound frames: one for high-priority (urgent) messages and one for low-priority (background) messages. The bounded nature of these channels provides robust back-pressure, suspending writers when buffers are full.
Learnt from: CR
PR: leynos/wireframe#0
File: docs/the-road-to-wireframe-1-0-feature-set-philosophy-and-capability-maturity.md:0-0
Timestamp: 2025-06-24T16:43:37.907Z
Learning: When multiplexing multiple sources of outbound frames in a connection actor, use tokio::select!(biased;) to prioritize critical events such as graceful shutdown signals and high-priority push channels over standard handler responses. This ensures timely handling of control messages.
Learnt from: CR
PR: leynos/wireframe#0
File: docs/multi-packet-and-streaming-responses-design.md:0-0
Timestamp: 2025-06-24T16:41:50.561Z
Learning: The connection actor's prioritized write loop should always poll for urgent, out-of-band push messages before polling the response stream, ensuring that high-priority messages are not starved by long-running streams.
Learnt from: CR
PR: leynos/wireframe#0
File: docs/asynchronous-outbound-messaging-design.md:0-0
Timestamp: 2025-06-24T16:40:33.385Z
Learning: The prioritised write loop naturally interleaves pushed messages and streaming responses, ensuring urgent pushes can interrupt long-running streams, and operates at the logical frame level, with fragmentation handled transparently by lower layers.
Learnt from: CR
PR: leynos/wireframe#0
File: docs/multi-packet-and-streaming-responses-design.md:0-0
Timestamp: 2025-06-24T16:41:50.561Z
Learning: In Rust-based protocol frameworks (such as wireframe), handlers should return a declarative Response enum that supports single-frame, multi-frame (Vec), and streaming (Stream) responses, enabling both simple and complex reply patterns without changing the handler signature.
Learnt from: CR
PR: leynos/wireframe#0
File: docs/asynchronous-outbound-messaging-design.md:0-0
Timestamp: 2025-06-24T16:40:33.385Z
Learning: For critical messages that must not be dropped, the framework supports an optional Dead Letter Queue (DLQ): frames that would be dropped due to full queues can be redirected to a user-provided mpsc::Sender for inspection, logging, or retry.
Learnt from: CR
PR: leynos/wireframe#0
File: docs/observability-operability-and-maturity.md:0-0
Timestamp: 2025-06-24T16:41:59.419Z
Learning: Support optional Dead Letter Queues (DLQ) for resilient messaging: if the primary push queue is full, route frames to a DLQ instead of dropping them, ensuring no critical messages are lost if the DLQ consumer can keep up.
Learnt from: CR
PR: leynos/wireframe#0
File: docs/the-road-to-wireframe-1-0-feature-set-philosophy-and-capability-maturity.md:0-0
Timestamp: 2025-06-24T16:43:37.907Z
Learning: For reliability, implement an optional Dead Letter Queue (DLQ) pattern for push mechanisms. If a push fails due to a full queue, route the frame to a separate channel for later inspection or reprocessing.
Learnt from: CR
PR: leynos/wireframe#0
File: docs/hardening-wireframe-a-guide-to-production-resilience.md:0-0
Timestamp: 2025-06-24T16:41:00.477Z
Learning: Support optional Dead Letter Queues (DLQ) in push mechanisms to guarantee message delivery under high load; route undeliverable messages to a DLQ for later inspection and reprocessing instead of dropping them.
🪛 LanguageTool
docs/asynchronous-outbound-messaging-design.md
[style] ~53-~53: Would you like to use the Oxford spelling “serializes”? The spelling ‘serialises’ is also correct.
Context: ...olated asynchronous task. This approach serialises all I/O for a given connection, elimina...
(OXFORD_SPELLING_Z_NOT_S)
[style] ~80-~80: Would you like to use the Oxford spelling “Prioritized”? The spelling ‘Prioritised’ is also correct.
Context: ...l space becomes available. ### 3.2 The Prioritised Write Loop The connection actor's writ...
(OXFORD_SPELLING_Z_NOT_S)
[grammar] ~82-~82: An apostrophe ‘s’ denotes possession. Did you mean to use the plural form of the noun (no apostrophe)?
Context: ... Prioritised Write Loop The connection actor's write logic will be implemented within ...
(NOUN_APOSTROPHE_S_VERB)
⏰ Context from checks skipped due to timeout of 90000ms (1)
- GitHub Check: build-test
| ```mermaid | ||
| sequenceDiagram | ||
| participant Timer as Heart-beat Timer | ||
| participant ConnectionActor | ||
| participant Socket | ||
| Timer->>ConnectionActor: push_high_priority(Ping frame) | ||
| ConnectionActor->>ConnectionActor: enqueue Ping in high-priority queue | ||
| ConnectionActor->>Socket: write Ping frame (even during response stream) | ||
| ``` |
There was a problem hiding this comment.
🧹 Nitpick (assertive)
Self-arrow ambiguity in WebSocket heart-beat diagram
Replace the self-message with a note or explicit queue participant to mirror the queued-write reality.
🤖 Prompt for AI Agents
In docs/asynchronous-outbound-messaging-design.md around lines 436 to 444, the
sequence diagram uses a self-arrow on ConnectionActor to represent enqueueing a
Ping, which is ambiguous. Replace this self-message with either a note
explaining the enqueue action or introduce an explicit queue participant in the
diagram to clearly show the Ping being added to the high-priority queue,
reflecting the actual queued-write process.
| ```mermaid | ||
| sequenceDiagram | ||
| participant AppTask as Application Task | ||
| participant SessionRegistry | ||
| participant ConnectionActor | ||
| participant Socket | ||
| AppTask->>SessionRegistry: get PushHandle for session | ||
| AppTask->>ConnectionActor: push(OK packet or LOCAL INFILE) | ||
| ConnectionActor->>ConnectionActor: queue frame in outbox | ||
| ConnectionActor->>Socket: write frame (when idle or after command completes) | ||
| ``` |
There was a problem hiding this comment.
🧹 Nitpick (assertive)
Same self-arrow ambiguity in MySQL push diagram
Reuse the clearer pattern suggested above to keep diagrams stylistically consistent and unambiguous.
🤖 Prompt for AI Agents
In docs/asynchronous-outbound-messaging-design.md around lines 418 to 428, the
self-arrow used in the sequence diagram for ConnectionActor is ambiguous.
Replace the self-arrow with a clearer pattern consistent with earlier diagrams,
such as using a note or a different arrow style, to improve readability and
maintain stylistic consistency.
| ```mermaid | ||
| sequenceDiagram | ||
| participant Client | ||
| participant ConnectionActor | ||
| participant Socket | ||
|
|
||
| Client->>ConnectionActor: Initiate connection/request | ||
| Note over ConnectionActor: Manages high/low priority queues | ||
| ConnectionActor->>ConnectionActor: enqueue outbound frame | ||
| ConnectionActor->>Socket: Write outbound frame | ||
| Socket-->>Client: Delivers outbound message | ||
| ``` |
There was a problem hiding this comment.
🧹 Nitpick (assertive)
Self-message arrow is visually ambiguous
ConnectionActor ->> ConnectionActor suggests a re-entrant call rather than an internal queue operation.
A note over or a dedicated Queue participant keeps the intent crystal-clear.
Example:
sequenceDiagram
participant Client
participant ConnectionActor
participant Queue as Outbox
participant Socket
Client->>ConnectionActor: Initiate connection/request
ConnectionActor->>Queue: enqueue outbound frame
Queue-->>ConnectionActor: dequeued frame
ConnectionActor->>Socket: Write outbound frame
Socket-->>Client: Deliver message
🤖 Prompt for AI Agents
In docs/asynchronous-outbound-messaging-design.md around lines 163 to 174, the
self-message arrow from ConnectionActor to itself is visually ambiguous and can
be mistaken for a re-entrant call. To clarify the intent of an internal queue
operation, refactor the diagram by introducing a dedicated Queue participant
(e.g., named Outbox). Replace the self-message with messages from
ConnectionActor to Queue for enqueueing and from Queue back to ConnectionActor
for dequeuing, and add a note if needed to explain the queue's role.
| ```mermaid | ||
| sequenceDiagram | ||
| participant Broker as MQTT Broker | ||
| participant SessionRegistry | ||
| participant ConnectionActor as Client ConnectionActor | ||
| participant Socket | ||
| Broker->>SessionRegistry: get PushHandle for subscriber | ||
| Broker->>ConnectionActor: try_push(PUBLISH frame) | ||
| alt Queue not full | ||
| ConnectionActor->>Socket: write PUBLISH frame | ||
| else Queue full | ||
| ConnectionActor->>ConnectionActor: drop frame | ||
| end | ||
| ``` |
There was a problem hiding this comment.
🧹 Nitpick (assertive)
Self-arrow ambiguity in MQTT fan-out diagram
For consistency and clarity across all diagrams, avoid self-messages that look like recursion; model the internal queue explicitly or annotate with a note over block.
🤖 Prompt for AI Agents
In docs/asynchronous-outbound-messaging-design.md around lines 452 to 465, the
sequence diagram uses a self-arrow on ConnectionActor to represent dropping a
frame, which can be confused with recursion. Replace this self-message with an
explicit representation of the internal queue or add a 'note over' annotation to
clarify that this action models dropping a frame due to a full queue, improving
diagram clarity and consistency.
| network connection is managed by a dedicated, isolated asynchronous task. This | ||
| approach serialises all I/O for a given connection, eliminating the need for | ||
| complex locking and simplifying reasoning about concurrency. 2 | ||
| complex locking and simplifying reasoning about concurrency. |
There was a problem hiding this comment.
🧹 Nitpick (assertive)
Use Oxford –ize spelling (“serialises” → “serializes”)
Project docs mandate en-GB-oxendict spelling, which prefers the -ize form.
Update the verb accordingly to stay consistent with the style guide.
-approach serialises all I/O for a given connection, eliminating the need for
+approach serializes all I/O for a given connection, eliminating the need for📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
| network connection is managed by a dedicated, isolated asynchronous task. This | |
| approach serialises all I/O for a given connection, eliminating the need for | |
| complex locking and simplifying reasoning about concurrency. 2 | |
| complex locking and simplifying reasoning about concurrency. | |
| network connection is managed by a dedicated, isolated asynchronous task. This | |
| approach serializes all I/O for a given connection, eliminating the need for | |
| complex locking and simplifying reasoning about concurrency. |
🧰 Tools
🪛 LanguageTool
[style] ~53-~53: Would you like to use the Oxford spelling “serializes”? The spelling ‘serialises’ is also correct.
Context: ...olated asynchronous task. This approach serialises all I/O for a given connection, elimina...
(OXFORD_SPELLING_Z_NOT_S)
🤖 Prompt for AI Agents
In docs/asynchronous-outbound-messaging-design.md around lines 52 to 54, the
word "serialises" uses en-GB spelling but the project style guide requires
Oxford –ize spelling. Change "serialises" to "serializes" to maintain
consistency with the mandated en-GB-oxendict style.
Summary
Testing
make fmtmake lintmake testmarkdownlint docs/asynchronous-outbound-messaging-design.mdnixie docs/asynchronous-outbound-messaging-design.mdhttps://chatgpt.com/codex/tasks/task_e_685a9d7fdaac83229e958179f181f055
Summary by Sourcery
Add visual diagrams and formatting refinements to the asynchronous outbound messaging design document to clarify the connection actor architecture, push-queue processing, WebSocket heart-beats, and MQTT fan-out behavior.
Enhancements:
Documentation: