@zukhruf/single-flight 0.3.16 → 0.3.18
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.
- package/README.md +13 -12
- package/dist/client/flight-client.d.ts +4 -4
- package/dist/client/flight-client.d.ts.map +1 -1
- package/dist/client/flight-client.js +20 -10
- package/dist/client/flight-client.js.map +1 -1
- package/dist/connection/connection-supervisor.d.ts +4 -4
- package/dist/connection/connection-supervisor.d.ts.map +1 -1
- package/dist/connection/connection-supervisor.js.map +1 -1
- package/dist/connection/connection.d.ts +4 -3
- package/dist/connection/connection.d.ts.map +1 -1
- package/dist/connection/connector.d.ts +5 -5
- package/dist/connection/connector.d.ts.map +1 -1
- package/dist/connection/electing-connector.d.ts +4 -5
- package/dist/connection/electing-connector.d.ts.map +1 -1
- package/dist/connection/electing-connector.js +38 -42
- package/dist/connection/electing-connector.js.map +1 -1
- package/dist/connection/flight-election.d.ts +11 -0
- package/dist/connection/flight-election.d.ts.map +1 -0
- package/dist/connection/flight-election.js +18 -0
- package/dist/connection/flight-election.js.map +1 -0
- package/dist/connection/handshake.d.ts.map +1 -1
- package/dist/connection/handshake.js +6 -5
- package/dist/connection/handshake.js.map +1 -1
- package/dist/connection/json-line.d.ts +6 -0
- package/dist/connection/json-line.d.ts.map +1 -0
- package/dist/connection/json-line.js +8 -0
- package/dist/connection/json-line.js.map +1 -0
- package/dist/connection/leave-errors-to-close.d.ts +9 -0
- package/dist/connection/leave-errors-to-close.d.ts.map +1 -0
- package/dist/connection/leave-errors-to-close.js +10 -0
- package/dist/connection/leave-errors-to-close.js.map +1 -0
- package/dist/connection/local-directory-connector.d.ts.map +1 -1
- package/dist/connection/local-directory-connector.js +1 -1
- package/dist/connection/local-directory-connector.js.map +1 -1
- package/dist/connection/socket-connection.d.ts +5 -5
- package/dist/connection/socket-connection.d.ts.map +1 -1
- package/dist/connection/socket-connection.js +21 -23
- package/dist/connection/socket-connection.js.map +1 -1
- package/dist/coordinator/flight-coordinator.d.ts +3 -3
- package/dist/coordinator/flight-coordinator.d.ts.map +1 -1
- package/dist/coordinator/flight-coordinator.js +12 -18
- package/dist/coordinator/flight-coordinator.js.map +1 -1
- package/dist/coordinator/flight-server.d.ts +7 -3
- package/dist/coordinator/flight-server.d.ts.map +1 -1
- package/dist/coordinator/flight-server.js +29 -25
- package/dist/coordinator/flight-server.js.map +1 -1
- package/dist/coordinator/flight.d.ts +4 -2
- package/dist/coordinator/flight.d.ts.map +1 -1
- package/dist/coordinator/flight.js +9 -5
- package/dist/coordinator/flight.js.map +1 -1
- package/dist/coordinator/party.d.ts +11 -2
- package/dist/coordinator/party.d.ts.map +1 -1
- package/dist/coordinator/party.js +15 -15
- package/dist/coordinator/party.js.map +1 -1
- package/dist/coordinator/session.d.ts +2 -2
- package/dist/coordinator/session.d.ts.map +1 -1
- package/dist/coordinator/session.js +9 -4
- package/dist/coordinator/session.js.map +1 -1
- package/dist/index.d.ts +1 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +1 -1
- package/dist/index.js.map +1 -1
- package/dist/protocol/flight-protocol.d.ts +6 -2
- package/dist/protocol/flight-protocol.d.ts.map +1 -1
- package/dist/protocol/flight-protocol.js +17 -10
- package/dist/protocol/flight-protocol.js.map +1 -1
- package/dist/single-flight.d.ts +7 -5
- package/dist/single-flight.d.ts.map +1 -1
- package/dist/single-flight.js +21 -16
- package/dist/single-flight.js.map +1 -1
- package/package.json +6 -5
- package/dist/election/leader-election.d.ts +0 -24
- package/dist/election/leader-election.d.ts.map +0 -1
- package/dist/election/leader-election.js +0 -80
- package/dist/election/leader-election.js.map +0 -1
- package/dist/election/leadership.d.ts +0 -14
- package/dist/election/leadership.d.ts.map +0 -1
- package/dist/election/leadership.js +0 -23
- package/dist/election/leadership.js.map +0 -1
- package/dist/local-directory/local-directory.d.ts +0 -7
- package/dist/local-directory/local-directory.d.ts.map +0 -1
- package/dist/local-directory/local-directory.js +0 -75
- package/dist/local-directory/local-directory.js.map +0 -1
- package/dist/local-directory/network-directory-error.d.ts +0 -8
- package/dist/local-directory/network-directory-error.d.ts.map +0 -1
- package/dist/local-directory/network-directory-error.js +0 -13
- package/dist/local-directory/network-directory-error.js.map +0 -1
- package/dist/shared/fs/durable-write.d.ts +0 -7
- package/dist/shared/fs/durable-write.d.ts.map +0 -1
- package/dist/shared/fs/durable-write.js +0 -47
- package/dist/shared/fs/durable-write.js.map +0 -1
- package/dist/shared/fs/errno.d.ts +0 -2
- package/dist/shared/fs/errno.d.ts.map +0 -1
- package/dist/shared/fs/errno.js +0 -4
- package/dist/shared/fs/errno.js.map +0 -1
- package/dist/shared/fs/patiently.d.ts +0 -3
- package/dist/shared/fs/patiently.d.ts.map +0 -1
- package/dist/shared/fs/patiently.js +0 -30
- package/dist/shared/fs/patiently.js.map +0 -1
- package/dist/shared/fs/replace-file.d.ts +0 -8
- package/dist/shared/fs/replace-file.d.ts.map +0 -1
- package/dist/shared/fs/replace-file.js +0 -12
- package/dist/shared/fs/replace-file.js.map +0 -1
- package/dist/shared/sqlite/is-busy.d.ts +0 -3
- package/dist/shared/sqlite/is-busy.d.ts.map +0 -1
- package/dist/shared/sqlite/is-busy.js +0 -10
- package/dist/shared/sqlite/is-busy.js.map +0 -1
|
@@ -10,13 +10,13 @@ export class Party {
|
|
|
10
10
|
get role() {
|
|
11
11
|
return this.#role;
|
|
12
12
|
}
|
|
13
|
+
/** Whether the party still waits: it has no answer yet, it was not withdrawn, and its connection is not gone. */
|
|
14
|
+
get waiting() {
|
|
15
|
+
return this.#role.kind === 'waiting';
|
|
16
|
+
}
|
|
13
17
|
lead(flight) {
|
|
14
18
|
this.#role = { kind: 'leading', flight };
|
|
15
|
-
this.#
|
|
16
|
-
op: 'lead',
|
|
17
|
-
id: this.id,
|
|
18
|
-
token: flight.token.toString(),
|
|
19
|
-
});
|
|
19
|
+
this.#reply({ op: 'lead', token: flight.token.toString() });
|
|
20
20
|
}
|
|
21
21
|
/** A leader from before a failover claimed its flight again; it already knows that it leads. */
|
|
22
22
|
resume(flight) {
|
|
@@ -24,20 +24,20 @@ export class Party {
|
|
|
24
24
|
}
|
|
25
25
|
join(flight) {
|
|
26
26
|
this.#role = { kind: 'joining', flight };
|
|
27
|
-
this.#
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
});
|
|
32
|
-
}
|
|
33
|
-
/** Answers for good with `response`, or ends without an answer when it was withdrawn or its connection is gone. */
|
|
34
|
-
end(response) {
|
|
27
|
+
this.#reply({ op: 'joined', flight: flight.id });
|
|
28
|
+
}
|
|
29
|
+
/** Answers for good with `answer`, or ends without an answer when it was withdrawn or its connection is gone. */
|
|
30
|
+
end(answer) {
|
|
35
31
|
if (this.#role.kind === 'gone')
|
|
36
32
|
return;
|
|
37
33
|
this.#role = { kind: 'gone' };
|
|
38
34
|
this.#inbox.forget(this.id);
|
|
39
|
-
if (
|
|
40
|
-
this.#
|
|
35
|
+
if (answer)
|
|
36
|
+
this.#reply(answer);
|
|
37
|
+
}
|
|
38
|
+
#reply(answer) {
|
|
39
|
+
// The id goes right after the op, so each line keeps its bytes: op, id, then the fields of the op.
|
|
40
|
+
this.#inbox.reply(Object.assign({ op: answer.op, id: this.id }, answer));
|
|
41
41
|
}
|
|
42
42
|
}
|
|
43
43
|
//# sourceMappingURL=party.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"party.js","sourceRoot":"","sources":["../../src/coordinator/party.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"party.js","sourceRoot":"","sources":["../../src/coordinator/party.ts"],"names":[],"mappings":"AAwBA,sHAAsH;AACtH,MAAM,OAAO,KAAK;IACP,EAAE,CAAS;IACX,MAAM,CAAQ;IACvB,KAAK,GAAS,EAAE,IAAI,EAAE,SAAS,EAAE,CAAC;IAElC,YAAY,EAAU,EAAE,KAAY;QAClC,IAAI,CAAC,EAAE,GAAG,EAAE,CAAC;QACb,IAAI,CAAC,MAAM,GAAG,KAAK,CAAC;IACtB,CAAC;IAED,IAAI,IAAI;QACN,OAAO,IAAI,CAAC,KAAK,CAAC;IACpB,CAAC;IAED,iHAAiH;IACjH,IAAI,OAAO;QACT,OAAO,IAAI,CAAC,KAAK,CAAC,IAAI,KAAK,SAAS,CAAC;IACvC,CAAC;IAED,IAAI,CAAC,MAAc;QACjB,IAAI,CAAC,KAAK,GAAG,EAAE,IAAI,EAAE,SAAS,EAAE,MAAM,EAAE,CAAC;QACzC,IAAI,CAAC,MAAM,CAAC,EAAE,EAAE,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,CAAC,KAAK,CAAC,QAAQ,EAAE,EAAE,CAAC,CAAC;IAC9D,CAAC;IAED,gGAAgG;IAChG,MAAM,CAAC,MAAc;QACnB,IAAI,CAAC,KAAK,GAAG,EAAE,IAAI,EAAE,SAAS,EAAE,MAAM,EAAE,CAAC;IAC3C,CAAC;IAED,IAAI,CAAC,MAAc;QACjB,IAAI,CAAC,KAAK,GAAG,EAAE,IAAI,EAAE,SAAS,EAAE,MAAM,EAAE,CAAC;QACzC,IAAI,CAAC,MAAM,CAAC,EAAE,EAAE,EAAE,QAAQ,EAAE,MAAM,EAAE,MAAM,CAAC,EAAE,EAAE,CAAC,CAAC;IACnD,CAAC;IAED,iHAAiH;IACjH,GAAG,CAAC,MAAe;QACjB,IAAI,IAAI,CAAC,KAAK,CAAC,IAAI,KAAK,MAAM;YAAE,OAAO;QACvC,IAAI,CAAC,KAAK,GAAG,EAAE,IAAI,EAAE,MAAM,EAAE,CAAC;QAC9B,IAAI,CAAC,MAAM,CAAC,MAAM,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;QAC5B,IAAI,MAAM;YAAE,IAAI,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC;IAClC,CAAC;IAED,MAAM,CAAC,MAAc;QACnB,mGAAmG;QACnG,IAAI,CAAC,MAAM,CAAC,KAAK,CAAC,MAAM,CAAC,MAAM,CAAC,EAAE,EAAE,EAAE,MAAM,CAAC,EAAE,EAAE,EAAE,EAAE,IAAI,CAAC,EAAE,EAAE,EAAE,MAAM,CAAC,CAAC,CAAC;IAC3E,CAAC;CACF"}
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import type { Connection } from '../connection/connection.ts';
|
|
2
|
-
import { type FlightResponse
|
|
2
|
+
import { type FlightResponse } from '../protocol/flight-protocol.ts';
|
|
3
3
|
import type { FlightCoordinator } from './flight-coordinator.ts';
|
|
4
4
|
import { type Inbox } from './party.ts';
|
|
5
5
|
/**
|
|
@@ -9,7 +9,7 @@ import { type Inbox } from './party.ts';
|
|
|
9
9
|
*/
|
|
10
10
|
export declare class Session implements Inbox {
|
|
11
11
|
#private;
|
|
12
|
-
constructor(coordinator: FlightCoordinator, connection: Connection<FlightResponse
|
|
12
|
+
constructor(coordinator: FlightCoordinator, connection: Connection<FlightResponse>);
|
|
13
13
|
reply(response: FlightResponse): void;
|
|
14
14
|
forget(id: string): void;
|
|
15
15
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"session.d.ts","sourceRoot":"","sources":["../../src/coordinator/session.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,6BAA6B,CAAC;AAC9D,OAAO,EACL,KAAK,cAAc,
|
|
1
|
+
{"version":3,"file":"session.d.ts","sourceRoot":"","sources":["../../src/coordinator/session.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,6BAA6B,CAAC;AAC9D,OAAO,EACL,KAAK,cAAc,EAIpB,MAAM,gCAAgC,CAAC;AACxC,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,yBAAyB,CAAC;AACjE,OAAO,EAAE,KAAK,KAAK,EAAS,MAAM,YAAY,CAAC;AAE/C;;;;GAIG;AACH,qBAAa,OAAQ,YAAW,KAAK;;gBAMjC,WAAW,EAAE,iBAAiB,EAC9B,UAAU,EAAE,UAAU,CAAC,cAAc,CAAC;IAYxC,KAAK,CAAC,QAAQ,EAAE,cAAc;IAI9B,MAAM,CAAC,EAAE,EAAE,MAAM;CAgElB"}
|
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { FencingToken } from '@zukhruf/
|
|
2
|
-
import { isFlightRequest, } from "../protocol/flight-protocol.js";
|
|
1
|
+
import { FencingToken } from '@zukhruf/fencing';
|
|
2
|
+
import { isFlightRequest, isRequestEnvelope, } from "../protocol/flight-protocol.js";
|
|
3
3
|
import { Party } from "./party.js";
|
|
4
4
|
/**
|
|
5
5
|
* One client connection. It turns each request into a party of the
|
|
@@ -13,7 +13,12 @@ export class Session {
|
|
|
13
13
|
constructor(coordinator, connection) {
|
|
14
14
|
this.#coordinator = coordinator;
|
|
15
15
|
this.#phase = new Serving(connection);
|
|
16
|
-
connection.on('message', (
|
|
16
|
+
connection.on('message', (message) => {
|
|
17
|
+
// A message with no op or no id cannot be answered, so it is ignored, and the peer keeps its flights (ADR 0008).
|
|
18
|
+
if (!isRequestEnvelope(message))
|
|
19
|
+
return;
|
|
20
|
+
this.#handle(message);
|
|
21
|
+
});
|
|
17
22
|
connection.once('close', () => this.#end());
|
|
18
23
|
}
|
|
19
24
|
reply(response) {
|
|
@@ -51,7 +56,7 @@ export class Session {
|
|
|
51
56
|
const party = this.#open(request.id);
|
|
52
57
|
if (!party)
|
|
53
58
|
return;
|
|
54
|
-
return this.#coordinator.reassert(party, request.key,
|
|
59
|
+
return this.#coordinator.reassert(party, request.key, FencingToken.parse(request.token));
|
|
55
60
|
}
|
|
56
61
|
}
|
|
57
62
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"session.js","sourceRoot":"","sources":["../../src/coordinator/session.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,YAAY,EAAE,MAAM,
|
|
1
|
+
{"version":3,"file":"session.js","sourceRoot":"","sources":["../../src/coordinator/session.ts"],"names":[],"mappings":"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"}
|
package/dist/index.d.ts
CHANGED
|
@@ -3,5 +3,5 @@ export type { Codec } from './codec.ts';
|
|
|
3
3
|
export type { Failure } from './protocol/flight-protocol.ts';
|
|
4
4
|
export { FlightFailedError, FlightInterruptedError } from './errors.ts';
|
|
5
5
|
export { ProtocolVersionError } from './connection/protocol-version-error.ts';
|
|
6
|
-
export { NetworkDirectoryError } from '
|
|
6
|
+
export { NetworkDirectoryError } from '@zukhruf/fs';
|
|
7
7
|
//# sourceMappingURL=index.d.ts.map
|
package/dist/index.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,KAAK,WAAW,EAChB,KAAK,UAAU,EACf,YAAY,EACZ,KAAK,mBAAmB,GACzB,MAAM,oBAAoB,CAAC;AAC5B,YAAY,EAAE,KAAK,EAAE,MAAM,YAAY,CAAC;AACxC,YAAY,EAAE,OAAO,EAAE,MAAM,+BAA+B,CAAC;AAC7D,OAAO,EAAE,iBAAiB,EAAE,sBAAsB,EAAE,MAAM,aAAa,CAAC;AACxE,OAAO,EAAE,oBAAoB,EAAE,MAAM,wCAAwC,CAAC;AAC9E,OAAO,EAAE,qBAAqB,EAAE,MAAM,
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,KAAK,WAAW,EAChB,KAAK,UAAU,EACf,YAAY,EACZ,KAAK,mBAAmB,GACzB,MAAM,oBAAoB,CAAC;AAC5B,YAAY,EAAE,KAAK,EAAE,MAAM,YAAY,CAAC;AACxC,YAAY,EAAE,OAAO,EAAE,MAAM,+BAA+B,CAAC;AAC7D,OAAO,EAAE,iBAAiB,EAAE,sBAAsB,EAAE,MAAM,aAAa,CAAC;AACxE,OAAO,EAAE,oBAAoB,EAAE,MAAM,wCAAwC,CAAC;AAC9E,OAAO,EAAE,qBAAqB,EAAE,MAAM,aAAa,CAAC"}
|
package/dist/index.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
export { SingleFlight, } from "./single-flight.js";
|
|
2
2
|
export { FlightFailedError, FlightInterruptedError } from "./errors.js";
|
|
3
3
|
export { ProtocolVersionError } from "./connection/protocol-version-error.js";
|
|
4
|
-
export { NetworkDirectoryError } from
|
|
4
|
+
export { NetworkDirectoryError } from '@zukhruf/fs';
|
|
5
5
|
//# sourceMappingURL=index.js.map
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAGL,YAAY,GAEb,MAAM,oBAAoB,CAAC;AAG5B,OAAO,EAAE,iBAAiB,EAAE,sBAAsB,EAAE,MAAM,aAAa,CAAC;AACxE,OAAO,EAAE,oBAAoB,EAAE,MAAM,wCAAwC,CAAC;AAC9E,OAAO,EAAE,qBAAqB,EAAE,MAAM,
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAGL,YAAY,GAEb,MAAM,oBAAoB,CAAC;AAG5B,OAAO,EAAE,iBAAiB,EAAE,sBAAsB,EAAE,MAAM,aAAa,CAAC;AACxE,OAAO,EAAE,oBAAoB,EAAE,MAAM,wCAAwC,CAAC;AAC9E,OAAO,EAAE,qBAAqB,EAAE,MAAM,aAAa,CAAC"}
|
|
@@ -88,7 +88,11 @@ export interface RequestEnvelope {
|
|
|
88
88
|
id: string;
|
|
89
89
|
}
|
|
90
90
|
export declare function isRequestEnvelope(message: unknown): message is RequestEnvelope;
|
|
91
|
-
/**
|
|
92
|
-
|
|
91
|
+
/**
|
|
92
|
+
* Messages arrive from another process, so their shape is checked before
|
|
93
|
+
* use. `isRequestEnvelope` already checked the `op` and the `id`, so only the
|
|
94
|
+
* fields of each request are left.
|
|
95
|
+
*/
|
|
96
|
+
export declare function isFlightRequest(request: RequestEnvelope): request is FlightRequest;
|
|
93
97
|
export declare function isFlightResponse(message: unknown): message is FlightResponse;
|
|
94
98
|
//# sourceMappingURL=flight-protocol.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"flight-protocol.d.ts","sourceRoot":"","sources":["../../src/protocol/flight-protocol.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"flight-protocol.d.ts","sourceRoot":"","sources":["../../src/protocol/flight-protocol.ts"],"names":[],"mappings":"AAIA,yFAAyF;AACzF,MAAM,WAAW,OAAO;IACtB,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAC;IACzB,iEAAiE;IACjE,QAAQ,CAAC,IAAI,CAAC,EAAE,MAAM,GAAG,MAAM,CAAC;CACjC;AAED,uFAAuF;AACvF,MAAM,MAAM,OAAO,GAAG;IAAE,KAAK,EAAE,MAAM,CAAA;CAAE,GAAG;IAAE,OAAO,EAAE,OAAO,CAAA;CAAE,CAAC;AAE/D,+EAA+E;AAC/E,MAAM,MAAM,aAAa;AACvB;;;;;;;GAOG;AACD;IAAE,EAAE,EAAE,KAAK,CAAC;IAAC,EAAE,EAAE,MAAM,CAAC;IAAC,GAAG,EAAE,MAAM,CAAC;IAAC,MAAM,CAAC,EAAE,MAAM,CAAA;CAAE;AACzD,mHAAmH;GACjH;IAAE,EAAE,EAAE,MAAM,CAAC;IAAC,EAAE,EAAE,MAAM,CAAC;IAAC,OAAO,EAAE,OAAO,CAAA;CAAE;AAC9C,6EAA6E;GAC3E;IAAE,EAAE,EAAE,QAAQ,CAAC;IAAC,EAAE,EAAE,MAAM,CAAA;CAAE;AAC9B,0GAA0G;GACxG;IAAE,EAAE,EAAE,UAAU,CAAC;IAAC,EAAE,EAAE,MAAM,CAAC;IAAC,GAAG,EAAE,MAAM,CAAC;IAAC,KAAK,EAAE,MAAM,CAAA;CAAE,CAAC;AAE/D,MAAM,MAAM,cAAc;AACxB,wEAAwE;AACtE;IAAE,EAAE,EAAE,MAAM,CAAC;IAAC,EAAE,EAAE,MAAM,CAAC;IAAC,KAAK,EAAE,MAAM,CAAA;CAAE;AAC3C,oFAAoF;GAClF;IAAE,EAAE,EAAE,QAAQ,CAAC;IAAC,EAAE,EAAE,MAAM,CAAC;IAAC,MAAM,EAAE,MAAM,CAAA;CAAE,GAC5C;IAAE,EAAE,EAAE,QAAQ,CAAC;IAAC,EAAE,EAAE,MAAM,CAAC;IAAC,OAAO,EAAE,OAAO,CAAA;CAAE;AAChD,qGAAqG;GACnG;IAAE,EAAE,EAAE,aAAa,CAAC;IAAC,EAAE,EAAE,MAAM,CAAA;CAAE;AACnC,uDAAuD;GACrD;IAAE,EAAE,EAAE,KAAK,CAAC;IAAC,EAAE,EAAE,MAAM,CAAA;CAAE;AAC3B,8FAA8F;GAC5F;IAAE,EAAE,EAAE,UAAU,CAAC;IAAC,EAAE,EAAE,MAAM,CAAA;CAAE;AAChC,2EAA2E;GACzE;IAAE,EAAE,EAAE,aAAa,CAAC;IAAC,EAAE,EAAE,MAAM,CAAA;CAAE,CAAC;AAEtC,qHAAqH;AACrH,MAAM,WAAW,eAAe;IAC9B,EAAE,EAAE,MAAM,CAAC;IACX,EAAE,EAAE,MAAM,CAAC;CACZ;AAKD,wBAAgB,iBAAiB,CAC/B,OAAO,EAAE,OAAO,GACf,OAAO,IAAI,eAAe,CAM5B;AAED;;;;GAIG;AACH,wBAAgB,eAAe,CAC7B,OAAO,EAAE,eAAe,GACvB,OAAO,IAAI,aAAa,CAsB1B;AAED,wBAAgB,gBAAgB,CAAC,OAAO,EAAE,OAAO,GAAG,OAAO,IAAI,cAAc,CAiB5E"}
|
|
@@ -1,24 +1,31 @@
|
|
|
1
|
+
import { FencingToken } from '@zukhruf/fencing';
|
|
1
2
|
import { isRecord } from "../shared/is-record.js";
|
|
2
|
-
const isToken = (value) => typeof value === 'string' &&
|
|
3
|
+
const isToken = (value) => typeof value === 'string' && FencingToken.parse(value) !== null;
|
|
3
4
|
export function isRequestEnvelope(message) {
|
|
4
5
|
return (isRecord(message) &&
|
|
5
6
|
typeof message.op === 'string' &&
|
|
6
7
|
typeof message.id === 'string');
|
|
7
8
|
}
|
|
8
|
-
/**
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
9
|
+
/**
|
|
10
|
+
* Messages arrive from another process, so their shape is checked before
|
|
11
|
+
* use. `isRequestEnvelope` already checked the `op` and the `id`, so only the
|
|
12
|
+
* fields of each request are left.
|
|
13
|
+
*/
|
|
14
|
+
export function isFlightRequest(request) {
|
|
15
|
+
switch (request.op) {
|
|
13
16
|
case 'run':
|
|
14
|
-
return (
|
|
15
|
-
|
|
17
|
+
return ('key' in request &&
|
|
18
|
+
typeof request.key === 'string' &&
|
|
19
|
+
(!('flight' in request) || isToken(request.flight)));
|
|
16
20
|
case 'land':
|
|
17
|
-
return isOutcome(
|
|
21
|
+
return 'outcome' in request && isOutcome(request.outcome);
|
|
18
22
|
case 'cancel':
|
|
19
23
|
return true;
|
|
20
24
|
case 'reassert':
|
|
21
|
-
return
|
|
25
|
+
return ('key' in request &&
|
|
26
|
+
typeof request.key === 'string' &&
|
|
27
|
+
'token' in request &&
|
|
28
|
+
isToken(request.token));
|
|
22
29
|
default:
|
|
23
30
|
return false;
|
|
24
31
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"flight-protocol.js","sourceRoot":"","sources":["../../src/protocol/flight-protocol.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,MAAM,wBAAwB,CAAC;AAoDlD,MAAM,OAAO,GAAG,CAAC,KAAc,EAAmB,EAAE,CAClD,OAAO,KAAK,KAAK,QAAQ,IAAI,
|
|
1
|
+
{"version":3,"file":"flight-protocol.js","sourceRoot":"","sources":["../../src/protocol/flight-protocol.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,YAAY,EAAE,MAAM,kBAAkB,CAAC;AAEhD,OAAO,EAAE,QAAQ,EAAE,MAAM,wBAAwB,CAAC;AAoDlD,MAAM,OAAO,GAAG,CAAC,KAAc,EAAmB,EAAE,CAClD,OAAO,KAAK,KAAK,QAAQ,IAAI,YAAY,CAAC,KAAK,CAAC,KAAK,CAAC,KAAK,IAAI,CAAC;AAElE,MAAM,UAAU,iBAAiB,CAC/B,OAAgB;IAEhB,OAAO,CACL,QAAQ,CAAC,OAAO,CAAC;QACjB,OAAO,OAAO,CAAC,EAAE,KAAK,QAAQ;QAC9B,OAAO,OAAO,CAAC,EAAE,KAAK,QAAQ,CAC/B,CAAC;AACJ,CAAC;AAED;;;;GAIG;AACH,MAAM,UAAU,eAAe,CAC7B,OAAwB;IAExB,QAAQ,OAAO,CAAC,EAAE,EAAE,CAAC;QACnB,KAAK,KAAK;YACR,OAAO,CACL,KAAK,IAAI,OAAO;gBAChB,OAAO,OAAO,CAAC,GAAG,KAAK,QAAQ;gBAC/B,CAAC,CAAC,CAAC,QAAQ,IAAI,OAAO,CAAC,IAAI,OAAO,CAAC,OAAO,CAAC,MAAM,CAAC,CAAC,CACpD,CAAC;QACJ,KAAK,MAAM;YACT,OAAO,SAAS,IAAI,OAAO,IAAI,SAAS,CAAC,OAAO,CAAC,OAAO,CAAC,CAAC;QAC5D,KAAK,QAAQ;YACX,OAAO,IAAI,CAAC;QACd,KAAK,UAAU;YACb,OAAO,CACL,KAAK,IAAI,OAAO;gBAChB,OAAO,OAAO,CAAC,GAAG,KAAK,QAAQ;gBAC/B,OAAO,IAAI,OAAO;gBAClB,OAAO,CAAC,OAAO,CAAC,KAAK,CAAC,CACvB,CAAC;QACJ;YACE,OAAO,KAAK,CAAC;IACjB,CAAC;AACH,CAAC;AAED,MAAM,UAAU,gBAAgB,CAAC,OAAgB;IAC/C,IAAI,CAAC,QAAQ,CAAC,OAAO,CAAC,IAAI,OAAO,OAAO,CAAC,EAAE,KAAK,QAAQ;QAAE,OAAO,KAAK,CAAC;IACvE,QAAQ,OAAO,CAAC,EAAE,EAAE,CAAC;QACnB,KAAK,MAAM;YACT,OAAO,OAAO,CAAC,OAAO,CAAC,KAAK,CAAC,CAAC;QAChC,KAAK,QAAQ;YACX,OAAO,OAAO,CAAC,OAAO,CAAC,MAAM,CAAC,CAAC;QACjC,KAAK,QAAQ;YACX,OAAO,SAAS,CAAC,OAAO,CAAC,OAAO,CAAC,CAAC;QACpC,KAAK,aAAa,CAAC;QACnB,KAAK,KAAK,CAAC;QACX,KAAK,UAAU,CAAC;QAChB,KAAK,aAAa;YAChB,OAAO,IAAI,CAAC;QACd;YACE,OAAO,KAAK,CAAC;IACjB,CAAC;AACH,CAAC;AAED,SAAS,SAAS,CAAC,KAAc;IAC/B,IAAI,CAAC,QAAQ,CAAC,KAAK,CAAC;QAAE,OAAO,KAAK,CAAC;IACnC,IAAI,OAAO,IAAI,KAAK;QAAE,OAAO,OAAO,KAAK,CAAC,KAAK,KAAK,QAAQ,CAAC;IAC7D,OAAO,SAAS,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC;AAClC,CAAC;AAED,SAAS,SAAS,CAAC,KAAc;IAC/B,OAAO,CACL,QAAQ,CAAC,KAAK,CAAC;QACf,OAAO,KAAK,CAAC,IAAI,KAAK,QAAQ;QAC9B,OAAO,KAAK,CAAC,OAAO,KAAK,QAAQ;QACjC,CAAC,KAAK,CAAC,IAAI,KAAK,SAAS;YACvB,OAAO,KAAK,CAAC,IAAI,KAAK,QAAQ;YAC9B,OAAO,KAAK,CAAC,IAAI,KAAK,QAAQ,CAAC,CAClC,CAAC;AACJ,CAAC"}
|
package/dist/single-flight.d.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import type {
|
|
1
|
+
import type { FencedLease } from '@zukhruf/fencing';
|
|
2
2
|
import type { Codec } from './codec.ts';
|
|
3
3
|
export interface SingleFlightOptions<T> {
|
|
4
4
|
/**
|
|
@@ -44,11 +44,13 @@ export declare class SingleFlight<T> implements AsyncDisposable {
|
|
|
44
44
|
/**
|
|
45
45
|
* Runs `work` for `key` as the leader of a new flight, or joins the flight
|
|
46
46
|
* of `key` in progress. `work` gets the flight's lease: its token, and a
|
|
47
|
-
* signal that aborts with `
|
|
48
|
-
* leader's.
|
|
49
|
-
*
|
|
47
|
+
* signal that aborts with `LeaseLostError` once the flight is no longer this
|
|
48
|
+
* leader's. After that loss, the leader's call rejects with `LeaseLostError`,
|
|
49
|
+
* also when the work throws its own error. A joiner gets the leader's value
|
|
50
|
+
* through the codec, or rejects with `FlightFailedError` or
|
|
51
|
+
* `FlightInterruptedError`.
|
|
50
52
|
*/
|
|
51
|
-
run(key: string, work: (lease:
|
|
53
|
+
run(key: string, work: (lease: FencedLease) => Promise<T>, { onJoin, signal }?: RunOptions): Promise<FlightValue<T>>;
|
|
52
54
|
/** Disconnects, and stops serving as the coordinator: the other processes elect a successor. */
|
|
53
55
|
[Symbol.asyncDispose](): Promise<void>;
|
|
54
56
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"single-flight.d.ts","sourceRoot":"","sources":["../src/single-flight.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,
|
|
1
|
+
{"version":3,"file":"single-flight.d.ts","sourceRoot":"","sources":["../src/single-flight.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,kBAAkB,CAAC;AAIpD,OAAO,KAAK,EAAE,KAAK,EAAE,MAAM,YAAY,CAAC;AAiBxC,MAAM,WAAW,mBAAmB,CAAC,CAAC;IACpC;;;;;;;;OAQG;IACH,SAAS,EAAE,MAAM,CAAC;IAClB,qFAAqF;IACrF,KAAK,EAAE,KAAK,CAAC,CAAC,CAAC,CAAC;IAChB;;;;OAIG;IACH,WAAW,CAAC,EAAE,MAAM,CAAC;CACtB;AAED,MAAM,WAAW,UAAU;IACzB,8EAA8E;IAC9E,MAAM,CAAC,EAAE,CAAC,MAAM,IAAI,CAAC,GAAG,SAAS,CAAC;IAClC,uGAAuG;IACvG,MAAM,CAAC,EAAE,WAAW,GAAG,SAAS,CAAC;CAClC;AAED,mHAAmH;AACnH,MAAM,WAAW,WAAW,CAAC,CAAC;IAC5B,QAAQ,CAAC,KAAK,EAAE,CAAC,CAAC;IAClB,QAAQ,CAAC,MAAM,EAAE,OAAO,CAAC;CAC1B;AAKD;;;;;;GAMG;AACH,qBAAa,YAAY,CAAC,CAAC,CAAE,YAAW,eAAe;;gBAMzC,EAAE,SAAS,EAAE,KAAK,EAAE,WAAiB,EAAE,EAAE,mBAAmB,CAAC,CAAC,CAAC;IA6B3E;;;;;;;;OAQG;IACG,GAAG,CACP,GAAG,EAAE,MAAM,EACX,IAAI,EAAE,CAAC,KAAK,EAAE,WAAW,KAAK,OAAO,CAAC,CAAC,CAAC,EACxC,EAAE,MAAM,EAAE,MAAM,EAAE,GAAE,UAAe,GAClC,OAAO,CAAC,WAAW,CAAC,CAAC,CAAC,CAAC;IAmB1B,gGAAgG;IAC1F,CAAC,MAAM,CAAC,YAAY,CAAC;CAmC5B"}
|
package/dist/single-flight.js
CHANGED
|
@@ -1,11 +1,12 @@
|
|
|
1
1
|
import { untilAborted } from '@zukhruf/async';
|
|
2
|
+
import { LeaseLostError } from '@zukhruf/lease';
|
|
2
3
|
import { FlightClient } from "./client/flight-client.js";
|
|
3
4
|
import { ConnectionSupervisor } from "./connection/connection-supervisor.js";
|
|
4
5
|
import { ElectingConnector } from "./connection/electing-connector.js";
|
|
6
|
+
import { flightElection } from "./connection/flight-election.js";
|
|
5
7
|
import { LocalDirectoryConnector } from "./connection/local-directory-connector.js";
|
|
6
8
|
import { socketPathFor } from "./connection/socket-path.js";
|
|
7
9
|
import { FlightServer } from "./coordinator/flight-server.js";
|
|
8
|
-
import { LeaderElection } from "./election/leader-election.js";
|
|
9
10
|
import { FlightFailedError, FlightInterruptedError, failureOf, } from "./errors.js";
|
|
10
11
|
/** Milliseconds between two attempts to reach the coordinator or to win its term. */
|
|
11
12
|
const POLL_INTERVAL = 10;
|
|
@@ -26,16 +27,14 @@ export class SingleFlight {
|
|
|
26
27
|
const socketPath = socketPathFor(directory);
|
|
27
28
|
this.#client = new FlightClient(new ConnectionSupervisor(new LocalDirectoryConnector(directory, new ElectingConnector({
|
|
28
29
|
socketPath,
|
|
29
|
-
election:
|
|
30
|
-
pollInterval: POLL_INTERVAL,
|
|
31
|
-
}),
|
|
30
|
+
election: flightElection(directory, POLL_INTERVAL),
|
|
32
31
|
pollInterval: POLL_INTERVAL,
|
|
33
|
-
serve: async (
|
|
32
|
+
serve: async (term) => {
|
|
34
33
|
// Until serving has fully started, a failure closes the new server, so no server outlives its term.
|
|
35
34
|
await using starting = new AsyncDisposableStack();
|
|
36
|
-
starting.adopt(await FlightServer.start(socketPath,
|
|
35
|
+
starting.adopt(await FlightServer.start(socketPath, term, {
|
|
37
36
|
// The first term of a directory has no flights to wait for.
|
|
38
|
-
graceWindow:
|
|
37
|
+
graceWindow: term.epoch > 1n ? graceWindow : 0,
|
|
39
38
|
}), (started) => started.close());
|
|
40
39
|
this.#servers.use(starting.move());
|
|
41
40
|
},
|
|
@@ -44,9 +43,11 @@ export class SingleFlight {
|
|
|
44
43
|
/**
|
|
45
44
|
* Runs `work` for `key` as the leader of a new flight, or joins the flight
|
|
46
45
|
* of `key` in progress. `work` gets the flight's lease: its token, and a
|
|
47
|
-
* signal that aborts with `
|
|
48
|
-
* leader's.
|
|
49
|
-
*
|
|
46
|
+
* signal that aborts with `LeaseLostError` once the flight is no longer this
|
|
47
|
+
* leader's. After that loss, the leader's call rejects with `LeaseLostError`,
|
|
48
|
+
* also when the work throws its own error. A joiner gets the leader's value
|
|
49
|
+
* through the codec, or rejects with `FlightFailedError` or
|
|
50
|
+
* `FlightInterruptedError`.
|
|
50
51
|
*/
|
|
51
52
|
async run(key, work, { onJoin, signal } = {}) {
|
|
52
53
|
const answer = await this.#client.run(key, { signal, onJoin });
|
|
@@ -57,7 +58,7 @@ export class SingleFlight {
|
|
|
57
58
|
throw new FlightInterruptedError(key);
|
|
58
59
|
case 'lead': {
|
|
59
60
|
// The signal stops only this caller's wait. The flight runs on for its joiners.
|
|
60
|
-
const settled = await untilAborted(this.#fly(work, answer.lead), signal);
|
|
61
|
+
const settled = await untilAborted(this.#fly(key, work, answer.lead), signal);
|
|
61
62
|
if ('error' in settled)
|
|
62
63
|
throw settled.error;
|
|
63
64
|
return { value: settled.value, joined: false };
|
|
@@ -70,18 +71,22 @@ export class SingleFlight {
|
|
|
70
71
|
await this.#servers.disposeAsync();
|
|
71
72
|
}
|
|
72
73
|
/** Runs the work and lands its outcome. Never rejects, so a caller that stopped waiting leaves no rejection behind. */
|
|
73
|
-
async #fly(work, lead) {
|
|
74
|
+
async #fly(key, work, lead) {
|
|
75
|
+
const { token, signal: lost } = lead;
|
|
74
76
|
let text;
|
|
75
77
|
try {
|
|
76
|
-
text = this.#codec.encode(await work({ token
|
|
78
|
+
text = this.#codec.encode(await work({ token, signal: lost }));
|
|
77
79
|
}
|
|
78
80
|
catch (error) {
|
|
79
81
|
lead.land({ failure: failureOf(error) });
|
|
80
|
-
|
|
82
|
+
// After a loss, every failure rejects with LeaseLostError: the work did not run alone (ADR 0007).
|
|
83
|
+
if (!lost.aborted || error === lost.reason)
|
|
84
|
+
return { error };
|
|
85
|
+
return { error: new LeaseLostError(key, { cause: error }) };
|
|
81
86
|
}
|
|
82
87
|
// A lost flight's joiners were told that it is interrupted, so this value reaches nobody.
|
|
83
|
-
if (
|
|
84
|
-
return { error:
|
|
88
|
+
if (lost.aborted)
|
|
89
|
+
return { error: lost.reason };
|
|
85
90
|
lead.land({ value: text });
|
|
86
91
|
try {
|
|
87
92
|
return { value: this.#codec.decode(text) };
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"single-flight.js","sourceRoot":"","sources":["../src/single-flight.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,YAAY,EAAE,MAAM,gBAAgB,CAAC;
|
|
1
|
+
{"version":3,"file":"single-flight.js","sourceRoot":"","sources":["../src/single-flight.ts"],"names":[],"mappings":"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"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@zukhruf/single-flight",
|
|
3
|
-
"version": "0.3.
|
|
3
|
+
"version": "0.3.18",
|
|
4
4
|
"description": "Callers of one key share the run already in flight, in one process or across the processes that use one directory, and get its outcome instead of a busy error.",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"repository": {
|
|
@@ -41,10 +41,11 @@
|
|
|
41
41
|
"access": "public"
|
|
42
42
|
},
|
|
43
43
|
"dependencies": {
|
|
44
|
-
"@zukhruf/async": "^0.3.13"
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
"@zukhruf/
|
|
44
|
+
"@zukhruf/async": "^0.3.13",
|
|
45
|
+
"@zukhruf/election": "^0.3.17",
|
|
46
|
+
"@zukhruf/fencing": "^0.3.16",
|
|
47
|
+
"@zukhruf/fs": "^0.3.16",
|
|
48
|
+
"@zukhruf/lease": "^0.3.16"
|
|
48
49
|
},
|
|
49
50
|
"devDependencies": {
|
|
50
51
|
"@zukhruf/mutex": "^0.3.11"
|
|
@@ -1,24 +0,0 @@
|
|
|
1
|
-
import { Leadership } from './leadership.ts';
|
|
2
|
-
export interface LeaderElectionOptions {
|
|
3
|
-
/** Milliseconds between attempts while another process coordinates. */
|
|
4
|
-
pollInterval?: number;
|
|
5
|
-
}
|
|
6
|
-
export interface CampaignOptions {
|
|
7
|
-
/** Milliseconds to keep trying before conceding to the current coordinator. */
|
|
8
|
-
timeout?: number;
|
|
9
|
-
}
|
|
10
|
-
/**
|
|
11
|
-
* Elects the coordinator among the processes sharing `directory`. The claim is
|
|
12
|
-
* an exclusive SQLite transaction on `flight.lock`, held for the whole term, so
|
|
13
|
-
* the kernel ends the term if the coordinator dies. Each term gets a higher
|
|
14
|
-
* epoch than every term before it, recorded in `flight.epoch`. Never delete
|
|
15
|
-
* `flight.lock` while campaigners run: a new file would let a second
|
|
16
|
-
* coordinator win.
|
|
17
|
-
*/
|
|
18
|
-
export declare class LeaderElection {
|
|
19
|
-
#private;
|
|
20
|
-
constructor(directory: string, { pollInterval }?: LeaderElectionOptions);
|
|
21
|
-
/** Resolves with the new term, or `undefined` if another process still coordinates after `timeout`. */
|
|
22
|
-
campaign({ timeout }?: CampaignOptions): Promise<Leadership | undefined>;
|
|
23
|
-
}
|
|
24
|
-
//# sourceMappingURL=leader-election.d.ts.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"leader-election.d.ts","sourceRoot":"","sources":["../../src/election/leader-election.ts"],"names":[],"mappings":"AASA,OAAO,EAAE,UAAU,EAAE,MAAM,iBAAiB,CAAC;AAE7C,MAAM,WAAW,qBAAqB;IACpC,uEAAuE;IACvE,YAAY,CAAC,EAAE,MAAM,CAAC;CACvB;AAED,MAAM,WAAW,eAAe;IAC9B,+EAA+E;IAC/E,OAAO,CAAC,EAAE,MAAM,CAAC;CAClB;AAED;;;;;;;GAOG;AACH,qBAAa,cAAc;;gBAKvB,SAAS,EAAE,MAAM,EACjB,EAAE,YAAiB,EAAE,GAAE,qBAA0B;IAMnD,uGAAuG;IACjG,QAAQ,CAAC,EAAE,OAAW,EAAE,GAAE,eAAoB,GAAG,OAAO,CAC5D,UAAU,GAAG,SAAS,CACvB;CAyCF"}
|
|
@@ -1,80 +0,0 @@
|
|
|
1
|
-
import { mkdir, readFile } from 'node:fs/promises';
|
|
2
|
-
import { join } from 'node:path';
|
|
3
|
-
import { DatabaseSync } from 'node:sqlite';
|
|
4
|
-
import { setTimeout as delay } from 'node:timers/promises';
|
|
5
|
-
import { assertLocalDirectory } from "../local-directory/local-directory.js";
|
|
6
|
-
import { durableWrite } from "../shared/fs/durable-write.js";
|
|
7
|
-
import { isErrno } from "../shared/fs/errno.js";
|
|
8
|
-
import { isBusy } from "../shared/sqlite/is-busy.js";
|
|
9
|
-
import { Leadership } from "./leadership.js";
|
|
10
|
-
/**
|
|
11
|
-
* Elects the coordinator among the processes sharing `directory`. The claim is
|
|
12
|
-
* an exclusive SQLite transaction on `flight.lock`, held for the whole term, so
|
|
13
|
-
* the kernel ends the term if the coordinator dies. Each term gets a higher
|
|
14
|
-
* epoch than every term before it, recorded in `flight.epoch`. Never delete
|
|
15
|
-
* `flight.lock` while campaigners run: a new file would let a second
|
|
16
|
-
* coordinator win.
|
|
17
|
-
*/
|
|
18
|
-
export class LeaderElection {
|
|
19
|
-
#directory;
|
|
20
|
-
#pollInterval;
|
|
21
|
-
constructor(directory, { pollInterval = 10 } = {}) {
|
|
22
|
-
this.#directory = directory;
|
|
23
|
-
this.#pollInterval = pollInterval;
|
|
24
|
-
}
|
|
25
|
-
/** Resolves with the new term, or `undefined` if another process still coordinates after `timeout`. */
|
|
26
|
-
async campaign({ timeout = 0 } = {}) {
|
|
27
|
-
await assertLocalDirectory(this.#directory);
|
|
28
|
-
await mkdir(this.#directory, { recursive: true });
|
|
29
|
-
// A busy timeout above zero would block this process's event loop while it
|
|
30
|
-
// waits, so the claim is retried here instead.
|
|
31
|
-
const claim = new DatabaseSync(join(this.#directory, 'flight.lock'), {
|
|
32
|
-
timeout: 0,
|
|
33
|
-
});
|
|
34
|
-
const deadline = performance.now() + timeout;
|
|
35
|
-
try {
|
|
36
|
-
for (;;) {
|
|
37
|
-
if (this.#tryClaim(claim))
|
|
38
|
-
return new Leadership(await this.#nextEpoch(), claim);
|
|
39
|
-
if (performance.now() >= deadline)
|
|
40
|
-
break;
|
|
41
|
-
await delay(this.#pollInterval);
|
|
42
|
-
}
|
|
43
|
-
}
|
|
44
|
-
catch (error) {
|
|
45
|
-
claim.close();
|
|
46
|
-
throw error;
|
|
47
|
-
}
|
|
48
|
-
claim.close();
|
|
49
|
-
return undefined;
|
|
50
|
-
}
|
|
51
|
-
#tryClaim(claim) {
|
|
52
|
-
try {
|
|
53
|
-
claim.exec('BEGIN EXCLUSIVE');
|
|
54
|
-
return true;
|
|
55
|
-
}
|
|
56
|
-
catch (error) {
|
|
57
|
-
if (isBusy(error))
|
|
58
|
-
return false;
|
|
59
|
-
throw error;
|
|
60
|
-
}
|
|
61
|
-
}
|
|
62
|
-
/** Safe without further locking: only the claim holder gets here. */
|
|
63
|
-
async #nextEpoch() {
|
|
64
|
-
const path = join(this.#directory, 'flight.epoch');
|
|
65
|
-
const epoch = (await readEpoch(path)) + 1n;
|
|
66
|
-
await durableWrite(path, epoch.toString());
|
|
67
|
-
return epoch;
|
|
68
|
-
}
|
|
69
|
-
}
|
|
70
|
-
async function readEpoch(path) {
|
|
71
|
-
try {
|
|
72
|
-
return BigInt(await readFile(path, 'utf8'));
|
|
73
|
-
}
|
|
74
|
-
catch (error) {
|
|
75
|
-
if (isErrno(error, 'ENOENT'))
|
|
76
|
-
return 0n;
|
|
77
|
-
throw error;
|
|
78
|
-
}
|
|
79
|
-
}
|
|
80
|
-
//# sourceMappingURL=leader-election.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"leader-election.js","sourceRoot":"","sources":["../../src/election/leader-election.ts"],"names":[],"mappings":"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"}
|
|
@@ -1,14 +0,0 @@
|
|
|
1
|
-
import type { DatabaseSync } from 'node:sqlite';
|
|
2
|
-
/**
|
|
3
|
-
* One term as the elected coordinator. It lasts until `resign` or until the
|
|
4
|
-
* process dies, when the kernel releases the claim and another campaigner can win.
|
|
5
|
-
*/
|
|
6
|
-
export declare class Leadership implements AsyncDisposable {
|
|
7
|
-
#private;
|
|
8
|
-
/** Grows with every term, so a newer coordinator's tokens always outrank an older one's. */
|
|
9
|
-
readonly epoch: bigint;
|
|
10
|
-
constructor(epoch: bigint, claim: DatabaseSync);
|
|
11
|
-
resign(): Promise<void>;
|
|
12
|
-
[Symbol.asyncDispose](): Promise<void>;
|
|
13
|
-
}
|
|
14
|
-
//# sourceMappingURL=leadership.d.ts.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"leadership.d.ts","sourceRoot":"","sources":["../../src/election/leadership.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,aAAa,CAAC;AAEhD;;;GAGG;AACH,qBAAa,UAAW,YAAW,eAAe;;IAChD,4FAA4F;IAC5F,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC;gBAGX,KAAK,EAAE,MAAM,EAAE,KAAK,EAAE,YAAY;IAKxC,MAAM,IAAI,OAAO,CAAC,IAAI,CAAC;IAM7B,CAAC,MAAM,CAAC,YAAY,CAAC,IAAI,OAAO,CAAC,IAAI,CAAC;CAGvC"}
|
|
@@ -1,23 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* One term as the elected coordinator. It lasts until `resign` or until the
|
|
3
|
-
* process dies, when the kernel releases the claim and another campaigner can win.
|
|
4
|
-
*/
|
|
5
|
-
export class Leadership {
|
|
6
|
-
/** Grows with every term, so a newer coordinator's tokens always outrank an older one's. */
|
|
7
|
-
epoch;
|
|
8
|
-
#claim;
|
|
9
|
-
constructor(epoch, claim) {
|
|
10
|
-
this.epoch = epoch;
|
|
11
|
-
this.#claim = claim;
|
|
12
|
-
}
|
|
13
|
-
async resign() {
|
|
14
|
-
if (!this.#claim.isOpen)
|
|
15
|
-
return;
|
|
16
|
-
this.#claim.exec('ROLLBACK');
|
|
17
|
-
this.#claim.close();
|
|
18
|
-
}
|
|
19
|
-
[Symbol.asyncDispose]() {
|
|
20
|
-
return this.resign();
|
|
21
|
-
}
|
|
22
|
-
}
|
|
23
|
-
//# sourceMappingURL=leadership.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"leadership.js","sourceRoot":"","sources":["../../src/election/leadership.ts"],"names":[],"mappings":"AAEA;;;GAGG;AACH,MAAM,OAAO,UAAU;IACrB,4FAA4F;IACnF,KAAK,CAAS;IACd,MAAM,CAAe;IAE9B,YAAY,KAAa,EAAE,KAAmB;QAC5C,IAAI,CAAC,KAAK,GAAG,KAAK,CAAC;QACnB,IAAI,CAAC,MAAM,GAAG,KAAK,CAAC;IACtB,CAAC;IAED,KAAK,CAAC,MAAM;QACV,IAAI,CAAC,IAAI,CAAC,MAAM,CAAC,MAAM;YAAE,OAAO;QAChC,IAAI,CAAC,MAAM,CAAC,IAAI,CAAC,UAAU,CAAC,CAAC;QAC7B,IAAI,CAAC,MAAM,CAAC,KAAK,EAAE,CAAC;IACtB,CAAC;IAED,CAAC,MAAM,CAAC,YAAY,CAAC;QACnB,OAAO,IAAI,CAAC,MAAM,EAAE,CAAC;IACvB,CAAC;CACF"}
|
|
@@ -1,7 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Rejects with `NetworkDirectoryError` when `directory` is on a network file
|
|
3
|
-
* system, where the election's lock is not shared reliably between machines.
|
|
4
|
-
* A directory that does not exist yet is judged by its nearest existing parent.
|
|
5
|
-
*/
|
|
6
|
-
export declare function assertLocalDirectory(directory: string): Promise<void>;
|
|
7
|
-
//# sourceMappingURL=local-directory.d.ts.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"local-directory.d.ts","sourceRoot":"","sources":["../../src/local-directory/local-directory.ts"],"names":[],"mappings":"AA+DA;;;;GAIG;AACH,wBAAsB,oBAAoB,CAAC,SAAS,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAQ3E"}
|