docs: convert standard diagrams from draw.io PNGs to inline Mermaid
Gitea renders mermaid inline, so the flow/state/hierarchy/DAG diagrams move to text-in-markdown: auto-layout (removes the manual overlap-prone draw.io step), diffable source, no committed binaries, and a dark-text theme so labels stay legible. Keep draw.io PNGs only for the two complex bespoke diagrams (logical architecture, env2 topology) where pixel control still wins. All 24 mermaid blocks validated by rendering.
This commit is contained in:
@@ -23,8 +23,39 @@ gRPC server-streaming is an established pattern for real-time tag value updates;
|
||||
|
||||
## Architecture
|
||||
|
||||

|
||||
<!-- source: diagrams/grpc-streams-architecture.drawio — edit, then re-export with export-drawio.sh -->
|
||||
```mermaid
|
||||
%%{init: {'theme':'base', 'themeVariables': {'textColor':'#111111','lineColor':'#555555','edgeLabelBackground':'#ffffff','fontSize':'15px'}}}%%
|
||||
flowchart TD
|
||||
subgraph CENTRAL["Central Cluster"]
|
||||
BT["DebugStreamBridgeActor"]
|
||||
GC["SiteStreamGrpcClient<br/>(per-site, on central)"]
|
||||
BB["DebugStreamBridgeActor"]
|
||||
SR(["SignalR Hub / Blazor UI"])
|
||||
end
|
||||
|
||||
subgraph SITE["Site Cluster"]
|
||||
IN["InstanceActor"]
|
||||
PB{"publishes<br/>AttributeValueChanged<br/>AlarmStateChanged"}
|
||||
GS["SiteStreamGrpcServer<br/>(Kestrel, on site)"]
|
||||
end
|
||||
|
||||
BT -.->|"SubscribeDebugView"| IN
|
||||
IN -.->|"DebugViewSnapshot"| BT
|
||||
IN --> PB
|
||||
PB --> GS
|
||||
GS -->|"gRPC stream (HTTP/2)"| GC
|
||||
GC --> BB
|
||||
BB --> SR
|
||||
|
||||
classDef start fill:#d5e8d4,stroke:#82b366,color:#111111;
|
||||
classDef proc fill:#dae8fc,stroke:#6c8ebf,color:#111111;
|
||||
classDef dec fill:#fff2cc,stroke:#d6b656,color:#111111;
|
||||
classDef warn fill:#ffe6cc,stroke:#d79b00,color:#111111;
|
||||
class BT,GC,BB proc
|
||||
class SR start
|
||||
class IN,GS warn
|
||||
class PB dec
|
||||
```
|
||||
|
||||
**Key separation**: ClusterClient handles subscribe/unsubscribe/snapshot (request-response). gRPC handles the ongoing value stream (server-streaming).
|
||||
|
||||
@@ -250,8 +281,23 @@ public override async Task SubscribeInstance(
|
||||
|
||||
`IServerStreamWriter<T>` is **not thread-safe**. Multiple Akka actors may publish events concurrently. The `Channel<SiteStreamEvent>` bridges these worlds:
|
||||
|
||||

|
||||
<!-- source: diagrams/grpc-channel-bridging.drawio — edit, then re-export with export-drawio.sh -->
|
||||
```mermaid
|
||||
%%{init: {'theme':'base', 'themeVariables': {'textColor':'#111111','lineColor':'#555555','edgeLabelBackground':'#ffffff','fontSize':'15px'}}}%%
|
||||
flowchart TD
|
||||
AKKA["Akka Actor Thread(s)"]
|
||||
CH(["Channel<SiteStreamEvent><br/><br/>BoundedChannelOptions(1000)<br/>FullMode = DropOldest"])
|
||||
GRPC["gRPC Response Stream"]
|
||||
|
||||
AKKA -->|"channel.Writer.TryWrite(evt)"| CH
|
||||
CH -->|"await responseStream.WriteAsync(evt)"| GRPC
|
||||
|
||||
classDef start fill:#d5e8d4,stroke:#82b366,color:#111111;
|
||||
classDef proc fill:#dae8fc,stroke:#6c8ebf,color:#111111;
|
||||
classDef warn fill:#ffe6cc,stroke:#d79b00,color:#111111;
|
||||
class AKKA warn
|
||||
class CH start
|
||||
class GRPC proc
|
||||
```
|
||||
|
||||
- **Bounded capacity** (1000): prevents unbounded memory growth if the gRPC client is slow
|
||||
- **DropOldest**: matches the existing `SiteStreamManager` overflow strategy
|
||||
@@ -401,8 +447,33 @@ private void HandleGrpcStreamError(Exception ex)
|
||||
|
||||
### Reconnection State Machine (DebugStreamBridgeActor)
|
||||
|
||||

|
||||
<!-- source: diagrams/grpc-reconnection-state-machine.drawio — edit, then re-export with export-drawio.sh -->
|
||||
```mermaid
|
||||
%%{init: {'theme':'base', 'themeVariables': {'textColor':'#111111','lineColor':'#555555','edgeLabelBackground':'#ffffff','fontSize':'15px'}}}%%
|
||||
flowchart TD
|
||||
S(["Streaming<br/><i>Normal state: gRPC stream active</i>"])
|
||||
R(["Reconnecting<br/><i>try other node endpoint</i>"])
|
||||
D{"reconnect result?"}
|
||||
RT["schedule retry<br/>(5s backoff)"]
|
||||
T(["Terminated<br/><i>notify consumer, stop actor</i>"])
|
||||
|
||||
S -->|"gRPC stream error / keepalive timeout"| R
|
||||
R --> D
|
||||
D -->|"success"| S
|
||||
D -->|"failure (retry < max)"| RT
|
||||
RT --> R
|
||||
D -->|"failure (retry >= max)"| T
|
||||
|
||||
classDef start fill:#d5e8d4,stroke:#82b366,color:#111111;
|
||||
classDef proc fill:#dae8fc,stroke:#6c8ebf,color:#111111;
|
||||
classDef dec fill:#fff2cc,stroke:#d6b656,color:#111111;
|
||||
classDef warn fill:#ffe6cc,stroke:#d79b00,color:#111111;
|
||||
classDef bad fill:#f8cecc,stroke:#b85450,color:#111111;
|
||||
class S start
|
||||
class R dec
|
||||
class D proc
|
||||
class RT warn
|
||||
class T bad
|
||||
```
|
||||
|
||||
### Summary
|
||||
|
||||
|
||||
Reference in New Issue
Block a user