@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
package/README.md
CHANGED
|
@@ -63,14 +63,14 @@ The first caller is the leader: its call runs the work of the flight. The other
|
|
|
63
63
|
This project is an experiment.
|
|
64
64
|
|
|
65
65
|
```sh
|
|
66
|
-
npm install @zukhruf/single-flight
|
|
66
|
+
npm install @zukhruf/single-flight
|
|
67
67
|
```
|
|
68
68
|
|
|
69
|
-
|
|
69
|
+
The lease that the work gets comes from `@zukhruf/lease`, and its token comes from `@zukhruf/fencing`. Both are dependencies of this package, so you install nothing more.
|
|
70
70
|
|
|
71
71
|
## The directory
|
|
72
72
|
|
|
73
|
-
The directory is the local folder where the processes that share flights meet. Each process that uses a `SingleFlight` keeps three files there: `flight.lock`, `flight.epoch` and `flight.sock`. All the processes that name the same directory are one group, and the callers of one key share a flight in that group only.
|
|
73
|
+
The directory is the local folder where the processes that share flights meet. Each process that uses a `SingleFlight` keeps three files there: `flight.lock`, `flight.epoch` and `flight.sock`. The election of [`@zukhruf/election`](../election/README.md) claims `flight.lock` with a file lock, and records the epoch of the last term in `flight.epoch`. The journal of the claim is in memory, so a coordinator that stops leaves no `flight.lock-journal` file. All the processes that name the same directory are one group, and the callers of one key share a flight in that group only.
|
|
74
74
|
|
|
75
75
|
There is no default directory. One default would put each application on the host into one group, and unrelated applications that use the same key would join each other's flights. Give each group its own directory, for example a folder of your application's data.
|
|
76
76
|
|
|
@@ -86,8 +86,8 @@ All the processes of the directory take part in one election. The winner is the
|
|
|
86
86
|
|
|
87
87
|
The work gets the lease of the flight:
|
|
88
88
|
|
|
89
|
-
- `token`: a
|
|
90
|
-
- `signal`: it aborts with `
|
|
89
|
+
- `token`: a `FencingToken`. Its high 32 bits are the epoch of the coordinator's term, so a newer term always gives higher tokens.
|
|
90
|
+
- `signal`: it aborts with `LeaseLostError` when the flight is no longer the leader's. The `subject` of the error is the key. This occurs when the leader misses the grace window of a new coordinator.
|
|
91
91
|
|
|
92
92
|
| Option | What it does |
|
|
93
93
|
| ------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
|
@@ -147,7 +147,8 @@ A codec that cannot encode the value fails the flight for all callers. A codec t
|
|
|
147
147
|
| The leader | Its work threw | The original error of the work |
|
|
148
148
|
| A joiner | Its work threw | `FlightFailedError` |
|
|
149
149
|
| A joiner | Interrupted: the leader's process stopped, or it lost the lease | `FlightInterruptedError` |
|
|
150
|
-
| The leader | It lost the lease | The reason of the lease's signal: `
|
|
150
|
+
| The leader | It lost the lease | The reason of the lease's signal: `LeaseLostError` |
|
|
151
|
+
| The leader | It lost the lease, and then its work threw | A new `LeaseLostError`. Its `cause` is the error of the work |
|
|
151
152
|
| Each caller | `encode` threw in the leader | The leader: the error of `encode`. A joiner: `FlightFailedError` |
|
|
152
153
|
| One caller | Its own `decode` threw | The error of `decode`, for that caller only |
|
|
153
154
|
| Each caller | The coordinator speaks another protocol version | `ProtocolVersionError` |
|
|
@@ -167,7 +168,7 @@ Give a signal to stop the wait of one caller: `flights.run(key, work, { signal:
|
|
|
167
168
|
- Each leader reasserts its flight, and sends its landing again when it has one.
|
|
168
169
|
- Each joiner rejoins its flight by the flight's token, and it gets the outcome of that flight.
|
|
169
170
|
- A new call waits for the grace window to end. Then it leads or joins.
|
|
170
|
-
- **A leader misses the grace window**, for example because its process was frozen. Its lease is lost: the signal of the lease aborts with `
|
|
171
|
+
- **A leader misses the grace window**, for example because its process was frozen. Its lease is lost: the signal of the lease aborts with `LeaseLostError`, and its call rejects with that error. When the work throws its own error after the loss, the call rejects with a new `LeaseLostError`, and the error of the work is its `cause`. Thus `LeaseLostError` always tells the leader that its work did not run alone. Its joiners get `FlightInterruptedError`. [ADR 0007](./docs/adr/0007-a-work-error-after-a-lost-lease-rejects-with-leaselosterror.md) tells why.
|
|
171
172
|
- **A joiner's leader and the coordinator stop together.** The joiner gets `FlightInterruptedError` at the end of the grace window. It never runs the work again.
|
|
172
173
|
|
|
173
174
|
A call that was on its way to a coordinator that stopped joined nothing. It goes again to the next coordinator as a new call. [ADR 0005](./docs/adr/0005-a-joiner-rejoins-its-flight-by-its-token.md) tells why.
|
|
@@ -191,7 +192,9 @@ Version 0.3.13 to 0.3.15 had a pull design. These parts changed:
|
|
|
191
192
|
- [ADR 0004: A cancel withdraws only its caller](./docs/adr/0004-a-cancel-withdraws-only-its-caller.md)
|
|
192
193
|
- [ADR 0005: A joiner rejoins its flight by its token](./docs/adr/0005-a-joiner-rejoins-its-flight-by-its-token.md)
|
|
193
194
|
- [ADR 0006: The election and the connection are a copy of the mutex code](./docs/adr/0006-the-election-and-the-connection-are-a-copy-of-the-mutex-code.md)
|
|
194
|
-
- [
|
|
195
|
+
- [ADR 0007: A work error after a lost lease rejects with LeaseLostError](./docs/adr/0007-a-work-error-after-a-lost-lease-rejects-with-leaselosterror.md)
|
|
196
|
+
- [ADR 0008: A connection closes only when its framing breaks](./docs/adr/0008-a-connection-closes-only-when-its-framing-breaks.md)
|
|
197
|
+
- [Code copied from the mutex](./docs/copied-from-mutex.md): each copied file, what changed, and why; the rules that the single flight shares with the mutex; and the code that is in two places inside the single flight.
|
|
195
198
|
- Superseded: [ADR 0001](./docs/adr/0001-a-joiner-follows-its-flight-record-without-acquiring-the-key.md) and [ADR 0002](./docs/adr/0002-a-flight-that-all-callers-left-is-abandoned.md).
|
|
196
199
|
|
|
197
200
|
## Development
|
|
@@ -215,9 +218,7 @@ src/
|
|
|
215
218
|
client/ the requests of one process: runs, leads, landings
|
|
216
219
|
coordinator/ the coordinator of one term: flights, sessions, its server
|
|
217
220
|
protocol/ the messages between a process and its coordinator
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
local-directory/ the check for a network file system (a copy)
|
|
221
|
-
shared/ file and SQLite helpers (a copy)
|
|
221
|
+
connection/ the socket, the handshake and the supervisor (a copy); the election of the directory (@zukhruf/election)
|
|
222
|
+
shared/ the record check (a copy); file writes and the network directory check are in @zukhruf/fs
|
|
222
223
|
testing/ the caller process that the tests start
|
|
223
224
|
```
|
|
@@ -1,10 +1,10 @@
|
|
|
1
|
-
import { FencingToken } from '@zukhruf/
|
|
1
|
+
import { FencingToken } from '@zukhruf/fencing';
|
|
2
2
|
import type { ConnectionSupervisor } from '../connection/connection-supervisor.ts';
|
|
3
|
-
import type
|
|
3
|
+
import { type FlightRequest, type Outcome } from '../protocol/flight-protocol.ts';
|
|
4
4
|
/** This process leads a flight: it runs the work and lands the outcome. */
|
|
5
5
|
export interface Lead {
|
|
6
6
|
readonly token: FencingToken;
|
|
7
|
-
/** Aborts with a `
|
|
7
|
+
/** Aborts with a `LeaseLostError` once the flight is no longer this leader's. */
|
|
8
8
|
readonly signal: AbortSignal;
|
|
9
9
|
/** Ends the flight with `outcome` for every joiner. Kept and sent again until a coordinator acknowledges it. */
|
|
10
10
|
land(outcome: Outcome): void;
|
|
@@ -32,7 +32,7 @@ export interface RunRequest {
|
|
|
32
32
|
*/
|
|
33
33
|
export declare class FlightClient {
|
|
34
34
|
#private;
|
|
35
|
-
constructor(link: ConnectionSupervisor<FlightRequest
|
|
35
|
+
constructor(link: ConnectionSupervisor<FlightRequest>);
|
|
36
36
|
run(key: string, { signal, onJoin }: RunRequest): Promise<Answer>;
|
|
37
37
|
/**
|
|
38
38
|
* Disconnects for good, once every landing reached a coordinator: a landing
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"flight-client.d.ts","sourceRoot":"","sources":["../../src/client/flight-client.ts"],"names":[],"mappings":"AAGA,OAAO,EAAE,YAAY,
|
|
1
|
+
{"version":3,"file":"flight-client.d.ts","sourceRoot":"","sources":["../../src/client/flight-client.ts"],"names":[],"mappings":"AAGA,OAAO,EAAE,YAAY,EAAE,MAAM,kBAAkB,CAAC;AAGhD,OAAO,KAAK,EAAE,oBAAoB,EAAE,MAAM,wCAAwC,CAAC;AACnF,OAAO,EACL,KAAK,aAAa,EAElB,KAAK,OAAO,EAEb,MAAM,gCAAgC,CAAC;AAExC,2EAA2E;AAC3E,MAAM,WAAW,IAAI;IACnB,QAAQ,CAAC,KAAK,EAAE,YAAY,CAAC;IAC7B,iFAAiF;IACjF,QAAQ,CAAC,MAAM,EAAE,WAAW,CAAC;IAC7B,gHAAgH;IAChH,IAAI,CAAC,OAAO,EAAE,OAAO,GAAG,IAAI,CAAC;CAC9B;AAED,mDAAmD;AACnD,MAAM,MAAM,MAAM,GACd;IAAE,IAAI,EAAE,MAAM,CAAC;IAAC,IAAI,EAAE,IAAI,CAAA;CAAE,GAC5B;IAAE,IAAI,EAAE,QAAQ,CAAC;IAAC,OAAO,EAAE,OAAO,CAAA;CAAE,GACpC;IAAE,IAAI,EAAE,aAAa,CAAA;CAAE,CAAC;AAE5B,MAAM,WAAW,UAAU;IACzB,MAAM,CAAC,EAAE,WAAW,GAAG,SAAS,CAAC;IACjC,MAAM,CAAC,EAAE,CAAC,MAAM,IAAI,CAAC,GAAG,SAAS,CAAC;CACnC;AAuBD;;;;;;GAMG;AACH,qBAAa,YAAY;;gBAOX,IAAI,EAAE,oBAAoB,CAAC,aAAa,CAAC;IAW/C,GAAG,CAAC,GAAG,EAAE,MAAM,EAAE,EAAE,MAAM,EAAE,MAAM,EAAE,EAAE,UAAU,GAAG,OAAO,CAAC,MAAM,CAAC;IA2BvE;;;;OAIG;IACG,KAAK;CAqKZ"}
|
|
@@ -1,6 +1,8 @@
|
|
|
1
1
|
import { randomUUID } from 'node:crypto';
|
|
2
2
|
import { untilAborted } from '@zukhruf/async';
|
|
3
|
-
import { FencingToken
|
|
3
|
+
import { FencingToken } from '@zukhruf/fencing';
|
|
4
|
+
import { LeaseController } from '@zukhruf/lease';
|
|
5
|
+
import { isFlightResponse, } from "../protocol/flight-protocol.js";
|
|
4
6
|
/**
|
|
5
7
|
* Sends runs to the coordinator over a supervised connection. When the
|
|
6
8
|
* connection is replaced, it reasserts the flights this process leads, sends
|
|
@@ -17,7 +19,11 @@ export class FlightClient {
|
|
|
17
19
|
constructor(link) {
|
|
18
20
|
this.#link = link;
|
|
19
21
|
link.on('connected', () => this.#resume());
|
|
20
|
-
|
|
22
|
+
// A message this client cannot read answers nothing it waits for.
|
|
23
|
+
link.on('message', (message) => {
|
|
24
|
+
if (isFlightResponse(message))
|
|
25
|
+
this.#receive(message);
|
|
26
|
+
});
|
|
21
27
|
link.on('disconnected', () => this.#interrupt());
|
|
22
28
|
link.on('failed', (error) => this.#fail(error));
|
|
23
29
|
}
|
|
@@ -85,13 +91,13 @@ export class FlightClient {
|
|
|
85
91
|
const held = {
|
|
86
92
|
key,
|
|
87
93
|
token,
|
|
88
|
-
|
|
94
|
+
lease: new LeaseController(key),
|
|
89
95
|
landing: undefined,
|
|
90
96
|
};
|
|
91
97
|
this.#held.set(id, held);
|
|
92
98
|
return {
|
|
93
99
|
token,
|
|
94
|
-
signal: held.
|
|
100
|
+
signal: held.lease.signal,
|
|
95
101
|
land: (outcome) => {
|
|
96
102
|
// A lost flight is no longer this leader's to land.
|
|
97
103
|
if (this.#held.get(id) !== held || held.landing)
|
|
@@ -108,7 +114,7 @@ export class FlightClient {
|
|
|
108
114
|
if (!held)
|
|
109
115
|
return;
|
|
110
116
|
this.#release(id);
|
|
111
|
-
held.
|
|
117
|
+
held.lease.lose();
|
|
112
118
|
}
|
|
113
119
|
/** The flight of `id` needs nothing more from this process. */
|
|
114
120
|
#release(id) {
|
|
@@ -126,7 +132,7 @@ export class FlightClient {
|
|
|
126
132
|
const pending = this.#take(response.id);
|
|
127
133
|
if (!pending)
|
|
128
134
|
return;
|
|
129
|
-
const token =
|
|
135
|
+
const token = FencingToken.parse(response.token);
|
|
130
136
|
pending.resolve({
|
|
131
137
|
kind: 'lead',
|
|
132
138
|
lead: this.#hold(response.id, pending.key, token),
|
|
@@ -152,11 +158,15 @@ export class FlightClient {
|
|
|
152
158
|
case 'interrupted':
|
|
153
159
|
this.#take(response.id)?.resolve({ kind: 'interrupted' });
|
|
154
160
|
return;
|
|
155
|
-
case 'ack':
|
|
156
|
-
// The joiners have the outcome, so there is nothing left to reassert.
|
|
157
|
-
|
|
158
|
-
|
|
161
|
+
case 'ack': {
|
|
162
|
+
// The joiners have the outcome, so there is nothing left to reassert, and no later loss of the lease.
|
|
163
|
+
const held = this.#held.get(response.id);
|
|
164
|
+
if (!held?.landing)
|
|
165
|
+
return;
|
|
166
|
+
this.#release(response.id);
|
|
167
|
+
held.lease.end();
|
|
159
168
|
return;
|
|
169
|
+
}
|
|
160
170
|
case 'rejected':
|
|
161
171
|
this.#lose(response.id);
|
|
162
172
|
return;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"flight-client.js","sourceRoot":"","sources":["../../src/client/flight-client.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,MAAM,aAAa,CAAC;AAEzC,OAAO,EAAE,YAAY,EAAE,MAAM,gBAAgB,CAAC;AAC9C,OAAO,EAAE,YAAY,EAAE,
|
|
1
|
+
{"version":3,"file":"flight-client.js","sourceRoot":"","sources":["../../src/client/flight-client.ts"],"names":[],"mappings":"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"}
|
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
import { EventEmitter } from 'node:events';
|
|
2
2
|
import type { Connector } from './connector.ts';
|
|
3
3
|
export type SupervisorStatus = 'idle' | 'connecting' | 'connected' | 'unavailable' | 'closed';
|
|
4
|
-
export interface SupervisorEvents
|
|
4
|
+
export interface SupervisorEvents {
|
|
5
5
|
/** A connection is open: the first one, or the replacement for a lost one. */
|
|
6
6
|
connected: [];
|
|
7
|
-
message: [message:
|
|
7
|
+
message: [message: unknown];
|
|
8
8
|
/** The open connection is gone and a replacement is on its way. Nothing sent on it will be answered. */
|
|
9
9
|
disconnected: [];
|
|
10
10
|
/** The connector can never connect again. */
|
|
@@ -18,9 +18,9 @@ export interface SupervisorEvents<Incoming> {
|
|
|
18
18
|
* left. It never reads the messages it carries: what a replacement must be
|
|
19
19
|
* told again is for its listener to decide.
|
|
20
20
|
*/
|
|
21
|
-
export declare class ConnectionSupervisor<Outgoing
|
|
21
|
+
export declare class ConnectionSupervisor<Outgoing> extends EventEmitter<SupervisorEvents> {
|
|
22
22
|
#private;
|
|
23
|
-
constructor(connector: Connector<Outgoing
|
|
23
|
+
constructor(connector: Connector<Outgoing>);
|
|
24
24
|
get status(): SupervisorStatus;
|
|
25
25
|
/** Starts connecting, unless a connection is open, on its way, or never coming. */
|
|
26
26
|
open(): void;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"connection-supervisor.d.ts","sourceRoot":"","sources":["../../src/connection/connection-supervisor.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,YAAY,EAAE,MAAM,aAAa,CAAC;AAK3C,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,gBAAgB,CAAC;AAEhD,MAAM,MAAM,gBAAgB,GAC1B,MAAM,GAAG,YAAY,GAAG,WAAW,GAAG,aAAa,GAAG,QAAQ,CAAC;AAEjE,MAAM,WAAW,gBAAgB
|
|
1
|
+
{"version":3,"file":"connection-supervisor.d.ts","sourceRoot":"","sources":["../../src/connection/connection-supervisor.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,YAAY,EAAE,MAAM,aAAa,CAAC;AAK3C,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,gBAAgB,CAAC;AAEhD,MAAM,MAAM,gBAAgB,GAC1B,MAAM,GAAG,YAAY,GAAG,WAAW,GAAG,aAAa,GAAG,QAAQ,CAAC;AAEjE,MAAM,WAAW,gBAAgB;IAC/B,8EAA8E;IAC9E,SAAS,EAAE,EAAE,CAAC;IACd,OAAO,EAAE,CAAC,OAAO,EAAE,OAAO,CAAC,CAAC;IAC5B,wGAAwG;IACxG,YAAY,EAAE,EAAE,CAAC;IACjB,6CAA6C;IAC7C,WAAW,EAAE,EAAE,CAAC;IAChB,kEAAkE;IAClE,MAAM,EAAE,CAAC,KAAK,EAAE,OAAO,CAAC,CAAC;CAC1B;AAED;;;;;GAKG;AACH,qBAAa,oBAAoB,CAC/B,QAAQ,CACR,SAAQ,YAAY,CAAC,gBAAgB,CAAC;;gBAG1B,SAAS,EAAE,SAAS,CAAC,QAAQ,CAAC;IAK1C,IAAI,MAAM,IAAI,gBAAgB,CAE7B;IAED,mFAAmF;IACnF,IAAI;IAIJ,mGAAmG;IACnG,IAAI,CAAC,OAAO,EAAE,QAAQ,GAAG,OAAO;IAIhC;;;;OAIG;IACH,GAAG;IAIH,KAAK;IAIL,uEAAuE;IACvE,KAAK,IAAI,OAAO,CAAC,IAAI,CAAC;CAGvB"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"connection-supervisor.js","sourceRoot":"","sources":["../../src/connection/connection-supervisor.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,YAAY,EAAE,MAAM,aAAa,CAAC;AAE3C,OAAO,EAAE,KAAK,EAAE,MAAM,gBAAgB,CAAC;AAoBvC;;;;;GAKG;AACH,MAAM,OAAO,
|
|
1
|
+
{"version":3,"file":"connection-supervisor.js","sourceRoot":"","sources":["../../src/connection/connection-supervisor.ts"],"names":[],"mappings":"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"}
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import type { EventEmitter } from 'node:events';
|
|
2
|
-
export interface ConnectionEvents
|
|
3
|
-
|
|
2
|
+
export interface ConnectionEvents {
|
|
3
|
+
/** Unchecked: the protocol owner that listens checks each message before it reads it. */
|
|
4
|
+
message: [message: unknown];
|
|
4
5
|
/** Emitted once, when the peer is gone. */
|
|
5
6
|
close: [];
|
|
6
7
|
}
|
|
@@ -9,7 +10,7 @@ export interface ConnectionEvents<Incoming> {
|
|
|
9
10
|
* Subscribe in the task that receives the connection: a message that arrives
|
|
10
11
|
* while nobody listens is not kept.
|
|
11
12
|
*/
|
|
12
|
-
export interface Connection<Outgoing
|
|
13
|
+
export interface Connection<Outgoing> extends EventEmitter<ConnectionEvents> {
|
|
13
14
|
/** Rejects when the message cannot be delivered because the peer is gone. */
|
|
14
15
|
send(message: Outgoing): Promise<void>;
|
|
15
16
|
/** Keeps the process alive while its owner waits for a message. */
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"connection.d.ts","sourceRoot":"","sources":["../../src/connection/connection.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,aAAa,CAAC;AAEhD,MAAM,WAAW,gBAAgB,
|
|
1
|
+
{"version":3,"file":"connection.d.ts","sourceRoot":"","sources":["../../src/connection/connection.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,aAAa,CAAC;AAEhD,MAAM,WAAW,gBAAgB;IAC/B,yFAAyF;IACzF,OAAO,EAAE,CAAC,OAAO,EAAE,OAAO,CAAC,CAAC;IAC5B,2CAA2C;IAC3C,KAAK,EAAE,EAAE,CAAC;CACX;AAED;;;;GAIG;AACH,MAAM,WAAW,UAAU,CAAC,QAAQ,CAAE,SAAQ,YAAY,CAAC,gBAAgB,CAAC;IAC1E,6EAA6E;IAC7E,IAAI,CAAC,OAAO,EAAE,QAAQ,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IACvC,mEAAmE;IACnE,GAAG,IAAI,IAAI,CAAC;IACZ,oFAAoF;IACpF,KAAK,IAAI,IAAI,CAAC;IACd,KAAK,IAAI,IAAI,CAAC;CACf"}
|
|
@@ -1,15 +1,15 @@
|
|
|
1
|
-
import type { FlightRequest
|
|
1
|
+
import type { FlightRequest } from '../protocol/flight-protocol.ts';
|
|
2
2
|
import type { Connection } from './connection.ts';
|
|
3
|
-
export type FlightConnection = Connection<FlightRequest
|
|
3
|
+
export type FlightConnection = Connection<FlightRequest>;
|
|
4
4
|
/** Decides how a client reaches its coordinator, and whether it can again after losing it. */
|
|
5
|
-
export interface Connector<Outgoing
|
|
5
|
+
export interface Connector<Outgoing> {
|
|
6
6
|
/**
|
|
7
7
|
* Resolves to `undefined` when the coordinator is gone for good and nothing
|
|
8
8
|
* can replace it.
|
|
9
9
|
* Rejects when this attempt failed and a later one may succeed. Once
|
|
10
10
|
* `signal` aborts, rejects with its reason and leaves nothing started.
|
|
11
11
|
*/
|
|
12
|
-
connect(signal: AbortSignal): Promise<Connection<Outgoing
|
|
12
|
+
connect(signal: AbortSignal): Promise<Connection<Outgoing> | undefined>;
|
|
13
13
|
}
|
|
14
|
-
export type FlightConnector = Connector<FlightRequest
|
|
14
|
+
export type FlightConnector = Connector<FlightRequest>;
|
|
15
15
|
//# sourceMappingURL=connector.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"connector.d.ts","sourceRoot":"","sources":["../../src/connection/connector.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,
|
|
1
|
+
{"version":3,"file":"connector.d.ts","sourceRoot":"","sources":["../../src/connection/connector.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,gCAAgC,CAAC;AACpE,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,iBAAiB,CAAC;AAElD,MAAM,MAAM,gBAAgB,GAAG,UAAU,CAAC,aAAa,CAAC,CAAC;AAEzD,8FAA8F;AAC9F,MAAM,WAAW,SAAS,CAAC,QAAQ;IACjC;;;;;OAKG;IACH,OAAO,CAAC,MAAM,EAAE,WAAW,GAAG,OAAO,CAAC,UAAU,CAAC,QAAQ,CAAC,GAAG,SAAS,CAAC,CAAC;CACzE;AAED,MAAM,MAAM,eAAe,GAAG,SAAS,CAAC,aAAa,CAAC,CAAC"}
|
|
@@ -1,13 +1,12 @@
|
|
|
1
|
-
import type { LeaderElection } from '
|
|
2
|
-
import type { Leadership } from '../election/leadership.ts';
|
|
1
|
+
import type { LeaderElection, Term } from '@zukhruf/election';
|
|
3
2
|
import type { FlightConnection, FlightConnector } from './connector.ts';
|
|
4
3
|
export interface ElectingConnectorOptions {
|
|
5
4
|
socketPath: string;
|
|
6
|
-
/**
|
|
7
|
-
election: Pick<LeaderElection
|
|
5
|
+
/** Only `campaign`: the connector never runs a backend's own steps, so an election of any backend fits. */
|
|
6
|
+
election: Pick<LeaderElection<unknown>, 'campaign'>;
|
|
8
7
|
pollInterval: number;
|
|
9
8
|
/** Starts serving for a term this process just won. */
|
|
10
|
-
serve(
|
|
9
|
+
serve(term: Term): Promise<void>;
|
|
11
10
|
}
|
|
12
11
|
/**
|
|
13
12
|
* Reaches the coordinator's socket, and when nobody serves it, campaigns to
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"electing-connector.d.ts","sourceRoot":"","sources":["../../src/connection/electing-connector.ts"],"names":[],"mappings":"AAKA,OAAO,KAAK,EAAE,cAAc,EAAE,
|
|
1
|
+
{"version":3,"file":"electing-connector.d.ts","sourceRoot":"","sources":["../../src/connection/electing-connector.ts"],"names":[],"mappings":"AAKA,OAAO,KAAK,EAAE,cAAc,EAAE,IAAI,EAAE,MAAM,mBAAmB,CAAC;AAG9D,OAAO,KAAK,EAAE,gBAAgB,EAAE,eAAe,EAAE,MAAM,gBAAgB,CAAC;AAWxE,MAAM,WAAW,wBAAwB;IACvC,UAAU,EAAE,MAAM,CAAC;IACnB,2GAA2G;IAC3G,QAAQ,EAAE,IAAI,CAAC,cAAc,CAAC,OAAO,CAAC,EAAE,UAAU,CAAC,CAAC;IACpD,YAAY,EAAE,MAAM,CAAC;IACrB,uDAAuD;IACvD,KAAK,CAAC,IAAI,EAAE,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;CAClC;AAED;;;;;GAKG;AACH,qBAAa,iBAAkB,YAAW,eAAe;;gBAG3C,OAAO,EAAE,wBAAwB;IAIvC,OAAO,CAAC,MAAM,EAAE,WAAW,GAAG,OAAO,CAAC,gBAAgB,CAAC;CA6F9D"}
|
|
@@ -1,7 +1,7 @@
|
|
|
1
|
+
import { once } from 'node:events';
|
|
1
2
|
import { connect } from 'node:net';
|
|
2
3
|
import { setTimeout as delay } from 'node:timers/promises';
|
|
3
4
|
import { untilAborted } from '@zukhruf/async';
|
|
4
|
-
import { isFlightResponse, } from "../protocol/flight-protocol.js";
|
|
5
5
|
import { PROTOCOL_VERSION, greet } from "./handshake.js";
|
|
6
6
|
import { ProtocolVersionError } from "./protocol-version-error.js";
|
|
7
7
|
import { SocketConnection } from "./socket-connection.js";
|
|
@@ -31,14 +31,14 @@ export class ElectingConnector {
|
|
|
31
31
|
if (connection)
|
|
32
32
|
return connection;
|
|
33
33
|
}
|
|
34
|
-
const
|
|
35
|
-
if (
|
|
36
|
-
const own = await this.#coordinate(
|
|
34
|
+
const term = await this.#campaign(pollInterval, signal);
|
|
35
|
+
if (term) {
|
|
36
|
+
const own = await this.#coordinate(term, signal);
|
|
37
37
|
if (own)
|
|
38
38
|
return own;
|
|
39
39
|
}
|
|
40
40
|
else {
|
|
41
|
-
await delay(pollInterval, undefined, { signal });
|
|
41
|
+
await untilAborted(delay(pollInterval, undefined, { signal }), signal);
|
|
42
42
|
}
|
|
43
43
|
}
|
|
44
44
|
}
|
|
@@ -54,9 +54,9 @@ export class ElectingConnector {
|
|
|
54
54
|
const { socketPath, pollInterval } = this.#options;
|
|
55
55
|
const deadline = performance.now() + HANDSHAKE_PATIENCE;
|
|
56
56
|
for (;;) {
|
|
57
|
-
const
|
|
58
|
-
if (
|
|
59
|
-
return this.#coordinate(
|
|
57
|
+
const term = await this.#campaign(0, signal);
|
|
58
|
+
if (term)
|
|
59
|
+
return this.#coordinate(term, signal);
|
|
60
60
|
const again = await reachUnlessAborted(socketPath, signal);
|
|
61
61
|
if (!again)
|
|
62
62
|
return undefined;
|
|
@@ -66,27 +66,28 @@ export class ElectingConnector {
|
|
|
66
66
|
if (performance.now() >= deadline) {
|
|
67
67
|
throw new ProtocolVersionError(PROTOCOL_VERSION, undefined);
|
|
68
68
|
}
|
|
69
|
-
await delay(pollInterval, undefined, { signal });
|
|
69
|
+
await untilAborted(delay(pollInterval, undefined, { signal }), signal);
|
|
70
70
|
}
|
|
71
71
|
}
|
|
72
|
-
/**
|
|
72
|
+
/**
|
|
73
|
+
* Campaigns until `timeout`; a term won after `signal` aborted is resigned.
|
|
74
|
+
* The election gives up a term that it wins after the abort, but the abort
|
|
75
|
+
* can also land after the campaign resolved, before this step continues.
|
|
76
|
+
*/
|
|
73
77
|
async #campaign(timeout, signal) {
|
|
74
|
-
const
|
|
78
|
+
const term = await this.#options.election.campaign({ timeout, signal });
|
|
75
79
|
if (signal.aborted)
|
|
76
|
-
await
|
|
80
|
+
await term?.resign();
|
|
77
81
|
signal.throwIfAborted();
|
|
78
|
-
return
|
|
82
|
+
return term;
|
|
79
83
|
}
|
|
80
84
|
/** Serves the term this process just won, and reaches its own server like any other process. */
|
|
81
|
-
async #coordinate(
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
await leadership.resign();
|
|
88
|
-
throw error;
|
|
89
|
-
}
|
|
85
|
+
async #coordinate(term, signal) {
|
|
86
|
+
await using serving = new AsyncDisposableStack();
|
|
87
|
+
// A term that nothing serves would stop every other candidate from coordinating.
|
|
88
|
+
serving.defer(() => term.resign());
|
|
89
|
+
await this.#options.serve(term);
|
|
90
|
+
serving.move();
|
|
90
91
|
const own = await reachUnlessAborted(this.#options.socketPath, signal);
|
|
91
92
|
if (!own)
|
|
92
93
|
return undefined;
|
|
@@ -109,7 +110,7 @@ export class ElectingConnector {
|
|
|
109
110
|
}
|
|
110
111
|
}
|
|
111
112
|
function flightConnection(socket) {
|
|
112
|
-
return new SocketConnection(socket
|
|
113
|
+
return new SocketConnection(socket);
|
|
113
114
|
}
|
|
114
115
|
/** Like `reach`, but a socket reached after `signal` aborted is destroyed, not returned. */
|
|
115
116
|
async function reachUnlessAborted(socketPath, signal) {
|
|
@@ -121,28 +122,23 @@ async function reachUnlessAborted(socketPath, signal) {
|
|
|
121
122
|
return socket;
|
|
122
123
|
}
|
|
123
124
|
/** Resolves `undefined` when nothing listens yet (no file, or a dead coordinator's file). */
|
|
124
|
-
function reach(socketPath) {
|
|
125
|
-
|
|
126
|
-
const socket = connect(socketPath);
|
|
127
|
-
const fail = () => {
|
|
128
|
-
socket.destroy();
|
|
129
|
-
resolve(undefined);
|
|
130
|
-
};
|
|
131
|
-
socket.once('error', fail);
|
|
132
|
-
socket.once('connect', () => {
|
|
133
|
-
socket.off('error', fail);
|
|
134
|
-
resolve(socket);
|
|
135
|
-
});
|
|
136
|
-
});
|
|
137
|
-
}
|
|
138
|
-
/** Greets the coordinator on `socket`; a client that closes meanwhile gives the socket up. */
|
|
139
|
-
async function greetUnlessAborted(socket, signal) {
|
|
125
|
+
async function reach(socketPath) {
|
|
126
|
+
const socket = connect(socketPath);
|
|
140
127
|
try {
|
|
141
|
-
|
|
128
|
+
await once(socket, 'connect');
|
|
129
|
+
return socket;
|
|
142
130
|
}
|
|
143
|
-
catch
|
|
131
|
+
catch {
|
|
144
132
|
socket.destroy();
|
|
145
|
-
|
|
133
|
+
return undefined;
|
|
146
134
|
}
|
|
147
135
|
}
|
|
136
|
+
/** Greets the coordinator on `socket`; a client that closes meanwhile gives the socket up. */
|
|
137
|
+
async function greetUnlessAborted(socket, signal) {
|
|
138
|
+
using greeting = new DisposableStack();
|
|
139
|
+
greeting.defer(() => socket.destroy());
|
|
140
|
+
const greeted = await untilAborted(greet(socket), signal);
|
|
141
|
+
greeting.move();
|
|
142
|
+
return greeted;
|
|
143
|
+
}
|
|
148
144
|
//# sourceMappingURL=electing-connector.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"electing-connector.js","sourceRoot":"","sources":["../../src/connection/electing-connector.ts"],"names":[],"mappings":"AAAA,OAAO,EAAe,OAAO,EAAE,MAAM,UAAU,CAAC;AAChD,OAAO,EAAE,UAAU,IAAI,KAAK,EAAE,MAAM,sBAAsB,CAAC;AAE3D,OAAO,EAAE,YAAY,EAAE,MAAM,gBAAgB,CAAC;
|
|
1
|
+
{"version":3,"file":"electing-connector.js","sourceRoot":"","sources":["../../src/connection/electing-connector.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import { SqliteElection } from '@zukhruf/election';
|
|
2
|
+
/**
|
|
3
|
+
* The election of the single flights that share `directory`. Every published
|
|
4
|
+
* version claims `flight.lock` and counts terms in `flight.epoch`
|
|
5
|
+
* (flight-protocol.test.ts pins both), so single flights of two versions
|
|
6
|
+
* elect one coordinator between them. The socket lock store of
|
|
7
|
+
* `@zukhruf/mutex` names its files `leader.*`, so it never joins this
|
|
8
|
+
* election in a shared directory.
|
|
9
|
+
*/
|
|
10
|
+
export declare function flightElection(directory: string, pollInterval: number): SqliteElection;
|
|
11
|
+
//# sourceMappingURL=flight-election.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"flight-election.d.ts","sourceRoot":"","sources":["../../src/connection/flight-election.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,cAAc,EAAE,MAAM,mBAAmB,CAAC;AAEnD;;;;;;;GAOG;AACH,wBAAgB,cAAc,CAC5B,SAAS,EAAE,MAAM,EACjB,YAAY,EAAE,MAAM,GACnB,cAAc,CAOhB"}
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import { SqliteElection } from '@zukhruf/election';
|
|
2
|
+
/**
|
|
3
|
+
* The election of the single flights that share `directory`. Every published
|
|
4
|
+
* version claims `flight.lock` and counts terms in `flight.epoch`
|
|
5
|
+
* (flight-protocol.test.ts pins both), so single flights of two versions
|
|
6
|
+
* elect one coordinator between them. The socket lock store of
|
|
7
|
+
* `@zukhruf/mutex` names its files `leader.*`, so it never joins this
|
|
8
|
+
* election in a shared directory.
|
|
9
|
+
*/
|
|
10
|
+
export function flightElection(directory, pollInterval) {
|
|
11
|
+
return new SqliteElection({
|
|
12
|
+
directory,
|
|
13
|
+
claimFile: 'flight.lock',
|
|
14
|
+
epochFile: 'flight.epoch',
|
|
15
|
+
pollInterval,
|
|
16
|
+
});
|
|
17
|
+
}
|
|
18
|
+
//# sourceMappingURL=flight-election.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"flight-election.js","sourceRoot":"","sources":["../../src/connection/flight-election.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,cAAc,EAAE,MAAM,mBAAmB,CAAC;AAEnD;;;;;;;GAOG;AACH,MAAM,UAAU,cAAc,CAC5B,SAAiB,EACjB,YAAoB;IAEpB,OAAO,IAAI,cAAc,CAAC;QACxB,SAAS;QACT,SAAS,EAAE,aAAa;QACxB,SAAS,EAAE,cAAc;QACzB,YAAY;KACb,CAAC,CAAC;AACL,CAAC"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"handshake.d.ts","sourceRoot":"","sources":["../../src/connection/handshake.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,UAAU,CAAC;
|
|
1
|
+
{"version":3,"file":"handshake.d.ts","sourceRoot":"","sources":["../../src/connection/handshake.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,UAAU,CAAC;AASvC;;;;;;GAMG;AACH,eAAO,MAAM,gBAAgB,IAAI,CAAC;AAElC,+DAA+D;AAC/D,MAAM,MAAM,QAAQ,GAChB;IAAE,IAAI,EAAE,SAAS,CAAA;CAAE,GACnB;IAAE,IAAI,EAAE,SAAS,CAAC;IAAC,OAAO,EAAE,MAAM,CAAA;CAAE;AACtC,yEAAyE;GACvE;IAAE,IAAI,EAAE,QAAQ,CAAA;CAAE,CAAC;AAEvB,mFAAmF;AACnF,wBAAsB,KAAK,CAAC,MAAM,EAAE,MAAM,GAAG,OAAO,CAAC,QAAQ,CAAC,CAc7D;AAED;;;;;;GAMG;AACH,wBAAsB,OAAO,CAAC,MAAM,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC,CAgB9D"}
|
|
@@ -1,4 +1,6 @@
|
|
|
1
1
|
import { isRecord } from "../shared/is-record.js";
|
|
2
|
+
import { jsonLine } from "./json-line.js";
|
|
3
|
+
import { leaveErrorsToClose } from "./leave-errors-to-close.js";
|
|
2
4
|
/** The protocol a single flight's processes speak, named in every hello, so no process of another protocol is ever served. */
|
|
3
5
|
const PROTOCOL = 'single-flight';
|
|
4
6
|
/**
|
|
@@ -11,7 +13,7 @@ const PROTOCOL = 'single-flight';
|
|
|
11
13
|
export const PROTOCOL_VERSION = 1;
|
|
12
14
|
/** Says which protocol this process speaks, and reads the coordinator's answer. */
|
|
13
15
|
export async function greet(socket) {
|
|
14
|
-
socket.write(
|
|
16
|
+
socket.write(jsonLine({ op: 'hello', protocol: PROTOCOL, version: PROTOCOL_VERSION }));
|
|
15
17
|
const answer = parse(await readLine(socket));
|
|
16
18
|
if (isRecord(answer) && answer.op === 'welcome')
|
|
17
19
|
return { kind: 'welcome' };
|
|
@@ -36,11 +38,11 @@ export async function welcome(socket) {
|
|
|
36
38
|
return false;
|
|
37
39
|
}
|
|
38
40
|
if (hello.protocol === PROTOCOL && hello.version === PROTOCOL_VERSION) {
|
|
39
|
-
socket.write(
|
|
41
|
+
socket.write(jsonLine({ op: 'welcome' }));
|
|
40
42
|
return true;
|
|
41
43
|
}
|
|
42
44
|
// Destroyed once the answer is written: a paused socket would never see a silent process hang up.
|
|
43
|
-
socket.end(
|
|
45
|
+
socket.end(jsonLine({ op: 'refused', protocol: PROTOCOL, version: PROTOCOL_VERSION }), () => socket.destroy());
|
|
44
46
|
return false;
|
|
45
47
|
}
|
|
46
48
|
function parse(line) {
|
|
@@ -93,8 +95,7 @@ function readLine(socket) {
|
|
|
93
95
|
socket.off('data', onData);
|
|
94
96
|
resolve(undefined);
|
|
95
97
|
};
|
|
96
|
-
|
|
97
|
-
socket.on('error', () => { });
|
|
98
|
+
leaveErrorsToClose(socket);
|
|
98
99
|
socket.on('data', onData);
|
|
99
100
|
socket.once('close', onClose);
|
|
100
101
|
return promise;
|