@mark1russell7/service 0.4.1 → 0.5.1
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 +358 -18
- package/build/builder-QVxu1WcL.d.ts +204 -0
- package/build/http.d.ts +277 -0
- package/build/http.js +782 -0
- package/build/http.js.map +1 -0
- package/build/index.d.ts +253 -6
- package/build/index.js +1506 -166
- package/build/index.js.map +1 -1
- package/build/knobs-BxG-c7Zb.js +39 -0
- package/build/knobs-BxG-c7Zb.js.map +1 -0
- package/build/{builder-DnfUDW9u.d.ts → lifecycle-DtJZW09J.d.ts} +272 -181
- package/build/redis.d.ts +2 -1
- package/build/testing.d.ts +98 -4
- package/build/testing.js +321 -8
- package/build/testing.js.map +1 -1
- package/package.json +10 -3
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
import { convertible, valueIn } from "@mark1russell7/quantity";
|
|
2
|
+
//#region src/knobs.ts
|
|
3
|
+
/**
|
|
4
|
+
* This function gives a time knob in milliseconds, or infinity for a time without a bound. The
|
|
5
|
+
* runtime has no defaults, thus a knob that is absent throws. A knob that is not a time, or that is
|
|
6
|
+
* less than zero, also throws.
|
|
7
|
+
*/
|
|
8
|
+
const millisecondsOf = (knobs, name, owner) => {
|
|
9
|
+
const amount = knobs[name];
|
|
10
|
+
if (amount === void 0) throw new Error(`${owner} needs the knob ${name}: it has no defaults`);
|
|
11
|
+
if (!convertible(amount.unit, "s")) throw new Error(`the knob ${name} is not a time`);
|
|
12
|
+
if (amount.value === "infinite") return Number.POSITIVE_INFINITY;
|
|
13
|
+
const value = valueIn(amount, "ms");
|
|
14
|
+
if (!(value >= 0)) throw new Error(`the knob ${name} is less than zero`);
|
|
15
|
+
return value;
|
|
16
|
+
};
|
|
17
|
+
/** This function gives a time knob in milliseconds, and it throws for a time without a bound. */
|
|
18
|
+
const boundedMillisecondsOf = (knobs, name, owner) => {
|
|
19
|
+
const value = millisecondsOf(knobs, name, owner);
|
|
20
|
+
if (!Number.isFinite(value)) throw new Error(`the knob ${name} of ${owner} has no bound: it needs a time`);
|
|
21
|
+
return value;
|
|
22
|
+
};
|
|
23
|
+
/**
|
|
24
|
+
* This function gives a count knob (the unit `count`) as a whole number above zero, or infinity
|
|
25
|
+
* for a count without a bound. A knob that is absent, not a count, or not a whole number above zero throws.
|
|
26
|
+
*/
|
|
27
|
+
const countOf = (knobs, name, owner) => {
|
|
28
|
+
const amount = knobs[name];
|
|
29
|
+
if (amount === void 0) throw new Error(`${owner} needs the knob ${name}: it has no defaults`);
|
|
30
|
+
if (!convertible(amount.unit, "count")) throw new Error(`the knob ${name} is not a count`);
|
|
31
|
+
if (amount.value === "infinite") return Number.POSITIVE_INFINITY;
|
|
32
|
+
const value = valueIn(amount, "count");
|
|
33
|
+
if (!(Number.isInteger(value) && value >= 1)) throw new Error(`the knob ${name} is ${value}, not a whole number above zero`);
|
|
34
|
+
return value;
|
|
35
|
+
};
|
|
36
|
+
//#endregion
|
|
37
|
+
export { countOf as n, millisecondsOf as r, boundedMillisecondsOf as t };
|
|
38
|
+
|
|
39
|
+
//# sourceMappingURL=knobs-BxG-c7Zb.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"knobs-BxG-c7Zb.js","names":[],"sources":["../src/knobs.ts"],"sourcesContent":["import type { Extent } from \"@mark1russell7/quantity\";\nimport { convertible, valueIn } from \"@mark1russell7/quantity\";\n\n/** A knob record is the knobs of a part, by name. A knob that is absent is undefined. */\nexport type KnobRecord = Readonly<Record<string, Extent | undefined>>;\n\n/**\n * This function gives a time knob in milliseconds, or infinity for a time without a bound. The\n * runtime has no defaults, thus a knob that is absent throws. A knob that is not a time, or that is\n * less than zero, also throws.\n */\nexport const millisecondsOf = (knobs: KnobRecord, name: string, owner: string): number => {\n const amount = knobs[name];\n if (amount === undefined) throw new Error(`${owner} needs the knob ${name}: it has no defaults`);\n if (!convertible(amount.unit, \"s\")) throw new Error(`the knob ${name} is not a time`);\n if (amount.value === \"infinite\") return Number.POSITIVE_INFINITY;\n const value = valueIn(amount, \"ms\");\n if (!(value >= 0)) throw new Error(`the knob ${name} is less than zero`);\n return value;\n};\n\n/** This function gives a time knob in milliseconds, and it throws for a time without a bound. */\nexport const boundedMillisecondsOf = (knobs: KnobRecord, name: string, owner: string): number => {\n const value = millisecondsOf(knobs, name, owner);\n if (!Number.isFinite(value)) throw new Error(`the knob ${name} of ${owner} has no bound: it needs a time`);\n return value;\n};\n\n/**\n * This function gives a count knob (the unit `count`) as a whole number above zero, or infinity\n * for a count without a bound. A knob that is absent, not a count, or not a whole number above zero throws.\n */\nexport const countOf = (knobs: KnobRecord, name: string, owner: string): number => {\n const amount = knobs[name];\n if (amount === undefined) throw new Error(`${owner} needs the knob ${name}: it has no defaults`);\n if (!convertible(amount.unit, \"count\")) throw new Error(`the knob ${name} is not a count`);\n if (amount.value === \"infinite\") return Number.POSITIVE_INFINITY;\n const value = valueIn(amount, \"count\");\n if (!(Number.isInteger(value) && value >= 1)) throw new Error(`the knob ${name} is ${value}, not a whole number above zero`);\n return value;\n};\n"],"mappings":";;;;;;;AAWA,MAAa,kBAAkB,OAAmB,MAAc,UAA0B;CACxF,MAAM,SAAS,MAAM;CACrB,IAAI,WAAW,KAAA,GAAW,MAAM,IAAI,MAAM,GAAG,MAAM,kBAAkB,KAAK,qBAAqB;CAC/F,IAAI,CAAC,YAAY,OAAO,MAAM,GAAG,GAAG,MAAM,IAAI,MAAM,YAAY,KAAK,eAAe;CACpF,IAAI,OAAO,UAAU,YAAY,OAAO,OAAO;CAC/C,MAAM,QAAQ,QAAQ,QAAQ,IAAI;CAClC,IAAI,EAAE,SAAS,IAAI,MAAM,IAAI,MAAM,YAAY,KAAK,mBAAmB;CACvE,OAAO;AACT;;AAGA,MAAa,yBAAyB,OAAmB,MAAc,UAA0B;CAC/F,MAAM,QAAQ,eAAe,OAAO,MAAM,KAAK;CAC/C,IAAI,CAAC,OAAO,SAAS,KAAK,GAAG,MAAM,IAAI,MAAM,YAAY,KAAK,MAAM,MAAM,+BAA+B;CACzG,OAAO;AACT;;;;;AAMA,MAAa,WAAW,OAAmB,MAAc,UAA0B;CACjF,MAAM,SAAS,MAAM;CACrB,IAAI,WAAW,KAAA,GAAW,MAAM,IAAI,MAAM,GAAG,MAAM,kBAAkB,KAAK,qBAAqB;CAC/F,IAAI,CAAC,YAAY,OAAO,MAAM,OAAO,GAAG,MAAM,IAAI,MAAM,YAAY,KAAK,gBAAgB;CACzF,IAAI,OAAO,UAAU,YAAY,OAAO,OAAO;CAC/C,MAAM,QAAQ,QAAQ,QAAQ,OAAO;CACrC,IAAI,EAAE,OAAO,UAAU,KAAK,KAAK,SAAS,IAAI,MAAM,IAAI,MAAM,YAAY,KAAK,MAAM,MAAM,gCAAgC;CAC3H,OAAO;AACT"}
|
|
@@ -1,5 +1,157 @@
|
|
|
1
1
|
import { n as Clock } from "./clock-D-38uH_z.js";
|
|
2
2
|
import { Extent, Quantity } from "@mark1russell7/quantity";
|
|
3
|
+
//#region src/operation.d.ts
|
|
4
|
+
/**
|
|
5
|
+
* This type tells if an operation can go again after a failure. It is a property of the
|
|
6
|
+
* operation, not of the dependency. One Redis client sends a GET, which is safe to send again. It
|
|
7
|
+
* also sends an INCR, which counts two times when it goes again after a timeout. Each operation
|
|
8
|
+
* declares its idempotency:
|
|
9
|
+
* - `true`: a second issue has the same effect. Examples are an HTTP GET or PUT, a SELECT, a
|
|
10
|
+
* Redis GET or SET, and a write that the server removes when it is a copy.
|
|
11
|
+
* - `false`: the client does not send it again after it can have reached the server.
|
|
12
|
+
* - keyed: the server keeps a key for a window, as with an `Idempotency-Key` header, and it
|
|
13
|
+
* ignores a copy in that window. A copy after the window is a second operation. Thus the
|
|
14
|
+
* window is a timer, and it must be longer than all retries of the operation.
|
|
15
|
+
*/
|
|
16
|
+
type Idempotency = boolean | {
|
|
17
|
+
readonly key: string;
|
|
18
|
+
readonly window: Extent;
|
|
19
|
+
};
|
|
20
|
+
/** An operation is an endpoint that the service calls or serves, a command, or a query. */
|
|
21
|
+
interface Operation {
|
|
22
|
+
readonly idempotent: Idempotency;
|
|
23
|
+
}
|
|
24
|
+
/**
|
|
25
|
+
* This function tells if an operation can go again `since` its first issue. An idempotent
|
|
26
|
+
* operation can always go again, and other operations cannot. A keyed operation can go again
|
|
27
|
+
* while the server keeps its key.
|
|
28
|
+
*/
|
|
29
|
+
declare const mayReissue: (operation: Operation, since: Quantity) => boolean;
|
|
30
|
+
//#endregion
|
|
31
|
+
//#region src/process.d.ts
|
|
32
|
+
/** An exit signal is a signal that asks the process to stop: each one starts the shutdown. */
|
|
33
|
+
type ExitSignal = "SIGINT" | "SIGTERM" | "SIGQUIT";
|
|
34
|
+
/** These are the signals that the runtime handles. */
|
|
35
|
+
declare const EXIT_SIGNALS: readonly ExitSignal[];
|
|
36
|
+
/**
|
|
37
|
+
* A process trigger is an event of the process, other than a signal, that starts the shutdown. A
|
|
38
|
+
* declaration opts in to each one (`svc.trigger`):
|
|
39
|
+
* - `stdin-close`: the standard input ends or closes, as when the parent of a stdio child goes away.
|
|
40
|
+
* The process must read its input, as a stdio transport does, or Node does not see the end.
|
|
41
|
+
* - `ipc-close`: the IPC channel to the parent process closes.
|
|
42
|
+
* - `ipc-message`: a message on the IPC channel matches a declared shape. Windows cannot give a
|
|
43
|
+
* child a SIGTERM that the child can catch, thus a parent sends a message.
|
|
44
|
+
*/
|
|
45
|
+
type ProcessTrigger = "stdin-close" | "ipc-close" | "ipc-message";
|
|
46
|
+
/** These are the process triggers that a declaration can opt in to. */
|
|
47
|
+
declare const PROCESS_TRIGGERS: readonly ProcessTrigger[];
|
|
48
|
+
/** An exit trigger is an event that starts the shutdown: an exit signal, or a declared process trigger. */
|
|
49
|
+
type ExitTrigger = ExitSignal | ProcessTrigger;
|
|
50
|
+
/** This function tells if a number is an exit code of a process: a whole number from 0 to 255. */
|
|
51
|
+
declare const isExitCode: (code: number) => boolean;
|
|
52
|
+
/** This function tells if a trigger is an exit signal. A repeat signal obeys `onRepeatSignal`. */
|
|
53
|
+
declare const isExitSignal: (trigger: string) => trigger is ExitSignal;
|
|
54
|
+
/**
|
|
55
|
+
* A message shape is a value of JSON that a message of the IPC channel can match. A string, a
|
|
56
|
+
* number, a boolean or null matches an equal message. An object matches a message that has each of
|
|
57
|
+
* its fields, and each value of the field matches. An array matches an array of the same length, item by item.
|
|
58
|
+
*/
|
|
59
|
+
type MessageShape = string | number | boolean | null | readonly MessageShape[] | {
|
|
60
|
+
readonly [field: string]: MessageShape;
|
|
61
|
+
};
|
|
62
|
+
/** This function tells if a value is a message shape: a value of JSON, with no function and no undefined. */
|
|
63
|
+
declare const isMessageShape: (value: unknown) => value is MessageShape;
|
|
64
|
+
/** This function tells if a message of the IPC channel matches a shape. */
|
|
65
|
+
declare const matchesMessage: (shape: MessageShape, message: unknown) => boolean;
|
|
66
|
+
/**
|
|
67
|
+
* A process port is the part of the process that the runtime uses: its exit triggers, its output
|
|
68
|
+
* and its exit. The runtime owns the handlers, because Node as PID 1 without a handler ignores
|
|
69
|
+
* SIGTERM. Only the runtime ends the process, and library code does not. A test gives a fake port,
|
|
70
|
+
* sends triggers, and reads the exit code.
|
|
71
|
+
*/
|
|
72
|
+
interface ProcessPort {
|
|
73
|
+
/**
|
|
74
|
+
* This method adds a handler for a trigger, and gives the function that removes it. The runtime
|
|
75
|
+
* asks for a process trigger only when the declaration opts in to it. For `ipc-message`, the
|
|
76
|
+
* handler gets each message of the IPC channel, and the runtime matches it.
|
|
77
|
+
*/
|
|
78
|
+
on(trigger: ExitTrigger, handler: (message?: unknown) => void): () => void;
|
|
79
|
+
/**
|
|
80
|
+
* This method writes each buffered line of the output, and its promise ends when the output is
|
|
81
|
+
* written. The stage `flush the output` uses it, in the cap of that stage.
|
|
82
|
+
*/
|
|
83
|
+
flush?(): Promise<void> | void;
|
|
84
|
+
/**
|
|
85
|
+
* This method keeps the process alive, and gives the function that releases it. The lifecycle
|
|
86
|
+
* holds its process from its start to its exit, as a listening socket does. Thus a process whose
|
|
87
|
+
* timers do not keep it alive does not end in the middle of its work. It keeps its teardown and its exit code.
|
|
88
|
+
*/
|
|
89
|
+
hold?(): () => void;
|
|
90
|
+
/** This method ends the process with a code: the code of the exit request, 1 after an error, or 0. */
|
|
91
|
+
exit(code: number): void;
|
|
92
|
+
}
|
|
93
|
+
/** A host stream is the part of a stream of Node that the port uses. */
|
|
94
|
+
interface HostStream {
|
|
95
|
+
readonly writable?: boolean;
|
|
96
|
+
readonly destroyed?: boolean;
|
|
97
|
+
readonly readableEnded?: boolean;
|
|
98
|
+
write(chunk: string, done: (error?: unknown) => void): boolean;
|
|
99
|
+
on(event: string, handler: () => void): unknown;
|
|
100
|
+
off(event: string, handler: () => void): unknown;
|
|
101
|
+
}
|
|
102
|
+
/** A process host is the part of the process of Node that the port uses. Its event `message` gives the message of the IPC channel. */
|
|
103
|
+
interface ProcessHost {
|
|
104
|
+
on(signal: string, handler: (message?: unknown) => void): unknown;
|
|
105
|
+
off(signal: string, handler: (message?: unknown) => void): unknown;
|
|
106
|
+
exit(code: number): unknown;
|
|
107
|
+
readonly stdin?: HostStream | undefined;
|
|
108
|
+
readonly stdout?: HostStream | undefined;
|
|
109
|
+
readonly stderr?: HostStream | undefined;
|
|
110
|
+
}
|
|
111
|
+
/**
|
|
112
|
+
* This function makes a process port on a host. `find` gives the host at each use, or undefined
|
|
113
|
+
* when the platform has no process. Then the use throws.
|
|
114
|
+
*/
|
|
115
|
+
declare const processPortOf: (find: () => ProcessHost | undefined) => ProcessPort;
|
|
116
|
+
/** This port is the process of Node. */
|
|
117
|
+
declare const nodeProcess: ProcessPort;
|
|
118
|
+
//#endregion
|
|
119
|
+
//#region src/routes.d.ts
|
|
120
|
+
/**
|
|
121
|
+
* A route pattern matches the routes of a controller that its exact routes do not name. A
|
|
122
|
+
* registry that changes while the service operates, for example a registry of procedures, thus
|
|
123
|
+
* needs no list of routes before the start. The syntax of a pattern:
|
|
124
|
+
* - `*` matches each text, also an empty text and a text with `/`. The pattern `*` alone matches
|
|
125
|
+
* each route.
|
|
126
|
+
* - `:name` matches a text of one character or more without `/`, and gives it in `params.name`.
|
|
127
|
+
* - Each other character matches itself.
|
|
128
|
+
*
|
|
129
|
+
* The declaration names the operations that a request of the pattern can be. Each operation
|
|
130
|
+
* declares its idempotency, as a route does. A function picks the operation of each request.
|
|
131
|
+
*/
|
|
132
|
+
interface RoutePattern {
|
|
133
|
+
readonly pattern: string;
|
|
134
|
+
/** These are the operations that a request of the pattern can be, by name. */
|
|
135
|
+
readonly operations: Readonly<Record<string, Operation>>;
|
|
136
|
+
}
|
|
137
|
+
/** A route request is what the function of a pattern gets for one request. */
|
|
138
|
+
interface RouteRequest {
|
|
139
|
+
readonly controller: string;
|
|
140
|
+
readonly route: string;
|
|
141
|
+
/** These are the texts of the `:name` parts of the pattern, by name. */
|
|
142
|
+
readonly params: Readonly<Record<string, string>>;
|
|
143
|
+
/** These are the texts of the `*` parts of the pattern, in their sequence. */
|
|
144
|
+
readonly wildcards: readonly string[];
|
|
145
|
+
/** This value is the detail that the transport gives with the request, or undefined. */
|
|
146
|
+
readonly detail: unknown;
|
|
147
|
+
}
|
|
148
|
+
/**
|
|
149
|
+
* An operation choice gives the name of the operation of one request: one of the operations that
|
|
150
|
+
* the pattern declares. Thus the function decides the idempotency of each request, and the
|
|
151
|
+
* declaration keeps each window of a keyed operation as data.
|
|
152
|
+
*/
|
|
153
|
+
type OperationOf = (request: RouteRequest) => string;
|
|
154
|
+
//#endregion
|
|
3
155
|
//#region src/timing.d.ts
|
|
4
156
|
/**
|
|
5
157
|
* All policies have the same timing shape. A timing is a count of polls (a debounce) or a
|
|
@@ -64,34 +216,6 @@ declare const asDebounce: (timing: Timing, poll: Poll) => Timing;
|
|
|
64
216
|
*/
|
|
65
217
|
declare const heartbeatDetection: (interval: Extent, timeout: Quantity, misses: number) => Extent;
|
|
66
218
|
//#endregion
|
|
67
|
-
//#region src/operation.d.ts
|
|
68
|
-
/**
|
|
69
|
-
* This type tells if an operation can go again after a failure. It is a property of the
|
|
70
|
-
* operation, not of the dependency. One Redis client sends a GET, which is safe to send again. It
|
|
71
|
-
* also sends an INCR, which counts two times when it goes again after a timeout. Each operation
|
|
72
|
-
* declares its idempotency:
|
|
73
|
-
* - `true`: a second issue has the same effect. Examples are an HTTP GET or PUT, a SELECT, a
|
|
74
|
-
* Redis GET or SET, and a write that the server removes when it is a copy.
|
|
75
|
-
* - `false`: the client does not send it again after it can have reached the server.
|
|
76
|
-
* - keyed: the server keeps a key for a window, as with an `Idempotency-Key` header, and it
|
|
77
|
-
* ignores a copy in that window. A copy after the window is a second operation. Thus the
|
|
78
|
-
* window is a timer, and it must be longer than all retries of the operation.
|
|
79
|
-
*/
|
|
80
|
-
type Idempotency = boolean | {
|
|
81
|
-
readonly key: string;
|
|
82
|
-
readonly window: Extent;
|
|
83
|
-
};
|
|
84
|
-
/** An operation is an endpoint that the service calls or serves, a command, or a query. */
|
|
85
|
-
interface Operation {
|
|
86
|
-
readonly idempotent: Idempotency;
|
|
87
|
-
}
|
|
88
|
-
/**
|
|
89
|
-
* This function tells if an operation can go again `since` its first issue. An idempotent
|
|
90
|
-
* operation can always go again, and other operations cannot. A keyed operation can go again
|
|
91
|
-
* while the server keeps its key.
|
|
92
|
-
*/
|
|
93
|
-
declare const mayReissue: (operation: Operation, since: Quantity) => boolean;
|
|
94
|
-
//#endregion
|
|
95
219
|
//#region src/description.d.ts
|
|
96
220
|
/**
|
|
97
221
|
* This is the format of a service as data: what `describe()` exports, and nothing starts. The
|
|
@@ -152,6 +276,12 @@ interface Controller {
|
|
|
152
276
|
readonly name: string;
|
|
153
277
|
readonly requires: readonly string[];
|
|
154
278
|
readonly routes: Readonly<Record<string, Operation>>;
|
|
279
|
+
/**
|
|
280
|
+
* These patterns match the routes that `routes` does not name, in their sequence: the first
|
|
281
|
+
* pattern that matches a route gives its operations. Without a declaration, the controller has
|
|
282
|
+
* no patterns.
|
|
283
|
+
*/
|
|
284
|
+
readonly patterns?: readonly RoutePattern[] | undefined;
|
|
155
285
|
}
|
|
156
286
|
/** A coupling is a declared edge between two policies. The algebra checks its margin. */
|
|
157
287
|
interface Coupling {
|
|
@@ -164,6 +294,31 @@ interface Phase {
|
|
|
164
294
|
readonly name: string;
|
|
165
295
|
readonly cap: Quantity;
|
|
166
296
|
}
|
|
297
|
+
/**
|
|
298
|
+
* A repeat signal policy tells what an exit signal does while the shutdown runs:
|
|
299
|
+
* - `ignore`: the signal has no effect, and the shutdown continues.
|
|
300
|
+
* - `exit`: the process exits with the code 1 at once, as a second Ctrl-C does in a terminal.
|
|
301
|
+
*/
|
|
302
|
+
type RepeatSignal = "ignore" | "exit";
|
|
303
|
+
/**
|
|
304
|
+
* A cooperative floor is the earliest time of the cooperative abort in the drain:
|
|
305
|
+
* - `half`: half the cap of the drain. The work in flight gets half the drain at the least.
|
|
306
|
+
* - `none`: no floor. A window of the whole cap or more aborts the work at the start of the drain.
|
|
307
|
+
*/
|
|
308
|
+
type CooperativeFloor = "half" | "none";
|
|
309
|
+
/** These exit codes replace the code 0 of a clean shutdown, by the trigger of the shutdown. */
|
|
310
|
+
type ExitCodes = Readonly<Partial<Record<ExitTrigger, number>>>;
|
|
311
|
+
/**
|
|
312
|
+
* A message trigger is a message of the IPC channel that starts the shutdown, for the trigger
|
|
313
|
+
* `ipc-message`. With `as`, the message is that exit signal: it has its exit code and the policy of a
|
|
314
|
+
* repeat signal. Without `as`, the message is the trigger `ipc-message`.
|
|
315
|
+
*/
|
|
316
|
+
interface MessageTrigger {
|
|
317
|
+
/** This shape is the message that starts the shutdown, for example `"shutdown"`. */
|
|
318
|
+
readonly match: MessageShape;
|
|
319
|
+
/** This signal is the exit signal that the message replaces, for example `SIGTERM` on Windows. */
|
|
320
|
+
readonly as?: ExitSignal | undefined;
|
|
321
|
+
}
|
|
167
322
|
/** A service description is the whole graph of a service, as data. */
|
|
168
323
|
interface ServiceDescription {
|
|
169
324
|
readonly format: typeof FORMAT;
|
|
@@ -185,6 +340,16 @@ interface ServiceDescription {
|
|
|
185
340
|
readonly phases: readonly Phase[];
|
|
186
341
|
/** This window is how long before the end of the drain the cooperative abort occurs, or no bound. */
|
|
187
342
|
readonly cooperativeWindow: Extent;
|
|
343
|
+
/** This floor is the earliest time of the cooperative abort. Without a declaration, the floor is `half`. */
|
|
344
|
+
readonly cooperativeFloor?: CooperativeFloor | undefined;
|
|
345
|
+
/** This policy tells what a signal does while the shutdown runs. Each declaration gives it, because the runtime has no defaults. */
|
|
346
|
+
readonly onRepeatSignal: RepeatSignal;
|
|
347
|
+
/** These triggers start the shutdown, in addition to the exit signals. Each one is opt-in. */
|
|
348
|
+
readonly triggers?: readonly ProcessTrigger[] | undefined;
|
|
349
|
+
/** These messages of the IPC channel start the shutdown. The trigger `ipc-message` needs one at the least. */
|
|
350
|
+
readonly messages?: readonly MessageTrigger[] | undefined;
|
|
351
|
+
/** These codes replace the exit code 0 by the trigger. Without a code, a clean shutdown exits 0. */
|
|
352
|
+
readonly exitCodes?: ExitCodes | undefined;
|
|
188
353
|
};
|
|
189
354
|
}
|
|
190
355
|
//#endregion
|
|
@@ -330,57 +495,70 @@ interface Health {
|
|
|
330
495
|
stop(): void;
|
|
331
496
|
}
|
|
332
497
|
//#endregion
|
|
333
|
-
//#region src/process.d.ts
|
|
334
|
-
/** An exit signal is a signal that asks the process to stop: each one starts the shutdown. */
|
|
335
|
-
type ExitSignal = "SIGINT" | "SIGTERM" | "SIGQUIT";
|
|
336
|
-
/** These are the signals that the runtime handles. */
|
|
337
|
-
declare const EXIT_SIGNALS: readonly ExitSignal[];
|
|
338
|
-
/**
|
|
339
|
-
* A process port is the part of the process that the runtime uses: its exit signals and its exit.
|
|
340
|
-
* The runtime owns the handlers, because Node as PID 1 without a handler ignores SIGTERM. Only the
|
|
341
|
-
* runtime ends the process, and library code does not. A test gives a fake port, sends signals,
|
|
342
|
-
* and reads the exit code.
|
|
343
|
-
*/
|
|
344
|
-
interface ProcessPort {
|
|
345
|
-
/** This method adds a handler for a signal, and gives the function that removes it. */
|
|
346
|
-
on(signal: ExitSignal, handler: () => void): () => void;
|
|
347
|
-
/** This method ends the process with a code: 0 after a clean shutdown, and 1 after an error. */
|
|
348
|
-
exit(code: number): void;
|
|
349
|
-
}
|
|
350
|
-
/** This port is the process of Node. */
|
|
351
|
-
declare const nodeProcess: ProcessPort;
|
|
352
|
-
//#endregion
|
|
353
498
|
//#region src/requests.d.ts
|
|
354
499
|
/**
|
|
355
|
-
* A request
|
|
356
|
-
*
|
|
357
|
-
*
|
|
358
|
-
*
|
|
500
|
+
* A request end is the one final result of the stream of a request. Its count `delivered` is the
|
|
501
|
+
* number of items that the stream gave before it. An end after the first item is in-band. The
|
|
502
|
+
* transport sent its answer, thus it writes the end as the last line of the stream, not as a status.
|
|
503
|
+
* - `done`: the work gave each of its items.
|
|
504
|
+
* - `failed`: the work failed for a cause of its own. Before the first item, the adapter answers it
|
|
505
|
+
* as it answers any error of the route.
|
|
359
506
|
* - `refused`: the service did not admit the request. A refused request did not start, thus its
|
|
360
507
|
* caller can send it again: 503, retryable.
|
|
361
|
-
* - `cut`: the shutdown stopped the request.
|
|
362
|
-
* retryable
|
|
363
|
-
*
|
|
508
|
+
* - `cut`: the shutdown stopped the request. Before the first item, a route whose callers can send
|
|
509
|
+
* it again answers 503, retryable, and each other route answers 500. After the first item, the
|
|
510
|
+
* status is null, and the end is in-band.
|
|
364
511
|
*/
|
|
365
|
-
type
|
|
512
|
+
type RequestEnd = {
|
|
366
513
|
readonly kind: "done";
|
|
367
|
-
readonly
|
|
514
|
+
readonly delivered: number;
|
|
368
515
|
} | {
|
|
369
516
|
readonly kind: "failed";
|
|
370
517
|
readonly error: unknown;
|
|
518
|
+
readonly delivered: number;
|
|
371
519
|
} | {
|
|
372
520
|
readonly kind: "refused";
|
|
373
521
|
readonly status: 503;
|
|
374
522
|
readonly retryable: true;
|
|
375
523
|
readonly cause: string;
|
|
524
|
+
readonly delivered: 0;
|
|
376
525
|
} | {
|
|
377
526
|
readonly kind: "cut";
|
|
378
|
-
readonly status: 503 | 500;
|
|
527
|
+
readonly status: 503 | 500 | null;
|
|
379
528
|
readonly retryable: boolean;
|
|
380
529
|
readonly cause: string;
|
|
530
|
+
readonly delivered: number;
|
|
381
531
|
};
|
|
532
|
+
/** A request event is one event of the stream of a request: an item, or the one end, which comes last. */
|
|
533
|
+
type RequestEvent<T> = {
|
|
534
|
+
readonly kind: "item";
|
|
535
|
+
readonly value: T;
|
|
536
|
+
} | RequestEnd;
|
|
537
|
+
/**
|
|
538
|
+
* A request stream is what a request comes to: its items, then one end. A unary work gives a stream
|
|
539
|
+
* of one item. The stream gives an item only when its reader asks for the next event. Thus a slow
|
|
540
|
+
* reader slows the work, and the request stays in flight until the work ends. When the reader
|
|
541
|
+
* stops before the end, the work gets its abort and the `return()` of its iterator.
|
|
542
|
+
*/
|
|
543
|
+
interface RequestStream<T> extends AsyncIterable<RequestEvent<T>> {
|
|
544
|
+
/** This method reads the whole stream, and gives its items and its end. */
|
|
545
|
+
collect(): Promise<{
|
|
546
|
+
readonly items: readonly T[];
|
|
547
|
+
readonly end: RequestEnd;
|
|
548
|
+
}>;
|
|
549
|
+
}
|
|
550
|
+
/**
|
|
551
|
+
* A request work is what a request function gives: one value, or a stream of values. A work that
|
|
552
|
+
* gives an async iterable is a stream, also through a promise. Each other value is a stream of one.
|
|
553
|
+
*/
|
|
554
|
+
type RequestWork<T> = T | PromiseLike<T> | AsyncIterable<T> | PromiseLike<AsyncIterable<T>>;
|
|
382
555
|
/** A request function does the work of one request. It receives a signal that the shutdown aborts. */
|
|
383
|
-
type RequestFn<T> = (signal: AbortSignal) =>
|
|
556
|
+
type RequestFn<T> = (signal: AbortSignal) => RequestWork<T>;
|
|
557
|
+
/** These options go with one request. */
|
|
558
|
+
interface RequestOptions {
|
|
559
|
+
/** This value goes to the function of a route pattern, for example the metadata of a procedure. */
|
|
560
|
+
readonly detail?: unknown;
|
|
561
|
+
}
|
|
384
562
|
//#endregion
|
|
385
563
|
//#region src/lifecycle.d.ts
|
|
386
564
|
/**
|
|
@@ -389,7 +567,13 @@ type RequestFn<T> = (signal: AbortSignal) => Promise<T> | T;
|
|
|
389
567
|
* and it closes. A second close has no effect.
|
|
390
568
|
*/
|
|
391
569
|
interface TransportImpl {
|
|
392
|
-
|
|
570
|
+
/**
|
|
571
|
+
* This method starts the transport. The lifecycle is the object that `run()` gives at the end of
|
|
572
|
+
* the startup. Its request tracking operates from the start: a request before the startup ends
|
|
573
|
+
* gets a retryable refusal, and `keepAlive()` is false. Do not wait for `life.started` here,
|
|
574
|
+
* because the startup waits for this method.
|
|
575
|
+
*/
|
|
576
|
+
start(signal: AbortSignal, life: Lifecycle): Promise<void> | void;
|
|
393
577
|
stopIntake(): Promise<void> | void;
|
|
394
578
|
/**
|
|
395
579
|
* This method lets the work in flight end until `deadline` (milliseconds on the monotonic
|
|
@@ -434,22 +618,32 @@ type PhaseWork = (context: PhaseContext) => Promise<void> | void;
|
|
|
434
618
|
* - `close transports`: each transport closes.
|
|
435
619
|
* - `stop the poller`: each check and watchdog stops. Then the signal of the service aborts.
|
|
436
620
|
* - `tear down dependencies`: each dependency closes, in the reverse sequence of its connection.
|
|
437
|
-
* - `close the health server`: the probes stop
|
|
621
|
+
* - `close the health server`: the probes stop.
|
|
622
|
+
* - `flush the output`: the work of the owners of this phase ends, and then the process port
|
|
623
|
+
* writes the buffered output. Without this phase, the process exits without a wait.
|
|
438
624
|
*/
|
|
439
|
-
declare const STAGES: readonly ["fail readiness", "stop intake", "drain", "close transports", "stop the poller", "tear down dependencies", "close the health server"];
|
|
625
|
+
declare const STAGES: readonly ["fail readiness", "stop intake", "drain", "close transports", "stop the poller", "tear down dependencies", "close the health server", "flush the output"];
|
|
440
626
|
type Stage = (typeof STAGES)[number];
|
|
441
627
|
/** This function gives the place of a stage in the sequence, or -1 for a phase of another name. */
|
|
442
628
|
declare const stageRank: (name: string) => number;
|
|
443
629
|
/**
|
|
444
630
|
* This function gives the time of the cooperative abort, in milliseconds after the drain starts. It
|
|
445
|
-
* is the cap less the cooperative window
|
|
446
|
-
* gives half the cap.
|
|
631
|
+
* is the cap less the cooperative window. With the floor `half`, it is not less than half the cap,
|
|
632
|
+
* and a window without a bound gives half the cap. With the floor `none`, it is not less than 0.
|
|
447
633
|
*/
|
|
448
|
-
declare const cooperativeAbortAt: (cap: number, window: Extent) => number;
|
|
634
|
+
declare const cooperativeAbortAt: (cap: number, window: Extent, floor?: CooperativeFloor) => number;
|
|
449
635
|
/** These options run the lifecycle. Without them, it uses the real clock and the process of Node. */
|
|
450
636
|
interface RunOptions extends StartOptions {
|
|
451
637
|
readonly process?: ProcessPort | undefined;
|
|
452
638
|
}
|
|
639
|
+
/** These options go with a request for the shutdown. */
|
|
640
|
+
interface ShutdownOptions {
|
|
641
|
+
/**
|
|
642
|
+
* This code is the exit code that the work of the process gives, a whole number from 0 to 255. The
|
|
643
|
+
* first exit request with a code sets it. A code of 0 lets an error make the exit code 1.
|
|
644
|
+
*/
|
|
645
|
+
readonly code?: number | undefined;
|
|
646
|
+
}
|
|
453
647
|
/** A lifecycle state tells where the service is in its life. */
|
|
454
648
|
type LifecycleState = "starting" | "running" | "draining" | "exited";
|
|
455
649
|
/** The lifecycle of a running service. */
|
|
@@ -458,7 +652,7 @@ interface Lifecycle {
|
|
|
458
652
|
readonly state: LifecycleState;
|
|
459
653
|
/** This code is the exit code, or null before the exit. */
|
|
460
654
|
readonly exitCode: number | null;
|
|
461
|
-
/** These texts are the errors
|
|
655
|
+
/** These texts are the errors of the lifecycle. An error makes the exit code 1, unless an exit request gives another code. */
|
|
462
656
|
readonly errors: readonly string[];
|
|
463
657
|
/** This promise ends when the startup ends: the service runs, or its startup failed. */
|
|
464
658
|
readonly started: Promise<void>;
|
|
@@ -466,13 +660,18 @@ interface Lifecycle {
|
|
|
466
660
|
readonly done: Promise<number>;
|
|
467
661
|
/** This signal aborts after the poller stops: the background work of the service stops with it. */
|
|
468
662
|
readonly signal: AbortSignal;
|
|
469
|
-
/** This method asks for the shutdown, as an exit signal does. A second request has no effect. */
|
|
470
|
-
shutdown(cause?: string): Promise<number>;
|
|
471
663
|
/**
|
|
472
|
-
* This method
|
|
473
|
-
*
|
|
664
|
+
* This method asks for the shutdown, as an exit signal does. A second request does not start a
|
|
665
|
+
* second shutdown. It can give the exit code, when no request gave one before.
|
|
666
|
+
*/
|
|
667
|
+
shutdown(cause?: string, options?: ShutdownOptions): Promise<number>;
|
|
668
|
+
/**
|
|
669
|
+
* This method does one request of a controller, on a route or a route pattern that the controller
|
|
670
|
+
* declares. It gives the stream of the request: each item of the work, then one end. The service
|
|
671
|
+
* refuses the request while it cannot take new work, and the shutdown can cut it. An undeclared
|
|
672
|
+
* route throws, because it has no idempotency.
|
|
474
673
|
*/
|
|
475
|
-
request<T>(controller: string, route: string, work: RequestFn<T
|
|
674
|
+
request<T>(controller: string, route: string, work: RequestFn<T>, options?: RequestOptions): RequestStream<T>;
|
|
476
675
|
inFlight(controller?: string): number;
|
|
477
676
|
/**
|
|
478
677
|
* This method tells if a response can keep its connection open. It is false while the service is
|
|
@@ -481,113 +680,5 @@ interface Lifecycle {
|
|
|
481
680
|
keepAlive(): boolean;
|
|
482
681
|
}
|
|
483
682
|
//#endregion
|
|
484
|
-
|
|
485
|
-
|
|
486
|
-
* A watchdog spec declares a watchdog of the event loop. The service declares it as a check whose
|
|
487
|
-
* function the watchdog gives: the process's own wedge, which a liveness window reads.
|
|
488
|
-
*/
|
|
489
|
-
interface WatchdogSpec {
|
|
490
|
-
readonly name: string;
|
|
491
|
-
/** This time is the interval of the tick of the watchdog. */
|
|
492
|
-
readonly tick: Quantity;
|
|
493
|
-
/** This time is the most that a tick can be late before the loop counts as blocked. */
|
|
494
|
-
readonly threshold: Quantity;
|
|
495
|
-
/** This gate is the policy that the check controls, or null for a check that only reports. */
|
|
496
|
-
readonly gates: Gate | null;
|
|
497
|
-
readonly poll: Poll;
|
|
498
|
-
}
|
|
499
|
-
/**
|
|
500
|
-
* A watchdog measures how late its own tick comes. A blocked event loop delays each timer, thus a
|
|
501
|
-
* tick that comes later than the threshold shows the block. Its states are `watching`, `blocked`
|
|
502
|
-
* and `stopped`.
|
|
503
|
-
*/
|
|
504
|
-
interface Watchdog {
|
|
505
|
-
/** This function is the check: it fails when a tick since the last poll came late, or the loop is still blocked. */
|
|
506
|
-
readonly check: () => Outcome;
|
|
507
|
-
/** This time is the most that a tick was late, in milliseconds, since the start. */
|
|
508
|
-
readonly worst: number;
|
|
509
|
-
readonly blocked: boolean;
|
|
510
|
-
stop(): void;
|
|
511
|
-
}
|
|
512
|
-
/** This function starts a watchdog on a clock. */
|
|
513
|
-
declare const watchdog: (clock: Clock, spec: WatchdogSpec, trace?: Trace) => Watchdog;
|
|
514
|
-
//#endregion
|
|
515
|
-
//#region src/builder.d.ts
|
|
516
|
-
/**
|
|
517
|
-
* A service is composed with plain method uses before it starts. The builder is imperative, and
|
|
518
|
-
* it holds static knowledge. The service does not use an `init` function that gives registrations.
|
|
519
|
-
*
|
|
520
|
-
* const svc = service("app");
|
|
521
|
-
* svc.dependency("weather", {
|
|
522
|
-
* system: null,
|
|
523
|
-
* knobs: { request_timeout },
|
|
524
|
-
* operations: { "GET /v1/forecast": { idempotent: true } },
|
|
525
|
-
* });
|
|
526
|
-
* svc.controller("forecast").requires("weather").route("GET /api/forecast", { idempotent: true });
|
|
527
|
-
* svc.check({ name: "weather.round-trip", dependency: "weather", … }, roundTrip);
|
|
528
|
-
* svc.describe(); // the whole graph as data, with nothing started
|
|
529
|
-
* const health = await svc.start();
|
|
530
|
-
*
|
|
531
|
-
* The graph has one source, thus its parts cannot disagree. A dependency or a check can join
|
|
532
|
-
* after the start. It starts tripped, and the export is partial. The runtime has no defaults of
|
|
533
|
-
* its own. Thus `describe()` refuses a service that does not declare a policy, its startup budget
|
|
534
|
-
* or its shutdown, and it tells which.
|
|
535
|
-
*
|
|
536
|
-
* `start()` starts only the health runtime. `run()` starts the whole lifecycle: the startup in its
|
|
537
|
-
* sequence, the exit signals, the capped phases of the shutdown, and the exit of the process.
|
|
538
|
-
*/
|
|
539
|
-
interface ControllerBuilder {
|
|
540
|
-
/** This method declares the dependencies that its routes need. The controller is ready only while they are ready. */
|
|
541
|
-
requires(...dependencies: string[]): ControllerBuilder;
|
|
542
|
-
/** This method declares a route that the controller serves, and if its callers can send it again. */
|
|
543
|
-
route(route: string, operation: Operation): ControllerBuilder;
|
|
544
|
-
}
|
|
545
|
-
/** A service builder composes a service, gives it as data, and starts it. */
|
|
546
|
-
interface ServiceBuilder {
|
|
547
|
-
readonly name: string;
|
|
548
|
-
/** This method declares a dependency, and the handle that connects to it and closes it, if it has one. */
|
|
549
|
-
dependency(name: string, spec: Omit<Dependency, "name">, handle?: DependencyHandle): ServiceBuilder;
|
|
550
|
-
/** This method declares a server, and its implementation. `run()` needs the implementation. */
|
|
551
|
-
server(name: string, knobs: Readonly<Record<string, Extent>>, impl?: TransportImpl): ServiceBuilder;
|
|
552
|
-
consumer(name: string, knobs: Readonly<Record<string, Extent>>, impl?: TransportImpl): ServiceBuilder;
|
|
553
|
-
worker(name: string, knobs: Readonly<Record<string, Extent>>, impl?: TransportImpl): ServiceBuilder;
|
|
554
|
-
/** This method gives the server of the probes. It starts first and closes last. */
|
|
555
|
-
healthServer(server: HealthServer): ServiceBuilder;
|
|
556
|
-
/** This method adds work to a declared phase of the shutdown: the owner of the work registers it. */
|
|
557
|
-
onPhase(phase: string, work: PhaseWork): ServiceBuilder;
|
|
558
|
-
/** This method declares a watchdog of the event loop, as a check on the state of the process. */
|
|
559
|
-
watchdog(spec: WatchdogSpec): ServiceBuilder;
|
|
560
|
-
controller(name: string): ControllerBuilder;
|
|
561
|
-
/** This method declares a check, and the function that measures its step. `start()` needs the function. */
|
|
562
|
-
check(check: Check, run?: CheckFn): ServiceBuilder;
|
|
563
|
-
readiness(timing: Timing): ServiceBuilder;
|
|
564
|
-
liveness(timing: Timing): ServiceBuilder;
|
|
565
|
-
startup(budget: Quantity): ServiceBuilder;
|
|
566
|
-
couple(coupling: Coupling): ServiceBuilder;
|
|
567
|
-
phase(name: string, cap: Quantity): ServiceBuilder;
|
|
568
|
-
cooperativeWindow(window: Extent): ServiceBuilder;
|
|
569
|
-
/** This method gives the service as data, and it starts nothing. */
|
|
570
|
-
describe(): ServiceDescription;
|
|
571
|
-
/**
|
|
572
|
-
* This method closes the composition, starts the health runtime, and gives it after one warm-up
|
|
573
|
-
* sweep of each check. A part that joins after it starts tripped, and it makes the export
|
|
574
|
-
* partial. A second use gives the same runtime.
|
|
575
|
-
*/
|
|
576
|
-
start(options?: StartOptions): Promise<Health>;
|
|
577
|
-
/**
|
|
578
|
-
* This method starts the whole lifecycle and gives it when its startup ends: the service operates,
|
|
579
|
-
* or its startup failed and it shuts down. It refuses a declaration that it cannot start: a transport
|
|
580
|
-
* without its implementation, or a stage with work and no declared phase.
|
|
581
|
-
*/
|
|
582
|
-
run(options?: RunOptions): Promise<Lifecycle>;
|
|
583
|
-
/**
|
|
584
|
-
* This value is the health runtime from the time that `start()` begins, or null before. Thus the
|
|
585
|
-
* probes can answer during the warm-up sweep: the startup probe fails until the sweep ends.
|
|
586
|
-
*/
|
|
587
|
-
readonly health: Health | null;
|
|
588
|
-
}
|
|
589
|
-
/** This function starts the composition of a service. */
|
|
590
|
-
declare const service: (name: string) => ServiceBuilder;
|
|
591
|
-
//#endregion
|
|
592
|
-
export { Timing as $, StartOptions as A, Dependency as B, ProcessPort as C, HealthVerdict as D, Health as E, MachineName as F, Step as G, Gate as H, Recorder as I, Operation as J, Transport as K, Check as L, Outcome as M, Result as N, ProbeAnswer as O, LifecycleEvent as P, Span as Q, Controller as R, ExitSignal as S, CheckVerdict as T, Phase as U, FORMAT as V, ServiceDescription as W, FailsBy as X, mayReissue as Y, Poll as Z, cooperativeAbortAt as _, WatchdogSpec as a, RequestOutcome as b, HealthServer as c, PhaseContext as d, asDebounce as et, PhaseWork as f, TransportImpl as g, Stage as h, Watchdog as i, recoverSpan as it, CheckFn as j, ProbeKind as k, Lifecycle as l, STAGES as m, ServiceBuilder as n, failSpan as nt, watchdog as o, RunOptions as p, Idempotency as q, service as r, heartbeatDetection as rt, DependencyHandle as s, ControllerBuilder as t, asWindow as tt, LifecycleState as u, stageRank as v, nodeProcess as w, EXIT_SIGNALS as x, RequestFn as y, Coupling as z };
|
|
593
|
-
//# sourceMappingURL=builder-DnfUDW9u.d.ts.map
|
|
683
|
+
export { failSpan as $, LifecycleEvent as A, Gate as B, ProbeAnswer as C, Outcome as D, CheckFn as E, CooperativeFloor as F, Step as G, Phase as H, Coupling as I, Poll as J, Transport as K, Dependency as L, Recorder as M, Check as N, Result as O, Controller as P, asWindow as Q, ExitCodes as R, HealthVerdict as S, mayReissue as St, StartOptions as T, RepeatSignal as U, MessageTrigger as V, ServiceDescription as W, Timing as X, Span as Y, asDebounce as Z, RequestOptions as _, matchesMessage as _t, PhaseContext as a, EXIT_SIGNALS as at, CheckVerdict as b, Idempotency as bt, STAGES as c, HostStream as ct, TransportImpl as d, ProcessHost as dt, heartbeatDetection as et, cooperativeAbortAt as f, ProcessPort as ft, RequestFn as g, isMessageShape as gt, RequestEvent as h, isExitSignal as ht, LifecycleState as i, RouteRequest as it, MachineName as j, Trace as k, ShutdownOptions as l, MessageShape as lt, RequestEnd as m, isExitCode as mt, HealthServer as n, OperationOf as nt, PhaseWork as o, ExitSignal as ot, stageRank as p, ProcessTrigger as pt, FailsBy as q, Lifecycle as r, RoutePattern as rt, RunOptions as s, ExitTrigger as st, DependencyHandle as t, recoverSpan as tt, Stage as u, PROCESS_TRIGGERS as ut, RequestStream as v, nodeProcess as vt, ProbeKind as w, Health as x, Operation as xt, RequestWork as y, processPortOf as yt, FORMAT as z };
|
|
684
|
+
//# sourceMappingURL=lifecycle-DtJZW09J.d.ts.map
|
package/build/redis.d.ts
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { t as Backoff } from "./backoff-B-jGWVDm.js";
|
|
2
2
|
import { n as Clock } from "./clock-D-38uH_z.js";
|
|
3
|
-
import { B as
|
|
3
|
+
import { B as Gate, E as CheckFn, G as Step, J as Poll, L as Dependency, M as Recorder, N as Check, W as ServiceDescription, et as heartbeatDetection, t as DependencyHandle, xt as Operation } from "./lifecycle-DtJZW09J.js";
|
|
4
|
+
import { n as ServiceBuilder } from "./builder-QVxu1WcL.js";
|
|
4
5
|
import { Extent, Quantity } from "@mark1russell7/quantity";
|
|
5
6
|
import { Machine } from "@mark1russell7/algebra";
|
|
6
7
|
//#region src/redis/connection.d.ts
|