@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 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 keep their message and a code matching `^[A-Z][A-Z0-9_]{1,80}$`; stacks and object graphs
125
- never cross. The supervisor's own failures are `HostError` with a code from `HOST_ERROR_CODES`.
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
@@ -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 {
@@ -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;CAC/B;AAED,qDAAqD;AACrD,MAAM,WAAW,WAAW;IAC1B,IAAI,CAAC,OAAO,EAAE,iBAAiB,GAAG,IAAI,CAAA;IACtC,SAAS,CAAC,QAAQ,EAAE,CAAC,OAAO,EAAE,OAAO,KAAK,IAAI,GAAG,IAAI,CAAA;IACrD,0DAA0D;IAC1D,MAAM,CAAC,QAAQ,EAAE,CAAC,IAAI,EAAE,WAAW,KAAK,IAAI,GAAG,IAAI,CAAA;IACnD,kEAAkE;IAClE,IAAI,IAAI,IAAI,CAAA;CACb;AAED,8FAA8F;AAC9F,MAAM,WAAW,aAAa;IAC5B,MAAM,IAAI,WAAW,CAAA;CACtB"}
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;
@@ -1 +1 @@
1
- {"version":3,"file":"errors.d.ts","sourceRoot":"","sources":["../src/errors.ts"],"names":[],"mappings":"AAAA,oGAAoG;AACpG,eAAO,MAAM,gBAAgB,kNAmBnB,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"}
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. */
@@ -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
- export interface HostOptions<Ops extends Contract<Ops>, Payload = undefined> {
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<void>;
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
@@ -1 +1 @@
1
- {"version":3,"file":"host.d.ts","sourceRoot":"","sources":["../src/host.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"host.d.ts","sourceRoot":"","sources":["../src/host.ts"],"names":[],"mappings":"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"}