@electron-stagewright/host-supervisor 0.1.0 → 0.2.0
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 +112 -2
- package/dist/contract.d.ts +2 -0
- package/dist/contract.d.ts.map +1 -1
- package/dist/errors.d.ts +1 -1
- package/dist/errors.d.ts.map +1 -1
- package/dist/errors.js +5 -0
- package/dist/errors.js.map +1 -1
- package/dist/host.d.ts +57 -7
- package/dist/host.d.ts.map +1 -1
- package/dist/host.js +216 -21
- package/dist/host.js.map +1 -1
- package/dist/in-process.d.ts +1 -1
- package/dist/in-process.d.ts.map +1 -1
- package/dist/in-process.js.map +1 -1
- package/dist/index.d.ts +3 -3
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +1 -1
- package/dist/index.js.map +1 -1
- package/dist/protocol.d.ts +15 -2
- package/dist/protocol.d.ts.map +1 -1
- package/dist/protocol.js +20 -3
- package/dist/protocol.js.map +1 -1
- package/dist/serve.d.ts +14 -4
- package/dist/serve.d.ts.map +1 -1
- package/dist/serve.js +50 -15
- package/dist/serve.js.map +1 -1
- package/dist/utility.d.ts +4 -1
- package/dist/utility.d.ts.map +1 -1
- package/dist/utility.js +1 -1
- package/dist/utility.js.map +1 -1
- package/package.json +2 -10
package/README.md
CHANGED
|
@@ -88,6 +88,18 @@ serveHost<DbOps, { key: string }>({
|
|
|
88
88
|
})
|
|
89
89
|
```
|
|
90
90
|
|
|
91
|
+
In a main process bundled as CommonJS (Vite, webpack, esbuild), hand the transport Electron's
|
|
92
|
+
`fork` instead of letting it load Electron itself:
|
|
93
|
+
|
|
94
|
+
```ts
|
|
95
|
+
import { utilityProcess } from 'electron'
|
|
96
|
+
|
|
97
|
+
utilityProcessTransport({ entry, serviceName: 'Database', fork: utilityProcess.fork })
|
|
98
|
+
```
|
|
99
|
+
|
|
100
|
+
The package has no dependency on Electron, not even a peer, so it adds nothing Electron-related to
|
|
101
|
+
a production dependency or license report.
|
|
102
|
+
|
|
91
103
|
`serveHost` finds its port: Electron's `process.parentPort` in a utility process, the
|
|
92
104
|
`worker_threads` parent port in a worker. The entry never imports Electron.
|
|
93
105
|
|
|
@@ -100,18 +112,47 @@ serveHost<DbOps, { key: string }>({
|
|
|
100
112
|
timeout or an abort rejects the call and aborts `context.signal` in the handler, which receives
|
|
101
113
|
it after the caller's arguments. Past `maxPending` calls and open streams, a call fails with
|
|
102
114
|
`HOST_QUEUE_FULL`.
|
|
115
|
+
- **Abort and settle.** By default an abort rejects with `HOST_CALL_ABORTED` at once, and the
|
|
116
|
+
host's late answer is dropped, so the caller cannot tell whether the work stopped. Set
|
|
117
|
+
`limits.abortGraceMs` (or `abortGraceMs` per call) to forward the abort and wait: the call then
|
|
118
|
+
settles with the host's own answer (the handler's abort error, or its value if it finished
|
|
119
|
+
anyway), or fails with `HOST_ABORT_UNSETTLED` once the grace passes, which means the work may
|
|
120
|
+
still be running and the host is a candidate for `kill()`. The call stays counted against
|
|
121
|
+
`maxPending` until it settles. A call the host never received still fails at once, and streams
|
|
122
|
+
always close at once.
|
|
103
123
|
- **Streams.** One item per pull; nothing is produced ahead. Leaving a `for await` early closes the
|
|
104
124
|
producer in the host.
|
|
105
125
|
- **Exits.** A call in flight when the host exits fails with `HOST_EXITED`; its `cause` is the
|
|
106
126
|
host's uncaught error when the host could report it. It is never resent. `onExit` then returns
|
|
107
127
|
`fatal` (the default), `on-demand` or `restart`. `restartPolicy()` restarts up to 3 times in 10
|
|
108
128
|
minutes with 0.5, 2 and 8 s of backoff, and a restart whose start fails counts.
|
|
129
|
+
Calls made while a restart is pending (during its backoff or its start) wait for the new host,
|
|
130
|
+
within their timeout.
|
|
131
|
+
- **Started.** `onStarted` runs after every successful start with `{ info, launches, restart }`;
|
|
132
|
+
`restart` is `{ exit, attempt }` when the host replaces one that exited on its own (`attempt`
|
|
133
|
+
is 1 for the first try after that exit and grows with each failed one), null otherwise.
|
|
109
134
|
- **Stop.** `stop()` refuses new calls, lets accepted ones answer, runs the host's `stop`, and
|
|
110
135
|
terminates the host after `graceMs`. It rejects with `HOST_STOP_TIMEOUT` or
|
|
111
136
|
`HOST_STOP_INCOMPLETE` when the host did not close cleanly, so code that is about to touch its
|
|
112
137
|
files can stop. `kill()` terminates without draining. `close()` stops and refuses every later
|
|
113
138
|
call. After `stop()` or `kill()` the next call starts a new host, once the old one has exited or
|
|
114
139
|
`retireWaitMs` has passed.
|
|
140
|
+
- **Pause.** A handle captured anywhere in the app starts a host on its next call. When the host's
|
|
141
|
+
files must stay closed (a backup, a restore, a key rotation), `await host.pause()` stops the host
|
|
142
|
+
like `stop()` and starts none until `host.resume()`. Calls made meanwhile wait (within their
|
|
143
|
+
timeout and `maxPending`), or fail with `HOST_PAUSED` under `pause({ calls: 'reject' })`. A pause
|
|
144
|
+
whose stop fails rejects like `stop()` but stays paused, so the caller can decide before touching
|
|
145
|
+
the files:
|
|
146
|
+
|
|
147
|
+
```ts
|
|
148
|
+
await host.pause()
|
|
149
|
+
try {
|
|
150
|
+
await swapDatabaseFiles()
|
|
151
|
+
} finally {
|
|
152
|
+
host.resume()
|
|
153
|
+
}
|
|
154
|
+
```
|
|
155
|
+
|
|
115
156
|
- **Memory.** Worker `resourceLimits` usually end only the worker, reported as `out-of-memory`;
|
|
116
157
|
one allocation far past the cap can still abort the whole process, so use `utilityProcess` when
|
|
117
158
|
the app must survive its host. A `utilityProcess` that runs out of heap is reported as a
|
|
@@ -121,11 +162,80 @@ serveHost<DbOps, { key: string }>({
|
|
|
121
162
|
the young generation to `maxOldGenerationSizeMb`. An `onStats` that throws or rejects becomes a
|
|
122
163
|
process warning.
|
|
123
164
|
|
|
124
|
-
Errors
|
|
125
|
-
|
|
165
|
+
## Errors
|
|
166
|
+
|
|
167
|
+
An error crosses as its name, its message and a code matching `^[A-Z][A-Z0-9_]{1,80}$`; stacks and
|
|
168
|
+
object graphs cross only as the detail a host picks with `errors.data`. The supervisor's own failures are `HostError` with a code from
|
|
169
|
+
`HOST_ERROR_CODES`, and a host can never make an application error pass for one.
|
|
170
|
+
|
|
171
|
+
When failures carry structured detail, say so on both sides instead of wrapping every answer:
|
|
172
|
+
|
|
173
|
+
```ts
|
|
174
|
+
// db-host.js
|
|
175
|
+
serveHost<DbOps>({
|
|
176
|
+
// ...
|
|
177
|
+
errors: {
|
|
178
|
+
codePattern: /^[a-z][a-z-]{1,40}$/, // also the app's own codes, such as `engine-gone`
|
|
179
|
+
data: (error) =>
|
|
180
|
+
error instanceof EditError ? { step: error.step, fix: error.fix } : undefined,
|
|
181
|
+
},
|
|
182
|
+
})
|
|
183
|
+
|
|
184
|
+
// main process
|
|
185
|
+
createHost<DbOps>({
|
|
186
|
+
// ...
|
|
187
|
+
errors: {
|
|
188
|
+
revive: (e) => (e.name === 'EditError' ? new EditError(e.message, e.code, e.data) : undefined),
|
|
189
|
+
},
|
|
190
|
+
})
|
|
191
|
+
```
|
|
192
|
+
|
|
193
|
+
`data` must survive structured clone; when it does not, the error still crosses without it.
|
|
194
|
+
Without `revive`, the rebuilt `Error` carries `name`, `message`, `code` and `data`.
|
|
195
|
+
|
|
196
|
+
## Start info
|
|
197
|
+
|
|
198
|
+
A host can hand back what it learned while starting, such as the port its server bound:
|
|
199
|
+
|
|
200
|
+
```ts
|
|
201
|
+
serveHost<ServerOps, Config, { url: string }>({
|
|
202
|
+
operations: ['ping'],
|
|
203
|
+
start: async (config, { setInfo }) => {
|
|
204
|
+
const server = await listen(config)
|
|
205
|
+
setInfo({ url: server.url })
|
|
206
|
+
return { ping: () => 'pong' }
|
|
207
|
+
},
|
|
208
|
+
})
|
|
209
|
+
|
|
210
|
+
const host = createHost<ServerOps, Config, { url: string }>({/* ... */})
|
|
211
|
+
const { url } = (await host.start())!
|
|
212
|
+
host.info // the running host's info, or undefined while none runs
|
|
213
|
+
```
|
|
214
|
+
|
|
215
|
+
Call `setInfo` before `start` resolves; later calls throw. Info that cannot be cloned fails the start.
|
|
216
|
+
|
|
217
|
+
## Exits
|
|
218
|
+
|
|
219
|
+
`onExit` and `restartPolicy({ isFatal })` receive a `HostExit`, not an `Error`:
|
|
220
|
+
|
|
221
|
+
| Field | Meaning |
|
|
222
|
+
| -------------- | ---------------------------------------------------------------------- |
|
|
223
|
+
| `kind` | `crash`, `out-of-memory` or `start-failed` |
|
|
224
|
+
| `reason` | `uncaught`, `out-of-memory`, `runtime-fatal`, `exit` or `start-failed` |
|
|
225
|
+
| `error` | Always an `Error`: the host's uncaught error when it reported one |
|
|
226
|
+
| `code` | The exit code, or null |
|
|
227
|
+
| `uptimeMs` | Time since `started`, or null when the host never started |
|
|
228
|
+
| `pendingCalls` | Calls the exit rejected with `HOST_EXITED` |
|
|
229
|
+
| `lastStats` | The last `HostStats` the host sent, or null |
|
|
230
|
+
|
|
231
|
+
`uncaught` means the host reported an uncaught exception (or a worker thread threw one).
|
|
232
|
+
`runtime-fatal` is Electron's utility process `error` event. `exit` is an end with no reported
|
|
233
|
+
cause: `process.exit`, a native crash, or a kill from outside.
|
|
126
234
|
|
|
127
235
|
## Platform notes
|
|
128
236
|
|
|
237
|
+
- The utility process transport needs Electron 42 or later. The package declares no Electron
|
|
238
|
+
dependency; it uses the app's own.
|
|
129
239
|
- `terminate()` cannot interrupt a synchronous native call: the grace period is honoured between
|
|
130
240
|
calls, not inside one.
|
|
131
241
|
- Large results should stream. `postMessage` copies by structured clone, and Electron's V8 memory
|
package/dist/contract.d.ts
CHANGED
|
@@ -32,6 +32,8 @@ export interface ChannelExit {
|
|
|
32
32
|
readonly error?: Error;
|
|
33
33
|
/** The runtime ended the host for exceeding its memory limit. */
|
|
34
34
|
readonly outOfMemory?: boolean;
|
|
35
|
+
/** The runtime hit an error it cannot continue from (Electron's utility process `error` event). */
|
|
36
|
+
readonly runtimeFatal?: boolean;
|
|
35
37
|
}
|
|
36
38
|
/** One running host, as seen from the supervisor. */
|
|
37
39
|
export interface HostChannel {
|
package/dist/contract.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"contract.d.ts","sourceRoot":"","sources":["../src/contract.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,eAAe,CAAA;AAEtD,4DAA4D;AAC5D,MAAM,WAAW,WAAW;IAC1B,yFAAyF;IACzF,QAAQ,CAAC,MAAM,EAAE,WAAW,CAAA;CAC7B;AAED,KAAK,UAAU,CAAC,CAAC,SAAS,SAAS,OAAO,EAAE,IAAI,MAAM,SAAS,CAAC,CAAC,QAAQ,CAAC,GACtE,KAAK,GACL,CAAC,SAAS,QAAQ,CAAC,CAAC,CAAC,GACnB,IAAI,GACJ,KAAK,CAAA;AAEX;;;;GAIG;AACH,MAAM,MAAM,QAAQ,CAAC,GAAG,IAAI;KACzB,CAAC,IAAI,MAAM,GAAG,GAAG,GAAG,CAAC,CAAC,CAAC,SAAS,CAAC,GAAG,IAAI,EAAE,MAAM,CAAC,KAAK,MAAM,CAAC,GAC1D,UAAU,CAAC,CAAC,CAAC,SAAS,IAAI,GACxB,CAAC,SAAS,OAAO,CAAC,OAAO,CAAC,GAAG,aAAa,CAAC,OAAO,CAAC,GACjD,GAAG,CAAC,CAAC,CAAC,GACN,CAAC,GAAG,IAAI,EAAE,KAAK,EAAE,KAAK,OAAO,CAAC,OAAO,CAAC,GAAG,aAAa,CAAC,OAAO,CAAC,GACjE,CAAC,GAAG,IAAI,EAAE,KAAK,EAAE,KAAK,gDAAgD,GACxE,KAAK;CACV,CAAA;AAED,MAAM,MAAM,MAAM,CAAC,CAAC,IAAI,CAAC,SAAS,CAAC,GAAG,IAAI,EAAE,MAAM,CAAC,KAAK,OAAO,GAAG,CAAC,GAAG,KAAK,CAAA;AAE3E,mCAAmC;AACnC,MAAM,MAAM,aAAa,CAAC,GAAG,IAAI;KAC9B,CAAC,IAAI,MAAM,GAAG,GAAG,GAAG,CAAC,CAAC,CAAC,SAAS,CAAC,GAAG,IAAI,EAAE,KAAK,EAAE,KAAK,OAAO,CAAC,OAAO,CAAC,GAAG,CAAC,GAAG,KAAK;CACpF,CAAC,MAAM,GAAG,CAAC,GACV,MAAM,CAAA;AAER,uEAAuE;AACvE,MAAM,MAAM,eAAe,CAAC,GAAG,IAAI;KAChC,CAAC,IAAI,MAAM,GAAG,GAAG,GAAG,CAAC,CAAC,CAAC,SAAS,CAAC,GAAG,IAAI,EAAE,KAAK,EAAE,KAAK,aAAa,CAAC,OAAO,CAAC,GAAG,CAAC,GAAG,KAAK;CAC1F,CAAC,MAAM,GAAG,CAAC,GACV,MAAM,CAAA;AAER,yFAAyF;AACzF,MAAM,MAAM,QAAQ,CAAC,GAAG,IAAI;KACzB,CAAC,IAAI,MAAM,GAAG,GAAG,GAAG,CAAC,CAAC,CAAC,SAAS,CAAC,GAAG,IAAI,EAAE,MAAM,CAAC,KAAK,OAAO,CAAC,MAAM,CAAC,CAAC,GACnE,CAAC,GAAG,IAAI,EAAE,CAAC,GAAG,CAAC,EAAE,WAAW,CAAC,KAAK,CAAC,GAAG,OAAO,CAAC,CAAC,CAAC,GAChD,GAAG,CAAC,CAAC,CAAC,SAAS,CAAC,GAAG,IAAI,EAAE,MAAM,CAAC,KAAK,aAAa,CAAC,MAAM,CAAC,CAAC,GACzD,CAAC,GAAG,IAAI,EAAE,CAAC,GAAG,CAAC,EAAE,WAAW,CAAC,KAAK,aAAa,CAAC,CAAC,CAAC,GAAG,QAAQ,CAAC,CAAC,CAAC,GAChE,KAAK;CACZ,CAAA;AAED,oDAAoD;AACpD,MAAM,WAAW,WAAW;IAC1B,QAAQ,CAAC,IAAI,EAAE,MAAM,GAAG,IAAI,CAAA;IAC5B,QAAQ,CAAC,KAAK,CAAC,EAAE,KAAK,CAAA;IACtB,iEAAiE;IACjE,QAAQ,CAAC,WAAW,CAAC,EAAE,OAAO,CAAA;
|
|
1
|
+
{"version":3,"file":"contract.d.ts","sourceRoot":"","sources":["../src/contract.ts"],"names":[],"mappings":"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"}
|
package/dist/errors.d.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
/** The supervisor's own failures. Application errors keep their own code when it is well formed. */
|
|
2
|
-
export declare const HOST_ERROR_CODES: readonly ["HOST_STOPPED", "HOST_EXITED", "HOST_START_FAILED", "HOST_FATAL", "HOST_CALL_TIMEOUT", "HOST_CALL_ABORTED", "HOST_QUEUE_FULL", "HOST_OPERATION_REJECTED", "HOST_STOP_TIMEOUT", "HOST_STOP_INCOMPLETE"];
|
|
2
|
+
export declare const HOST_ERROR_CODES: readonly ["HOST_STOPPED", "HOST_EXITED", "HOST_START_FAILED", "HOST_FATAL", "HOST_CALL_TIMEOUT", "HOST_CALL_ABORTED", "HOST_ABORT_UNSETTLED", "HOST_PAUSED", "HOST_QUEUE_FULL", "HOST_OPERATION_REJECTED", "HOST_STOP_TIMEOUT", "HOST_STOP_INCOMPLETE"];
|
|
3
3
|
export type HostErrorCode = (typeof HOST_ERROR_CODES)[number];
|
|
4
4
|
export declare class HostError extends Error {
|
|
5
5
|
readonly code: HostErrorCode;
|
package/dist/errors.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"errors.d.ts","sourceRoot":"","sources":["../src/errors.ts"],"names":[],"mappings":"AAAA,oGAAoG;AACpG,eAAO,MAAM,gBAAgB,
|
|
1
|
+
{"version":3,"file":"errors.d.ts","sourceRoot":"","sources":["../src/errors.ts"],"names":[],"mappings":"AAAA,oGAAoG;AACpG,eAAO,MAAM,gBAAgB,yPAwBnB,CAAA;AAEV,MAAM,MAAM,aAAa,GAAG,CAAC,OAAO,gBAAgB,CAAC,CAAC,MAAM,CAAC,CAAA;AAE7D,qBAAa,SAAU,SAAQ,KAAK;IAClC,QAAQ,CAAC,IAAI,EAAE,aAAa,CAAA;gBAEhB,IAAI,EAAE,aAAa,EAAE,OAAO,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE;QAAE,KAAK,CAAC,EAAE,OAAO,CAAA;KAAE;CAKhF;AAED,wBAAgB,WAAW,CAAC,KAAK,EAAE,OAAO,EAAE,IAAI,CAAC,EAAE,aAAa,GAAG,KAAK,IAAI,SAAS,CAEpF"}
|
package/dist/errors.js
CHANGED
|
@@ -9,7 +9,12 @@ export const HOST_ERROR_CODES = [
|
|
|
9
9
|
/** `onExit` chose `fatal`; the host never starts again. */
|
|
10
10
|
'HOST_FATAL',
|
|
11
11
|
'HOST_CALL_TIMEOUT',
|
|
12
|
+
/** The call was aborted before the host settled it; the host may still be working on it. */
|
|
12
13
|
'HOST_CALL_ABORTED',
|
|
14
|
+
/** With `abortGraceMs`: the host did not settle an aborted call within the grace period. */
|
|
15
|
+
'HOST_ABORT_UNSETTLED',
|
|
16
|
+
/** `pause({ calls: 'reject' })` is in effect. */
|
|
17
|
+
'HOST_PAUSED',
|
|
13
18
|
/** More than `maxPending` calls were waiting. */
|
|
14
19
|
'HOST_QUEUE_FULL',
|
|
15
20
|
/** The host refused an operation outside its closed list. */
|
package/dist/errors.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"errors.js","sourceRoot":"","sources":["../src/errors.ts"],"names":[],"mappings":"AAAA,oGAAoG;AACpG,MAAM,CAAC,MAAM,gBAAgB,GAAG;IAC9B,iFAAiF;IACjF,cAAc;IACd,4EAA4E;IAC5E,aAAa;IACb,oEAAoE;IACpE,mBAAmB;IACnB,2DAA2D;IAC3D,YAAY;IACZ,mBAAmB;IACnB,mBAAmB;IACnB,iDAAiD;IACjD,iBAAiB;IACjB,6DAA6D;IAC7D,yBAAyB;IACzB,kFAAkF;IAClF,mBAAmB;IACnB,kFAAkF;IAClF,sBAAsB;CACd,CAAA;AAIV,MAAM,OAAO,SAAU,SAAQ,KAAK;IACzB,IAAI,CAAe;IAE5B,YAAY,IAAmB,EAAE,OAAe,EAAE,OAA6B;QAC7E,KAAK,CAAC,OAAO,EAAE,OAAO,CAAC,CAAA;QACvB,IAAI,CAAC,IAAI,GAAG,WAAW,CAAA;QACvB,IAAI,CAAC,IAAI,GAAG,IAAI,CAAA;IAClB,CAAC;CACF;AAED,MAAM,UAAU,WAAW,CAAC,KAAc,EAAE,IAAoB;IAC9D,OAAO,KAAK,YAAY,SAAS,IAAI,CAAC,IAAI,KAAK,SAAS,IAAI,KAAK,CAAC,IAAI,KAAK,IAAI,CAAC,CAAA;AAClF,CAAC"}
|
|
1
|
+
{"version":3,"file":"errors.js","sourceRoot":"","sources":["../src/errors.ts"],"names":[],"mappings":"AAAA,oGAAoG;AACpG,MAAM,CAAC,MAAM,gBAAgB,GAAG;IAC9B,iFAAiF;IACjF,cAAc;IACd,4EAA4E;IAC5E,aAAa;IACb,oEAAoE;IACpE,mBAAmB;IACnB,2DAA2D;IAC3D,YAAY;IACZ,mBAAmB;IACnB,4FAA4F;IAC5F,mBAAmB;IACnB,4FAA4F;IAC5F,sBAAsB;IACtB,iDAAiD;IACjD,aAAa;IACb,iDAAiD;IACjD,iBAAiB;IACjB,6DAA6D;IAC7D,yBAAyB;IACzB,kFAAkF;IAClF,mBAAmB;IACnB,kFAAkF;IAClF,sBAAsB;CACd,CAAA;AAIV,MAAM,OAAO,SAAU,SAAQ,KAAK;IACzB,IAAI,CAAe;IAE5B,YAAY,IAAmB,EAAE,OAAe,EAAE,OAA6B;QAC7E,KAAK,CAAC,OAAO,EAAE,OAAO,CAAC,CAAA;QACvB,IAAI,CAAC,IAAI,GAAG,WAAW,CAAA;QACvB,IAAI,CAAC,IAAI,GAAG,IAAI,CAAA;IAClB,CAAC;CACF;AAED,MAAM,UAAU,WAAW,CAAC,KAAc,EAAE,IAAoB;IAC9D,OAAO,KAAK,YAAY,SAAS,IAAI,CAAC,IAAI,KAAK,SAAS,IAAI,KAAK,CAAC,IAAI,KAAK,IAAI,CAAC,CAAA;AAClF,CAAC"}
|
package/dist/host.d.ts
CHANGED
|
@@ -3,14 +3,25 @@
|
|
|
3
3
|
* when the host exits on its own.
|
|
4
4
|
*/
|
|
5
5
|
import type { ArgsOf, CallOperation, Contract, HostTransport, StreamOperation } from './contract.js';
|
|
6
|
-
import { type HostStats } from './protocol.js';
|
|
6
|
+
import { type HostStats, type SerializedError } from './protocol.js';
|
|
7
7
|
export declare const DEFAULT_STOP_GRACE_MS = 10000;
|
|
8
8
|
export declare const DEFAULT_RETIRE_WAIT_MS = 5000;
|
|
9
|
-
export type HostState = 'idle' | 'starting' | 'running' | 'restarting' | 'stopping' | 'fatal' | 'closed';
|
|
9
|
+
export type HostState = 'idle' | 'starting' | 'running' | 'restarting' | 'stopping' | 'paused' | 'fatal' | 'closed';
|
|
10
|
+
/**
|
|
11
|
+
* Why a host ended:
|
|
12
|
+
* - `out-of-memory`: the runtime ended it at its heap limit (worker threads only).
|
|
13
|
+
* - `uncaught`: the host reported an uncaught exception, which is `error`.
|
|
14
|
+
* - `runtime-fatal`: the runtime hit an error it cannot continue from (utility process).
|
|
15
|
+
* - `exit`: it ended without reporting a cause: `process.exit`, a native crash, a signal.
|
|
16
|
+
* - `start-failed`: a restart whose start failed.
|
|
17
|
+
*/
|
|
18
|
+
export type HostExitReason = 'out-of-memory' | 'uncaught' | 'runtime-fatal' | 'exit' | 'start-failed';
|
|
10
19
|
/** What the supervisor knows about a host that exited without being asked to. */
|
|
11
20
|
export interface HostExit {
|
|
12
21
|
/** `start-failed` is a restart whose start failed; the first start rejects its callers instead. */
|
|
13
22
|
readonly kind: 'crash' | 'out-of-memory' | 'start-failed';
|
|
23
|
+
readonly reason: HostExitReason;
|
|
24
|
+
/** Always an `Error`: the host's own when it reported one, else one describing the exit. */
|
|
14
25
|
readonly error: Error;
|
|
15
26
|
readonly code: number | null;
|
|
16
27
|
/** Milliseconds between `started` and the exit; null when the host never started. */
|
|
@@ -32,8 +43,27 @@ export interface CallOptions {
|
|
|
32
43
|
readonly signal?: AbortSignal;
|
|
33
44
|
/** Overrides `limits.callTimeoutMs`; for a stream it bounds each item. */
|
|
34
45
|
readonly timeoutMs?: number;
|
|
46
|
+
/** Overrides `limits.abortGraceMs`. */
|
|
47
|
+
readonly abortGraceMs?: number;
|
|
48
|
+
}
|
|
49
|
+
export interface PauseOptions {
|
|
50
|
+
/** What a call does while paused: wait for `resume()` (default) or fail with `HOST_PAUSED`. */
|
|
51
|
+
readonly calls?: 'wait' | 'reject';
|
|
35
52
|
}
|
|
36
|
-
|
|
53
|
+
/** A host answered `start`. */
|
|
54
|
+
export interface HostStartedEvent<Info = undefined> {
|
|
55
|
+
readonly info: Info | undefined;
|
|
56
|
+
/** Hosts started so far by this supervisor, this one included. */
|
|
57
|
+
readonly launches: number;
|
|
58
|
+
/** Set when this host replaces one that exited on its own. */
|
|
59
|
+
readonly restart: {
|
|
60
|
+
/** The exit that started the recovery. */
|
|
61
|
+
readonly exit: HostExit;
|
|
62
|
+
/** 1 for the first try after that exit, 2 after one failed restart, and so on. */
|
|
63
|
+
readonly attempt: number;
|
|
64
|
+
} | null;
|
|
65
|
+
}
|
|
66
|
+
export interface HostOptions<Ops extends Contract<Ops>, Payload = undefined, Info = undefined> {
|
|
37
67
|
/** The closed list of operations that answer once. */
|
|
38
68
|
readonly operations: readonly CallOperation<Ops>[];
|
|
39
69
|
/** The closed list of operations that answer with a stream. */
|
|
@@ -54,26 +84,46 @@ export interface HostOptions<Ops extends Contract<Ops>, Payload = undefined> {
|
|
|
54
84
|
/** Calls and open streams allowed at once; one more fails with `HOST_QUEUE_FULL`. */
|
|
55
85
|
readonly maxPending?: number;
|
|
56
86
|
readonly callTimeoutMs?: number;
|
|
87
|
+
/**
|
|
88
|
+
* After an abort, wait this long for the host to settle the call: it settles with the host's
|
|
89
|
+
* own answer, or fails with `HOST_ABORT_UNSETTLED`. Unset, an abort fails the call at once.
|
|
90
|
+
*/
|
|
91
|
+
readonly abortGraceMs?: number;
|
|
57
92
|
};
|
|
58
93
|
/** Decides what follows an exit nobody asked for. Defaults to `fatal`. */
|
|
59
94
|
readonly onExit?: (exit: HostExit) => ExitDecision | Promise<ExitDecision>;
|
|
60
95
|
readonly onStats?: (stats: HostStats) => void;
|
|
96
|
+
/** Every successful start, restarts included. A throw or rejection becomes a process warning. */
|
|
97
|
+
readonly onStarted?: (event: HostStartedEvent<Info>) => void | Promise<void>;
|
|
98
|
+
readonly errors?: {
|
|
99
|
+
/** Rebuilds an application error, such as the app's own class; `undefined` keeps the default. */
|
|
100
|
+
readonly revive?: (serialized: SerializedError) => Error | undefined;
|
|
101
|
+
};
|
|
61
102
|
readonly now?: () => number;
|
|
62
103
|
}
|
|
63
|
-
export interface Host<Ops extends Contract<Ops
|
|
104
|
+
export interface Host<Ops extends Contract<Ops>, Info = undefined> {
|
|
64
105
|
/** One method per operation, with the contract's own signature. */
|
|
65
106
|
readonly ops: Ops;
|
|
66
107
|
call<K extends CallOperation<Ops>>(op: K, args: ArgsOf<Ops[K]>, options?: CallOptions): ReturnType<Ops[K]>;
|
|
67
108
|
stream<K extends StreamOperation<Ops>>(op: K, args: ArgsOf<Ops[K]>, options?: CallOptions): ReturnType<Ops[K]>;
|
|
68
|
-
/** Starts the host now instead of on the first call
|
|
69
|
-
start(): Promise<
|
|
109
|
+
/** Starts the host now instead of on the first call, and resolves with its `info`. */
|
|
110
|
+
start(): Promise<Info | undefined>;
|
|
70
111
|
/** Drains and stops the host. The next call starts a new one. */
|
|
71
112
|
stop(): Promise<void>;
|
|
72
113
|
/** Terminates the host without draining, and waits (bounded) for it to exit. Never throws. */
|
|
73
114
|
kill(): Promise<void>;
|
|
74
115
|
/** Stops the host and refuses every later call. */
|
|
75
116
|
close(): Promise<void>;
|
|
117
|
+
/**
|
|
118
|
+
* Stops the host like `stop()` and starts none until `resume()`, so its files can be swapped.
|
|
119
|
+
* Rejects as `stop()` does, but stays paused either way.
|
|
120
|
+
*/
|
|
121
|
+
pause(options?: PauseOptions): Promise<void>;
|
|
122
|
+
/** Lets hosts start again; calls that waited start one. */
|
|
123
|
+
resume(): void;
|
|
76
124
|
readonly state: HostState;
|
|
125
|
+
/** What the running host passed to `setInfo`; `undefined` while no host is running. */
|
|
126
|
+
readonly info: Info | undefined;
|
|
77
127
|
}
|
|
78
|
-
export declare function createHost<Ops extends Contract<Ops>, Payload = undefined>(options: HostOptions<Ops, Payload>): Host<Ops>;
|
|
128
|
+
export declare function createHost<Ops extends Contract<Ops>, Payload = undefined, Info = undefined>(options: HostOptions<Ops, Payload, Info>): Host<Ops, Info>;
|
|
79
129
|
//# sourceMappingURL=host.d.ts.map
|
package/dist/host.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"host.d.ts","sourceRoot":"","sources":["../src/host.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,KAAK,EACV,MAAM,EACN,aAAa,EAEb,QAAQ,EAER,aAAa,EACb,eAAe,EAChB,MAAM,eAAe,CAAA;AAEtB,OAAO,EAIL,KAAK,SAAS,
|
|
1
|
+
{"version":3,"file":"host.d.ts","sourceRoot":"","sources":["../src/host.ts"],"names":[],"mappings":"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"}
|