docs: render architecture & flow diagrams as draw.io charts
Replace ASCII-art diagrams across the README and docs/ with editable .drawio sources plus exported PNGs, so the diagrams render clearly in rendered markdown and can be maintained/regenerated instead of being hand-edited as fragile text art. Non-diagram blocks (code, folder trees, UI wireframes) were left as text.
@@ -167,20 +167,8 @@ Keepalive settings are configurable via `CommunicationOptions`:
|
||||
|
||||
## Topology
|
||||
|
||||
```
|
||||
Central Cluster
|
||||
├── ClusterClient → Site A Cluster (SiteCommunicationActor via Receptionist) [command/control]
|
||||
├── ClusterClient → Site B Cluster (SiteCommunicationActor via Receptionist) [command/control]
|
||||
└── ClusterClient → Site N Cluster (SiteCommunicationActor via Receptionist) [command/control]
|
||||
│
|
||||
├── SiteStreamGrpcClient ◄── gRPC stream ── Site A (SiteStreamGrpcServer) [real-time data]
|
||||
├── SiteStreamGrpcClient ◄── gRPC stream ── Site B (SiteStreamGrpcServer) [real-time data]
|
||||
└── SiteStreamGrpcClient ◄── gRPC stream ── Site N (SiteStreamGrpcServer) [real-time data]
|
||||
|
||||
Site Clusters
|
||||
└── ClusterClient → Central Cluster (CentralCommunicationActor via Receptionist) [command/control]
|
||||
└── SiteStreamGrpcServer (Kestrel HTTP/2, port 8083) → serves gRPC streams [real-time data]
|
||||
```
|
||||

|
||||
<!-- source: diagrams/communication-topology.drawio — edit, then re-export with export-drawio.sh -->
|
||||
|
||||
- Sites do **not** communicate with each other.
|
||||
- All inter-cluster communication flows through central.
|
||||
|
||||
@@ -143,15 +143,8 @@ EF Core's DbContext naturally provides unit-of-work semantics:
|
||||
|
||||
### Example Transactional Flow
|
||||
|
||||
```
|
||||
Template Engine: Create Template
|
||||
│
|
||||
├── repository.AddTemplate(template) // template is a Commons POCO
|
||||
├── repository.AddAttributes(attributes) // attributes are Commons POCOs
|
||||
├── repository.AddAlarms(alarms) // alarms are Commons POCOs
|
||||
├── repository.AddScripts(scripts) // scripts are Commons POCOs
|
||||
└── repository.SaveChangesAsync() // single transaction commits all
|
||||
```
|
||||

|
||||
<!-- source: diagrams/configdb-transactional-flow.drawio — edit, then re-export with export-drawio.sh -->
|
||||
|
||||
---
|
||||
|
||||
@@ -184,14 +177,8 @@ Audit entries are written **synchronously** within the same database transaction
|
||||
|
||||
### Integration Example
|
||||
|
||||
```
|
||||
Template Engine: Update Template
|
||||
│
|
||||
├── repository.UpdateTemplate(template)
|
||||
├── auditService.LogAsync(user, "Update", "Template", template.Id,
|
||||
│ template.Name, template)
|
||||
└── repository.SaveChangesAsync() ← both the change and audit entry commit together
|
||||
```
|
||||

|
||||
<!-- source: diagrams/configdb-integration-example.drawio — edit, then re-export with export-drawio.sh -->
|
||||
|
||||
### Audit Entry Schema
|
||||
|
||||
|
||||
@@ -80,12 +80,8 @@ Data connections support an optional backup endpoint for automatic failover when
|
||||
|
||||
**Failover state machine:**
|
||||
|
||||
```
|
||||
Connected → disconnect → push bad quality → retry active endpoint (5s)
|
||||
→ N failures (≥ FailoverRetryCount) → switch to other endpoint
|
||||
→ dispose adapter, create fresh adapter with other config
|
||||
→ reconnect → ReSubscribeAll → Connected
|
||||
```
|
||||

|
||||
<!-- source: diagrams/dcl-endpoint-redundancy.drawio — edit, then re-export with export-drawio.sh -->
|
||||
|
||||
- **Round-robin**: primary → backup → primary → backup. No preferred endpoint after first failover — the connection stays on whichever endpoint is working.
|
||||
- **No auto-failback**: The connection remains on the active endpoint until it fails.
|
||||
|
||||
@@ -22,24 +22,8 @@ Central cluster only. The site-side deployment responsibilities (receiving confi
|
||||
|
||||
## Deployment Flow
|
||||
|
||||
```
|
||||
Engineer (UI) → Deployment Manager (Central)
|
||||
│
|
||||
├── 1. Request validated + flattened config from Template Engine
|
||||
│ (validation includes flattening, script compilation,
|
||||
│ trigger references, connection binding completeness)
|
||||
├── 2. If validation fails → return errors to UI, stop
|
||||
├── 3. Send config to site via Communication Layer
|
||||
│ │
|
||||
│ ▼
|
||||
│ Site Runtime (Deployment Manager Singleton)
|
||||
│ ├── 4. Store new flattened config locally (SQLite)
|
||||
│ ├── 5. Compile scripts at site
|
||||
│ ├── 6. Create/update Instance Actor (with child Script + Alarm Actors)
|
||||
│ └── 7. Report success/failure back to central
|
||||
│
|
||||
└── 8. Update deployment status in config DB
|
||||
```
|
||||

|
||||
<!-- source: diagrams/deployment-flow.drawio — edit, then re-export with export-drawio.sh -->
|
||||
|
||||
## Deployment Identity & Idempotency
|
||||
|
||||
|
||||
@@ -123,20 +123,8 @@ API method scripts are compiled at central startup — all method definitions ar
|
||||
|
||||
## Request Flow
|
||||
|
||||
```
|
||||
External System
|
||||
│
|
||||
▼
|
||||
Inbound API (Central)
|
||||
├── 1. Extract API key from request
|
||||
├── 2. Validate key exists and is enabled
|
||||
├── 3. Resolve method by name
|
||||
├── 4. Check API key is in method's approved list
|
||||
├── 5. Validate and deserialize parameters
|
||||
├── 6. Execute implementation script (subject to method timeout)
|
||||
├── 7. Serialize return value
|
||||
└── 8. Return response
|
||||
```
|
||||

|
||||
<!-- source: diagrams/inboundapi-request-flow.drawio — edit, then re-export with export-drawio.sh -->
|
||||
|
||||
## Implementation Script Capabilities
|
||||
|
||||
|
||||
@@ -24,24 +24,8 @@ SMTP and HTTP delivery is blocking I/O. Delivery work runs on a **dedicated bloc
|
||||
|
||||
## End-to-End Flow
|
||||
|
||||
```
|
||||
Site script: Notify.To("list").Send(subject, body)
|
||||
│ generate NotificationId (GUID) locally; return it to the script immediately
|
||||
▼
|
||||
Site Store-and-Forward Engine (notification category, target = central)
|
||||
│ durably forwards to central via Central–Site Communication (ClusterClient);
|
||||
│ buffers/retries if central is unreachable
|
||||
▼
|
||||
Central ingest: insert-if-not-exists on NotificationId → Notifications table (Pending)
|
||||
│ ack the site → site S&F clears the message
|
||||
▼
|
||||
Central Notification Outbox actor (singleton, active central node)
|
||||
│ polls due rows; resolves the list; delivers via the matching adapter
|
||||
├── success → Delivered
|
||||
├── transient failure → Retrying (schedule NextAttemptAt)
|
||||
└── permanent failure
|
||||
/ retries exhausted → Parked
|
||||
```
|
||||

|
||||
<!-- source: diagrams/notificationoutbox-flow.drawio — edit, then re-export with export-drawio.sh -->
|
||||
|
||||
The site forwards only `(listName, subject, body)` plus provenance — recipient resolution happens at central, at delivery time. This keeps notification-list definitions in one place and removes the deploy-to-sites artifact entirely.
|
||||
|
||||
|
||||
@@ -27,21 +27,8 @@ Site clusters only.
|
||||
|
||||
## Actor Hierarchy
|
||||
|
||||
```
|
||||
Deployment Manager Singleton (Cluster Singleton)
|
||||
├── Instance Actor ("MachineA-001")
|
||||
│ ├── Script Actor ("MonitorSpeed") — coordinator
|
||||
│ │ └── Script Execution Actor — short-lived, per invocation
|
||||
│ ├── Script Actor ("CalculateOEE") — coordinator
|
||||
│ │ └── Script Execution Actor — short-lived, per invocation
|
||||
│ ├── Alarm Actor ("OverTemp") — coordinator (computed)
|
||||
│ │ └── Alarm Execution Actor — short-lived, per on-trigger invocation
|
||||
│ ├── Alarm Actor ("LowPressure") — coordinator (computed)
|
||||
│ └── Native Alarm Actor ("OpcUaServer1") — read-only mirror, peer to Alarm Actor
|
||||
├── Instance Actor ("MachineA-002")
|
||||
│ └── ...
|
||||
└── ...
|
||||
```
|
||||

|
||||
<!-- source: diagrams/siteruntime-actor-hierarchy.drawio — edit, then re-export with export-drawio.sh -->
|
||||
|
||||
---
|
||||
|
||||
|
||||
@@ -25,23 +25,8 @@ Site clusters only. The central cluster does not buffer messages.
|
||||
|
||||
## Message Lifecycle
|
||||
|
||||
```
|
||||
Script submits message
|
||||
│
|
||||
▼
|
||||
Attempt immediate delivery
|
||||
│
|
||||
├── Success → Remove from buffer
|
||||
│
|
||||
└── Failure → Buffer message
|
||||
│
|
||||
▼
|
||||
Retry loop (per retry policy)
|
||||
│
|
||||
├── Success → Remove from buffer + notify standby
|
||||
│
|
||||
└── Max retries exhausted → Park message
|
||||
```
|
||||

|
||||
<!-- source: diagrams/storeforward-message-lifecycle.drawio — edit, then re-export with export-drawio.sh -->
|
||||
|
||||
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`).
|
||||
|
||||
|
||||
@@ -92,20 +92,8 @@ The manifest is plaintext so the import wizard can preview bundle contents and s
|
||||
|
||||
## Architecture
|
||||
|
||||
```
|
||||
ZB.MOM.WW.ScadaBridge.Transport
|
||||
├── IBundleExporter
|
||||
│ ExportAsync(ExportSelection, Passphrase?, ct) → Stream
|
||||
├── IBundleImporter
|
||||
│ LoadAsync(stream, Passphrase?, ct) → BundleSession
|
||||
│ PreviewAsync(sessionId, ct) → ImportPreview
|
||||
│ ApplyAsync(sessionId, resolutions, ct) → ImportResult
|
||||
├── DependencyResolver
|
||||
├── BundleSerializer (manifest + content JSON; ZIP packer)
|
||||
├── BundleSecretEncryptor (AES-256-GCM + PBKDF2)
|
||||
├── BundleSessionStore (in-memory, TTL'd)
|
||||
└── ManifestValidator (schema/version gating, hash check)
|
||||
```
|
||||

|
||||
<!-- source: diagrams/transport-architecture.drawio — edit, then re-export with export-drawio.sh -->
|
||||
|
||||
The component is central-only. It is registered in `ZB.MOM.WW.ScadaBridge.Host` for central roles only, never for site roles. All persistence flows through existing audited repository interfaces in `ZB.MOM.WW.ScadaBridge.ConfigurationDatabase` — the component does not call `DbContext.SaveChangesAsync` directly. `BundleSessionStore` is in-process on the active central node (matching Blazor Server circuit affinity): 30-minute TTL, eviction on expiry, 3-strike passphrase lockout per session.
|
||||
|
||||
@@ -132,22 +120,8 @@ The user can toggle "include all dependencies" off (with a warning that the bund
|
||||
|
||||
### Backend
|
||||
|
||||
```
|
||||
User (Design role) ─► Central UI Export wizard
|
||||
│
|
||||
▼
|
||||
IBundleExporter
|
||||
│
|
||||
├─► DependencyResolver ─► repositories (read)
|
||||
├─► EntitySerializer ─► content.json
|
||||
├─► BundleSecretEncryptor ► content.enc (if passphrase)
|
||||
├─► ManifestBuilder ─► manifest.json
|
||||
▼
|
||||
ZIP packer → temp file → browser download
|
||||
│
|
||||
▼
|
||||
IAuditService.LogAsync(BundleExported …)
|
||||
```
|
||||

|
||||
<!-- source: diagrams/transport-export-flow.drawio — edit, then re-export with export-drawio.sh -->
|
||||
|
||||
Audit event: `BundleExported` — caller, artifact count, content hash, encrypted yes/no, bundle filename.
|
||||
|
||||
@@ -179,35 +153,8 @@ Bundle references that cannot be satisfied in either the bundle or the target DB
|
||||
|
||||
### Backend
|
||||
|
||||
```
|
||||
User (Admin role) ─► uploads bundle
|
||||
│
|
||||
▼
|
||||
IBundleImporter.LoadAsync
|
||||
· verify SHA-256 (manifest vs content)
|
||||
· check bundleFormatVersion supported
|
||||
· decrypt content.enc with passphrase (if encrypted)
|
||||
· deserialize entities
|
||||
· open BundleSession (30-min TTL)
|
||||
│
|
||||
▼
|
||||
PreviewAsync → diff vs target DB → ImportPreview
|
||||
│
|
||||
▼ (user reviews + resolves conflicts)
|
||||
│
|
||||
ApplyAsync (single EF transaction)
|
||||
· run two-tier semantic validation (minimal name scan + full SemanticValidator)
|
||||
· apply resolutions (add / overwrite / skip / rename)
|
||||
· upsert TemplateFolder hierarchy
|
||||
· IAuditService.LogAsync(BundleImported …)
|
||||
· commit
|
||||
│
|
||||
▼
|
||||
ImportResult → UI step 5
|
||||
│
|
||||
▼
|
||||
"View on Deployments →" (existing page)
|
||||
```
|
||||

|
||||
<!-- source: diagrams/transport-import-flow.drawio — edit, then re-export with export-drawio.sh -->
|
||||
|
||||
Authorization: `RequireAdmin` on both the Razor page and `IBundleImporter.*` entrypoints.
|
||||
|
||||
|
||||
@@ -0,0 +1,116 @@
|
||||
<mxfile host="app.diagrams.net">
|
||||
<diagram id="topology" name="Topology">
|
||||
<mxGraphModel dx="1400" dy="900" grid="1" gridSize="10" guides="1" arrows="1"
|
||||
fold="1" page="1" pageScale="1" pageWidth="1300" pageHeight="900" math="0" shadow="0">
|
||||
<root>
|
||||
<mxCell id="0" />
|
||||
<mxCell id="1" parent="0" />
|
||||
|
||||
<!-- Central Cluster container -->
|
||||
<mxCell id="central" value="Central Cluster" style="rounded=1;whiteSpace=wrap;html=1;fillColor=#dae8fc;strokeColor=#6c8ebf;verticalAlign=top;fontStyle=1;fontSize=14;" vertex="1" parent="1">
|
||||
<mxGeometry x="60" y="60" width="380" height="320" as="geometry" />
|
||||
</mxCell>
|
||||
<mxCell id="cc-a" value="ClusterClient (command/control)" style="rounded=1;whiteSpace=wrap;html=1;fillColor=#fff2cc;strokeColor=#d6b656;fontSize=12;" vertex="1" parent="1">
|
||||
<mxGeometry x="90" y="110" width="150" height="50" as="geometry" />
|
||||
</mxCell>
|
||||
<mxCell id="cc-b" value="ClusterClient (command/control)" style="rounded=1;whiteSpace=wrap;html=1;fillColor=#fff2cc;strokeColor=#d6b656;fontSize=12;" vertex="1" parent="1">
|
||||
<mxGeometry x="90" y="170" width="150" height="50" as="geometry" />
|
||||
</mxCell>
|
||||
<mxCell id="cc-n" value="ClusterClient (command/control)" style="rounded=1;whiteSpace=wrap;html=1;fillColor=#fff2cc;strokeColor=#d6b656;fontSize=12;" vertex="1" parent="1">
|
||||
<mxGeometry x="90" y="230" width="150" height="50" as="geometry" />
|
||||
</mxCell>
|
||||
<mxCell id="grpc-client" value="SiteStreamGrpcClient (real-time data)" style="rounded=1;whiteSpace=wrap;html=1;fillColor=#d5e8d4;strokeColor=#82b366;fontSize=12;" vertex="1" parent="1">
|
||||
<mxGeometry x="90" y="300" width="150" height="50" as="geometry" />
|
||||
</mxCell>
|
||||
|
||||
<!-- Site A -->
|
||||
<mxCell id="siteA" value="Site A Cluster" style="rounded=1;whiteSpace=wrap;html=1;fillColor=#e1d5e7;strokeColor=#9673a6;verticalAlign=top;fontStyle=1;fontSize=14;" vertex="1" parent="1">
|
||||
<mxGeometry x="720" y="60" width="380" height="250" as="geometry" />
|
||||
</mxCell>
|
||||
<mxCell id="siteA-comm" value="SiteCommunicationActor (via Receptionist)" style="rounded=1;whiteSpace=wrap;html=1;fillColor=#fff2cc;strokeColor=#d6b656;fontSize=12;" vertex="1" parent="1">
|
||||
<mxGeometry x="760" y="110" width="190" height="50" as="geometry" />
|
||||
</mxCell>
|
||||
<mxCell id="siteA-grpc" value="SiteStreamGrpcServer (Kestrel HTTP/2, port 8083)" style="rounded=1;whiteSpace=wrap;html=1;fillColor=#d5e8d4;strokeColor=#82b366;fontSize=12;" vertex="1" parent="1">
|
||||
<mxGeometry x="760" y="180" width="190" height="50" as="geometry" />
|
||||
</mxCell>
|
||||
<mxCell id="siteA-clusterclient" value="ClusterClient → Central (CentralCommunicationActor)" style="rounded=1;whiteSpace=wrap;html=1;fillColor=#fff2cc;strokeColor=#d6b656;fontSize=11;" vertex="1" parent="1">
|
||||
<mxGeometry x="760" y="245" width="190" height="50" as="geometry" />
|
||||
</mxCell>
|
||||
|
||||
<!-- Site B -->
|
||||
<mxCell id="siteB" value="Site B Cluster" style="rounded=1;whiteSpace=wrap;html=1;fillColor=#e1d5e7;strokeColor=#9673a6;verticalAlign=top;fontStyle=1;fontSize=14;" vertex="1" parent="1">
|
||||
<mxGeometry x="720" y="370" width="380" height="130" as="geometry" />
|
||||
</mxCell>
|
||||
<mxCell id="siteB-comm" value="SiteCommunicationActor (via Receptionist)" style="rounded=1;whiteSpace=wrap;html=1;fillColor=#fff2cc;strokeColor=#d6b656;fontSize=12;" vertex="1" parent="1">
|
||||
<mxGeometry x="760" y="410" width="190" height="40" as="geometry" />
|
||||
</mxCell>
|
||||
<mxCell id="siteB-grpc" value="SiteStreamGrpcServer" style="rounded=1;whiteSpace=wrap;html=1;fillColor=#d5e8d4;strokeColor=#82b366;fontSize=12;" vertex="1" parent="1">
|
||||
<mxGeometry x="760" y="455" width="190" height="35" as="geometry" />
|
||||
</mxCell>
|
||||
|
||||
<!-- Site N -->
|
||||
<mxCell id="siteN" value="Site N Cluster" style="rounded=1;whiteSpace=wrap;html=1;fillColor=#e1d5e7;strokeColor=#9673a6;verticalAlign=top;fontStyle=1;fontSize=14;" vertex="1" parent="1">
|
||||
<mxGeometry x="720" y="560" width="380" height="130" as="geometry" />
|
||||
</mxCell>
|
||||
<mxCell id="siteN-comm" value="SiteCommunicationActor (via Receptionist)" style="rounded=1;whiteSpace=wrap;html=1;fillColor=#fff2cc;strokeColor=#d6b656;fontSize=12;" vertex="1" parent="1">
|
||||
<mxGeometry x="760" y="600" width="190" height="40" as="geometry" />
|
||||
</mxCell>
|
||||
<mxCell id="siteN-grpc" value="SiteStreamGrpcServer" style="rounded=1;whiteSpace=wrap;html=1;fillColor=#d5e8d4;strokeColor=#82b366;fontSize=12;" vertex="1" parent="1">
|
||||
<mxGeometry x="760" y="645" width="190" height="35" as="geometry" />
|
||||
</mxCell>
|
||||
|
||||
<!-- Command/control edges: Central ClusterClients -> Site comm actors -->
|
||||
<mxCell id="e-cca" value="command/control" style="edgeStyle=orthogonalEdgeStyle;rounded=0;html=1;endArrow=block;fontSize=11;" edge="1" parent="1" source="cc-a" target="siteA-comm">
|
||||
<mxGeometry relative="1" as="geometry" />
|
||||
</mxCell>
|
||||
<mxCell id="e-ccb" value="command/control" style="edgeStyle=orthogonalEdgeStyle;rounded=0;html=1;endArrow=block;fontSize=11;" edge="1" parent="1" source="cc-b" target="siteB-comm">
|
||||
<mxGeometry relative="1" as="geometry" />
|
||||
</mxCell>
|
||||
<mxCell id="e-ccn" value="command/control" style="edgeStyle=orthogonalEdgeStyle;rounded=0;html=1;endArrow=block;fontSize=11;" edge="1" parent="1" source="cc-n" target="siteN-comm">
|
||||
<mxGeometry relative="1" as="geometry" />
|
||||
</mxCell>
|
||||
|
||||
<!-- gRPC stream edges: site servers -> central grpc client (data flows site->central) -->
|
||||
<mxCell id="e-grpca" value="gRPC stream (real-time data)" style="edgeStyle=orthogonalEdgeStyle;rounded=0;html=1;endArrow=block;fontSize=11;exitX=0;exitY=0.5;exitDx=0;exitDy=0;entryX=1;entryY=0.5;entryDx=0;entryDy=0;" edge="1" parent="1" source="siteA-grpc" target="grpc-client">
|
||||
<mxGeometry relative="1" as="geometry">
|
||||
<Array as="points">
|
||||
<mxPoint x="540" y="205" />
|
||||
<mxPoint x="540" y="325" />
|
||||
</Array>
|
||||
</mxGeometry>
|
||||
</mxCell>
|
||||
<mxCell id="e-grpcb" value="gRPC stream" style="edgeStyle=orthogonalEdgeStyle;rounded=0;html=1;endArrow=block;fontSize=11;exitX=0;exitY=0.5;exitDx=0;exitDy=0;entryX=1;entryY=0.5;entryDx=0;entryDy=0;" edge="1" parent="1" source="siteB-grpc" target="grpc-client">
|
||||
<mxGeometry relative="1" as="geometry">
|
||||
<Array as="points">
|
||||
<mxPoint x="600" y="472" />
|
||||
<mxPoint x="600" y="335" />
|
||||
</Array>
|
||||
</mxGeometry>
|
||||
</mxCell>
|
||||
<mxCell id="e-grpcn" value="gRPC stream" style="edgeStyle=orthogonalEdgeStyle;rounded=0;html=1;endArrow=block;fontSize=11;exitX=0;exitY=0.5;exitDx=0;exitDy=0;entryX=1;entryY=0.5;entryDx=0;entryDy=0;" edge="1" parent="1" source="siteN-grpc" target="grpc-client">
|
||||
<mxGeometry relative="1" as="geometry">
|
||||
<Array as="points">
|
||||
<mxPoint x="660" y="662" />
|
||||
<mxPoint x="660" y="345" />
|
||||
</Array>
|
||||
</mxGeometry>
|
||||
</mxCell>
|
||||
|
||||
<!-- Site A -> Central command/control (ClusterClient to central) -->
|
||||
<mxCell id="e-sa-central" value="command/control" style="edgeStyle=orthogonalEdgeStyle;rounded=0;html=1;endArrow=block;fontSize=11;dashed=1;exitX=0;exitY=0.5;exitDx=0;exitDy=0;entryX=1;entryY=0.7;entryDx=0;entryDy=0;" edge="1" parent="1" source="siteA-clusterclient" target="central">
|
||||
<mxGeometry relative="1" as="geometry">
|
||||
<Array as="points">
|
||||
<mxPoint x="480" y="270" />
|
||||
<mxPoint x="480" y="284" />
|
||||
</Array>
|
||||
</mxGeometry>
|
||||
</mxCell>
|
||||
|
||||
<!-- Note: sites do not talk to each other -->
|
||||
<mxCell id="note" value="Sites do NOT communicate with each other. All inter-cluster communication flows through Central." style="shape=note;whiteSpace=wrap;html=1;fillColor=#f5f5f5;strokeColor=#666666;fontSize=11;" vertex="1" parent="1">
|
||||
<mxGeometry x="60" y="560" width="380" height="80" as="geometry" />
|
||||
</mxCell>
|
||||
</root>
|
||||
</mxGraphModel>
|
||||
</diagram>
|
||||
</mxfile>
|
||||
|
After Width: | Height: | Size: 341 KiB |
@@ -0,0 +1,37 @@
|
||||
<mxfile host="app.diagrams.net">
|
||||
<diagram id="configdb-integration-example" name="Integration Example">
|
||||
<mxGraphModel dx="800" dy="600" grid="1" gridSize="10" guides="1" arrows="1" fold="1" page="1" pageScale="1" pageWidth="850" pageHeight="1100" math="0" shadow="0">
|
||||
<root>
|
||||
<mxCell id="0" />
|
||||
<mxCell id="1" parent="0" />
|
||||
<mxCell id="start" value="Template Engine: Update Template" style="rounded=1;arcSize=40;whiteSpace=wrap;html=1;fillColor=#d5e8d4;strokeColor=#82b366;fontStyle=1;" vertex="1" parent="1">
|
||||
<mxGeometry x="220" y="40" width="360" height="50" as="geometry" />
|
||||
</mxCell>
|
||||
<mxCell id="upd" value="repository.UpdateTemplate(template)" style="whiteSpace=wrap;html=1;fillColor=#dae8fc;strokeColor=#6c8ebf;align=left;spacingLeft=12;" vertex="1" parent="1">
|
||||
<mxGeometry x="220" y="150" width="360" height="50" as="geometry" />
|
||||
</mxCell>
|
||||
<mxCell id="audit" value="auditService.LogAsync(user, "Update", "Template",     template.Id, template.Name, template)" style="whiteSpace=wrap;html=1;fillColor=#e1d5e7;strokeColor=#9673a6;align=left;spacingLeft=12;" vertex="1" parent="1">
|
||||
<mxGeometry x="220" y="230" width="360" height="60" as="geometry" />
|
||||
</mxCell>
|
||||
<mxCell id="save" value="repository.SaveChangesAsync()" style="rounded=1;whiteSpace=wrap;html=1;fillColor=#fff2cc;strokeColor=#d6b656;align=left;spacingLeft=12;fontStyle=1;" vertex="1" parent="1">
|
||||
<mxGeometry x="220" y="330" width="360" height="50" as="geometry" />
|
||||
</mxCell>
|
||||
<mxCell id="note" value="both the change and audit entry commit together" style="shape=note;whiteSpace=wrap;html=1;fillColor=#ffe6cc;strokeColor=#d79b00;size=14;align=left;spacingLeft=10;" vertex="1" parent="1">
|
||||
<mxGeometry x="630" y="330" width="180" height="50" as="geometry" />
|
||||
</mxCell>
|
||||
<mxCell id="e0" style="edgeStyle=orthogonalEdgeStyle;rounded=0;html=1;endArrow=block;" edge="1" parent="1" source="start" target="upd">
|
||||
<mxGeometry relative="1" as="geometry" />
|
||||
</mxCell>
|
||||
<mxCell id="e1" style="edgeStyle=orthogonalEdgeStyle;rounded=0;html=1;endArrow=block;" edge="1" parent="1" source="upd" target="audit">
|
||||
<mxGeometry relative="1" as="geometry" />
|
||||
</mxCell>
|
||||
<mxCell id="e2" style="edgeStyle=orthogonalEdgeStyle;rounded=0;html=1;endArrow=block;" edge="1" parent="1" source="audit" target="save">
|
||||
<mxGeometry relative="1" as="geometry" />
|
||||
</mxCell>
|
||||
<mxCell id="e3" style="edgeStyle=orthogonalEdgeStyle;rounded=0;html=1;endArrow=none;dashed=1;" edge="1" parent="1" source="save" target="note">
|
||||
<mxGeometry relative="1" as="geometry" />
|
||||
</mxCell>
|
||||
</root>
|
||||
</mxGraphModel>
|
||||
</diagram>
|
||||
</mxfile>
|
||||
|
After Width: | Height: | Size: 109 KiB |
@@ -0,0 +1,49 @@
|
||||
<mxfile host="app.diagrams.net">
|
||||
<diagram id="configdb-transactional-flow" name="Transactional Flow">
|
||||
<mxGraphModel dx="800" dy="600" grid="1" gridSize="10" guides="1" arrows="1" fold="1" page="1" pageScale="1" pageWidth="850" pageHeight="1100" math="0" shadow="0">
|
||||
<root>
|
||||
<mxCell id="0" />
|
||||
<mxCell id="1" parent="0" />
|
||||
<mxCell id="start" value="Template Engine: Create Template" style="rounded=1;arcSize=40;whiteSpace=wrap;html=1;fillColor=#d5e8d4;strokeColor=#82b366;fontStyle=1;" vertex="1" parent="1">
|
||||
<mxGeometry x="240" y="40" width="320" height="50" as="geometry" />
|
||||
</mxCell>
|
||||
<mxCell id="add1" value="repository.AddTemplate(template) // template is a Commons POCO" style="whiteSpace=wrap;html=1;fillColor=#dae8fc;strokeColor=#6c8ebf;align=left;spacingLeft=12;" vertex="1" parent="1">
|
||||
<mxGeometry x="240" y="150" width="320" height="50" as="geometry" />
|
||||
</mxCell>
|
||||
<mxCell id="add2" value="repository.AddAttributes(attributes) // attributes are Commons POCOs" style="whiteSpace=wrap;html=1;fillColor=#dae8fc;strokeColor=#6c8ebf;align=left;spacingLeft=12;" vertex="1" parent="1">
|
||||
<mxGeometry x="240" y="230" width="320" height="50" as="geometry" />
|
||||
</mxCell>
|
||||
<mxCell id="add3" value="repository.AddAlarms(alarms) // alarms are Commons POCOs" style="whiteSpace=wrap;html=1;fillColor=#dae8fc;strokeColor=#6c8ebf;align=left;spacingLeft=12;" vertex="1" parent="1">
|
||||
<mxGeometry x="240" y="310" width="320" height="50" as="geometry" />
|
||||
</mxCell>
|
||||
<mxCell id="add4" value="repository.AddScripts(scripts) // scripts are Commons POCOs" style="whiteSpace=wrap;html=1;fillColor=#dae8fc;strokeColor=#6c8ebf;align=left;spacingLeft=12;" vertex="1" parent="1">
|
||||
<mxGeometry x="240" y="390" width="320" height="50" as="geometry" />
|
||||
</mxCell>
|
||||
<mxCell id="save" value="repository.SaveChangesAsync() // single transaction commits all" style="rounded=1;whiteSpace=wrap;html=1;fillColor=#fff2cc;strokeColor=#d6b656;align=left;spacingLeft=12;fontStyle=1;" vertex="1" parent="1">
|
||||
<mxGeometry x="240" y="480" width="320" height="50" as="geometry" />
|
||||
</mxCell>
|
||||
<mxCell id="db" value="Configuration DB (MS SQL)" style="shape=cylinder3;whiteSpace=wrap;html=1;fillColor=#f5f5f5;strokeColor=#666666;" vertex="1" parent="1">
|
||||
<mxGeometry x="640" y="475" width="120" height="70" as="geometry" />
|
||||
</mxCell>
|
||||
<mxCell id="e0" style="edgeStyle=orthogonalEdgeStyle;rounded=0;html=1;endArrow=block;" edge="1" parent="1" source="start" target="add1">
|
||||
<mxGeometry relative="1" as="geometry" />
|
||||
</mxCell>
|
||||
<mxCell id="e1" style="edgeStyle=orthogonalEdgeStyle;rounded=0;html=1;endArrow=block;" edge="1" parent="1" source="add1" target="add2">
|
||||
<mxGeometry relative="1" as="geometry" />
|
||||
</mxCell>
|
||||
<mxCell id="e2" style="edgeStyle=orthogonalEdgeStyle;rounded=0;html=1;endArrow=block;" edge="1" parent="1" source="add2" target="add3">
|
||||
<mxGeometry relative="1" as="geometry" />
|
||||
</mxCell>
|
||||
<mxCell id="e3" style="edgeStyle=orthogonalEdgeStyle;rounded=0;html=1;endArrow=block;" edge="1" parent="1" source="add3" target="add4">
|
||||
<mxGeometry relative="1" as="geometry" />
|
||||
</mxCell>
|
||||
<mxCell id="e4" style="edgeStyle=orthogonalEdgeStyle;rounded=0;html=1;endArrow=block;" edge="1" parent="1" source="add4" target="save">
|
||||
<mxGeometry relative="1" as="geometry" />
|
||||
</mxCell>
|
||||
<mxCell id="e5" value="single transaction" style="edgeStyle=orthogonalEdgeStyle;rounded=0;html=1;endArrow=block;dashed=1;" edge="1" parent="1" source="save" target="db">
|
||||
<mxGeometry relative="1" as="geometry" />
|
||||
</mxCell>
|
||||
</root>
|
||||
</mxGraphModel>
|
||||
</diagram>
|
||||
</mxfile>
|
||||
|
After Width: | Height: | Size: 182 KiB |
@@ -0,0 +1,71 @@
|
||||
<mxfile host="app.diagrams.net">
|
||||
<diagram id="dcl-endpoint-redundancy" name="Failover State Machine">
|
||||
<mxGraphModel dx="900" dy="700" grid="1" gridSize="10" guides="1" arrows="1" fold="1" page="1" pageScale="1" pageWidth="850" pageHeight="1100" math="0" shadow="0">
|
||||
<root>
|
||||
<mxCell id="0" />
|
||||
<mxCell id="1" parent="0" />
|
||||
<mxCell id="connected" value="Connected" style="rounded=1;arcSize=50;whiteSpace=wrap;html=1;fillColor=#d5e8d4;strokeColor=#82b366;fontStyle=1;" vertex="1" parent="1">
|
||||
<mxGeometry x="360" y="40" width="160" height="50" as="geometry" />
|
||||
</mxCell>
|
||||
<mxCell id="pushbad" value="push bad quality" style="whiteSpace=wrap;html=1;fillColor=#f8cecc;strokeColor=#b85450;" vertex="1" parent="1">
|
||||
<mxGeometry x="360" y="150" width="160" height="50" as="geometry" />
|
||||
</mxCell>
|
||||
<mxCell id="retry" value="retry active endpoint (5s)" style="whiteSpace=wrap;html=1;fillColor=#dae8fc;strokeColor=#6c8ebf;" vertex="1" parent="1">
|
||||
<mxGeometry x="360" y="250" width="160" height="50" as="geometry" />
|
||||
</mxCell>
|
||||
<mxCell id="decide" value="N failures (≥ FailoverRetryCount)?" style="rhombus;whiteSpace=wrap;html=1;fillColor=#fff2cc;strokeColor=#d6b656;" vertex="1" parent="1">
|
||||
<mxGeometry x="350" y="350" width="180" height="100" as="geometry" />
|
||||
</mxCell>
|
||||
<mxCell id="switch" value="switch to other endpoint" style="whiteSpace=wrap;html=1;fillColor=#ffe6cc;strokeColor=#d79b00;" vertex="1" parent="1">
|
||||
<mxGeometry x="360" y="500" width="160" height="50" as="geometry" />
|
||||
</mxCell>
|
||||
<mxCell id="dispose" value="dispose adapter, create fresh adapter with other config" style="whiteSpace=wrap;html=1;fillColor=#ffe6cc;strokeColor=#d79b00;" vertex="1" parent="1">
|
||||
<mxGeometry x="360" y="600" width="160" height="60" as="geometry" />
|
||||
</mxCell>
|
||||
<mxCell id="reconnect" value="reconnect" style="whiteSpace=wrap;html=1;fillColor=#dae8fc;strokeColor=#6c8ebf;" vertex="1" parent="1">
|
||||
<mxGeometry x="360" y="710" width="160" height="50" as="geometry" />
|
||||
</mxCell>
|
||||
<mxCell id="resub" value="ReSubscribeAll" style="whiteSpace=wrap;html=1;fillColor=#dae8fc;strokeColor=#6c8ebf;" vertex="1" parent="1">
|
||||
<mxGeometry x="360" y="800" width="160" height="50" as="geometry" />
|
||||
</mxCell>
|
||||
<mxCell id="e0" value="disconnect" style="edgeStyle=orthogonalEdgeStyle;rounded=0;html=1;endArrow=block;" edge="1" parent="1" source="connected" target="pushbad">
|
||||
<mxGeometry relative="1" as="geometry" />
|
||||
</mxCell>
|
||||
<mxCell id="e1" style="edgeStyle=orthogonalEdgeStyle;rounded=0;html=1;endArrow=block;" edge="1" parent="1" source="pushbad" target="retry">
|
||||
<mxGeometry relative="1" as="geometry" />
|
||||
</mxCell>
|
||||
<mxCell id="e2" style="edgeStyle=orthogonalEdgeStyle;rounded=0;html=1;endArrow=block;" edge="1" parent="1" source="retry" target="decide">
|
||||
<mxGeometry relative="1" as="geometry" />
|
||||
</mxCell>
|
||||
<mxCell id="e2b" value="no (retry again)" style="edgeStyle=orthogonalEdgeStyle;rounded=0;html=1;endArrow=block;exitX=1;exitY=0.5;exitDx=0;exitDy=0;entryX=1;entryY=0.5;entryDx=0;entryDy=0;" edge="1" parent="1" source="decide" target="retry">
|
||||
<mxGeometry relative="1" as="geometry">
|
||||
<Array as="points">
|
||||
<mxPoint x="620" y="400" />
|
||||
<mxPoint x="620" y="275" />
|
||||
</Array>
|
||||
</mxGeometry>
|
||||
</mxCell>
|
||||
<mxCell id="e3" value="yes" style="edgeStyle=orthogonalEdgeStyle;rounded=0;html=1;endArrow=block;" edge="1" parent="1" source="decide" target="switch">
|
||||
<mxGeometry relative="1" as="geometry" />
|
||||
</mxCell>
|
||||
<mxCell id="e4" style="edgeStyle=orthogonalEdgeStyle;rounded=0;html=1;endArrow=block;" edge="1" parent="1" source="switch" target="dispose">
|
||||
<mxGeometry relative="1" as="geometry" />
|
||||
</mxCell>
|
||||
<mxCell id="e5" style="edgeStyle=orthogonalEdgeStyle;rounded=0;html=1;endArrow=block;" edge="1" parent="1" source="dispose" target="reconnect">
|
||||
<mxGeometry relative="1" as="geometry" />
|
||||
</mxCell>
|
||||
<mxCell id="e6" style="edgeStyle=orthogonalEdgeStyle;rounded=0;html=1;endArrow=block;" edge="1" parent="1" source="reconnect" target="resub">
|
||||
<mxGeometry relative="1" as="geometry" />
|
||||
</mxCell>
|
||||
<mxCell id="e7" value="back to Connected" style="edgeStyle=orthogonalEdgeStyle;rounded=0;html=1;endArrow=block;exitX=0;exitY=0.5;exitDx=0;exitDy=0;entryX=0;entryY=0.5;entryDx=0;entryDy=0;" edge="1" parent="1" source="resub" target="connected">
|
||||
<mxGeometry relative="1" as="geometry">
|
||||
<Array as="points">
|
||||
<mxPoint x="240" y="825" />
|
||||
<mxPoint x="240" y="65" />
|
||||
</Array>
|
||||
</mxGeometry>
|
||||
</mxCell>
|
||||
</root>
|
||||
</mxGraphModel>
|
||||
</diagram>
|
||||
</mxfile>
|
||||
|
After Width: | Height: | Size: 128 KiB |
@@ -0,0 +1,96 @@
|
||||
<mxfile host="app.diagrams.net">
|
||||
<diagram id="deployflow" name="Deployment Flow">
|
||||
<mxGraphModel dx="1200" dy="1400" grid="1" gridSize="10" guides="1" arrows="1"
|
||||
fold="1" page="1" pageScale="1" pageWidth="900" pageHeight="1500" math="0" shadow="0">
|
||||
<root>
|
||||
<mxCell id="0" />
|
||||
<mxCell id="1" parent="0" />
|
||||
|
||||
<!-- Start: Engineer -->
|
||||
<mxCell id="engineer" value="Engineer (UI)" style="rounded=1;arcSize=50;whiteSpace=wrap;html=1;fillColor=#d5e8d4;strokeColor=#82b366;fontSize=13;" vertex="1" parent="1">
|
||||
<mxGeometry x="320" y="40" width="200" height="50" as="geometry" />
|
||||
</mxCell>
|
||||
|
||||
<!-- Deployment Manager (Central) container header -->
|
||||
<mxCell id="dm-central" value="Deployment Manager (Central)" style="rounded=1;whiteSpace=wrap;html=1;fillColor=#dae8fc;strokeColor=#6c8ebf;verticalAlign=top;fontStyle=1;fontSize=13;" vertex="1" parent="1">
|
||||
<mxGeometry x="120" y="130" width="640" height="430" as="geometry" />
|
||||
</mxCell>
|
||||
|
||||
<mxCell id="step1" value="1. Request validated + flattened config from Template Engine (validation: flattening, script compilation, trigger references, connection binding completeness)" style="whiteSpace=wrap;html=1;fillColor=#fff2cc;strokeColor=#d6b656;fontSize=12;" vertex="1" parent="1">
|
||||
<mxGeometry x="160" y="180" width="560" height="60" as="geometry" />
|
||||
</mxCell>
|
||||
|
||||
<mxCell id="step2" value="2. Validation fails?" style="rhombus;whiteSpace=wrap;html=1;fillColor=#f8cecc;strokeColor=#b85450;fontSize=12;" vertex="1" parent="1">
|
||||
<mxGeometry x="350" y="270" width="180" height="80" as="geometry" />
|
||||
</mxCell>
|
||||
|
||||
<mxCell id="step2fail" value="Return errors to UI, stop" style="rounded=1;arcSize=50;whiteSpace=wrap;html=1;fillColor=#f8cecc;strokeColor=#b85450;fontSize=12;" vertex="1" parent="1">
|
||||
<mxGeometry x="600" y="280" width="140" height="60" as="geometry" />
|
||||
</mxCell>
|
||||
|
||||
<mxCell id="step3" value="3. Send config to site via Communication Layer" style="whiteSpace=wrap;html=1;fillColor=#fff2cc;strokeColor=#d6b656;fontSize=12;" vertex="1" parent="1">
|
||||
<mxGeometry x="220" y="390" width="440" height="50" as="geometry" />
|
||||
</mxCell>
|
||||
|
||||
<mxCell id="step8" value="8. Update deployment status in config DB" style="shape=cylinder3;whiteSpace=wrap;html=1;fillColor=#dae8fc;strokeColor=#6c8ebf;fontSize=12;" vertex="1" parent="1">
|
||||
<mxGeometry x="280" y="480" width="320" height="70" as="geometry" />
|
||||
</mxCell>
|
||||
|
||||
<!-- Site Runtime container -->
|
||||
<mxCell id="site-runtime" value="Site Runtime (Deployment Manager Singleton)" style="rounded=1;whiteSpace=wrap;html=1;fillColor=#e1d5e7;strokeColor=#9673a6;verticalAlign=top;fontStyle=1;fontSize=13;" vertex="1" parent="1">
|
||||
<mxGeometry x="120" y="620" width="640" height="380" as="geometry" />
|
||||
</mxCell>
|
||||
|
||||
<mxCell id="step4" value="4. Store new flattened config locally (SQLite)" style="shape=cylinder3;whiteSpace=wrap;html=1;fillColor=#d5e8d4;strokeColor=#82b366;fontSize=12;" vertex="1" parent="1">
|
||||
<mxGeometry x="200" y="670" width="480" height="70" as="geometry" />
|
||||
</mxCell>
|
||||
|
||||
<mxCell id="step5" value="5. Compile scripts at site" style="whiteSpace=wrap;html=1;fillColor=#fff2cc;strokeColor=#d6b656;fontSize=12;" vertex="1" parent="1">
|
||||
<mxGeometry x="240" y="770" width="400" height="50" as="geometry" />
|
||||
</mxCell>
|
||||
|
||||
<mxCell id="step6" value="6. Create/update Instance Actor (with child Script + Alarm Actors)" style="whiteSpace=wrap;html=1;fillColor=#fff2cc;strokeColor=#d6b656;fontSize=12;" vertex="1" parent="1">
|
||||
<mxGeometry x="240" y="850" width="400" height="60" as="geometry" />
|
||||
</mxCell>
|
||||
|
||||
<mxCell id="step7" value="7. Report success/failure back to central" style="whiteSpace=wrap;html=1;fillColor=#fff2cc;strokeColor=#d6b656;fontSize=12;" vertex="1" parent="1">
|
||||
<mxGeometry x="240" y="940" width="400" height="50" as="geometry" />
|
||||
</mxCell>
|
||||
|
||||
<!-- Edges -->
|
||||
<mxCell id="e0" style="edgeStyle=orthogonalEdgeStyle;rounded=0;html=1;endArrow=block;" edge="1" parent="1" source="engineer" target="step1">
|
||||
<mxGeometry relative="1" as="geometry" />
|
||||
</mxCell>
|
||||
<mxCell id="e1" style="edgeStyle=orthogonalEdgeStyle;rounded=0;html=1;endArrow=block;" edge="1" parent="1" source="step1" target="step2">
|
||||
<mxGeometry relative="1" as="geometry" />
|
||||
</mxCell>
|
||||
<mxCell id="e2yes" value="yes" style="edgeStyle=orthogonalEdgeStyle;rounded=0;html=1;endArrow=block;fontSize=12;" edge="1" parent="1" source="step2" target="step2fail">
|
||||
<mxGeometry relative="1" as="geometry" />
|
||||
</mxCell>
|
||||
<mxCell id="e2no" value="no" style="edgeStyle=orthogonalEdgeStyle;rounded=0;html=1;endArrow=block;fontSize=12;" edge="1" parent="1" source="step2" target="step3">
|
||||
<mxGeometry relative="1" as="geometry" />
|
||||
</mxCell>
|
||||
<mxCell id="e3" value="config" style="edgeStyle=orthogonalEdgeStyle;rounded=0;html=1;endArrow=block;fontSize=12;" edge="1" parent="1" source="step3" target="step4">
|
||||
<mxGeometry relative="1" as="geometry" />
|
||||
</mxCell>
|
||||
<mxCell id="e4" style="edgeStyle=orthogonalEdgeStyle;rounded=0;html=1;endArrow=block;" edge="1" parent="1" source="step4" target="step5">
|
||||
<mxGeometry relative="1" as="geometry" />
|
||||
</mxCell>
|
||||
<mxCell id="e5" style="edgeStyle=orthogonalEdgeStyle;rounded=0;html=1;endArrow=block;" edge="1" parent="1" source="step5" target="step6">
|
||||
<mxGeometry relative="1" as="geometry" />
|
||||
</mxCell>
|
||||
<mxCell id="e6" style="edgeStyle=orthogonalEdgeStyle;rounded=0;html=1;endArrow=block;" edge="1" parent="1" source="step6" target="step7">
|
||||
<mxGeometry relative="1" as="geometry" />
|
||||
</mxCell>
|
||||
<mxCell id="e7" value="report success/failure" style="edgeStyle=orthogonalEdgeStyle;rounded=0;html=1;endArrow=block;fontSize=12;dashed=1;exitX=1;exitY=0.5;exitDx=0;exitDy=0;" edge="1" parent="1" source="step7" target="step8">
|
||||
<mxGeometry relative="1" as="geometry">
|
||||
<Array as="points">
|
||||
<mxPoint x="780" y="965" />
|
||||
<mxPoint x="780" y="515" />
|
||||
</Array>
|
||||
</mxGeometry>
|
||||
</mxCell>
|
||||
</root>
|
||||
</mxGraphModel>
|
||||
</diagram>
|
||||
</mxfile>
|
||||
|
After Width: | Height: | Size: 354 KiB |
@@ -0,0 +1,67 @@
|
||||
<mxfile host="app.diagrams.net">
|
||||
<diagram id="inboundapi-request-flow" name="Request Flow">
|
||||
<mxGraphModel dx="900" dy="900" grid="1" gridSize="10" guides="1" arrows="1" fold="1" page="1" pageScale="1" pageWidth="850" pageHeight="1100" math="0" shadow="0">
|
||||
<root>
|
||||
<mxCell id="0" />
|
||||
<mxCell id="1" parent="0" />
|
||||
<mxCell id="ext" value="External System" style="rounded=1;arcSize=50;whiteSpace=wrap;html=1;fillColor=#d5e8d4;strokeColor=#82b366;fontStyle=1;" vertex="1" parent="1">
|
||||
<mxGeometry x="320" y="40" width="200" height="50" as="geometry" />
|
||||
</mxCell>
|
||||
<mxCell id="api" value="Inbound API (Central)" style="rounded=1;whiteSpace=wrap;html=1;fillColor=#dae8fc;strokeColor=#6c8ebf;fontStyle=1;" vertex="1" parent="1">
|
||||
<mxGeometry x="320" y="140" width="200" height="50" as="geometry" />
|
||||
</mxCell>
|
||||
<mxCell id="s1" value="1. Extract API key from request" style="whiteSpace=wrap;html=1;fillColor=#fff2cc;strokeColor=#d6b656;align=left;spacingLeft=12;" vertex="1" parent="1">
|
||||
<mxGeometry x="280" y="240" width="280" height="40" as="geometry" />
|
||||
</mxCell>
|
||||
<mxCell id="s2" value="2. Validate key exists and is enabled" style="whiteSpace=wrap;html=1;fillColor=#fff2cc;strokeColor=#d6b656;align=left;spacingLeft=12;" vertex="1" parent="1">
|
||||
<mxGeometry x="280" y="300" width="280" height="40" as="geometry" />
|
||||
</mxCell>
|
||||
<mxCell id="s3" value="3. Resolve method by name" style="whiteSpace=wrap;html=1;fillColor=#fff2cc;strokeColor=#d6b656;align=left;spacingLeft=12;" vertex="1" parent="1">
|
||||
<mxGeometry x="280" y="360" width="280" height="40" as="geometry" />
|
||||
</mxCell>
|
||||
<mxCell id="s4" value="4. Check API key is in method's approved list" style="whiteSpace=wrap;html=1;fillColor=#fff2cc;strokeColor=#d6b656;align=left;spacingLeft=12;" vertex="1" parent="1">
|
||||
<mxGeometry x="280" y="420" width="280" height="40" as="geometry" />
|
||||
</mxCell>
|
||||
<mxCell id="s5" value="5. Validate and deserialize parameters" style="whiteSpace=wrap;html=1;fillColor=#fff2cc;strokeColor=#d6b656;align=left;spacingLeft=12;" vertex="1" parent="1">
|
||||
<mxGeometry x="280" y="480" width="280" height="40" as="geometry" />
|
||||
</mxCell>
|
||||
<mxCell id="s6" value="6. Execute implementation script (subject to method timeout)" style="whiteSpace=wrap;html=1;fillColor=#e1d5e7;strokeColor=#9673a6;align=left;spacingLeft=12;" vertex="1" parent="1">
|
||||
<mxGeometry x="280" y="540" width="280" height="50" as="geometry" />
|
||||
</mxCell>
|
||||
<mxCell id="s7" value="7. Serialize return value" style="whiteSpace=wrap;html=1;fillColor=#fff2cc;strokeColor=#d6b656;align=left;spacingLeft=12;" vertex="1" parent="1">
|
||||
<mxGeometry x="280" y="610" width="280" height="40" as="geometry" />
|
||||
</mxCell>
|
||||
<mxCell id="s8" value="8. Return response" style="rounded=1;whiteSpace=wrap;html=1;fillColor=#ffe6cc;strokeColor=#d79b00;align=left;spacingLeft=12;fontStyle=1;" vertex="1" parent="1">
|
||||
<mxGeometry x="280" y="670" width="280" height="40" as="geometry" />
|
||||
</mxCell>
|
||||
<mxCell id="e0" style="edgeStyle=orthogonalEdgeStyle;rounded=0;html=1;endArrow=block;" edge="1" parent="1" source="ext" target="api">
|
||||
<mxGeometry relative="1" as="geometry" />
|
||||
</mxCell>
|
||||
<mxCell id="e1" style="edgeStyle=orthogonalEdgeStyle;rounded=0;html=1;endArrow=block;" edge="1" parent="1" source="api" target="s1">
|
||||
<mxGeometry relative="1" as="geometry" />
|
||||
</mxCell>
|
||||
<mxCell id="e2" style="edgeStyle=orthogonalEdgeStyle;rounded=0;html=1;endArrow=block;" edge="1" parent="1" source="s1" target="s2">
|
||||
<mxGeometry relative="1" as="geometry" />
|
||||
</mxCell>
|
||||
<mxCell id="e3" style="edgeStyle=orthogonalEdgeStyle;rounded=0;html=1;endArrow=block;" edge="1" parent="1" source="s2" target="s3">
|
||||
<mxGeometry relative="1" as="geometry" />
|
||||
</mxCell>
|
||||
<mxCell id="e4" style="edgeStyle=orthogonalEdgeStyle;rounded=0;html=1;endArrow=block;" edge="1" parent="1" source="s3" target="s4">
|
||||
<mxGeometry relative="1" as="geometry" />
|
||||
</mxCell>
|
||||
<mxCell id="e5" style="edgeStyle=orthogonalEdgeStyle;rounded=0;html=1;endArrow=block;" edge="1" parent="1" source="s4" target="s5">
|
||||
<mxGeometry relative="1" as="geometry" />
|
||||
</mxCell>
|
||||
<mxCell id="e6" style="edgeStyle=orthogonalEdgeStyle;rounded=0;html=1;endArrow=block;" edge="1" parent="1" source="s5" target="s6">
|
||||
<mxGeometry relative="1" as="geometry" />
|
||||
</mxCell>
|
||||
<mxCell id="e7" style="edgeStyle=orthogonalEdgeStyle;rounded=0;html=1;endArrow=block;" edge="1" parent="1" source="s6" target="s7">
|
||||
<mxGeometry relative="1" as="geometry" />
|
||||
</mxCell>
|
||||
<mxCell id="e8" style="edgeStyle=orthogonalEdgeStyle;rounded=0;html=1;endArrow=block;" edge="1" parent="1" source="s7" target="s8">
|
||||
<mxGeometry relative="1" as="geometry" />
|
||||
</mxCell>
|
||||
</root>
|
||||
</mxGraphModel>
|
||||
</diagram>
|
||||
</mxfile>
|
||||
|
After Width: | Height: | Size: 146 KiB |
@@ -0,0 +1,83 @@
|
||||
<mxfile host="app.diagrams.net">
|
||||
<diagram id="outboxflow" name="End-to-End Flow">
|
||||
<mxGraphModel dx="1000" dy="1400" grid="1" gridSize="10" guides="1" arrows="1"
|
||||
fold="1" page="1" pageScale="1" pageWidth="950" pageHeight="1400" math="0" shadow="0">
|
||||
<root>
|
||||
<mxCell id="0" />
|
||||
<mxCell id="1" parent="0" />
|
||||
|
||||
<!-- Site script -->
|
||||
<mxCell id="script" value="Site script: Notify.To("list").Send(subject, body) generate NotificationId (GUID) locally; return it to the script immediately" style="rounded=1;arcSize=20;whiteSpace=wrap;html=1;fillColor=#d5e8d4;strokeColor=#82b366;fontSize=12;" vertex="1" parent="1">
|
||||
<mxGeometry x="280" y="40" width="380" height="70" as="geometry" />
|
||||
</mxCell>
|
||||
|
||||
<!-- Site S&F Engine -->
|
||||
<mxCell id="snf" value="Site Store-and-Forward Engine (notification category, target = central) durably forwards to central via Central–Site Communication (ClusterClient); buffers/retries if central is unreachable" style="whiteSpace=wrap;html=1;fillColor=#ffe6cc;strokeColor=#d79b00;fontSize=12;" vertex="1" parent="1">
|
||||
<mxGeometry x="240" y="170" width="460" height="80" as="geometry" />
|
||||
</mxCell>
|
||||
|
||||
<!-- Central ingest -->
|
||||
<mxCell id="ingest" value="Central ingest: insert-if-not-exists on NotificationId → Notifications table (Pending) ack the site → site S&F clears the message" style="shape=cylinder3;whiteSpace=wrap;html=1;fillColor=#dae8fc;strokeColor=#6c8ebf;fontSize=12;" vertex="1" parent="1">
|
||||
<mxGeometry x="270" y="310" width="400" height="90" as="geometry" />
|
||||
</mxCell>
|
||||
|
||||
<!-- Central Notification Outbox actor -->
|
||||
<mxCell id="outbox" value="Central Notification Outbox actor (singleton, active central node) polls due rows; resolves the list; delivers via the matching adapter" style="whiteSpace=wrap;html=1;fillColor=#e1d5e7;strokeColor=#9673a6;fontSize=12;" vertex="1" parent="1">
|
||||
<mxGeometry x="280" y="460" width="380" height="80" as="geometry" />
|
||||
</mxCell>
|
||||
|
||||
<!-- Delivery decision -->
|
||||
<mxCell id="d1" value="Delivery outcome" style="rhombus;whiteSpace=wrap;html=1;fillColor=#fff2cc;strokeColor=#d6b656;fontSize=12;" vertex="1" parent="1">
|
||||
<mxGeometry x="400" y="610" width="140" height="100" as="geometry" />
|
||||
</mxCell>
|
||||
|
||||
<!-- Delivered -->
|
||||
<mxCell id="delivered" value="Delivered" style="rounded=1;arcSize=50;whiteSpace=wrap;html=1;fillColor=#d5e8d4;strokeColor=#82b366;fontSize=12;" vertex="1" parent="1">
|
||||
<mxGeometry x="120" y="630" width="180" height="60" as="geometry" />
|
||||
</mxCell>
|
||||
|
||||
<!-- Retrying -->
|
||||
<mxCell id="retrying" value="Retrying (schedule NextAttemptAt)" style="rounded=1;arcSize=20;whiteSpace=wrap;html=1;fillColor=#fff2cc;strokeColor=#d6b656;fontSize=12;" vertex="1" parent="1">
|
||||
<mxGeometry x="380" y="790" width="180" height="60" as="geometry" />
|
||||
</mxCell>
|
||||
|
||||
<!-- Parked -->
|
||||
<mxCell id="parked" value="Parked" style="rounded=1;arcSize=50;whiteSpace=wrap;html=1;fillColor=#f8cecc;strokeColor=#b85450;fontSize=12;" vertex="1" parent="1">
|
||||
<mxGeometry x="650" y="630" width="180" height="60" as="geometry" />
|
||||
</mxCell>
|
||||
|
||||
<!-- Edges -->
|
||||
<mxCell id="e1" style="edgeStyle=orthogonalEdgeStyle;rounded=0;html=1;endArrow=block;" edge="1" parent="1" source="script" target="snf">
|
||||
<mxGeometry relative="1" as="geometry" />
|
||||
</mxCell>
|
||||
<mxCell id="e2" style="edgeStyle=orthogonalEdgeStyle;rounded=0;html=1;endArrow=block;" edge="1" parent="1" source="snf" target="ingest">
|
||||
<mxGeometry relative="1" as="geometry" />
|
||||
</mxCell>
|
||||
<mxCell id="e3" style="edgeStyle=orthogonalEdgeStyle;rounded=0;html=1;endArrow=block;" edge="1" parent="1" source="ingest" target="outbox">
|
||||
<mxGeometry relative="1" as="geometry" />
|
||||
</mxCell>
|
||||
<mxCell id="e4" style="edgeStyle=orthogonalEdgeStyle;rounded=0;html=1;endArrow=block;" edge="1" parent="1" source="outbox" target="d1">
|
||||
<mxGeometry relative="1" as="geometry" />
|
||||
</mxCell>
|
||||
<mxCell id="e5" value="success" style="edgeStyle=orthogonalEdgeStyle;rounded=0;html=1;endArrow=block;fontSize=12;" edge="1" parent="1" source="d1" target="delivered">
|
||||
<mxGeometry relative="1" as="geometry" />
|
||||
</mxCell>
|
||||
<mxCell id="e6" value="transient failure" style="edgeStyle=orthogonalEdgeStyle;rounded=0;html=1;endArrow=block;fontSize=12;" edge="1" parent="1" source="d1" target="retrying">
|
||||
<mxGeometry relative="1" as="geometry" />
|
||||
</mxCell>
|
||||
<mxCell id="e7" value="permanent failure / retries exhausted" style="edgeStyle=orthogonalEdgeStyle;rounded=0;html=1;endArrow=block;fontSize=12;" edge="1" parent="1" source="d1" target="parked">
|
||||
<mxGeometry relative="1" as="geometry" />
|
||||
</mxCell>
|
||||
<!-- Retrying loops back to outbox poll -->
|
||||
<mxCell id="e8" value="retry due" style="edgeStyle=orthogonalEdgeStyle;rounded=0;html=1;endArrow=block;fontSize=11;dashed=1;exitX=1;exitY=0.5;exitDx=0;exitDy=0;entryX=1;entryY=0.5;entryDx=0;entryDy=0;" edge="1" parent="1" source="retrying" target="outbox">
|
||||
<mxGeometry relative="1" as="geometry">
|
||||
<Array as="points">
|
||||
<mxPoint x="780" y="820" />
|
||||
<mxPoint x="780" y="500" />
|
||||
</Array>
|
||||
</mxGeometry>
|
||||
</mxCell>
|
||||
</root>
|
||||
</mxGraphModel>
|
||||
</diagram>
|
||||
</mxfile>
|
||||
|
After Width: | Height: | Size: 333 KiB |
@@ -0,0 +1,104 @@
|
||||
<mxfile host="app.diagrams.net">
|
||||
<diagram id="actorhierarchy" name="Actor Hierarchy">
|
||||
<mxGraphModel dx="1400" dy="1000" grid="1" gridSize="10" guides="1" arrows="1"
|
||||
fold="1" page="1" pageScale="1" pageWidth="1320" pageHeight="560" math="0" shadow="0">
|
||||
<root>
|
||||
<mxCell id="0" />
|
||||
<mxCell id="1" parent="0" />
|
||||
|
||||
<!-- Root: Deployment Manager Singleton -->
|
||||
<mxCell id="dms" value="Deployment Manager Singleton (Cluster Singleton)" style="rounded=1;whiteSpace=wrap;html=1;fillColor=#dae8fc;strokeColor=#6c8ebf;fontStyle=1;fontSize=13;" vertex="1" parent="1">
|
||||
<mxGeometry x="490" y="30" width="280" height="60" as="geometry" />
|
||||
</mxCell>
|
||||
|
||||
<!-- Instance Actors -->
|
||||
<mxCell id="ia1" value="Instance Actor ("MachineA-001")" style="rounded=1;whiteSpace=wrap;html=1;fillColor=#d5e8d4;strokeColor=#82b366;fontStyle=1;fontSize=12;" vertex="1" parent="1">
|
||||
<mxGeometry x="368" y="160" width="184" height="60" as="geometry" />
|
||||
</mxCell>
|
||||
<mxCell id="ia2" value="Instance Actor ("MachineA-002")" style="rounded=1;whiteSpace=wrap;html=1;fillColor=#d5e8d4;strokeColor=#82b366;fontStyle=1;fontSize=12;" vertex="1" parent="1">
|
||||
<mxGeometry x="980" y="160" width="184" height="60" as="geometry" />
|
||||
</mxCell>
|
||||
<mxCell id="iamore" value="… more Instance Actors" style="text;html=1;align=center;verticalAlign=middle;fontSize=12;fontStyle=2;" vertex="1" parent="1">
|
||||
<mxGeometry x="1190" y="170" width="120" height="40" as="geometry" />
|
||||
</mxCell>
|
||||
|
||||
<!-- Children of MachineA-001 (top row) -->
|
||||
<mxCell id="sa1" value="Script Actor ("MonitorSpeed") — coordinator" style="whiteSpace=wrap;html=1;fillColor=#fff2cc;strokeColor=#d6b656;fontSize=11;" vertex="1" parent="1">
|
||||
<mxGeometry x="16" y="300" width="164" height="74" as="geometry" />
|
||||
</mxCell>
|
||||
<mxCell id="sa2" value="Script Actor ("CalculateOEE") — coordinator" style="whiteSpace=wrap;html=1;fillColor=#fff2cc;strokeColor=#d6b656;fontSize=11;" vertex="1" parent="1">
|
||||
<mxGeometry x="196" y="300" width="164" height="74" as="geometry" />
|
||||
</mxCell>
|
||||
<mxCell id="aa1" value="Alarm Actor ("OverTemp") — coordinator (computed)" style="whiteSpace=wrap;html=1;fillColor=#f8cecc;strokeColor=#b85450;fontSize=11;" vertex="1" parent="1">
|
||||
<mxGeometry x="376" y="300" width="164" height="74" as="geometry" />
|
||||
</mxCell>
|
||||
<mxCell id="aa2" value="Alarm Actor ("LowPressure") — coordinator (computed)" style="whiteSpace=wrap;html=1;fillColor=#f8cecc;strokeColor=#b85450;fontSize=11;" vertex="1" parent="1">
|
||||
<mxGeometry x="556" y="300" width="164" height="74" as="geometry" />
|
||||
</mxCell>
|
||||
<mxCell id="naa1" value="Native Alarm Actor ("OpcUaServer1") — read-only mirror, peer to Alarm Actor" style="whiteSpace=wrap;html=1;fillColor=#e1d5e7;strokeColor=#9673a6;fontSize=11;" vertex="1" parent="1">
|
||||
<mxGeometry x="736" y="300" width="164" height="74" as="geometry" />
|
||||
</mxCell>
|
||||
|
||||
<!-- Execution actors (bottom row, under their coordinators) -->
|
||||
<mxCell id="sea1" value="Script Execution Actor — short-lived, per invocation" style="rounded=1;whiteSpace=wrap;html=1;fillColor=#ffe6cc;strokeColor=#d79b00;dashed=1;fontSize=11;" vertex="1" parent="1">
|
||||
<mxGeometry x="16" y="430" width="164" height="64" as="geometry" />
|
||||
</mxCell>
|
||||
<mxCell id="sea2" value="Script Execution Actor — short-lived, per invocation" style="rounded=1;whiteSpace=wrap;html=1;fillColor=#ffe6cc;strokeColor=#d79b00;dashed=1;fontSize=11;" vertex="1" parent="1">
|
||||
<mxGeometry x="196" y="430" width="164" height="64" as="geometry" />
|
||||
</mxCell>
|
||||
<mxCell id="aea1" value="Alarm Execution Actor — short-lived, per on-trigger invocation" style="rounded=1;whiteSpace=wrap;html=1;fillColor=#ffe6cc;strokeColor=#d79b00;dashed=1;fontSize=11;" vertex="1" parent="1">
|
||||
<mxGeometry x="376" y="430" width="164" height="64" as="geometry" />
|
||||
</mxCell>
|
||||
|
||||
<!-- Child of MachineA-002 -->
|
||||
<mxCell id="ia2child" value="… (Script / Alarm Actors)" style="text;html=1;align=center;verticalAlign=middle;fontSize=12;fontStyle=2;" vertex="1" parent="1">
|
||||
<mxGeometry x="992" y="304" width="160" height="40" as="geometry" />
|
||||
</mxCell>
|
||||
|
||||
<!-- Edges: root -> instances -->
|
||||
<mxCell id="e-dms-ia1" style="edgeStyle=orthogonalEdgeStyle;rounded=0;html=1;endArrow=block;" edge="1" parent="1" source="dms" target="ia1">
|
||||
<mxGeometry relative="1" as="geometry" />
|
||||
</mxCell>
|
||||
<mxCell id="e-dms-ia2" style="edgeStyle=orthogonalEdgeStyle;rounded=0;html=1;endArrow=block;" edge="1" parent="1" source="dms" target="ia2">
|
||||
<mxGeometry relative="1" as="geometry" />
|
||||
</mxCell>
|
||||
<mxCell id="e-dms-more" style="edgeStyle=orthogonalEdgeStyle;rounded=0;html=1;endArrow=block;dashed=1;" edge="1" parent="1" source="dms" target="iamore">
|
||||
<mxGeometry relative="1" as="geometry" />
|
||||
</mxCell>
|
||||
|
||||
<!-- Edges: MachineA-001 -> its children (all top-row, no box in between) -->
|
||||
<mxCell id="e-ia1-sa1" style="edgeStyle=orthogonalEdgeStyle;rounded=0;html=1;endArrow=block;" edge="1" parent="1" source="ia1" target="sa1">
|
||||
<mxGeometry relative="1" as="geometry" />
|
||||
</mxCell>
|
||||
<mxCell id="e-ia1-sa2" style="edgeStyle=orthogonalEdgeStyle;rounded=0;html=1;endArrow=block;" edge="1" parent="1" source="ia1" target="sa2">
|
||||
<mxGeometry relative="1" as="geometry" />
|
||||
</mxCell>
|
||||
<mxCell id="e-ia1-aa1" style="edgeStyle=orthogonalEdgeStyle;rounded=0;html=1;endArrow=block;" edge="1" parent="1" source="ia1" target="aa1">
|
||||
<mxGeometry relative="1" as="geometry" />
|
||||
</mxCell>
|
||||
<mxCell id="e-ia1-aa2" style="edgeStyle=orthogonalEdgeStyle;rounded=0;html=1;endArrow=block;" edge="1" parent="1" source="ia1" target="aa2">
|
||||
<mxGeometry relative="1" as="geometry" />
|
||||
</mxCell>
|
||||
<mxCell id="e-ia1-naa1" style="edgeStyle=orthogonalEdgeStyle;rounded=0;html=1;endArrow=block;" edge="1" parent="1" source="ia1" target="naa1">
|
||||
<mxGeometry relative="1" as="geometry" />
|
||||
</mxCell>
|
||||
|
||||
<!-- Edges: coordinator -> execution actor (short vertical, own column) -->
|
||||
<mxCell id="e-sa1-sea1" style="edgeStyle=orthogonalEdgeStyle;rounded=0;html=1;endArrow=block;" edge="1" parent="1" source="sa1" target="sea1">
|
||||
<mxGeometry relative="1" as="geometry" />
|
||||
</mxCell>
|
||||
<mxCell id="e-sa2-sea2" style="edgeStyle=orthogonalEdgeStyle;rounded=0;html=1;endArrow=block;" edge="1" parent="1" source="sa2" target="sea2">
|
||||
<mxGeometry relative="1" as="geometry" />
|
||||
</mxCell>
|
||||
<mxCell id="e-aa1-aea1" style="edgeStyle=orthogonalEdgeStyle;rounded=0;html=1;endArrow=block;" edge="1" parent="1" source="aa1" target="aea1">
|
||||
<mxGeometry relative="1" as="geometry" />
|
||||
</mxCell>
|
||||
|
||||
<!-- Edge: MachineA-002 -> its child -->
|
||||
<mxCell id="e-ia2-child" style="edgeStyle=orthogonalEdgeStyle;rounded=0;html=1;endArrow=block;dashed=1;" edge="1" parent="1" source="ia2" target="ia2child">
|
||||
<mxGeometry relative="1" as="geometry" />
|
||||
</mxCell>
|
||||
</root>
|
||||
</mxGraphModel>
|
||||
</diagram>
|
||||
</mxfile>
|
||||
|
After Width: | Height: | Size: 217 KiB |
@@ -0,0 +1,82 @@
|
||||
<mxfile host="app.diagrams.net">
|
||||
<diagram id="msglifecycle" name="Message Lifecycle">
|
||||
<mxGraphModel dx="1000" dy="1300" grid="1" gridSize="10" guides="1" arrows="1"
|
||||
fold="1" page="1" pageScale="1" pageWidth="900" pageHeight="1300" math="0" shadow="0">
|
||||
<root>
|
||||
<mxCell id="0" />
|
||||
<mxCell id="1" parent="0" />
|
||||
|
||||
<!-- Start -->
|
||||
<mxCell id="submit" value="Script submits message" style="rounded=1;arcSize=50;whiteSpace=wrap;html=1;fillColor=#d5e8d4;strokeColor=#82b366;fontSize=13;" vertex="1" parent="1">
|
||||
<mxGeometry x="320" y="40" width="220" height="50" as="geometry" />
|
||||
</mxCell>
|
||||
|
||||
<!-- Attempt immediate delivery -->
|
||||
<mxCell id="attempt" value="Attempt immediate delivery" style="whiteSpace=wrap;html=1;fillColor=#dae8fc;strokeColor=#6c8ebf;fontSize=13;" vertex="1" parent="1">
|
||||
<mxGeometry x="320" y="140" width="220" height="50" as="geometry" />
|
||||
</mxCell>
|
||||
|
||||
<!-- Decision: success or failure -->
|
||||
<mxCell id="d1" value="Delivered?" style="rhombus;whiteSpace=wrap;html=1;fillColor=#fff2cc;strokeColor=#d6b656;fontSize=12;" vertex="1" parent="1">
|
||||
<mxGeometry x="350" y="240" width="160" height="90" as="geometry" />
|
||||
</mxCell>
|
||||
|
||||
<!-- Success -> Remove from buffer -->
|
||||
<mxCell id="remove1" value="Remove from buffer" style="rounded=1;arcSize=50;whiteSpace=wrap;html=1;fillColor=#d5e8d4;strokeColor=#82b366;fontSize=12;" vertex="1" parent="1">
|
||||
<mxGeometry x="620" y="255" width="200" height="60" as="geometry" />
|
||||
</mxCell>
|
||||
|
||||
<!-- Failure -> Buffer message -->
|
||||
<mxCell id="buffer" value="Buffer message" style="whiteSpace=wrap;html=1;fillColor=#ffe6cc;strokeColor=#d79b00;fontSize=12;" vertex="1" parent="1">
|
||||
<mxGeometry x="330" y="390" width="200" height="50" as="geometry" />
|
||||
</mxCell>
|
||||
|
||||
<!-- Retry loop -->
|
||||
<mxCell id="retry" value="Retry loop (per retry policy)" style="whiteSpace=wrap;html=1;fillColor=#dae8fc;strokeColor=#6c8ebf;fontSize=12;" vertex="1" parent="1">
|
||||
<mxGeometry x="330" y="490" width="200" height="60" as="geometry" />
|
||||
</mxCell>
|
||||
|
||||
<!-- Retry decision -->
|
||||
<mxCell id="d2" value="Retry outcome" style="rhombus;whiteSpace=wrap;html=1;fillColor=#fff2cc;strokeColor=#d6b656;fontSize=12;" vertex="1" parent="1">
|
||||
<mxGeometry x="350" y="610" width="160" height="100" as="geometry" />
|
||||
</mxCell>
|
||||
|
||||
<!-- Retry success -> Remove from buffer + notify standby -->
|
||||
<mxCell id="remove2" value="Remove from buffer + notify standby" style="rounded=1;arcSize=50;whiteSpace=wrap;html=1;fillColor=#d5e8d4;strokeColor=#82b366;fontSize=12;" vertex="1" parent="1">
|
||||
<mxGeometry x="620" y="625" width="200" height="70" as="geometry" />
|
||||
</mxCell>
|
||||
|
||||
<!-- Max retries exhausted -> Park message -->
|
||||
<mxCell id="park" value="Park message (dead-letter)" style="rounded=1;arcSize=50;whiteSpace=wrap;html=1;fillColor=#f8cecc;strokeColor=#b85450;fontSize=12;" vertex="1" parent="1">
|
||||
<mxGeometry x="330" y="770" width="200" height="60" as="geometry" />
|
||||
</mxCell>
|
||||
|
||||
<!-- Edges -->
|
||||
<mxCell id="e1" style="edgeStyle=orthogonalEdgeStyle;rounded=0;html=1;endArrow=block;" edge="1" parent="1" source="submit" target="attempt">
|
||||
<mxGeometry relative="1" as="geometry" />
|
||||
</mxCell>
|
||||
<mxCell id="e2" style="edgeStyle=orthogonalEdgeStyle;rounded=0;html=1;endArrow=block;" edge="1" parent="1" source="attempt" target="d1">
|
||||
<mxGeometry relative="1" as="geometry" />
|
||||
</mxCell>
|
||||
<mxCell id="e3" value="Success" style="edgeStyle=orthogonalEdgeStyle;rounded=0;html=1;endArrow=block;fontSize=12;" edge="1" parent="1" source="d1" target="remove1">
|
||||
<mxGeometry relative="1" as="geometry" />
|
||||
</mxCell>
|
||||
<mxCell id="e4" value="Failure" style="edgeStyle=orthogonalEdgeStyle;rounded=0;html=1;endArrow=block;fontSize=12;" edge="1" parent="1" source="d1" target="buffer">
|
||||
<mxGeometry relative="1" as="geometry" />
|
||||
</mxCell>
|
||||
<mxCell id="e5" style="edgeStyle=orthogonalEdgeStyle;rounded=0;html=1;endArrow=block;" edge="1" parent="1" source="buffer" target="retry">
|
||||
<mxGeometry relative="1" as="geometry" />
|
||||
</mxCell>
|
||||
<mxCell id="e6" style="edgeStyle=orthogonalEdgeStyle;rounded=0;html=1;endArrow=block;" edge="1" parent="1" source="retry" target="d2">
|
||||
<mxGeometry relative="1" as="geometry" />
|
||||
</mxCell>
|
||||
<mxCell id="e7" value="Success" style="edgeStyle=orthogonalEdgeStyle;rounded=0;html=1;endArrow=block;fontSize=12;" edge="1" parent="1" source="d2" target="remove2">
|
||||
<mxGeometry relative="1" as="geometry" />
|
||||
</mxCell>
|
||||
<mxCell id="e8" value="Max retries exhausted" style="edgeStyle=orthogonalEdgeStyle;rounded=0;html=1;endArrow=block;fontSize=12;" edge="1" parent="1" source="d2" target="park">
|
||||
<mxGeometry relative="1" as="geometry" />
|
||||
</mxCell>
|
||||
</root>
|
||||
</mxGraphModel>
|
||||
</diagram>
|
||||
</mxfile>
|
||||
|
After Width: | Height: | Size: 154 KiB |
@@ -0,0 +1,34 @@
|
||||
<mxfile host="app.diagrams.net">
|
||||
<diagram id="transport-architecture" name="Architecture">
|
||||
<mxGraphModel dx="900" dy="800" grid="1" gridSize="10" guides="1" arrows="1" fold="1" page="1" pageScale="1" pageWidth="850" pageHeight="1100" math="0" shadow="0">
|
||||
<root>
|
||||
<mxCell id="0" />
|
||||
<mxCell id="1" parent="0" />
|
||||
<mxCell id="container" value="ZB.MOM.WW.ScadaBridge.Transport" style="swimlane;whiteSpace=wrap;html=1;startSize=34;fillColor=#f5f5f5;strokeColor=#666666;fontStyle=1;fontSize=14;verticalAlign=top;" vertex="1" parent="1">
|
||||
<mxGeometry x="80" y="40" width="560" height="610" as="geometry" />
|
||||
</mxCell>
|
||||
<mxCell id="exporter" value="IBundleExporter ExportAsync(ExportSelection, Passphrase?, ct) → Stream" style="rounded=1;whiteSpace=wrap;html=1;fillColor=#dae8fc;strokeColor=#6c8ebf;align=left;spacingLeft=12;verticalAlign=top;spacingTop=8;" vertex="1" parent="container">
|
||||
<mxGeometry x="30" y="50" width="500" height="70" as="geometry" />
|
||||
</mxCell>
|
||||
<mxCell id="importer" value="IBundleImporter LoadAsync(stream, Passphrase?, ct) → BundleSession PreviewAsync(sessionId, ct) → ImportPreview ApplyAsync(sessionId, resolutions, ct) → ImportResult" style="rounded=1;whiteSpace=wrap;html=1;fillColor=#dae8fc;strokeColor=#6c8ebf;align=left;spacingLeft=12;verticalAlign=top;spacingTop=8;" vertex="1" parent="container">
|
||||
<mxGeometry x="30" y="140" width="500" height="110" as="geometry" />
|
||||
</mxCell>
|
||||
<mxCell id="resolver" value="DependencyResolver" style="rounded=1;whiteSpace=wrap;html=1;fillColor=#d5e8d4;strokeColor=#82b366;align=left;spacingLeft=12;" vertex="1" parent="container">
|
||||
<mxGeometry x="30" y="270" width="500" height="40" as="geometry" />
|
||||
</mxCell>
|
||||
<mxCell id="serializer" value="BundleSerializer (manifest + content JSON; ZIP packer)" style="rounded=1;whiteSpace=wrap;html=1;fillColor=#d5e8d4;strokeColor=#82b366;align=left;spacingLeft=12;" vertex="1" parent="container">
|
||||
<mxGeometry x="30" y="330" width="500" height="40" as="geometry" />
|
||||
</mxCell>
|
||||
<mxCell id="encryptor" value="BundleSecretEncryptor (AES-256-GCM + PBKDF2)" style="rounded=1;whiteSpace=wrap;html=1;fillColor=#e1d5e7;strokeColor=#9673a6;align=left;spacingLeft=12;" vertex="1" parent="container">
|
||||
<mxGeometry x="30" y="390" width="500" height="40" as="geometry" />
|
||||
</mxCell>
|
||||
<mxCell id="sessionstore" value="BundleSessionStore (in-memory, TTL'd)" style="rounded=1;whiteSpace=wrap;html=1;fillColor=#ffe6cc;strokeColor=#d79b00;align=left;spacingLeft=12;" vertex="1" parent="container">
|
||||
<mxGeometry x="30" y="450" width="500" height="40" as="geometry" />
|
||||
</mxCell>
|
||||
<mxCell id="manifestvalidator" value="ManifestValidator (schema/version gating, hash check)" style="rounded=1;whiteSpace=wrap;html=1;fillColor=#fff2cc;strokeColor=#d6b656;align=left;spacingLeft=12;" vertex="1" parent="container">
|
||||
<mxGeometry x="30" y="510" width="500" height="40" as="geometry" />
|
||||
</mxCell>
|
||||
</root>
|
||||
</mxGraphModel>
|
||||
</diagram>
|
||||
</mxfile>
|
||||
|
After Width: | Height: | Size: 228 KiB |
@@ -0,0 +1,85 @@
|
||||
<mxfile host="app.diagrams.net">
|
||||
<diagram id="transport-export-flow" name="Export Flow (Backend)">
|
||||
<mxGraphModel dx="1000" dy="800" grid="1" gridSize="10" guides="1" arrows="1" fold="1" page="1" pageScale="1" pageWidth="900" pageHeight="1100" math="0" shadow="0">
|
||||
<root>
|
||||
<mxCell id="0" />
|
||||
<mxCell id="1" parent="0" />
|
||||
<mxCell id="user" value="User (Design role)" style="rounded=1;arcSize=50;whiteSpace=wrap;html=1;fillColor=#d5e8d4;strokeColor=#82b366;fontStyle=1;" vertex="1" parent="1">
|
||||
<mxGeometry x="40" y="40" width="160" height="50" as="geometry" />
|
||||
</mxCell>
|
||||
<mxCell id="wizard" value="Central UI Export wizard" style="rounded=1;whiteSpace=wrap;html=1;fillColor=#dae8fc;strokeColor=#6c8ebf;" vertex="1" parent="1">
|
||||
<mxGeometry x="280" y="40" width="200" height="50" as="geometry" />
|
||||
</mxCell>
|
||||
<mxCell id="exporter" value="IBundleExporter" style="rounded=1;whiteSpace=wrap;html=1;fillColor=#dae8fc;strokeColor=#6c8ebf;fontStyle=1;" vertex="1" parent="1">
|
||||
<mxGeometry x="280" y="150" width="200" height="50" as="geometry" />
|
||||
</mxCell>
|
||||
<mxCell id="resolver" value="DependencyResolver" style="whiteSpace=wrap;html=1;fillColor=#fff2cc;strokeColor=#d6b656;" vertex="1" parent="1">
|
||||
<mxGeometry x="280" y="250" width="200" height="40" as="geometry" />
|
||||
</mxCell>
|
||||
<mxCell id="repos" value="repositories (read)" style="shape=cylinder3;whiteSpace=wrap;html=1;fillColor=#f5f5f5;strokeColor=#666666;" vertex="1" parent="1">
|
||||
<mxGeometry x="600" y="245" width="120" height="60" as="geometry" />
|
||||
</mxCell>
|
||||
<mxCell id="serializer" value="EntitySerializer" style="whiteSpace=wrap;html=1;fillColor=#fff2cc;strokeColor=#d6b656;" vertex="1" parent="1">
|
||||
<mxGeometry x="280" y="310" width="200" height="40" as="geometry" />
|
||||
</mxCell>
|
||||
<mxCell id="contentjson" value="content.json" style="shape=note;whiteSpace=wrap;html=1;fillColor=#ffe6cc;strokeColor=#d79b00;size=12;" vertex="1" parent="1">
|
||||
<mxGeometry x="610" y="310" width="110" height="40" as="geometry" />
|
||||
</mxCell>
|
||||
<mxCell id="encryptor" value="BundleSecretEncryptor" style="whiteSpace=wrap;html=1;fillColor=#e1d5e7;strokeColor=#9673a6;" vertex="1" parent="1">
|
||||
<mxGeometry x="280" y="370" width="200" height="40" as="geometry" />
|
||||
</mxCell>
|
||||
<mxCell id="contentenc" value="content.enc (if passphrase)" style="shape=note;whiteSpace=wrap;html=1;fillColor=#ffe6cc;strokeColor=#d79b00;size=12;" vertex="1" parent="1">
|
||||
<mxGeometry x="610" y="368" width="110" height="44" as="geometry" />
|
||||
</mxCell>
|
||||
<mxCell id="manifestbuilder" value="ManifestBuilder" style="whiteSpace=wrap;html=1;fillColor=#fff2cc;strokeColor=#d6b656;" vertex="1" parent="1">
|
||||
<mxGeometry x="280" y="430" width="200" height="40" as="geometry" />
|
||||
</mxCell>
|
||||
<mxCell id="manifestjson" value="manifest.json" style="shape=note;whiteSpace=wrap;html=1;fillColor=#ffe6cc;strokeColor=#d79b00;size=12;" vertex="1" parent="1">
|
||||
<mxGeometry x="610" y="430" width="110" height="40" as="geometry" />
|
||||
</mxCell>
|
||||
<mxCell id="zip" value="ZIP packer → temp file → browser download" style="rounded=1;whiteSpace=wrap;html=1;fillColor=#dae8fc;strokeColor=#6c8ebf;" vertex="1" parent="1">
|
||||
<mxGeometry x="240" y="520" width="280" height="50" as="geometry" />
|
||||
</mxCell>
|
||||
<mxCell id="audit" value="IAuditService.LogAsync(BundleExported …)" style="rounded=1;whiteSpace=wrap;html=1;fillColor=#d5e8d4;strokeColor=#82b366;fontStyle=1;" vertex="1" parent="1">
|
||||
<mxGeometry x="240" y="620" width="280" height="50" as="geometry" />
|
||||
</mxCell>
|
||||
<mxCell id="e0" style="edgeStyle=orthogonalEdgeStyle;rounded=0;html=1;endArrow=block;" edge="1" parent="1" source="user" target="wizard">
|
||||
<mxGeometry relative="1" as="geometry" />
|
||||
</mxCell>
|
||||
<mxCell id="e1" style="edgeStyle=orthogonalEdgeStyle;rounded=0;html=1;endArrow=block;" edge="1" parent="1" source="wizard" target="exporter">
|
||||
<mxGeometry relative="1" as="geometry" />
|
||||
</mxCell>
|
||||
<mxCell id="e2" style="edgeStyle=orthogonalEdgeStyle;rounded=0;html=1;endArrow=block;" edge="1" parent="1" source="exporter" target="resolver">
|
||||
<mxGeometry relative="1" as="geometry" />
|
||||
</mxCell>
|
||||
<mxCell id="e3" style="edgeStyle=orthogonalEdgeStyle;rounded=0;html=1;endArrow=block;" edge="1" parent="1" source="resolver" target="serializer">
|
||||
<mxGeometry relative="1" as="geometry" />
|
||||
</mxCell>
|
||||
<mxCell id="e4" style="edgeStyle=orthogonalEdgeStyle;rounded=0;html=1;endArrow=block;" edge="1" parent="1" source="serializer" target="encryptor">
|
||||
<mxGeometry relative="1" as="geometry" />
|
||||
</mxCell>
|
||||
<mxCell id="e5" style="edgeStyle=orthogonalEdgeStyle;rounded=0;html=1;endArrow=block;" edge="1" parent="1" source="encryptor" target="manifestbuilder">
|
||||
<mxGeometry relative="1" as="geometry" />
|
||||
</mxCell>
|
||||
<mxCell id="e6" style="edgeStyle=orthogonalEdgeStyle;rounded=0;html=1;endArrow=block;" edge="1" parent="1" source="manifestbuilder" target="zip">
|
||||
<mxGeometry relative="1" as="geometry" />
|
||||
</mxCell>
|
||||
<mxCell id="e7" style="edgeStyle=orthogonalEdgeStyle;rounded=0;html=1;endArrow=block;" edge="1" parent="1" source="zip" target="audit">
|
||||
<mxGeometry relative="1" as="geometry" />
|
||||
</mxCell>
|
||||
<mxCell id="b1" style="edgeStyle=orthogonalEdgeStyle;rounded=0;html=1;endArrow=block;" edge="1" parent="1" source="resolver" target="repos">
|
||||
<mxGeometry relative="1" as="geometry" />
|
||||
</mxCell>
|
||||
<mxCell id="b2" style="edgeStyle=orthogonalEdgeStyle;rounded=0;html=1;endArrow=block;" edge="1" parent="1" source="serializer" target="contentjson">
|
||||
<mxGeometry relative="1" as="geometry" />
|
||||
</mxCell>
|
||||
<mxCell id="b3" style="edgeStyle=orthogonalEdgeStyle;rounded=0;html=1;endArrow=block;" edge="1" parent="1" source="encryptor" target="contentenc">
|
||||
<mxGeometry relative="1" as="geometry" />
|
||||
</mxCell>
|
||||
<mxCell id="b4" style="edgeStyle=orthogonalEdgeStyle;rounded=0;html=1;endArrow=block;" edge="1" parent="1" source="manifestbuilder" target="manifestjson">
|
||||
<mxGeometry relative="1" as="geometry" />
|
||||
</mxCell>
|
||||
</root>
|
||||
</mxGraphModel>
|
||||
</diagram>
|
||||
</mxfile>
|
||||
|
After Width: | Height: | Size: 164 KiB |
@@ -0,0 +1,49 @@
|
||||
<mxfile host="app.diagrams.net">
|
||||
<diagram id="transport-import-flow" name="Import Flow (Backend)">
|
||||
<mxGraphModel dx="1000" dy="900" grid="1" gridSize="10" guides="1" arrows="1" fold="1" page="1" pageScale="1" pageWidth="900" pageHeight="1100" math="0" shadow="0">
|
||||
<root>
|
||||
<mxCell id="0" />
|
||||
<mxCell id="1" parent="0" />
|
||||
<mxCell id="user" value="User (Admin role) ─► uploads bundle" style="rounded=1;arcSize=30;whiteSpace=wrap;html=1;fillColor=#d5e8d4;strokeColor=#82b366;fontStyle=1;" vertex="1" parent="1">
|
||||
<mxGeometry x="260" y="40" width="320" height="50" as="geometry" />
|
||||
</mxCell>
|
||||
<mxCell id="load" value="IBundleImporter.LoadAsync   · verify SHA-256 (manifest vs content)   · check bundleFormatVersion supported   · decrypt content.enc with passphrase (if encrypted)   · deserialize entities   · open BundleSession (30-min TTL)" style="rounded=1;whiteSpace=wrap;html=1;fillColor=#dae8fc;strokeColor=#6c8ebf;align=left;spacingLeft=12;verticalAlign=top;spacingTop=8;fontStyle=1;" vertex="1" parent="1">
|
||||
<mxGeometry x="220" y="150" width="400" height="140" as="geometry" />
|
||||
</mxCell>
|
||||
<mxCell id="preview" value="PreviewAsync → diff vs target DB → ImportPreview" style="rounded=1;whiteSpace=wrap;html=1;fillColor=#fff2cc;strokeColor=#d6b656;" vertex="1" parent="1">
|
||||
<mxGeometry x="220" y="350" width="400" height="50" as="geometry" />
|
||||
</mxCell>
|
||||
<mxCell id="review" value="(user reviews + resolves conflicts)" style="whiteSpace=wrap;html=1;fillColor=none;strokeColor=none;fontStyle=2;align=left;" vertex="1" parent="1">
|
||||
<mxGeometry x="630" y="425" width="240" height="30" as="geometry" />
|
||||
</mxCell>
|
||||
<mxCell id="apply" value="ApplyAsync (single EF transaction)   · run two-tier semantic validation     (minimal name scan + full SemanticValidator)   · apply resolutions (add / overwrite / skip / rename)   · upsert TemplateFolder hierarchy   · IAuditService.LogAsync(BundleImported …)   · commit" style="rounded=1;whiteSpace=wrap;html=1;fillColor=#e1d5e7;strokeColor=#9673a6;align=left;spacingLeft=12;verticalAlign=top;spacingTop=8;fontStyle=1;" vertex="1" parent="1">
|
||||
<mxGeometry x="220" y="460" width="400" height="160" as="geometry" />
|
||||
</mxCell>
|
||||
<mxCell id="result" value="ImportResult → UI step 5" style="rounded=1;whiteSpace=wrap;html=1;fillColor=#dae8fc;strokeColor=#6c8ebf;" vertex="1" parent="1">
|
||||
<mxGeometry x="260" y="680" width="320" height="50" as="geometry" />
|
||||
</mxCell>
|
||||
<mxCell id="deployments" value=""View on Deployments →" (existing page)" style="rounded=1;whiteSpace=wrap;html=1;fillColor=#ffe6cc;strokeColor=#d79b00;fontStyle=1;" vertex="1" parent="1">
|
||||
<mxGeometry x="260" y="780" width="320" height="50" as="geometry" />
|
||||
</mxCell>
|
||||
<mxCell id="e0" style="edgeStyle=orthogonalEdgeStyle;rounded=0;html=1;endArrow=block;" edge="1" parent="1" source="user" target="load">
|
||||
<mxGeometry relative="1" as="geometry" />
|
||||
</mxCell>
|
||||
<mxCell id="e1" style="edgeStyle=orthogonalEdgeStyle;rounded=0;html=1;endArrow=block;" edge="1" parent="1" source="load" target="preview">
|
||||
<mxGeometry relative="1" as="geometry" />
|
||||
</mxCell>
|
||||
<mxCell id="e2" style="edgeStyle=orthogonalEdgeStyle;rounded=0;html=1;endArrow=block;" edge="1" parent="1" source="preview" target="apply">
|
||||
<mxGeometry relative="1" as="geometry" />
|
||||
</mxCell>
|
||||
<mxCell id="e2b" style="edgeStyle=orthogonalEdgeStyle;rounded=0;html=1;endArrow=none;dashed=1;exitX=1;exitY=0.5;exitDx=0;exitDy=0;" edge="1" parent="1" source="preview" target="review">
|
||||
<mxGeometry relative="1" as="geometry" />
|
||||
</mxCell>
|
||||
<mxCell id="e3" style="edgeStyle=orthogonalEdgeStyle;rounded=0;html=1;endArrow=block;" edge="1" parent="1" source="apply" target="result">
|
||||
<mxGeometry relative="1" as="geometry" />
|
||||
</mxCell>
|
||||
<mxCell id="e4" style="edgeStyle=orthogonalEdgeStyle;rounded=0;html=1;endArrow=block;" edge="1" parent="1" source="result" target="deployments">
|
||||
<mxGeometry relative="1" as="geometry" />
|
||||
</mxCell>
|
||||
</root>
|
||||
</mxGraphModel>
|
||||
</diagram>
|
||||
</mxfile>
|
||||
|
After Width: | Height: | Size: 282 KiB |