Files
ScadaBridge/docs/plans/diagrams/primary-backup-failover-state-machine.drawio
T
Joseph Doherty bdee12f4e9 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.
2026-05-31 23:32:53 -04:00

167 lines
8.4 KiB
Plaintext

<mxfile host="app.diagrams.net">
<diagram id="failover" name="Failover State Machine">
<mxGraphModel dx="1200" dy="900" grid="1" gridSize="10" guides="1" arrows="1"
fold="1" page="1" pageScale="1" pageWidth="1100" pageHeight="1300" math="0" shadow="0">
<root>
<mxCell id="0" />
<mxCell id="1" parent="0" />
<!-- Connected (start state) -->
<mxCell id="connected" value="Connected"
style="rounded=1;arcSize=40;whiteSpace=wrap;html=1;fillColor=#d5e8d4;strokeColor=#82b366;fontSize=14;fontStyle=1;"
vertex="1" parent="1">
<mxGeometry x="420" y="40" width="200" height="50" as="geometry" />
</mxCell>
<!-- Push bad quality -->
<mxCell id="badquality" value="Push bad quality&#10;to all subscribers"
style="rounded=1;whiteSpace=wrap;html=1;fillColor=#dae8fc;strokeColor=#6c8ebf;fontSize=13;"
vertex="1" parent="1">
<mxGeometry x="420" y="150" width="200" height="50" as="geometry" />
</mxCell>
<!-- Retry active endpoint -->
<mxCell id="retry" value="Retry active endpoint&#10;(5s interval)"
style="rounded=1;whiteSpace=wrap;html=1;fillColor=#dae8fc;strokeColor=#6c8ebf;fontSize=13;"
vertex="1" parent="1">
<mxGeometry x="420" y="260" width="200" height="50" as="geometry" />
</mxCell>
<!-- _consecutiveFailures++ -->
<mxCell id="incr" value="_consecutiveFailures++"
style="rounded=1;whiteSpace=wrap;html=1;fillColor=#fff2cc;strokeColor=#d6b656;fontSize=13;"
vertex="1" parent="1">
<mxGeometry x="420" y="370" width="200" height="50" as="geometry" />
</mxCell>
<!-- Branch decision diamond -->
<mxCell id="branch" value="Evaluate&#10;_consecutiveFailures"
style="rhombus;whiteSpace=wrap;html=1;fillColor=#fff2cc;strokeColor=#d6b656;fontSize=12;"
vertex="1" parent="1">
<mxGeometry x="450" y="470" width="140" height="100" as="geometry" />
</mxCell>
<!-- Branch 1: retry same endpoint -->
<mxCell id="same" value="Retry same endpoint"
style="rounded=1;whiteSpace=wrap;html=1;fillColor=#dae8fc;strokeColor=#6c8ebf;fontSize=13;"
vertex="1" parent="1">
<mxGeometry x="80" y="495" width="200" height="50" as="geometry" />
</mxCell>
<!-- Branch 2: failover to backup -->
<mxCell id="failover" value="Failover&#10;&#8226; dispose adapter, switch _activeEndpoint, reset counter&#10;&#8226; create fresh adapter with other config&#10;&#8226; attempt connect"
style="rounded=1;whiteSpace=wrap;html=1;fillColor=#ffe6cc;strokeColor=#d79b00;fontSize=12;align=left;spacingLeft=8;verticalAlign=middle;"
vertex="1" parent="1">
<mxGeometry x="380" y="640" width="280" height="110" as="geometry" />
</mxCell>
<!-- Branch 3: no backup -->
<mxCell id="nobackup" value="Keep retrying indefinitely&#10;(current behavior)"
style="rounded=1;whiteSpace=wrap;html=1;fillColor=#f8cecc;strokeColor=#b85450;fontSize=13;"
vertex="1" parent="1">
<mxGeometry x="760" y="495" width="220" height="60" as="geometry" />
</mxCell>
<!-- Successful reconnect outcome -->
<mxCell id="reconnect" value="On successful reconnect (either endpoint)&#10;1. Reset _consecutiveFailures = 0&#10;2. ReSubscribeAll() — re-create subscriptions on new adapter&#10;3. Transition to Connected&#10;4. Log failover event if endpoint changed&#10;5. Report active endpoint in health metrics"
style="rounded=1;whiteSpace=wrap;html=1;fillColor=#d5e8d4;strokeColor=#82b366;fontSize=12;align=left;spacingLeft=10;verticalAlign=middle;"
vertex="1" parent="1">
<mxGeometry x="360" y="830" width="320" height="140" as="geometry" />
</mxCell>
<!-- Edges -->
<mxCell id="e1" value="disconnect detected"
style="edgeStyle=orthogonalEdgeStyle;rounded=0;html=1;endArrow=block;fontSize=12;"
edge="1" parent="1" source="connected" target="badquality">
<mxGeometry relative="1" as="geometry" />
</mxCell>
<mxCell id="e2" style="edgeStyle=orthogonalEdgeStyle;rounded=0;html=1;endArrow=block;"
edge="1" parent="1" source="badquality" target="retry">
<mxGeometry relative="1" as="geometry" />
</mxCell>
<mxCell id="e3" value="failure"
style="edgeStyle=orthogonalEdgeStyle;rounded=0;html=1;endArrow=block;fontSize=12;"
edge="1" parent="1" source="retry" target="incr">
<mxGeometry relative="1" as="geometry" />
</mxCell>
<mxCell id="e4" style="edgeStyle=orthogonalEdgeStyle;rounded=0;html=1;endArrow=block;"
edge="1" parent="1" source="incr" target="branch">
<mxGeometry relative="1" as="geometry" />
</mxCell>
<!-- Branch 1 edge -->
<mxCell id="b1" value="&lt; FailoverRetryCount"
style="edgeStyle=orthogonalEdgeStyle;rounded=0;html=1;endArrow=block;fontSize=11;"
edge="1" parent="1" source="branch" target="same">
<mxGeometry relative="1" as="geometry" />
</mxCell>
<!-- Branch 1 loops back to retry -->
<mxCell id="b1loop" value="retry"
style="edgeStyle=orthogonalEdgeStyle;rounded=0;html=1;endArrow=block;fontSize=11;dashed=1;"
edge="1" parent="1" source="same" target="retry">
<mxGeometry relative="1" as="geometry">
<Array as="points">
<mxPoint x="180" y="285" />
</Array>
</mxGeometry>
</mxCell>
<!-- Branch 2 edge -->
<mxCell id="b2" value="&#8805; FailoverRetryCount&#10;AND backup exists"
style="edgeStyle=orthogonalEdgeStyle;rounded=0;html=1;endArrow=block;fontSize=11;"
edge="1" parent="1" source="branch" target="failover">
<mxGeometry relative="1" as="geometry" />
</mxCell>
<!-- Branch 3 edge -->
<mxCell id="b3" value="&#8805; FailoverRetryCount&#10;AND no backup"
style="edgeStyle=orthogonalEdgeStyle;rounded=0;html=1;endArrow=block;fontSize=11;"
edge="1" parent="1" source="branch" target="nobackup">
<mxGeometry relative="1" as="geometry" />
</mxCell>
<!-- no backup loops back to retry -->
<mxCell id="b3loop" value="retry (round-robin n/a)"
style="edgeStyle=orthogonalEdgeStyle;rounded=0;html=1;endArrow=block;fontSize=11;dashed=1;"
edge="1" parent="1" source="nobackup" target="retry">
<mxGeometry relative="1" as="geometry">
<Array as="points">
<mxPoint x="870" y="285" />
</Array>
</mxGeometry>
</mxCell>
<!-- failover -> attempt connect -> success -> reconnect -->
<mxCell id="b2ok" value="connect succeeds"
style="edgeStyle=orthogonalEdgeStyle;rounded=0;html=1;endArrow=block;fontSize=11;"
edge="1" parent="1" source="failover" target="reconnect">
<mxGeometry relative="1" as="geometry" />
</mxCell>
<!-- failover -> attempt connect -> failure -> back to retry loop -->
<mxCell id="b2fail" value="connect fails&#10;(round-robin: primary &#8594; backup &#8594; primary...)"
style="edgeStyle=orthogonalEdgeStyle;rounded=0;html=1;endArrow=block;fontSize=11;dashed=1;"
edge="1" parent="1" source="failover" target="retry">
<mxGeometry relative="1" as="geometry">
<Array as="points">
<mxPoint x="700" y="695" />
<mxPoint x="700" y="285" />
</Array>
</mxGeometry>
</mxCell>
<!-- reconnect -> Connected -->
<mxCell id="bdone" value="Transition to Connected"
style="edgeStyle=orthogonalEdgeStyle;rounded=0;html=1;endArrow=block;fontSize=11;"
edge="1" parent="1" source="reconnect" target="connected">
<mxGeometry relative="1" as="geometry">
<Array as="points">
<mxPoint x="320" y="900" />
<mxPoint x="320" y="65" />
</Array>
</mxGeometry>
</mxCell>
</root>
</mxGraphModel>
</diagram>
</mxfile>