diff --git a/docs/requirements/Component-StoreAndForward.md b/docs/requirements/Component-StoreAndForward.md index 4b6fa379..3396fa57 100644 --- a/docs/requirements/Component-StoreAndForward.md +++ b/docs/requirements/Component-StoreAndForward.md @@ -25,8 +25,28 @@ Site clusters only. The central cluster does not buffer messages. ## Message Lifecycle -![storeforward-message-lifecycle](diagrams/storeforward-message-lifecycle.png) - +```mermaid +flowchart TD + A([Script submits message]) --> B[Attempt immediate delivery] + B --> C{Delivered?} + C -->|Success| D([Remove from buffer]) + C -->|Failure| E[Buffer message] + E --> F[Retry loop
per retry policy] + F --> G{Retry outcome} + G -->|Success| H([Remove from buffer
+ notify standby]) + G -->|Max retries exhausted| I([Park message
dead-letter]) + + classDef ok fill:#d5e8d4,stroke:#82b366; + classDef proc fill:#dae8fc,stroke:#6c8ebf; + classDef dec fill:#fff2cc,stroke:#d6b656; + classDef buf fill:#ffe6cc,stroke:#d79b00; + classDef bad fill:#f8cecc,stroke:#b85450; + class A,D,H ok + class B,F proc + class C,G dec + class E buf + class I bad +``` For notifications, "delivery" means forwarding the message to the central cluster via Central–Site Communication; "success" is central's ack, on which the message is cleared. Notifications are retried at the fixed forward interval until central acks, but — like every other category — they are bounded by the engine's `DefaultMaxRetries` cap: a sustained central outage that exceeds `DefaultMaxRetries × forward-interval` will park the buffered notification, after which an operator can Retry/Discard it via the parked-message UI. Operationally, the cap is sized so the normal central-recovery window stays well inside it; "do not park" is the design's operational intent on the happy path, not an absolute invariant. Callers that genuinely require unbounded retry pass `maxRetries: 0` on `EnqueueAsync` (the documented "no limit" escape hatch — see `StoreAndForward-015`).