Skip to content

Commit 48a71ef

Browse files
committed
Fix further inconsistencies.
1 parent 607eee7 commit 48a71ef

4 files changed

Lines changed: 40 additions & 32 deletions

File tree

02-inconsistency.md

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -83,14 +83,14 @@ Time →
8383
California node: curtail -80 ──────────────────────────► gm1 sees it first
8484
New York node: dispatch +100 ────────────► gm1 sees it second
8585
86-
gm1 final: -130 MW ✓ no event
86+
gm1 final: -50 MW ✓ no event
8787
8888
California node: curtail -80 ────────────────────────────────────────────────► gm2 sees it second
8989
New York node: dispatch +100 ──────────────────────────────► gm2 sees it first
9090
91-
gm2 final: -50 MW ✓ no event
91+
gm2 final: -130 MW ✓ no event
9292
93-
But gm1 (-130) ≠ gm2 (-50): INCONSISTENT STATE!
93+
But gm1 (-50) ≠ gm2 (-130): INCONSISTENT STATE!
9494
```
9595

9696
In a real grid, this inconsistency means the two control centers have **contradictory views of grid health**. Automated systems making decisions based on these views could take opposing corrective actions, worsening the situation.

06-cal-theorem.md

Lines changed: 22 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -28,34 +28,31 @@ The CAL theorem says that strong consistency requires enough waiting, or enough
2828

2929
## The Design Space, Summarized
3030

31-
Here is a map of the designs from this tutorial against the consistency-availability tradeoff:
31+
Here is a map of the designs from this tutorial against the consistency-availability tradeoff. Step 5 is shown as two paths because it deliberately gives different guarantees to different classes of commands:
3232

3333
```
3434
CONSISTENCY
35-
36-
│ Step 4 (Chandy-Misra, maxwait=forever)
37-
│ Strong consistency
38-
│ Availability: unbounded wait on failure
39-
40-
│ Step 3 (Timestamps, finite maxwait)
41-
│ Strong consistency when maxwait ≥ latency
42-
│ Availability: bounded wait (<= maxwait)
43-
│ Risk: fault is possible if maxwait < actual latency
44-
45-
│ Step 5 (Hybrid)
46-
│ Strong consistency for curtailments (maxwait=forever)
47-
│ Bounded availability for dispatches (maxwait=30ms)
48-
│ Fault handler handles occasional stale estimates
49-
50-
│ Step 2 (Non-commutative, no coordination)
51-
│ No consistency (permanent divergence)
52-
│ High availability (no wait)
53-
54-
│ Step 1 (Commutative CRDT)
55-
│ Eventual consistency
56-
│ Maximum availability (no wait)
57-
58-
└────────────────────────────────────────────► AVAILABILITY
35+
strong ▲ Step 4: conservative coordination
36+
│ Strong consistency; may wait forever if an upstream node stops.
37+
38+
│ Step 5 slow path: curtailments
39+
│ Same strong-consistency path as Step 4 for high-risk commands.
40+
41+
│ Step 3: finite maxwait
42+
│ Strong consistency only while apparent latency <= maxwait;
43+
│ otherwise the tardy handler is part of the design.
44+
45+
eventual│ Step 5 fast path: dispatch-up
46+
│ Fast response with later reconciliation.
47+
48+
│ Step 1: commutative actor
49+
│ Eventual consistency and maximum availability.
50+
51+
none │ Step 2: non-commutative actor
52+
│ High availability, but possible permanent divergence.
53+
54+
└────────────────────────────────────────────────────────► AVAILABILITY
55+
low / may block high / responds fast
5956
```
6057

6158
---

src/Step2_Inconsistency.lf

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -96,7 +96,7 @@ reactor InconsistentGridManager(node_id: int = 1) {
9696
// ------------------------------------------------------------
9797
federated reactor {
9898
gi1 = new GridInterface(id=1, node_name="California")
99-
gi2 = new GridInterface(id=2, node_name="NewYork")
99+
gi2 = new GridInterface(id=2, node_name="New York")
100100
gm1 = new InconsistentGridManager(node_id=1)
101101
gm2 = new InconsistentGridManager(node_id=2)
102102

src/Step3_Timestamps.lf

Lines changed: 14 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -91,6 +91,17 @@ reactor GridManager {
9191
}
9292
}
9393
lf_set(out, self->balance);
94+
=} tardy {=
95+
tag_t intended_tag;
96+
if (in1->is_present) {
97+
intended_tag = in1->intended_tag;
98+
} else {
99+
intended_tag = in2->intended_tag;
100+
}
101+
lf_print_warning("[ts=%lld] Tardy message with intended timestamp %lld received at physical time %lld",
102+
lf_time_logical_elapsed(),
103+
intended_tag.time - lf_time_start(),
104+
lf_time_physical_elapsed());
94105
=}
95106
}
96107

@@ -101,7 +112,7 @@ reactor GridManager {
101112
// ------------------------------------------------------------
102113
federated reactor {
103114
gi1 = new GridInterface(id=1, node_name="California")
104-
gi2 = new GridInterface(id=2, node_name="NewYork")
115+
gi2 = new GridInterface(id=2, node_name="New York")
105116

106117
// maxwait: physical time to wait before assuming no more messages will
107118
// arrive at a given logical time or earlier. A tardy message is one that
@@ -112,9 +123,9 @@ federated reactor {
112123
// maxwait = 100 ms: safe for cross-continental links with NTP sync.
113124
// A smaller maxwait will improve responsiveness, but increase the risk
114125
// of tardy messages.
115-
@maxwait(1 us)
126+
@maxwait(100 ms)
116127
gm1 = new GridManager()
117-
@maxwait(1 us)
128+
@maxwait(100 ms)
118129
gm2 = new GridManager()
119130

120131
gi1.command -> gm1.in1 // Logical connections: timestamps are carried and ordering is enforced.

0 commit comments

Comments
 (0)