@zudojs/runtime 0.1.0 → 1.0.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/LICENSE +21 -0
- package/README.md +127 -6
- package/dist/dependencyGraph/dependencyGraph.core.d.ts +11 -5
- package/dist/dependencyGraph/dependencyGraph.core.js +13 -12
- package/dist/dependencyGraph/dependencyGraph.type.d.ts +0 -7
- package/dist/dependencyGraph/index.d.ts +2 -2
- package/dist/dependencyGraph/index.js +1 -1
- package/dist/health/health.core.d.ts +12 -0
- package/dist/health/health.core.js +55 -0
- package/dist/health/index.d.ts +5 -0
- package/dist/health/index.js +5 -0
- package/dist/index.d.ts +1 -1
- package/dist/index.js +4 -1
- package/dist/lifecycle/index.d.ts +1 -1
- package/dist/lifecycle/lifecycle.core.d.ts +41 -10
- package/dist/lifecycle/lifecycle.core.js +238 -61
- package/dist/lifecycle/lifecycle.type.d.ts +48 -1
- package/dist/readiness/index.d.ts +1 -1
- package/dist/readiness/readiness.core.d.ts +36 -4
- package/dist/readiness/readiness.core.js +109 -6
- package/dist/readiness/readiness.type.d.ts +15 -1
- package/dist/registry/registry.core.d.ts +14 -1
- package/dist/registry/registry.core.js +41 -2
- package/dist/runtime/runtime.core.d.ts +75 -5
- package/dist/runtime/runtime.core.js +199 -43
- package/dist/runtimeContext/index.d.ts +2 -2
- package/dist/runtimeContext/index.js +1 -1
- package/dist/runtimeContext/runtimeContext.core.d.ts +13 -4
- package/dist/runtimeContext/runtimeContext.core.js +22 -11
- package/dist/runtimeContext/runtimeContext.type.d.ts +12 -13
- package/dist/runtimeError/runtimeError.base.js +1 -1
- package/dist/runtimeEvents/index.d.ts +2 -2
- package/dist/runtimeEvents/index.js +1 -1
- package/dist/runtimeEvents/runtimeEvents.core.d.ts +15 -1
- package/dist/runtimeEvents/runtimeEvents.core.js +26 -0
- package/dist/runtimeEvents/runtimeEvents.type.d.ts +19 -4
- package/dist/runtimeOptions/runtimeOptions.core.js +8 -2
- package/dist/runtimeOptions/runtimeOptions.type.d.ts +29 -1
- package/dist/runtimeOptions/runtimeOptions.type.js +6 -0
- package/dist/runtimeState/index.d.ts +1 -1
- package/dist/runtimeState/runtimeState.core.d.ts +4 -0
- package/dist/runtimeState/runtimeState.core.js +17 -4
- package/dist/runtimeState/runtimeState.type.d.ts +14 -17
- package/dist/shutdown/shutdown.core.d.ts +20 -1
- package/dist/shutdown/shutdown.core.js +55 -29
- package/dist/signalHandler/signalHandler.core.d.ts +53 -13
- package/dist/signalHandler/signalHandler.core.js +97 -27
- package/dist/startup/startup.core.d.ts +3 -2
- package/dist/startup/startup.core.js +52 -46
- package/dist/testRuntime/index.d.ts +6 -1
- package/dist/testRuntime/index.js +5 -1
- package/dist/testRuntime/testRuntime.core.d.ts +21 -2
- package/dist/testRuntime/testRuntime.core.js +23 -6
- package/package.json +29 -22
- package/dist/.tsbuildinfo +0 -1
- package/dist/dependencyGraph/dependencyGraph.core.d.ts.map +0 -1
- package/dist/dependencyGraph/dependencyGraph.core.js.map +0 -1
- package/dist/dependencyGraph/dependencyGraph.type.d.ts.map +0 -1
- package/dist/dependencyGraph/dependencyGraph.type.js.map +0 -1
- package/dist/dependencyGraph/index.d.ts.map +0 -1
- package/dist/dependencyGraph/index.js.map +0 -1
- package/dist/index.d.ts.map +0 -1
- package/dist/index.js.map +0 -1
- package/dist/lifecycle/index.d.ts.map +0 -1
- package/dist/lifecycle/index.js.map +0 -1
- package/dist/lifecycle/lifecycle.core.d.ts.map +0 -1
- package/dist/lifecycle/lifecycle.core.js.map +0 -1
- package/dist/lifecycle/lifecycle.type.d.ts.map +0 -1
- package/dist/lifecycle/lifecycle.type.js.map +0 -1
- package/dist/readiness/index.d.ts.map +0 -1
- package/dist/readiness/index.js.map +0 -1
- package/dist/readiness/readiness.core.d.ts.map +0 -1
- package/dist/readiness/readiness.core.js.map +0 -1
- package/dist/readiness/readiness.type.d.ts.map +0 -1
- package/dist/readiness/readiness.type.js.map +0 -1
- package/dist/registry/index.d.ts.map +0 -1
- package/dist/registry/index.js.map +0 -1
- package/dist/registry/registry.core.d.ts.map +0 -1
- package/dist/registry/registry.core.js.map +0 -1
- package/dist/runtime/runtime.core.d.ts.map +0 -1
- package/dist/runtime/runtime.core.js.map +0 -1
- package/dist/runtimeContext/index.d.ts.map +0 -1
- package/dist/runtimeContext/index.js.map +0 -1
- package/dist/runtimeContext/runtimeContext.core.d.ts.map +0 -1
- package/dist/runtimeContext/runtimeContext.core.js.map +0 -1
- package/dist/runtimeContext/runtimeContext.factory.d.ts.map +0 -1
- package/dist/runtimeContext/runtimeContext.factory.js.map +0 -1
- package/dist/runtimeContext/runtimeContext.type.d.ts.map +0 -1
- package/dist/runtimeContext/runtimeContext.type.js.map +0 -1
- package/dist/runtimeError/index.d.ts.map +0 -1
- package/dist/runtimeError/index.js.map +0 -1
- package/dist/runtimeError/runtimeError.base.d.ts.map +0 -1
- package/dist/runtimeError/runtimeError.base.js.map +0 -1
- package/dist/runtimeEvents/index.d.ts.map +0 -1
- package/dist/runtimeEvents/index.js.map +0 -1
- package/dist/runtimeEvents/runtimeEvents.core.d.ts.map +0 -1
- package/dist/runtimeEvents/runtimeEvents.core.js.map +0 -1
- package/dist/runtimeEvents/runtimeEvents.type.d.ts.map +0 -1
- package/dist/runtimeEvents/runtimeEvents.type.js.map +0 -1
- package/dist/runtimeOptions/index.d.ts.map +0 -1
- package/dist/runtimeOptions/index.js.map +0 -1
- package/dist/runtimeOptions/runtimeOptions.core.d.ts.map +0 -1
- package/dist/runtimeOptions/runtimeOptions.core.js.map +0 -1
- package/dist/runtimeOptions/runtimeOptions.type.d.ts.map +0 -1
- package/dist/runtimeOptions/runtimeOptions.type.js.map +0 -1
- package/dist/runtimeState/index.d.ts.map +0 -1
- package/dist/runtimeState/index.js.map +0 -1
- package/dist/runtimeState/runtimeState.core.d.ts.map +0 -1
- package/dist/runtimeState/runtimeState.core.js.map +0 -1
- package/dist/runtimeState/runtimeState.type.d.ts.map +0 -1
- package/dist/runtimeState/runtimeState.type.js.map +0 -1
- package/dist/shutdown/index.d.ts.map +0 -1
- package/dist/shutdown/index.js.map +0 -1
- package/dist/shutdown/shutdown.core.d.ts.map +0 -1
- package/dist/shutdown/shutdown.core.js.map +0 -1
- package/dist/signalHandler/index.d.ts.map +0 -1
- package/dist/signalHandler/index.js.map +0 -1
- package/dist/signalHandler/signalHandler.core.d.ts.map +0 -1
- package/dist/signalHandler/signalHandler.core.js.map +0 -1
- package/dist/startup/index.d.ts.map +0 -1
- package/dist/startup/index.js.map +0 -1
- package/dist/startup/startup.core.d.ts.map +0 -1
- package/dist/startup/startup.core.js.map +0 -1
- package/dist/testRuntime/index.d.ts.map +0 -1
- package/dist/testRuntime/index.js.map +0 -1
- package/dist/testRuntime/testRuntime.core.d.ts.map +0 -1
- package/dist/testRuntime/testRuntime.core.js.map +0 -1
|
@@ -1,14 +1,27 @@
|
|
|
1
|
+
import { RuntimeStateError } from "../runtimeError/index.js";
|
|
2
|
+
/**
|
|
3
|
+
* How long a single readiness check may run before it counts as failed.
|
|
4
|
+
*
|
|
5
|
+
* Without a bound, one hanging probe hangs the readiness endpoint
|
|
6
|
+
* indefinitely — a health check that never answers is worse than one
|
|
7
|
+
* that answers "unhealthy".
|
|
8
|
+
*/
|
|
9
|
+
const DEFAULT_CHECK_TIMEOUT = 5_000;
|
|
1
10
|
/**
|
|
2
11
|
* Tracks runtime readiness state.
|
|
3
12
|
*/
|
|
4
13
|
export class ReadinessTracker {
|
|
5
14
|
state = "not_ready";
|
|
6
15
|
checks = new Map();
|
|
16
|
+
checkFns = new Map();
|
|
7
17
|
autoMarkReady;
|
|
18
|
+
checkTimeout;
|
|
8
19
|
ready = false;
|
|
9
20
|
reason;
|
|
21
|
+
running;
|
|
10
22
|
constructor(options = {}) {
|
|
11
23
|
this.autoMarkReady = options.autoMarkReady ?? true;
|
|
24
|
+
this.checkTimeout = options.checkTimeout ?? DEFAULT_CHECK_TIMEOUT;
|
|
12
25
|
if (options.initialChecks) {
|
|
13
26
|
for (const check of options.initialChecks) {
|
|
14
27
|
this.registerCheck(check.name, check.check);
|
|
@@ -17,37 +30,127 @@ export class ReadinessTracker {
|
|
|
17
30
|
}
|
|
18
31
|
/**
|
|
19
32
|
* Registers a readiness check.
|
|
33
|
+
*
|
|
34
|
+
* The check function is retained so it can be re-evaluated later by
|
|
35
|
+
* `updateCheck(name)` or `runChecks()`. Registration does not run the
|
|
36
|
+
* check: it starts out not-ready until it is first evaluated.
|
|
20
37
|
*/
|
|
21
38
|
registerCheck(name, check) {
|
|
39
|
+
this.checkFns.set(name, check);
|
|
22
40
|
this.checks.set(name, {
|
|
23
41
|
name,
|
|
24
42
|
ready: false,
|
|
25
43
|
lastCheckedAt: new Date(),
|
|
44
|
+
durationMs: 0,
|
|
26
45
|
});
|
|
27
46
|
this.evaluateReadiness();
|
|
28
47
|
}
|
|
29
48
|
/**
|
|
30
|
-
*
|
|
49
|
+
* Removes a readiness check.
|
|
50
|
+
*
|
|
51
|
+
* Returns whether a check with that name was registered.
|
|
52
|
+
*/
|
|
53
|
+
removeCheck(name) {
|
|
54
|
+
const existed = this.checks.delete(name);
|
|
55
|
+
this.checkFns.delete(name);
|
|
56
|
+
if (existed) {
|
|
57
|
+
this.evaluateReadiness();
|
|
58
|
+
}
|
|
59
|
+
return existed;
|
|
60
|
+
}
|
|
61
|
+
/**
|
|
62
|
+
* Evaluates a readiness check and records its result.
|
|
63
|
+
*
|
|
64
|
+
* Re-runs the function registered under `name` unless a replacement is
|
|
65
|
+
* supplied, in which case the replacement is stored and used from then on.
|
|
31
66
|
*/
|
|
32
67
|
async updateCheck(name, check) {
|
|
33
|
-
|
|
68
|
+
if (check !== undefined) {
|
|
69
|
+
this.checkFns.set(name, check);
|
|
70
|
+
}
|
|
71
|
+
const fn = this.checkFns.get(name);
|
|
72
|
+
if (fn === undefined) {
|
|
73
|
+
throw new RuntimeStateError(`Readiness check "${name}" is not registered.`);
|
|
74
|
+
}
|
|
75
|
+
await this.evaluateCheck(name, fn);
|
|
76
|
+
this.evaluateReadiness();
|
|
77
|
+
}
|
|
78
|
+
/**
|
|
79
|
+
* Re-evaluates every registered check.
|
|
80
|
+
*/
|
|
81
|
+
async runChecks() {
|
|
82
|
+
// Overlapping runs would interleave their writes into `checks`;
|
|
83
|
+
// callers that arrive mid-run join the run already in flight.
|
|
84
|
+
if (this.running) {
|
|
85
|
+
return this.running;
|
|
86
|
+
}
|
|
87
|
+
this.running = (async () => {
|
|
88
|
+
try {
|
|
89
|
+
await Promise.all([...this.checkFns].map(([name, fn]) => this.evaluateCheck(name, fn)));
|
|
90
|
+
this.evaluateReadiness();
|
|
91
|
+
}
|
|
92
|
+
finally {
|
|
93
|
+
this.running = undefined;
|
|
94
|
+
}
|
|
95
|
+
})();
|
|
96
|
+
return this.running;
|
|
97
|
+
}
|
|
98
|
+
/**
|
|
99
|
+
* Whether any readiness check is registered.
|
|
100
|
+
*/
|
|
101
|
+
hasChecks() {
|
|
102
|
+
return this.checkFns.size > 0;
|
|
103
|
+
}
|
|
104
|
+
/**
|
|
105
|
+
* Runs a single check and records its result and duration.
|
|
106
|
+
*/
|
|
107
|
+
async evaluateCheck(name, fn) {
|
|
108
|
+
const startedAt = Date.now();
|
|
34
109
|
try {
|
|
35
|
-
const result = await
|
|
110
|
+
const result = await this.withCheckTimeout(name, fn);
|
|
36
111
|
this.checks.set(name, {
|
|
37
112
|
name,
|
|
38
113
|
ready: result,
|
|
39
114
|
lastCheckedAt: new Date(),
|
|
115
|
+
durationMs: Date.now() - startedAt,
|
|
40
116
|
});
|
|
41
117
|
}
|
|
42
|
-
catch {
|
|
118
|
+
catch (error) {
|
|
43
119
|
this.checks.set(name, {
|
|
44
120
|
name,
|
|
45
121
|
ready: false,
|
|
46
122
|
lastCheckedAt: new Date(),
|
|
47
|
-
|
|
123
|
+
durationMs: Date.now() - startedAt,
|
|
124
|
+
message: error instanceof Error
|
|
125
|
+
? `Check threw an error: ${error.message}`
|
|
126
|
+
: "Check threw an error",
|
|
48
127
|
});
|
|
49
128
|
}
|
|
50
|
-
|
|
129
|
+
}
|
|
130
|
+
/**
|
|
131
|
+
* Runs a check under a timeout, clearing the timer either way.
|
|
132
|
+
*/
|
|
133
|
+
async withCheckTimeout(name, fn) {
|
|
134
|
+
if (this.checkTimeout <= 0) {
|
|
135
|
+
return fn();
|
|
136
|
+
}
|
|
137
|
+
let timer;
|
|
138
|
+
try {
|
|
139
|
+
return await Promise.race([
|
|
140
|
+
Promise.resolve(fn()),
|
|
141
|
+
new Promise((_, reject) => {
|
|
142
|
+
timer = setTimeout(() => {
|
|
143
|
+
reject(new Error(`Readiness check "${name}" did not settle within ${this.checkTimeout}ms.`));
|
|
144
|
+
}, this.checkTimeout);
|
|
145
|
+
timer.unref?.();
|
|
146
|
+
}),
|
|
147
|
+
]);
|
|
148
|
+
}
|
|
149
|
+
finally {
|
|
150
|
+
if (timer !== undefined) {
|
|
151
|
+
clearTimeout(timer);
|
|
152
|
+
}
|
|
153
|
+
}
|
|
51
154
|
}
|
|
52
155
|
/**
|
|
53
156
|
* Marks the runtime as ready.
|
|
@@ -10,7 +10,16 @@ export interface ReadinessCheck {
|
|
|
10
10
|
readonly ready: boolean;
|
|
11
11
|
readonly message?: string;
|
|
12
12
|
readonly lastCheckedAt: Date;
|
|
13
|
+
/**
|
|
14
|
+
* How long the last evaluation of this check took, in milliseconds.
|
|
15
|
+
* `0` for a check that has been registered but not yet run.
|
|
16
|
+
*/
|
|
17
|
+
readonly durationMs: number;
|
|
13
18
|
}
|
|
19
|
+
/**
|
|
20
|
+
* A readiness check function.
|
|
21
|
+
*/
|
|
22
|
+
export type ReadinessCheckFn = () => boolean | Promise<boolean>;
|
|
14
23
|
/**
|
|
15
24
|
* Readiness tracker state.
|
|
16
25
|
*/
|
|
@@ -29,12 +38,17 @@ export interface ReadinessOptions {
|
|
|
29
38
|
*/
|
|
30
39
|
readonly initialChecks?: ReadonlyArray<{
|
|
31
40
|
readonly name: string;
|
|
32
|
-
readonly check:
|
|
41
|
+
readonly check: ReadinessCheckFn;
|
|
33
42
|
}>;
|
|
34
43
|
/**
|
|
35
44
|
* Whether to automatically mark as ready when all checks pass.
|
|
36
45
|
* @default true
|
|
37
46
|
*/
|
|
38
47
|
readonly autoMarkReady?: boolean;
|
|
48
|
+
/**
|
|
49
|
+
* How long a single check may run before it is recorded as failed, in
|
|
50
|
+
* milliseconds. Defaults to 5000; set to `0` to disable the bound.
|
|
51
|
+
*/
|
|
52
|
+
readonly checkTimeout?: number;
|
|
39
53
|
}
|
|
40
54
|
//# sourceMappingURL=readiness.type.d.ts.map
|
|
@@ -21,8 +21,15 @@ export declare class RuntimeRegistry {
|
|
|
21
21
|
register(id: string, runtime: Runtime): void;
|
|
22
22
|
/**
|
|
23
23
|
* Unregister a runtime instance.
|
|
24
|
+
*
|
|
25
|
+
* Dropping the reference does not stop the runtime; use
|
|
26
|
+
* {@link removeAndStop} when the runtime should also be shut down.
|
|
24
27
|
*/
|
|
25
|
-
unregister(id: string):
|
|
28
|
+
unregister(id: string): boolean;
|
|
29
|
+
/**
|
|
30
|
+
* Unregister a runtime and stop it.
|
|
31
|
+
*/
|
|
32
|
+
removeAndStop(id: string): Promise<boolean>;
|
|
26
33
|
/**
|
|
27
34
|
* Get a runtime by ID.
|
|
28
35
|
*/
|
|
@@ -50,6 +57,12 @@ export declare class RuntimeRegistry {
|
|
|
50
57
|
/**
|
|
51
58
|
* Start all registered runtimes.
|
|
52
59
|
*/
|
|
60
|
+
/**
|
|
61
|
+
* Start all registered runtimes.
|
|
62
|
+
*
|
|
63
|
+
* A failure stops whatever already started before rethrowing, so a
|
|
64
|
+
* partially started process does not linger.
|
|
65
|
+
*/
|
|
53
66
|
startAll(): Promise<void>;
|
|
54
67
|
/**
|
|
55
68
|
* Stop all registered runtimes.
|
|
@@ -25,9 +25,24 @@ export class RuntimeRegistry {
|
|
|
25
25
|
}
|
|
26
26
|
/**
|
|
27
27
|
* Unregister a runtime instance.
|
|
28
|
+
*
|
|
29
|
+
* Dropping the reference does not stop the runtime; use
|
|
30
|
+
* {@link removeAndStop} when the runtime should also be shut down.
|
|
28
31
|
*/
|
|
29
32
|
unregister(id) {
|
|
33
|
+
return this.runtimes.delete(id);
|
|
34
|
+
}
|
|
35
|
+
/**
|
|
36
|
+
* Unregister a runtime and stop it.
|
|
37
|
+
*/
|
|
38
|
+
async removeAndStop(id) {
|
|
39
|
+
const runtime = this.runtimes.get(id);
|
|
40
|
+
if (!runtime) {
|
|
41
|
+
return false;
|
|
42
|
+
}
|
|
30
43
|
this.runtimes.delete(id);
|
|
44
|
+
await runtime.stop();
|
|
45
|
+
return true;
|
|
31
46
|
}
|
|
32
47
|
/**
|
|
33
48
|
* Get a runtime by ID.
|
|
@@ -72,9 +87,30 @@ export class RuntimeRegistry {
|
|
|
72
87
|
/**
|
|
73
88
|
* Start all registered runtimes.
|
|
74
89
|
*/
|
|
90
|
+
/**
|
|
91
|
+
* Start all registered runtimes.
|
|
92
|
+
*
|
|
93
|
+
* A failure stops whatever already started before rethrowing, so a
|
|
94
|
+
* partially started process does not linger.
|
|
95
|
+
*/
|
|
75
96
|
async startAll() {
|
|
97
|
+
const started = [];
|
|
76
98
|
for (const runtime of this.runtimes.values()) {
|
|
77
|
-
|
|
99
|
+
try {
|
|
100
|
+
await runtime.start();
|
|
101
|
+
started.push(runtime);
|
|
102
|
+
}
|
|
103
|
+
catch (error) {
|
|
104
|
+
for (const running of started.reverse()) {
|
|
105
|
+
try {
|
|
106
|
+
await running.stop();
|
|
107
|
+
}
|
|
108
|
+
catch {
|
|
109
|
+
// Continue unwinding; the original error is what matters.
|
|
110
|
+
}
|
|
111
|
+
}
|
|
112
|
+
throw error;
|
|
113
|
+
}
|
|
78
114
|
}
|
|
79
115
|
}
|
|
80
116
|
/**
|
|
@@ -107,7 +143,10 @@ export class RuntimeRegistry {
|
|
|
107
143
|
* Get status of all runtimes.
|
|
108
144
|
*/
|
|
109
145
|
getStatus() {
|
|
110
|
-
|
|
146
|
+
// Null-prototype: ids come from callers, and assigning a key of
|
|
147
|
+
// "__proto__" to an object literal reassigns its prototype instead
|
|
148
|
+
// of adding a property.
|
|
149
|
+
const result = Object.create(null);
|
|
111
150
|
for (const [id, runtime] of this.runtimes) {
|
|
112
151
|
result[id] = {
|
|
113
152
|
state: runtime.state,
|
|
@@ -1,10 +1,11 @@
|
|
|
1
1
|
import type { Logger } from "@zudojs/logger";
|
|
2
2
|
import type { EventBus } from "@zudojs/events";
|
|
3
3
|
import type { Container } from "@zudojs/container";
|
|
4
|
-
import type { Module } from "@zudojs/core";
|
|
5
|
-
import type { RuntimeState, RuntimeStatus } from "../runtimeState/index.js";
|
|
4
|
+
import type { ConfigurationManager, Module, ModuleContext } from "@zudojs/core";
|
|
5
|
+
import type { RuntimeState, RuntimeStatus, RuntimeHealth } from "../runtimeState/index.js";
|
|
6
6
|
import type { RuntimeOptions } from "../runtimeOptions/index.js";
|
|
7
7
|
import type { RuntimeContext } from "../runtimeContext/index.js";
|
|
8
|
+
import type { ReadinessCheckFn, ReadinessTrackerState } from "../readiness/index.js";
|
|
8
9
|
/**
|
|
9
10
|
* Zudojs runtime interface.
|
|
10
11
|
*
|
|
@@ -15,9 +16,30 @@ export interface Runtime {
|
|
|
15
16
|
readonly state: RuntimeState;
|
|
16
17
|
readonly status: RuntimeStatus;
|
|
17
18
|
readonly context: RuntimeContext;
|
|
19
|
+
readonly health: RuntimeHealth;
|
|
18
20
|
readonly ready: boolean;
|
|
19
21
|
start(): Promise<void>;
|
|
20
22
|
stop(): Promise<void>;
|
|
23
|
+
/**
|
|
24
|
+
* Registers a readiness check.
|
|
25
|
+
*
|
|
26
|
+
* A registered check starts out failing until it is first evaluated by
|
|
27
|
+
* `runReadinessChecks`, so registering one on a running runtime moves it
|
|
28
|
+
* to `degraded` until the check passes.
|
|
29
|
+
*/
|
|
30
|
+
registerReadinessCheck(name: string, check: ReadinessCheckFn): void;
|
|
31
|
+
/**
|
|
32
|
+
* Removes a readiness check. Returns whether one was registered.
|
|
33
|
+
*/
|
|
34
|
+
removeReadinessCheck(name: string): boolean;
|
|
35
|
+
/**
|
|
36
|
+
* Re-evaluates every registered readiness check.
|
|
37
|
+
*/
|
|
38
|
+
runReadinessChecks(): Promise<void>;
|
|
39
|
+
/**
|
|
40
|
+
* Current readiness state, including per-check results.
|
|
41
|
+
*/
|
|
42
|
+
readonly readiness: ReadinessTrackerState;
|
|
21
43
|
}
|
|
22
44
|
/**
|
|
23
45
|
* Dependencies required to create a runtime.
|
|
@@ -27,19 +49,28 @@ export interface RuntimeDependencies {
|
|
|
27
49
|
readonly logger: Logger;
|
|
28
50
|
readonly container: Container;
|
|
29
51
|
readonly eventBus: EventBus;
|
|
52
|
+
/**
|
|
53
|
+
* Configuration manager exposed to modules through their context.
|
|
54
|
+
* Defaults to an empty manager loaded at startup.
|
|
55
|
+
*/
|
|
56
|
+
readonly configuration?: ConfigurationManager;
|
|
57
|
+
/**
|
|
58
|
+
* Application context exposed to modules as `context.application`.
|
|
59
|
+
* Modules that read it without one supplied get a clear error.
|
|
60
|
+
*/
|
|
61
|
+
readonly application?: ModuleContext["application"];
|
|
30
62
|
}
|
|
31
63
|
/**
|
|
32
64
|
* Default runtime implementation.
|
|
33
65
|
*/
|
|
34
66
|
export declare class DefaultRuntime implements Runtime {
|
|
35
67
|
private _state;
|
|
36
|
-
private
|
|
37
|
-
private _context;
|
|
38
|
-
private _ready;
|
|
68
|
+
private readonly _contextBase;
|
|
39
69
|
private _startedAt?;
|
|
40
70
|
private _stoppedAt?;
|
|
41
71
|
private _failedAt?;
|
|
42
72
|
private _error?;
|
|
73
|
+
private _shutdownFailures;
|
|
43
74
|
private readonly options;
|
|
44
75
|
private readonly modules;
|
|
45
76
|
private readonly logger;
|
|
@@ -61,6 +92,27 @@ export declare class DefaultRuntime implements Runtime {
|
|
|
61
92
|
* Runtime context.
|
|
62
93
|
*/
|
|
63
94
|
get context(): RuntimeContext;
|
|
95
|
+
/**
|
|
96
|
+
* Current runtime health, derived from the lifecycle state and the
|
|
97
|
+
* registered readiness checks.
|
|
98
|
+
*/
|
|
99
|
+
get health(): RuntimeHealth;
|
|
100
|
+
/**
|
|
101
|
+
* Current readiness state, including per-check results.
|
|
102
|
+
*/
|
|
103
|
+
get readiness(): ReadinessTrackerState;
|
|
104
|
+
/**
|
|
105
|
+
* Registers a readiness check.
|
|
106
|
+
*/
|
|
107
|
+
registerReadinessCheck(name: string, check: ReadinessCheckFn): void;
|
|
108
|
+
/**
|
|
109
|
+
* Removes a readiness check.
|
|
110
|
+
*/
|
|
111
|
+
removeReadinessCheck(name: string): boolean;
|
|
112
|
+
/**
|
|
113
|
+
* Re-evaluates every registered readiness check.
|
|
114
|
+
*/
|
|
115
|
+
runReadinessChecks(): Promise<void>;
|
|
64
116
|
/**
|
|
65
117
|
* Whether the runtime is ready.
|
|
66
118
|
*/
|
|
@@ -72,6 +124,14 @@ export declare class DefaultRuntime implements Runtime {
|
|
|
72
124
|
/**
|
|
73
125
|
* Stops the runtime.
|
|
74
126
|
*/
|
|
127
|
+
/**
|
|
128
|
+
* Stops the runtime.
|
|
129
|
+
*
|
|
130
|
+
* A failed runtime is stoppable: startup rollback only reaches modules
|
|
131
|
+
* that were started, so this is the operator's route to releasing
|
|
132
|
+
* everything else. It is also idempotent — stopping an already-stopped
|
|
133
|
+
* runtime is a no-op rather than an error.
|
|
134
|
+
*/
|
|
75
135
|
stop(): Promise<void>;
|
|
76
136
|
/**
|
|
77
137
|
* Performs runtime startup.
|
|
@@ -81,10 +141,20 @@ export declare class DefaultRuntime implements Runtime {
|
|
|
81
141
|
* Performs runtime shutdown.
|
|
82
142
|
*/
|
|
83
143
|
private performStop;
|
|
144
|
+
/**
|
|
145
|
+
* Runs shutdown in response to a termination signal.
|
|
146
|
+
*/
|
|
147
|
+
private handleShutdownSignal;
|
|
84
148
|
/**
|
|
85
149
|
* Transitions to a new state.
|
|
86
150
|
*/
|
|
87
151
|
private transitionTo;
|
|
152
|
+
/**
|
|
153
|
+
* Emits `runtime.health.changed` when the derived health state has moved
|
|
154
|
+
* away from `previousHealth`. Health is derived rather than stored, so
|
|
155
|
+
* callers compare against a value captured before the change.
|
|
156
|
+
*/
|
|
157
|
+
private emitHealthChange;
|
|
88
158
|
/**
|
|
89
159
|
* Emits a runtime event.
|
|
90
160
|
*/
|