diff --git a/docs/asynchronous-outbound-messaging-design.md b/docs/asynchronous-outbound-messaging-design.md index d2b53cfe..ccdcea9d 100644 --- a/docs/asynchronous-outbound-messaging-design.md +++ b/docs/asynchronous-outbound-messaging-design.md @@ -24,6 +24,8 @@ protocols. The implementation must satisfy the following core requirements: + + | ID | Requirement | | G1 | Any async task must be able to push frames to a live connection. | | G2 | Ordering-safety: Pushed frames must interleave correctly with normal request/response traffic and respect any per-message sequencing rules. | @@ -31,6 +33,8 @@ The implementation must satisfy the following core requirements: | G4 | Generic—independent of any particular protocol; usable by both servers and clients built on wireframe. | | G5 | Preserve the simple “return a reply” path for code that does not need pushes, ensuring backward compatibility and low friction for existing users. | + + ## 3. Core Architecture: The Connection Actor The foundation of this design is the **actor-per-connection** model, where each @@ -153,8 +157,8 @@ impl PushHandle { &self, frame: F, priority: PushPriority, - policy: PushPolicy -) -> Result<(), PushError>; + policy: PushPolicy, + ) -> Result<(), PushError>; } ``` @@ -182,41 +186,46 @@ classDiagram high_prio_tx: mpsc::Sender low_prio_tx: mpsc::Sender } - class PushHandle { + class PushHandle~F~ { +push_high_priority(frame: F): Result<(), PushError> +push_low_priority(frame: F): Result<(), PushError> +try_push(frame: F, priority: PushPriority, policy: PushPolicy): Result<(), PushError> } - class PushQueues { + class PushQueues~F~ { +high_priority_rx: mpsc::Receiver +low_priority_rx: mpsc::Receiver - +bounded(high_capacity: usize, low_capacity: usize): (PushQueues, PushHandle) + +bounded(high_capacity: usize, low_capacity: usize): (PushQueues~F~, PushHandle~F~) +recv(): Option<(PushPriority, F)> } - PushHandleInner <.. PushHandle : contains - PushQueues o-- PushHandle : bounded() + PushHandleInner <.. PushHandle~F~ : contains + PushQueues~F~ o-- PushHandle~F~ : bounded(high_capacity, low_capacity) PushHandle --> PushPriority PushHandle --> PushPolicy PushHandle --> PushError - PushQueues --> PushHandle - PushQueues --> FrameLike - PushHandle --> FrameLike ``` +The diagram uses `~F~` to represent the `` generic parameter because Mermaid +treats angle brackets as HTML. + ```mermaid flowchart TD Producer[Producer] - PushHandle[PushHandle] + Handle[PushHandle~F~] HighQueue[High Priority Queue] LowQueue[Low Priority Queue] Policy[PushPolicy] Error[PushError or Drop] - Producer -->|push_high_priority / push_low_priority / try_push| PushHandle - PushHandle -->|High| HighQueue - PushHandle -->|Low| LowQueue - PushHandle -->|If queue full| Policy + Producer -->|push_high_priority| Handle + Handle -->|priority: High| HighQueue + Producer -->|push_low_priority| Handle + Handle -->|priority: Low| LowQueue + + Producer -->|try_push| Policy + Policy -->|Queue available| Handle + Handle -->|priority: High| HighQueue + Handle -->|priority: Low| LowQueue Policy -->|ReturnErrorIfFull| Error Policy -->|DropIfFull| Error Policy -->|WarnAndDropIfFull| Error @@ -342,6 +351,8 @@ features of the 1.0 release. ## 7. Measurable Objectives & Success Criteria + + | Category | Objective | Success Metric | | API Correctness | The PushHandle, SessionRegistry, and WireframeProtocol trait are implemented exactly as specified in this document. | 100% of the public API surface is present and correctly typed. | | Functionality | Pushed frames are delivered reliably and in the correct order of priority. | A test with concurrent high-priority, low-priority, and streaming producers must show that all frames are delivered and that the final written sequence respects the strict priority order. | @@ -349,3 +360,5 @@ features of the 1.0 release. | Resilience | The SessionRegistry must not leak memory when connections are terminated. | A long-running test that creates and destroys thousands of connections must show no corresponding growth in the SessionRegistry's size or the process's overall memory footprint. | | Performance | The overhead of the push mechanism should be minimal for connections that do not use it. | A benchmark of a simple request-response workload with the push feature enabled (but unused) should show < 2% performance degradation compared to a build without the feature. | | Performance | The latency for a high-priority push under no contention should be negligible. | The time from push_high_priority().await returning to the frame being written to the socket buffer should be < 10µs. | + +