@zukhruf/single-flight 0.3.19 → 0.3.21

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (45) hide show
  1. package/README.md +28 -17
  2. package/dist/client/flight-client.d.ts +9 -1
  3. package/dist/client/flight-client.d.ts.map +1 -1
  4. package/dist/client/flight-client.js +86 -16
  5. package/dist/client/flight-client.js.map +1 -1
  6. package/dist/coordinator/flight-coordinator.d.ts +24 -12
  7. package/dist/coordinator/flight-coordinator.d.ts.map +1 -1
  8. package/dist/coordinator/flight-coordinator.js +92 -143
  9. package/dist/coordinator/flight-coordinator.js.map +1 -1
  10. package/dist/coordinator/flight-server.d.ts +7 -7
  11. package/dist/coordinator/flight-server.d.ts.map +1 -1
  12. package/dist/coordinator/flight-server.js +7 -13
  13. package/dist/coordinator/flight-server.js.map +1 -1
  14. package/dist/coordinator/flight.d.ts +13 -2
  15. package/dist/coordinator/flight.d.ts.map +1 -1
  16. package/dist/coordinator/flight.js +20 -4
  17. package/dist/coordinator/flight.js.map +1 -1
  18. package/dist/coordinator/parked-runs.d.ts +26 -0
  19. package/dist/coordinator/parked-runs.d.ts.map +1 -0
  20. package/dist/coordinator/parked-runs.js +65 -0
  21. package/dist/coordinator/parked-runs.js.map +1 -0
  22. package/dist/coordinator/party.d.ts +1 -1
  23. package/dist/coordinator/party.d.ts.map +1 -1
  24. package/dist/coordinator/session.d.ts.map +1 -1
  25. package/dist/coordinator/session.js +6 -3
  26. package/dist/coordinator/session.js.map +1 -1
  27. package/dist/index.d.ts +1 -0
  28. package/dist/index.d.ts.map +1 -1
  29. package/dist/index.js +1 -0
  30. package/dist/index.js.map +1 -1
  31. package/dist/key-lock/key-hold.d.ts +16 -0
  32. package/dist/key-lock/key-hold.d.ts.map +1 -0
  33. package/dist/key-lock/key-hold.js +24 -0
  34. package/dist/key-lock/key-hold.js.map +1 -0
  35. package/dist/key-lock/key-locks.d.ts +35 -0
  36. package/dist/key-lock/key-locks.d.ts.map +1 -0
  37. package/dist/key-lock/key-locks.js +67 -0
  38. package/dist/key-lock/key-locks.js.map +1 -0
  39. package/dist/protocol/flight-protocol.d.ts +2 -2
  40. package/dist/protocol/flight-protocol.d.ts.map +1 -1
  41. package/dist/single-flight.d.ts +4 -12
  42. package/dist/single-flight.d.ts.map +1 -1
  43. package/dist/single-flight.js +36 -29
  44. package/dist/single-flight.js.map +1 -1
  45. package/package.json +7 -8
@@ -1,186 +1,135 @@
1
- import { Latch } from '@zukhruf/async';
2
1
  import { Flight } from "./flight.js";
2
+ import { ParkedRuns } from "./parked-runs.js";
3
3
  import { Session } from "./session.js";
4
4
  /**
5
5
  * Coordinates the flights of one term. A run leads a new flight of its key, or
6
6
  * joins the flight of that key in progress, in one step, so two runs never
7
7
  * both lead. The outcome is pushed to every joiner as soon as it lands.
8
+ *
9
+ * A key whose lock another process holds, while no flight of it is known
10
+ * here, runs the work of a leader that has not reasserted its flight yet, so
11
+ * its runs and rejoins wait for that flight or for the lock to free. A leader
12
+ * keeps its flight while its process lives.
8
13
  */
9
14
  export class FlightCoordinator {
10
- #phase;
11
- constructor({ tokens, graceWindow }) {
12
- const flights = new Map();
13
- const coordinating = new Coordinating(flights, tokens);
14
- if (graceWindow > 0) {
15
- const over = new Latch();
16
- this.#phase = new GraceWindow(flights, over, coordinating);
17
- setTimeout(() => {
18
- // Coordinating is current before the latch lets the waiting runs resume.
19
- this.#phase = coordinating;
20
- over.open();
21
- }, graceWindow).unref();
22
- }
23
- else {
24
- this.#phase = coordinating;
25
- }
26
- }
27
- /**
28
- * Whether the next coordinator would find nothing to recover: no flight is
29
- * in progress, and the grace window is over or there was none.
30
- */
31
- get leavesNothingToRecover() {
32
- return this.#phase.leavesNothingToRecover;
15
+ #flights = new Map();
16
+ /** The latest ending of a reasserted flight, per key. */
17
+ #endings = new Map();
18
+ #tokens;
19
+ #locks;
20
+ #parked;
21
+ #closing = new AbortController();
22
+ constructor({ tokens, locks }) {
23
+ this.#tokens = tokens;
24
+ this.#locks = locks;
25
+ this.#parked = new ParkedRuns(locks, this.#closing.signal);
33
26
  }
34
27
  serve(connection) {
35
28
  new Session(this, connection);
36
29
  }
37
- run(party, key) {
38
- return this.#phase.run(party, key);
39
- }
40
- /** A joiner that lost its connection, back for the flight it joined: it never leads, so its work never runs twice. */
41
- rejoin(party, key, flight) {
42
- return this.#phase.rejoin(party, key, flight);
43
- }
44
- reassert(party, key, token) {
45
- this.#phase.reassert(party, key, token);
46
- }
47
- land(flight, outcome) {
48
- this.#phase.land(flight, outcome);
49
- }
50
- /** The leader withdrew or its connection is gone. */
51
- interrupt(flight) {
52
- this.#phase.interrupt(flight);
53
- }
54
- }
55
- /** The only phase that starts flights. A leader that reasserts now is too late. */
56
- class Coordinating {
57
- #flights;
58
- #tokens;
59
- constructor(flights, tokens) {
60
- this.#flights = flights;
61
- this.#tokens = tokens;
62
- }
63
- get leavesNothingToRecover() {
64
- return this.#flights.size === 0;
30
+ /** Stops watching the locks of the keys whose runs wait. */
31
+ close() {
32
+ this.#closing.abort();
65
33
  }
34
+ /** Rejects only when no token can be minted. */
66
35
  async run(party, key) {
67
36
  // A token that goes unused is harmless: tokens only need to grow.
68
- const token = await this.#tokens.next(key);
69
- // The client may have withdrawn the run while the token was minted.
70
- if (!party.waiting)
71
- return;
72
- const inProgress = this.#flights.get(key);
73
- if (inProgress)
74
- return inProgress.add(party);
75
- const flight = new Flight(key, token, party);
76
- this.#flights.set(key, flight);
77
- party.lead(flight);
37
+ this.#decide(party, key, await this.#tokens.next(key));
78
38
  }
79
- /** A rejoin joins only its own flight; any other answer could be a second run of the work. */
80
- async rejoin(party, key, flight) {
39
+ /**
40
+ * A joiner that lost its connection, back for the flight it joined: it never
41
+ * leads, so its work never runs twice. A rejoin joins only its own flight;
42
+ * any other answer could be a second run of the work.
43
+ */
44
+ rejoin(party, key, flight) {
81
45
  if (!party.waiting)
82
46
  return;
83
47
  const inProgress = this.#flights.get(key);
84
48
  if (inProgress?.is(flight))
85
49
  return inProgress.add(party);
50
+ const ending = this.#endings.get(key);
51
+ if (ending?.flight.is(flight))
52
+ return party.end(ending.answer);
53
+ // Its leader may still run the work, and not have reasserted it yet.
54
+ if (!inProgress && this.#held(key)) {
55
+ return this.#parked.park(key, party, () => this.rejoin(party, key, flight));
56
+ }
86
57
  party.end({ op: 'interrupted' });
87
58
  }
88
- reassert(party) {
89
- party.end({ op: 'rejected' });
59
+ /**
60
+ * A leader claims its flight again after its connection was lost. The same
61
+ * flight, through a new connection, stays one flight with its joiners. For
62
+ * two flights of one key, the newer token wins, and the older flight is lost.
63
+ */
64
+ reassert(party, key, token) {
65
+ const claimed = this.#flights.get(key);
66
+ if (claimed?.token.value === token.value)
67
+ return claimed.handOver(party);
68
+ if (claimed && !token.isNewerThan(claimed.token)) {
69
+ return party.end({ op: 'rejected' });
70
+ }
71
+ if (claimed) {
72
+ claimed.leader.end({ op: 'rejected' });
73
+ this.interrupt(claimed);
74
+ }
75
+ this.#start(new Flight(key, token, party, { reasserted: true }), (flight) => party.resume(flight));
90
76
  }
91
77
  land(flight, outcome) {
92
- this.#forget(flight);
78
+ this.#end(flight, { op: 'landed', outcome });
93
79
  flight.land(outcome);
94
80
  }
81
+ /** The leader withdrew or its connection is gone. */
95
82
  interrupt(flight) {
96
- this.#forget(flight);
83
+ this.#end(flight, { op: 'interrupted' });
97
84
  flight.interrupt();
98
85
  }
99
- #forget(flight) {
86
+ /** Every new flight takes the runs parked on its key, in the step that starts it. */
87
+ #start(flight, tell) {
88
+ this.#flights.set(flight.key, flight);
89
+ tell(flight);
90
+ this.#parked.wake(flight.key);
91
+ }
92
+ #end(flight, answer) {
100
93
  if (this.#flights.get(flight.key) === flight) {
101
94
  this.#flights.delete(flight.key);
102
95
  }
103
- }
104
- }
105
- /** Starts no flight, so leaders from a previous coordinator can reassert theirs first. */
106
- class GraceWindow {
107
- #flights;
108
- #over;
109
- #next;
110
- #endings = new Map();
111
- /** Wakes the rejoins that wait for a reassertion of their key. */
112
- #wakers = new Map();
113
- constructor(flights, over, next) {
114
- this.#flights = flights;
115
- this.#over = over;
116
- this.#next = next;
117
- }
118
- /** A leader of the previous term may not have reasserted its flight yet, so this coordinator cannot know. */
119
- get leavesNothingToRecover() {
120
- return false;
121
- }
122
- /** A fresh run leads or joins only once every leader had its chance to reassert. */
123
- async run(party, key) {
124
- await this.#over.wait();
125
- return this.#next.run(party, key);
96
+ if (flight.reasserted)
97
+ this.#endings.set(flight.key, { flight, answer });
126
98
  }
127
99
  /**
128
- * A rejoin gets its flight's outcome when the flight's leader reasserted it
129
- * and it ends during the window, and joins it while it is in progress. Once
130
- * the window ends, it is answered as in any other phase.
100
+ * Joins the flight of `key` in progress, waits while another process holds
101
+ * the key, or leads. A flight of the key that starts while the run waits
102
+ * takes it in the step that starts it, so a landing read right behind a
103
+ * reassertion reaches it.
131
104
  */
132
- async rejoin(party, key, flight) {
133
- const over = this.#over.wait().then(() => 'over');
134
- for (;;) {
135
- if (!party.waiting)
136
- return;
137
- const inProgress = this.#flights.get(key);
138
- if (inProgress?.is(flight))
139
- return inProgress.add(party);
140
- const ending = this.#endings.get(key);
141
- if (ending?.flight.is(flight)) {
142
- return party.end('landed' in ending
143
- ? { op: 'landed', outcome: ending.landed }
144
- : { op: 'interrupted' });
145
- }
146
- const woken = await Promise.race([over, this.#reassertionOf(key)]);
147
- if (woken === 'over')
148
- return this.#next.rejoin(party, key, flight);
105
+ #decide(party, key, token) {
106
+ // The client may have withdrawn the run while the token was minted or while it waited.
107
+ if (!party.waiting || this.#join(party, key))
108
+ return;
109
+ if (this.#held(key)) {
110
+ return this.#parked.park(key, party, () => this.#decide(party, key, token));
149
111
  }
112
+ // No flight of the key started while the run waited, so its token is still newer than every flight of the key.
113
+ this.#start(new Flight(key, token, party), (flight) => party.lead(flight));
150
114
  }
151
- /** For two claims on one key, the newer token wins, and the older flight is lost. */
152
- reassert(party, key, token) {
153
- const claimed = this.#flights.get(key);
154
- if (claimed && !token.isNewerThan(claimed.token)) {
155
- return party.end({ op: 'rejected' });
115
+ /** Joins `party` to the flight of `key` in progress, if there is one. */
116
+ #join(party, key) {
117
+ const inProgress = this.#flights.get(key);
118
+ inProgress?.add(party);
119
+ return inProgress !== undefined;
120
+ }
121
+ /**
122
+ * The lock check is advice only (F5). A fault answers "not held", so the
123
+ * run leads and its leader's own lock decides; a fault never rejects a run
124
+ * or a rejoin, which would close its connection.
125
+ */
126
+ #held(key) {
127
+ try {
128
+ return this.#locks.isHeld(key);
156
129
  }
157
- if (claimed) {
158
- claimed.leader.end({ op: 'rejected' });
159
- this.interrupt(claimed);
130
+ catch {
131
+ return false;
160
132
  }
161
- const flight = new Flight(key, token, party);
162
- this.#flights.set(key, flight);
163
- party.resume(flight);
164
- const wakers = this.#wakers.get(key);
165
- this.#wakers.delete(key);
166
- for (const wake of wakers ?? [])
167
- wake();
168
- }
169
- land(flight, outcome) {
170
- this.#endings.set(flight.key, { flight, landed: outcome });
171
- this.#next.land(flight, outcome);
172
- }
173
- interrupt(flight) {
174
- this.#endings.set(flight.key, { flight, interrupted: true });
175
- this.#next.interrupt(flight);
176
- }
177
- #reassertionOf(key) {
178
- const { promise, resolve } = Promise.withResolvers();
179
- let wakers = this.#wakers.get(key);
180
- if (!wakers)
181
- this.#wakers.set(key, (wakers = new Set()));
182
- wakers.add(() => resolve('reasserted'));
183
- return promise;
184
133
  }
185
134
  }
186
135
  //# sourceMappingURL=flight-coordinator.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"flight-coordinator.js","sourceRoot":"","sources":["../../src/coordinator/flight-coordinator.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,EAAE,MAAM,gBAAgB,CAAC;AAKvC,OAAO,EAAE,MAAM,EAAE,MAAM,aAAa,CAAC;AAErC,OAAO,EAAE,OAAO,EAAE,MAAM,cAAc,CAAC;AAsBvC;;;;GAIG;AACH,MAAM,OAAO,iBAAiB;IAC5B,MAAM,CAAQ;IAEd,YAAY,EAAE,MAAM,EAAE,WAAW,EAA4B;QAC3D,MAAM,OAAO,GAAG,IAAI,GAAG,EAAkB,CAAC;QAC1C,MAAM,YAAY,GAAG,IAAI,YAAY,CAAC,OAAO,EAAE,MAAM,CAAC,CAAC;QACvD,IAAI,WAAW,GAAG,CAAC,EAAE,CAAC;YACpB,MAAM,IAAI,GAAG,IAAI,KAAK,EAAE,CAAC;YACzB,IAAI,CAAC,MAAM,GAAG,IAAI,WAAW,CAAC,OAAO,EAAE,IAAI,EAAE,YAAY,CAAC,CAAC;YAC3D,UAAU,CAAC,GAAG,EAAE;gBACd,yEAAyE;gBACzE,IAAI,CAAC,MAAM,GAAG,YAAY,CAAC;gBAC3B,IAAI,CAAC,IAAI,EAAE,CAAC;YACd,CAAC,EAAE,WAAW,CAAC,CAAC,KAAK,EAAE,CAAC;QAC1B,CAAC;aAAM,CAAC;YACN,IAAI,CAAC,MAAM,GAAG,YAAY,CAAC;QAC7B,CAAC;IACH,CAAC;IAED;;;OAGG;IACH,IAAI,sBAAsB;QACxB,OAAO,IAAI,CAAC,MAAM,CAAC,sBAAsB,CAAC;IAC5C,CAAC;IAED,KAAK,CAAC,UAAsC;QAC1C,IAAI,OAAO,CAAC,IAAI,EAAE,UAAU,CAAC,CAAC;IAChC,CAAC;IAED,GAAG,CAAC,KAAY,EAAE,GAAW;QAC3B,OAAO,IAAI,CAAC,MAAM,CAAC,GAAG,CAAC,KAAK,EAAE,GAAG,CAAC,CAAC;IACrC,CAAC;IAED,sHAAsH;IACtH,MAAM,CAAC,KAAY,EAAE,GAAW,EAAE,MAAc;QAC9C,OAAO,IAAI,CAAC,MAAM,CAAC,MAAM,CAAC,KAAK,EAAE,GAAG,EAAE,MAAM,CAAC,CAAC;IAChD,CAAC;IAED,QAAQ,CAAC,KAAY,EAAE,GAAW,EAAE,KAAmB;QACrD,IAAI,CAAC,MAAM,CAAC,QAAQ,CAAC,KAAK,EAAE,GAAG,EAAE,KAAK,CAAC,CAAC;IAC1C,CAAC;IAED,IAAI,CAAC,MAAc,EAAE,OAAgB;QACnC,IAAI,CAAC,MAAM,CAAC,IAAI,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IACpC,CAAC;IAED,qDAAqD;IACrD,SAAS,CAAC,MAAc;QACtB,IAAI,CAAC,MAAM,CAAC,SAAS,CAAC,MAAM,CAAC,CAAC;IAChC,CAAC;CACF;AAED,mFAAmF;AACnF,MAAM,YAAY;IACP,QAAQ,CAAsB;IAC9B,OAAO,CAAc;IAE9B,YAAY,OAA4B,EAAE,MAAmB;QAC3D,IAAI,CAAC,QAAQ,GAAG,OAAO,CAAC;QACxB,IAAI,CAAC,OAAO,GAAG,MAAM,CAAC;IACxB,CAAC;IAED,IAAI,sBAAsB;QACxB,OAAO,IAAI,CAAC,QAAQ,CAAC,IAAI,KAAK,CAAC,CAAC;IAClC,CAAC;IAED,KAAK,CAAC,GAAG,CAAC,KAAY,EAAE,GAAW;QACjC,kEAAkE;QAClE,MAAM,KAAK,GAAG,MAAM,IAAI,CAAC,OAAO,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;QAC3C,oEAAoE;QACpE,IAAI,CAAC,KAAK,CAAC,OAAO;YAAE,OAAO;QAC3B,MAAM,UAAU,GAAG,IAAI,CAAC,QAAQ,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC;QAC1C,IAAI,UAAU;YAAE,OAAO,UAAU,CAAC,GAAG,CAAC,KAAK,CAAC,CAAC;QAC7C,MAAM,MAAM,GAAG,IAAI,MAAM,CAAC,GAAG,EAAE,KAAK,EAAE,KAAK,CAAC,CAAC;QAC7C,IAAI,CAAC,QAAQ,CAAC,GAAG,CAAC,GAAG,EAAE,MAAM,CAAC,CAAC;QAC/B,KAAK,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC;IACrB,CAAC;IAED,8FAA8F;IAC9F,KAAK,CAAC,MAAM,CAAC,KAAY,EAAE,GAAW,EAAE,MAAc;QACpD,IAAI,CAAC,KAAK,CAAC,OAAO;YAAE,OAAO;QAC3B,MAAM,UAAU,GAAG,IAAI,CAAC,QAAQ,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC;QAC1C,IAAI,UAAU,EAAE,EAAE,CAAC,MAAM,CAAC;YAAE,OAAO,UAAU,CAAC,GAAG,CAAC,KAAK,CAAC,CAAC;QACzD,KAAK,CAAC,GAAG,CAAC,EAAE,EAAE,EAAE,aAAa,EAAE,CAAC,CAAC;IACnC,CAAC;IAED,QAAQ,CAAC,KAAY;QACnB,KAAK,CAAC,GAAG,CAAC,EAAE,EAAE,EAAE,UAAU,EAAE,CAAC,CAAC;IAChC,CAAC;IAED,IAAI,CAAC,MAAc,EAAE,OAAgB;QACnC,IAAI,CAAC,OAAO,CAAC,MAAM,CAAC,CAAC;QACrB,MAAM,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC;IACvB,CAAC;IAED,SAAS,CAAC,MAAc;QACtB,IAAI,CAAC,OAAO,CAAC,MAAM,CAAC,CAAC;QACrB,MAAM,CAAC,SAAS,EAAE,CAAC;IACrB,CAAC;IAED,OAAO,CAAC,MAAc;QACpB,IAAI,IAAI,CAAC,QAAQ,CAAC,GAAG,CAAC,MAAM,CAAC,GAAG,CAAC,KAAK,MAAM,EAAE,CAAC;YAC7C,IAAI,CAAC,QAAQ,CAAC,MAAM,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC;QACnC,CAAC;IACH,CAAC;CACF;AAOD,0FAA0F;AAC1F,MAAM,WAAW;IACN,QAAQ,CAAsB;IAC9B,KAAK,CAAQ;IACb,KAAK,CAAe;IACpB,QAAQ,GAAG,IAAI,GAAG,EAAkB,CAAC;IAC9C,kEAAkE;IACzD,OAAO,GAAG,IAAI,GAAG,EAA2B,CAAC;IAEtD,YAAY,OAA4B,EAAE,IAAW,EAAE,IAAkB;QACvE,IAAI,CAAC,QAAQ,GAAG,OAAO,CAAC;QACxB,IAAI,CAAC,KAAK,GAAG,IAAI,CAAC;QAClB,IAAI,CAAC,KAAK,GAAG,IAAI,CAAC;IACpB,CAAC;IAED,6GAA6G;IAC7G,IAAI,sBAAsB;QACxB,OAAO,KAAK,CAAC;IACf,CAAC;IAED,oFAAoF;IACpF,KAAK,CAAC,GAAG,CAAC,KAAY,EAAE,GAAW;QACjC,MAAM,IAAI,CAAC,KAAK,CAAC,IAAI,EAAE,CAAC;QACxB,OAAO,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,KAAK,EAAE,GAAG,CAAC,CAAC;IACpC,CAAC;IAED;;;;OAIG;IACH,KAAK,CAAC,MAAM,CAAC,KAAY,EAAE,GAAW,EAAE,MAAc;QACpD,MAAM,IAAI,GAAG,IAAI,CAAC,KAAK,CAAC,IAAI,EAAE,CAAC,IAAI,CAAC,GAAG,EAAE,CAAC,MAAe,CAAC,CAAC;QAC3D,SAAS,CAAC;YACR,IAAI,CAAC,KAAK,CAAC,OAAO;gBAAE,OAAO;YAC3B,MAAM,UAAU,GAAG,IAAI,CAAC,QAAQ,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC;YAC1C,IAAI,UAAU,EAAE,EAAE,CAAC,MAAM,CAAC;gBAAE,OAAO,UAAU,CAAC,GAAG,CAAC,KAAK,CAAC,CAAC;YACzD,MAAM,MAAM,GAAG,IAAI,CAAC,QAAQ,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC;YACtC,IAAI,MAAM,EAAE,MAAM,CAAC,EAAE,CAAC,MAAM,CAAC,EAAE,CAAC;gBAC9B,OAAO,KAAK,CAAC,GAAG,CACd,QAAQ,IAAI,MAAM;oBAChB,CAAC,CAAC,EAAE,EAAE,EAAE,QAAQ,EAAE,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE;oBAC1C,CAAC,CAAC,EAAE,EAAE,EAAE,aAAa,EAAE,CAC1B,CAAC;YACJ,CAAC;YACD,MAAM,KAAK,GAAG,MAAM,OAAO,CAAC,IAAI,CAAC,CAAC,IAAI,EAAE,IAAI,CAAC,cAAc,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC;YACnE,IAAI,KAAK,KAAK,MAAM;gBAAE,OAAO,IAAI,CAAC,KAAK,CAAC,MAAM,CAAC,KAAK,EAAE,GAAG,EAAE,MAAM,CAAC,CAAC;QACrE,CAAC;IACH,CAAC;IAED,qFAAqF;IACrF,QAAQ,CAAC,KAAY,EAAE,GAAW,EAAE,KAAmB;QACrD,MAAM,OAAO,GAAG,IAAI,CAAC,QAAQ,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC;QACvC,IAAI,OAAO,IAAI,CAAC,KAAK,CAAC,WAAW,CAAC,OAAO,CAAC,KAAK,CAAC,EAAE,CAAC;YACjD,OAAO,KAAK,CAAC,GAAG,CAAC,EAAE,EAAE,EAAE,UAAU,EAAE,CAAC,CAAC;QACvC,CAAC;QACD,IAAI,OAAO,EAAE,CAAC;YACZ,OAAO,CAAC,MAAM,CAAC,GAAG,CAAC,EAAE,EAAE,EAAE,UAAU,EAAE,CAAC,CAAC;YACvC,IAAI,CAAC,SAAS,CAAC,OAAO,CAAC,CAAC;QAC1B,CAAC;QACD,MAAM,MAAM,GAAG,IAAI,MAAM,CAAC,GAAG,EAAE,KAAK,EAAE,KAAK,CAAC,CAAC;QAC7C,IAAI,CAAC,QAAQ,CAAC,GAAG,CAAC,GAAG,EAAE,MAAM,CAAC,CAAC;QAC/B,KAAK,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC;QACrB,MAAM,MAAM,GAAG,IAAI,CAAC,OAAO,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC;QACrC,IAAI,CAAC,OAAO,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC;QACzB,KAAK,MAAM,IAAI,IAAI,MAAM,IAAI,EAAE;YAAE,IAAI,EAAE,CAAC;IAC1C,CAAC;IAED,IAAI,CAAC,MAAc,EAAE,OAAgB;QACnC,IAAI,CAAC,QAAQ,CAAC,GAAG,CAAC,MAAM,CAAC,GAAG,EAAE,EAAE,MAAM,EAAE,MAAM,EAAE,OAAO,EAAE,CAAC,CAAC;QAC3D,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IACnC,CAAC;IAED,SAAS,CAAC,MAAc;QACtB,IAAI,CAAC,QAAQ,CAAC,GAAG,CAAC,MAAM,CAAC,GAAG,EAAE,EAAE,MAAM,EAAE,WAAW,EAAE,IAAI,EAAE,CAAC,CAAC;QAC7D,IAAI,CAAC,KAAK,CAAC,SAAS,CAAC,MAAM,CAAC,CAAC;IAC/B,CAAC;IAED,cAAc,CAAC,GAAW;QACxB,MAAM,EAAE,OAAO,EAAE,OAAO,EAAE,GAAG,OAAO,CAAC,aAAa,EAAgB,CAAC;QACnE,IAAI,MAAM,GAAG,IAAI,CAAC,OAAO,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC;QACnC,IAAI,CAAC,MAAM;YAAE,IAAI,CAAC,OAAO,CAAC,GAAG,CAAC,GAAG,EAAE,CAAC,MAAM,GAAG,IAAI,GAAG,EAAE,CAAC,CAAC,CAAC;QACzD,MAAM,CAAC,GAAG,CAAC,GAAG,EAAE,CAAC,OAAO,CAAC,YAAY,CAAC,CAAC,CAAC;QACxC,OAAO,OAAO,CAAC;IACjB,CAAC;CACF"}
1
+ {"version":3,"file":"flight-coordinator.js","sourceRoot":"","sources":["../../src/coordinator/flight-coordinator.ts"],"names":[],"mappings":"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"}
@@ -1,7 +1,8 @@
1
1
  import type { Term } from '@zukhruf/election';
2
+ import type { KeyLocks } from '../key-lock/key-locks.ts';
2
3
  export interface FlightServerOptions {
3
- /** Milliseconds the new term starts no flight, so leaders from the last term can reassert theirs. */
4
- graceWindow: number;
4
+ /** The kernel locks on the keys, which the coordinator checks before a run leads. */
5
+ locks: KeyLocks;
5
6
  }
6
7
  /**
7
8
  * Serves a `FlightCoordinator` on a Unix socket for one term. Lease tokens
@@ -12,18 +13,17 @@ export interface FlightServerOptions {
12
13
  export declare class FlightServer {
13
14
  #private;
14
15
  private constructor();
15
- static start(socketPath: string, term: Term, { graceWindow }: FlightServerOptions): Promise<FlightServer>;
16
+ static start(socketPath: string, term: Term, { locks }: FlightServerOptions): Promise<FlightServer>;
16
17
  /**
17
18
  * Hands the term over. Ending every connection tells the other processes to
18
- * elect a successor and reassert their flights during its grace window;
19
- * `close` alone would wait for clients that never disconnect on their own.
19
+ * elect a successor and reassert their flights to it; `close` alone would
20
+ * wait for clients that never disconnect on their own.
20
21
  * Each connection ends only after what was written to it, such as an
21
22
  * outcome for a joiner, is sent. The term ends only after the socket is
22
23
  * gone: in the other order, this close could remove a successor's socket file.
23
- * The term resigns clean when the coordinator leaves nothing to recover, so
24
- * the successor skips its grace window; a lost term records nothing.
25
24
  * The first call removes the file at once, so a second caller finds it gone,
26
25
  * and it too resolves only once the term ended as the first call ended it.
26
+ * The coordinator stops watching the locks of the keys whose runs wait.
27
27
  */
28
28
  close(): Promise<void>;
29
29
  }
@@ -1 +1 @@
1
- {"version":3,"file":"flight-server.d.ts","sourceRoot":"","sources":["../../src/coordinator/flight-server.ts"],"names":[],"mappings":"AAIA,OAAO,KAAK,EAAE,IAAI,EAAE,MAAM,mBAAmB,CAAC;AAQ9C,MAAM,WAAW,mBAAmB;IAClC,qGAAqG;IACrG,WAAW,EAAE,MAAM,CAAC;CACrB;AAED;;;;;GAKG;AACH,qBAAa,YAAY;;IAOvB,OAAO;WAaM,KAAK,CAChB,UAAU,EAAE,MAAM,EAClB,IAAI,EAAE,IAAI,EACV,EAAE,WAAW,EAAE,EAAE,mBAAmB,GACnC,OAAO,CAAC,YAAY,CAAC;IAkCxB;;;;;;;;;;;OAWG;IACG,KAAK;CAaZ"}
1
+ {"version":3,"file":"flight-server.d.ts","sourceRoot":"","sources":["../../src/coordinator/flight-server.ts"],"names":[],"mappings":"AAIA,OAAO,KAAK,EAAE,IAAI,EAAE,MAAM,mBAAmB,CAAC;AAK9C,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,0BAA0B,CAAC;AAIzD,MAAM,WAAW,mBAAmB;IAClC,qFAAqF;IACrF,KAAK,EAAE,QAAQ,CAAC;CACjB;AAED;;;;;GAKG;AACH,qBAAa,YAAY;;IAOvB,OAAO;WAaM,KAAK,CAChB,UAAU,EAAE,MAAM,EAClB,IAAI,EAAE,IAAI,EACV,EAAE,KAAK,EAAE,EAAE,mBAAmB,GAC7B,OAAO,CAAC,YAAY,CAAC;IAkCxB;;;;;;;;;;OAUG;IACG,KAAK;CAQZ"}
@@ -24,7 +24,7 @@ export class FlightServer {
24
24
  this.#term = term;
25
25
  this.#closeOnLoss = addAbortListener(term.signal, () => void this.close());
26
26
  }
27
- static async start(socketPath, term, { graceWindow }) {
27
+ static async start(socketPath, term, { locks }) {
28
28
  // Only the coordinator gets here, so removing a dead coordinator's socket file cannot race another server.
29
29
  // Windows removes a named pipe when its process stops, so there is no file to remove.
30
30
  if (process.platform !== 'win32') {
@@ -32,7 +32,7 @@ export class FlightServer {
32
32
  }
33
33
  const coordinator = new FlightCoordinator({
34
34
  tokens: new EpochTokenSource(term.epoch),
35
- graceWindow,
35
+ locks,
36
36
  });
37
37
  const connections = new Set();
38
38
  // Serving others never keeps the coordinator alive: when its own work ends, it exits and another process takes over.
@@ -60,29 +60,23 @@ export class FlightServer {
60
60
  }
61
61
  /**
62
62
  * Hands the term over. Ending every connection tells the other processes to
63
- * elect a successor and reassert their flights during its grace window;
64
- * `close` alone would wait for clients that never disconnect on their own.
63
+ * elect a successor and reassert their flights to it; `close` alone would
64
+ * wait for clients that never disconnect on their own.
65
65
  * Each connection ends only after what was written to it, such as an
66
66
  * outcome for a joiner, is sent. The term ends only after the socket is
67
67
  * gone: in the other order, this close could remove a successor's socket file.
68
- * The term resigns clean when the coordinator leaves nothing to recover, so
69
- * the successor skips its grace window; a lost term records nothing.
70
68
  * The first call removes the file at once, so a second caller finds it gone,
71
69
  * and it too resolves only once the term ended as the first call ended it.
70
+ * The coordinator stops watching the locks of the keys whose runs wait.
72
71
  */
73
72
  async close() {
74
73
  this.#closeOnLoss[Symbol.dispose]();
74
+ this.#coordinator.close();
75
75
  const closed = this.#server[Symbol.asyncDispose]();
76
- // Read in the step that ends the connections: each session that ends
77
- // withdraws its flights, so later there is never a flight in progress.
78
- // An answer written after this step, such as the `lead` of a run whose
79
- // token is being minted, never reaches its client, which sends the run
80
- // again to the successor. So no client knows of a flight this read missed.
81
- const clean = this.#coordinator.leavesNothingToRecover;
82
76
  for (const socket of this.#connections)
83
77
  socket.destroySoon();
84
78
  await closed;
85
- await this.#term.resign({ clean });
79
+ await this.#term.resign();
86
80
  }
87
81
  }
88
82
  //# sourceMappingURL=flight-server.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"flight-server.js","sourceRoot":"","sources":["../../src/coordinator/flight-server.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"flight-server.js","sourceRoot":"","sources":["../../src/coordinator/flight-server.ts"],"names":[],"mappings":"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"}
@@ -1,17 +1,28 @@
1
1
  import type { FencingToken } from '@zukhruf/fencing';
2
2
  import type { Outcome } from '../protocol/flight-protocol.ts';
3
3
  import type { Party } from './party.ts';
4
+ export interface FlightOptions {
5
+ /** A leader claimed this flight again after its connection was lost, so a rejoin may come after its end. */
6
+ reasserted?: boolean;
7
+ }
4
8
  /** A flight in progress: the key, the leader that runs the work, its lease token, and the parties that joined. */
5
9
  export declare class Flight {
6
10
  #private;
7
11
  readonly key: string;
8
12
  readonly token: FencingToken;
9
- readonly leader: Party;
10
- constructor(key: string, token: FencingToken, leader: Party);
13
+ readonly reasserted: boolean;
14
+ constructor(key: string, token: FencingToken, leader: Party, { reasserted }?: FlightOptions);
15
+ get leader(): Party;
11
16
  /** The flight's name on the wire: its token as decimal text, which a joined answer and a rejoin carry. */
12
17
  get id(): string;
13
18
  /** Whether this is the flight with the id `flight`, which a rejoin names. */
14
19
  is(flight: string): boolean;
20
+ /**
21
+ * The leader claimed this flight again through a new connection. The new
22
+ * party leads it, and the old one ends without an answer, so the close of
23
+ * the old connection interrupts nothing.
24
+ */
25
+ handOver(leader: Party): void;
15
26
  add(joiner: Party): void;
16
27
  remove(joiner: Party): void;
17
28
  /** Pushes the outcome to every joiner, then tells the leader that it was handed over. */
@@ -1 +1 @@
1
- {"version":3,"file":"flight.d.ts","sourceRoot":"","sources":["../../src/coordinator/flight.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,kBAAkB,CAAC;AAErD,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,gCAAgC,CAAC;AAC9D,OAAO,KAAK,EAAE,KAAK,EAAE,MAAM,YAAY,CAAC;AAExC,kHAAkH;AAClH,qBAAa,MAAM;;IACjB,QAAQ,CAAC,GAAG,EAAE,MAAM,CAAC;IACrB,QAAQ,CAAC,KAAK,EAAE,YAAY,CAAC;IAC7B,QAAQ,CAAC,MAAM,EAAE,KAAK,CAAC;gBAGX,GAAG,EAAE,MAAM,EAAE,KAAK,EAAE,YAAY,EAAE,MAAM,EAAE,KAAK;IAM3D,0GAA0G;IAC1G,IAAI,EAAE,IAAI,MAAM,CAEf;IAED,6EAA6E;IAC7E,EAAE,CAAC,MAAM,EAAE,MAAM,GAAG,OAAO;IAI3B,GAAG,CAAC,MAAM,EAAE,KAAK;IAKjB,MAAM,CAAC,MAAM,EAAE,KAAK;IAIpB,yFAAyF;IACzF,IAAI,CAAC,OAAO,EAAE,OAAO;IAQrB,0GAA0G;IAC1G,SAAS;CAMV"}
1
+ {"version":3,"file":"flight.d.ts","sourceRoot":"","sources":["../../src/coordinator/flight.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,kBAAkB,CAAC;AAErD,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,gCAAgC,CAAC;AAC9D,OAAO,KAAK,EAAE,KAAK,EAAE,MAAM,YAAY,CAAC;AAExC,MAAM,WAAW,aAAa;IAC5B,4GAA4G;IAC5G,UAAU,CAAC,EAAE,OAAO,CAAC;CACtB;AAED,kHAAkH;AAClH,qBAAa,MAAM;;IACjB,QAAQ,CAAC,GAAG,EAAE,MAAM,CAAC;IACrB,QAAQ,CAAC,KAAK,EAAE,YAAY,CAAC;IAC7B,QAAQ,CAAC,UAAU,EAAE,OAAO,CAAC;gBAK3B,GAAG,EAAE,MAAM,EACX,KAAK,EAAE,YAAY,EACnB,MAAM,EAAE,KAAK,EACb,EAAE,UAAkB,EAAE,GAAE,aAAkB;IAQ5C,IAAI,MAAM,IAAI,KAAK,CAElB;IAED,0GAA0G;IAC1G,IAAI,EAAE,IAAI,MAAM,CAEf;IAED,6EAA6E;IAC7E,EAAE,CAAC,MAAM,EAAE,MAAM,GAAG,OAAO;IAI3B;;;;OAIG;IACH,QAAQ,CAAC,MAAM,EAAE,KAAK;IAOtB,GAAG,CAAC,MAAM,EAAE,KAAK;IAKjB,MAAM,CAAC,MAAM,EAAE,KAAK;IAIpB,yFAAyF;IACzF,IAAI,CAAC,OAAO,EAAE,OAAO;IAQrB,0GAA0G;IAC1G,SAAS;CAMV"}
@@ -2,12 +2,17 @@
2
2
  export class Flight {
3
3
  key;
4
4
  token;
5
- leader;
5
+ reasserted;
6
6
  #joiners = new Set();
7
- constructor(key, token, leader) {
7
+ #leader;
8
+ constructor(key, token, leader, { reasserted = false } = {}) {
8
9
  this.key = key;
9
10
  this.token = token;
10
- this.leader = leader;
11
+ this.reasserted = reasserted;
12
+ this.#leader = leader;
13
+ }
14
+ get leader() {
15
+ return this.#leader;
11
16
  }
12
17
  /** The flight's name on the wire: its token as decimal text, which a joined answer and a rejoin carry. */
13
18
  get id() {
@@ -17,6 +22,17 @@ export class Flight {
17
22
  is(flight) {
18
23
  return flight === this.id;
19
24
  }
25
+ /**
26
+ * The leader claimed this flight again through a new connection. The new
27
+ * party leads it, and the old one ends without an answer, so the close of
28
+ * the old connection interrupts nothing.
29
+ */
30
+ handOver(leader) {
31
+ const previous = this.#leader;
32
+ this.#leader = leader;
33
+ previous.end();
34
+ leader.resume(this);
35
+ }
20
36
  add(joiner) {
21
37
  this.#joiners.add(joiner);
22
38
  joiner.join(this);
@@ -30,7 +46,7 @@ export class Flight {
30
46
  joiner.end({ op: 'landed', outcome });
31
47
  }
32
48
  this.#joiners.clear();
33
- this.leader.end({ op: 'ack' });
49
+ this.#leader.end({ op: 'ack' });
34
50
  }
35
51
  /** Ends without an outcome: every joiner learns that its flight is lost, and none runs the work again. */
36
52
  interrupt() {
@@ -1 +1 @@
1
- {"version":3,"file":"flight.js","sourceRoot":"","sources":["../../src/coordinator/flight.ts"],"names":[],"mappings":"AAKA,kHAAkH;AAClH,MAAM,OAAO,MAAM;IACR,GAAG,CAAS;IACZ,KAAK,CAAe;IACpB,MAAM,CAAQ;IACd,QAAQ,GAAG,IAAI,GAAG,EAAS,CAAC;IAErC,YAAY,GAAW,EAAE,KAAmB,EAAE,MAAa;QACzD,IAAI,CAAC,GAAG,GAAG,GAAG,CAAC;QACf,IAAI,CAAC,KAAK,GAAG,KAAK,CAAC;QACnB,IAAI,CAAC,MAAM,GAAG,MAAM,CAAC;IACvB,CAAC;IAED,0GAA0G;IAC1G,IAAI,EAAE;QACJ,OAAO,IAAI,CAAC,KAAK,CAAC,QAAQ,EAAE,CAAC;IAC/B,CAAC;IAED,6EAA6E;IAC7E,EAAE,CAAC,MAAc;QACf,OAAO,MAAM,KAAK,IAAI,CAAC,EAAE,CAAC;IAC5B,CAAC;IAED,GAAG,CAAC,MAAa;QACf,IAAI,CAAC,QAAQ,CAAC,GAAG,CAAC,MAAM,CAAC,CAAC;QAC1B,MAAM,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;IACpB,CAAC;IAED,MAAM,CAAC,MAAa;QAClB,IAAI,CAAC,QAAQ,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC;IAC/B,CAAC;IAED,yFAAyF;IACzF,IAAI,CAAC,OAAgB;QACnB,KAAK,MAAM,MAAM,IAAI,IAAI,CAAC,QAAQ,EAAE,CAAC;YACnC,MAAM,CAAC,GAAG,CAAC,EAAE,EAAE,EAAE,QAAQ,EAAE,OAAO,EAAE,CAAC,CAAC;QACxC,CAAC;QACD,IAAI,CAAC,QAAQ,CAAC,KAAK,EAAE,CAAC;QACtB,IAAI,CAAC,MAAM,CAAC,GAAG,CAAC,EAAE,EAAE,EAAE,KAAK,EAAE,CAAC,CAAC;IACjC,CAAC;IAED,0GAA0G;IAC1G,SAAS;QACP,KAAK,MAAM,MAAM,IAAI,IAAI,CAAC,QAAQ,EAAE,CAAC;YACnC,MAAM,CAAC,GAAG,CAAC,EAAE,EAAE,EAAE,aAAa,EAAE,CAAC,CAAC;QACpC,CAAC;QACD,IAAI,CAAC,QAAQ,CAAC,KAAK,EAAE,CAAC;IACxB,CAAC;CACF"}
1
+ {"version":3,"file":"flight.js","sourceRoot":"","sources":["../../src/coordinator/flight.ts"],"names":[],"mappings":"AAUA,kHAAkH;AAClH,MAAM,OAAO,MAAM;IACR,GAAG,CAAS;IACZ,KAAK,CAAe;IACpB,UAAU,CAAU;IACpB,QAAQ,GAAG,IAAI,GAAG,EAAS,CAAC;IACrC,OAAO,CAAQ;IAEf,YACE,GAAW,EACX,KAAmB,EACnB,MAAa,EACb,EAAE,UAAU,GAAG,KAAK,KAAoB,EAAE;QAE1C,IAAI,CAAC,GAAG,GAAG,GAAG,CAAC;QACf,IAAI,CAAC,KAAK,GAAG,KAAK,CAAC;QACnB,IAAI,CAAC,UAAU,GAAG,UAAU,CAAC;QAC7B,IAAI,CAAC,OAAO,GAAG,MAAM,CAAC;IACxB,CAAC;IAED,IAAI,MAAM;QACR,OAAO,IAAI,CAAC,OAAO,CAAC;IACtB,CAAC;IAED,0GAA0G;IAC1G,IAAI,EAAE;QACJ,OAAO,IAAI,CAAC,KAAK,CAAC,QAAQ,EAAE,CAAC;IAC/B,CAAC;IAED,6EAA6E;IAC7E,EAAE,CAAC,MAAc;QACf,OAAO,MAAM,KAAK,IAAI,CAAC,EAAE,CAAC;IAC5B,CAAC;IAED;;;;OAIG;IACH,QAAQ,CAAC,MAAa;QACpB,MAAM,QAAQ,GAAG,IAAI,CAAC,OAAO,CAAC;QAC9B,IAAI,CAAC,OAAO,GAAG,MAAM,CAAC;QACtB,QAAQ,CAAC,GAAG,EAAE,CAAC;QACf,MAAM,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC;IACtB,CAAC;IAED,GAAG,CAAC,MAAa;QACf,IAAI,CAAC,QAAQ,CAAC,GAAG,CAAC,MAAM,CAAC,CAAC;QAC1B,MAAM,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;IACpB,CAAC;IAED,MAAM,CAAC,MAAa;QAClB,IAAI,CAAC,QAAQ,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC;IAC/B,CAAC;IAED,yFAAyF;IACzF,IAAI,CAAC,OAAgB;QACnB,KAAK,MAAM,MAAM,IAAI,IAAI,CAAC,QAAQ,EAAE,CAAC;YACnC,MAAM,CAAC,GAAG,CAAC,EAAE,EAAE,EAAE,QAAQ,EAAE,OAAO,EAAE,CAAC,CAAC;QACxC,CAAC;QACD,IAAI,CAAC,QAAQ,CAAC,KAAK,EAAE,CAAC;QACtB,IAAI,CAAC,OAAO,CAAC,GAAG,CAAC,EAAE,EAAE,EAAE,KAAK,EAAE,CAAC,CAAC;IAClC,CAAC;IAED,0GAA0G;IAC1G,SAAS;QACP,KAAK,MAAM,MAAM,IAAI,IAAI,CAAC,QAAQ,EAAE,CAAC;YACnC,MAAM,CAAC,GAAG,CAAC,EAAE,EAAE,EAAE,aAAa,EAAE,CAAC,CAAC;QACpC,CAAC;QACD,IAAI,CAAC,QAAQ,CAAC,KAAK,EAAE,CAAC;IACxB,CAAC;CACF"}
@@ -0,0 +1,26 @@
1
+ import type { KeyLocks } from '../key-lock/key-locks.ts';
2
+ import type { Party } from './party.ts';
3
+ /**
4
+ * The runs and rejoins of keys that another process holds while this
5
+ * coordinator knows no flight of them: a leader of an earlier term that has
6
+ * not reasserted its flight yet, or a leader whose flight ended and that
7
+ * still lets its key go. They wait until a flight of the key starts or the
8
+ * key's lock frees.
9
+ *
10
+ * Each key with parked runs has one watch of its lock. It stops when the lock
11
+ * frees, when the key's runs were woken, when none of them waits any more, or
12
+ * when the coordinator closes. It never keeps the process alive.
13
+ */
14
+ export declare class ParkedRuns {
15
+ #private;
16
+ constructor(locks: KeyLocks, closed: AbortSignal);
17
+ /** Parks `party` on `key`; `retry` runs once the key's runs are woken. */
18
+ park(key: string, party: Party, retry: () => void): void;
19
+ /**
20
+ * Decides every parked run of `key` again, now, in this step. A flight of
21
+ * the key that just started takes them before anything else is read, such
22
+ * as a landing that arrived right behind its reassertion.
23
+ */
24
+ wake(key: string): void;
25
+ }
26
+ //# sourceMappingURL=parked-runs.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"parked-runs.d.ts","sourceRoot":"","sources":["../../src/coordinator/parked-runs.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,0BAA0B,CAAC;AACzD,OAAO,KAAK,EAAE,KAAK,EAAE,MAAM,YAAY,CAAC;AAQxC;;;;;;;;;;GAUG;AACH,qBAAa,UAAU;;gBAKT,KAAK,EAAE,QAAQ,EAAE,MAAM,EAAE,WAAW;IAKhD,0EAA0E;IAC1E,IAAI,CAAC,GAAG,EAAE,MAAM,EAAE,KAAK,EAAE,KAAK,EAAE,KAAK,EAAE,MAAM,IAAI,GAAG,IAAI;IAWxD;;;;OAIG;IACH,IAAI,CAAC,GAAG,EAAE,MAAM,GAAG,IAAI;CA0BxB"}
@@ -0,0 +1,65 @@
1
+ /**
2
+ * The runs and rejoins of keys that another process holds while this
3
+ * coordinator knows no flight of them: a leader of an earlier term that has
4
+ * not reasserted its flight yet, or a leader whose flight ended and that
5
+ * still lets its key go. They wait until a flight of the key starts or the
6
+ * key's lock frees.
7
+ *
8
+ * Each key with parked runs has one watch of its lock. It stops when the lock
9
+ * frees, when the key's runs were woken, when none of them waits any more, or
10
+ * when the coordinator closes. It never keeps the process alive.
11
+ */
12
+ export class ParkedRuns {
13
+ #locks;
14
+ #closed;
15
+ #parked = new Map();
16
+ constructor(locks, closed) {
17
+ this.#locks = locks;
18
+ this.#closed = closed;
19
+ }
20
+ /** Parks `party` on `key`; `retry` runs once the key's runs are woken. */
21
+ park(key, party, retry) {
22
+ const parked = this.#parked.get(key);
23
+ if (parked) {
24
+ parked.add({ party, retry });
25
+ return;
26
+ }
27
+ const first = new Set([{ party, retry }]);
28
+ this.#parked.set(key, first);
29
+ void this.#watch(key, first);
30
+ }
31
+ /**
32
+ * Decides every parked run of `key` again, now, in this step. A flight of
33
+ * the key that just started takes them before anything else is read, such
34
+ * as a landing that arrived right behind its reassertion.
35
+ */
36
+ wake(key) {
37
+ const parked = this.#parked.get(key);
38
+ if (!parked)
39
+ return;
40
+ this.#parked.delete(key);
41
+ for (const { retry } of parked)
42
+ retry();
43
+ }
44
+ async #watch(key, parked) {
45
+ const current = () => this.#parked.get(key) === parked;
46
+ let free;
47
+ try {
48
+ free = await this.#locks.whenFree(key, () => current() && [...parked].some(({ party }) => party.waiting), this.#closed);
49
+ }
50
+ catch {
51
+ if (this.#closed.aborted)
52
+ return;
53
+ // The check is advice only (F5), so a fault counts as free: each run is
54
+ // decided again, and a leader's own lock is the truth.
55
+ free = true;
56
+ }
57
+ if (!current())
58
+ return;
59
+ if (free)
60
+ this.wake(key);
61
+ else
62
+ this.#parked.delete(key);
63
+ }
64
+ }
65
+ //# sourceMappingURL=parked-runs.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"parked-runs.js","sourceRoot":"","sources":["../../src/coordinator/parked-runs.ts"],"names":[],"mappings":"AASA;;;;;;;;;;GAUG;AACH,MAAM,OAAO,UAAU;IACZ,MAAM,CAAW;IACjB,OAAO,CAAc;IACrB,OAAO,GAAG,IAAI,GAAG,EAA0B,CAAC;IAErD,YAAY,KAAe,EAAE,MAAmB;QAC9C,IAAI,CAAC,MAAM,GAAG,KAAK,CAAC;QACpB,IAAI,CAAC,OAAO,GAAG,MAAM,CAAC;IACxB,CAAC;IAED,0EAA0E;IAC1E,IAAI,CAAC,GAAW,EAAE,KAAY,EAAE,KAAiB;QAC/C,MAAM,MAAM,GAAG,IAAI,CAAC,OAAO,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC;QACrC,IAAI,MAAM,EAAE,CAAC;YACX,MAAM,CAAC,GAAG,CAAC,EAAE,KAAK,EAAE,KAAK,EAAE,CAAC,CAAC;YAC7B,OAAO;QACT,CAAC;QACD,MAAM,KAAK,GAAG,IAAI,GAAG,CAAC,CAAC,EAAE,KAAK,EAAE,KAAK,EAAE,CAAC,CAAC,CAAC;QAC1C,IAAI,CAAC,OAAO,CAAC,GAAG,CAAC,GAAG,EAAE,KAAK,CAAC,CAAC;QAC7B,KAAK,IAAI,CAAC,MAAM,CAAC,GAAG,EAAE,KAAK,CAAC,CAAC;IAC/B,CAAC;IAED;;;;OAIG;IACH,IAAI,CAAC,GAAW;QACd,MAAM,MAAM,GAAG,IAAI,CAAC,OAAO,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC;QACrC,IAAI,CAAC,MAAM;YAAE,OAAO;QACpB,IAAI,CAAC,OAAO,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC;QACzB,KAAK,MAAM,EAAE,KAAK,EAAE,IAAI,MAAM;YAAE,KAAK,EAAE,CAAC;IAC1C,CAAC;IAED,KAAK,CAAC,MAAM,CAAC,GAAW,EAAE,MAAsB;QAC9C,MAAM,OAAO,GAAG,GAAG,EAAE,CAAC,IAAI,CAAC,OAAO,CAAC,GAAG,CAAC,GAAG,CAAC,KAAK,MAAM,CAAC;QACvD,IAAI,IAAa,CAAC;QAClB,IAAI,CAAC;YACH,IAAI,GAAG,MAAM,IAAI,CAAC,MAAM,CAAC,QAAQ,CAC/B,GAAG,EACH,GAAG,EAAE,CAAC,OAAO,EAAE,IAAI,CAAC,GAAG,MAAM,CAAC,CAAC,IAAI,CAAC,CAAC,EAAE,KAAK,EAAE,EAAE,EAAE,CAAC,KAAK,CAAC,OAAO,CAAC,EACjE,IAAI,CAAC,OAAO,CACb,CAAC;QACJ,CAAC;QAAC,MAAM,CAAC;YACP,IAAI,IAAI,CAAC,OAAO,CAAC,OAAO;gBAAE,OAAO;YACjC,wEAAwE;YACxE,uDAAuD;YACvD,IAAI,GAAG,IAAI,CAAC;QACd,CAAC;QACD,IAAI,CAAC,OAAO,EAAE;YAAE,OAAO;QACvB,IAAI,IAAI;YAAE,IAAI,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;;YACpB,IAAI,CAAC,OAAO,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC;IAChC,CAAC;CACF"}
@@ -14,7 +14,7 @@ export interface Inbox {
14
14
  }
15
15
  /** What a party is to the coordinator now. */
16
16
  export type Role =
17
- /** A run that waits for the grace window, a token, or the reassertion of its flight. */
17
+ /** A run that waits for a token, or for its key's lock: for a flight of the key or for the lock to free. */
18
18
  {
19
19
  kind: 'waiting';
20
20
  } | {