@zudojs/runtime 0.1.0 → 1.1.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.
Files changed (128) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +127 -6
  3. package/dist/dependencyGraph/dependencyGraph.core.d.ts +11 -5
  4. package/dist/dependencyGraph/dependencyGraph.core.js +13 -12
  5. package/dist/dependencyGraph/dependencyGraph.type.d.ts +0 -7
  6. package/dist/dependencyGraph/index.d.ts +2 -2
  7. package/dist/dependencyGraph/index.js +1 -1
  8. package/dist/health/health.core.d.ts +12 -0
  9. package/dist/health/health.core.js +55 -0
  10. package/dist/health/index.d.ts +5 -0
  11. package/dist/health/index.js +5 -0
  12. package/dist/index.d.ts +1 -1
  13. package/dist/index.js +4 -1
  14. package/dist/lifecycle/index.d.ts +1 -1
  15. package/dist/lifecycle/lifecycle.core.d.ts +41 -10
  16. package/dist/lifecycle/lifecycle.core.js +238 -61
  17. package/dist/lifecycle/lifecycle.type.d.ts +48 -1
  18. package/dist/readiness/index.d.ts +1 -1
  19. package/dist/readiness/readiness.core.d.ts +36 -4
  20. package/dist/readiness/readiness.core.js +122 -6
  21. package/dist/readiness/readiness.type.d.ts +15 -1
  22. package/dist/registry/registry.core.d.ts +14 -1
  23. package/dist/registry/registry.core.js +41 -2
  24. package/dist/runtime/runtime.core.d.ts +75 -5
  25. package/dist/runtime/runtime.core.js +210 -43
  26. package/dist/runtimeContext/index.d.ts +2 -2
  27. package/dist/runtimeContext/index.js +1 -1
  28. package/dist/runtimeContext/runtimeContext.core.d.ts +13 -4
  29. package/dist/runtimeContext/runtimeContext.core.js +22 -11
  30. package/dist/runtimeContext/runtimeContext.type.d.ts +12 -13
  31. package/dist/runtimeError/runtimeError.base.js +1 -1
  32. package/dist/runtimeEvents/index.d.ts +2 -2
  33. package/dist/runtimeEvents/index.js +1 -1
  34. package/dist/runtimeEvents/runtimeEvents.core.d.ts +15 -1
  35. package/dist/runtimeEvents/runtimeEvents.core.js +26 -0
  36. package/dist/runtimeEvents/runtimeEvents.type.d.ts +19 -4
  37. package/dist/runtimeOptions/runtimeOptions.core.d.ts +5 -0
  38. package/dist/runtimeOptions/runtimeOptions.core.js +14 -1
  39. package/dist/runtimeOptions/runtimeOptions.type.d.ts +29 -1
  40. package/dist/runtimeOptions/runtimeOptions.type.js +6 -0
  41. package/dist/runtimeState/index.d.ts +1 -1
  42. package/dist/runtimeState/runtimeState.core.d.ts +4 -0
  43. package/dist/runtimeState/runtimeState.core.js +17 -4
  44. package/dist/runtimeState/runtimeState.type.d.ts +14 -17
  45. package/dist/shutdown/shutdown.core.d.ts +20 -1
  46. package/dist/shutdown/shutdown.core.js +55 -29
  47. package/dist/signalHandler/signalHandler.core.d.ts +53 -13
  48. package/dist/signalHandler/signalHandler.core.js +97 -27
  49. package/dist/startup/startup.core.d.ts +3 -2
  50. package/dist/startup/startup.core.js +52 -46
  51. package/dist/testRuntime/index.d.ts +6 -1
  52. package/dist/testRuntime/index.js +5 -1
  53. package/dist/testRuntime/testRuntime.core.d.ts +21 -2
  54. package/dist/testRuntime/testRuntime.core.js +23 -6
  55. package/package.json +33 -22
  56. package/dist/.tsbuildinfo +0 -1
  57. package/dist/dependencyGraph/dependencyGraph.core.d.ts.map +0 -1
  58. package/dist/dependencyGraph/dependencyGraph.core.js.map +0 -1
  59. package/dist/dependencyGraph/dependencyGraph.type.d.ts.map +0 -1
  60. package/dist/dependencyGraph/dependencyGraph.type.js.map +0 -1
  61. package/dist/dependencyGraph/index.d.ts.map +0 -1
  62. package/dist/dependencyGraph/index.js.map +0 -1
  63. package/dist/index.d.ts.map +0 -1
  64. package/dist/index.js.map +0 -1
  65. package/dist/lifecycle/index.d.ts.map +0 -1
  66. package/dist/lifecycle/index.js.map +0 -1
  67. package/dist/lifecycle/lifecycle.core.d.ts.map +0 -1
  68. package/dist/lifecycle/lifecycle.core.js.map +0 -1
  69. package/dist/lifecycle/lifecycle.type.d.ts.map +0 -1
  70. package/dist/lifecycle/lifecycle.type.js.map +0 -1
  71. package/dist/readiness/index.d.ts.map +0 -1
  72. package/dist/readiness/index.js.map +0 -1
  73. package/dist/readiness/readiness.core.d.ts.map +0 -1
  74. package/dist/readiness/readiness.core.js.map +0 -1
  75. package/dist/readiness/readiness.type.d.ts.map +0 -1
  76. package/dist/readiness/readiness.type.js.map +0 -1
  77. package/dist/registry/index.d.ts.map +0 -1
  78. package/dist/registry/index.js.map +0 -1
  79. package/dist/registry/registry.core.d.ts.map +0 -1
  80. package/dist/registry/registry.core.js.map +0 -1
  81. package/dist/runtime/runtime.core.d.ts.map +0 -1
  82. package/dist/runtime/runtime.core.js.map +0 -1
  83. package/dist/runtimeContext/index.d.ts.map +0 -1
  84. package/dist/runtimeContext/index.js.map +0 -1
  85. package/dist/runtimeContext/runtimeContext.core.d.ts.map +0 -1
  86. package/dist/runtimeContext/runtimeContext.core.js.map +0 -1
  87. package/dist/runtimeContext/runtimeContext.factory.d.ts.map +0 -1
  88. package/dist/runtimeContext/runtimeContext.factory.js.map +0 -1
  89. package/dist/runtimeContext/runtimeContext.type.d.ts.map +0 -1
  90. package/dist/runtimeContext/runtimeContext.type.js.map +0 -1
  91. package/dist/runtimeError/index.d.ts.map +0 -1
  92. package/dist/runtimeError/index.js.map +0 -1
  93. package/dist/runtimeError/runtimeError.base.d.ts.map +0 -1
  94. package/dist/runtimeError/runtimeError.base.js.map +0 -1
  95. package/dist/runtimeEvents/index.d.ts.map +0 -1
  96. package/dist/runtimeEvents/index.js.map +0 -1
  97. package/dist/runtimeEvents/runtimeEvents.core.d.ts.map +0 -1
  98. package/dist/runtimeEvents/runtimeEvents.core.js.map +0 -1
  99. package/dist/runtimeEvents/runtimeEvents.type.d.ts.map +0 -1
  100. package/dist/runtimeEvents/runtimeEvents.type.js.map +0 -1
  101. package/dist/runtimeOptions/index.d.ts.map +0 -1
  102. package/dist/runtimeOptions/index.js.map +0 -1
  103. package/dist/runtimeOptions/runtimeOptions.core.d.ts.map +0 -1
  104. package/dist/runtimeOptions/runtimeOptions.core.js.map +0 -1
  105. package/dist/runtimeOptions/runtimeOptions.type.d.ts.map +0 -1
  106. package/dist/runtimeOptions/runtimeOptions.type.js.map +0 -1
  107. package/dist/runtimeState/index.d.ts.map +0 -1
  108. package/dist/runtimeState/index.js.map +0 -1
  109. package/dist/runtimeState/runtimeState.core.d.ts.map +0 -1
  110. package/dist/runtimeState/runtimeState.core.js.map +0 -1
  111. package/dist/runtimeState/runtimeState.type.d.ts.map +0 -1
  112. package/dist/runtimeState/runtimeState.type.js.map +0 -1
  113. package/dist/shutdown/index.d.ts.map +0 -1
  114. package/dist/shutdown/index.js.map +0 -1
  115. package/dist/shutdown/shutdown.core.d.ts.map +0 -1
  116. package/dist/shutdown/shutdown.core.js.map +0 -1
  117. package/dist/signalHandler/index.d.ts.map +0 -1
  118. package/dist/signalHandler/index.js.map +0 -1
  119. package/dist/signalHandler/signalHandler.core.d.ts.map +0 -1
  120. package/dist/signalHandler/signalHandler.core.js.map +0 -1
  121. package/dist/startup/index.d.ts.map +0 -1
  122. package/dist/startup/index.js.map +0 -1
  123. package/dist/startup/startup.core.d.ts.map +0 -1
  124. package/dist/startup/startup.core.js.map +0 -1
  125. package/dist/testRuntime/index.d.ts.map +0 -1
  126. package/dist/testRuntime/index.js.map +0 -1
  127. package/dist/testRuntime/testRuntime.core.d.ts.map +0 -1
  128. 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,140 @@ 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
- * Updates a readiness check result.
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
+ return false;
58
+ }
59
+ if (this.autoMarkReady &&
60
+ this.checks.size === 0 &&
61
+ this.state === "degraded") {
62
+ // `degraded` is only ever entered from `ready` because a check
63
+ // failed. Removing the last check leaves nothing failing, so the
64
+ // tracker returns to ready — otherwise `evaluateReadiness()` (which
65
+ // only acts when checks exist) left it stuck at `ready: false` while
66
+ // the derived health, seeing no checks, reported `healthy`.
67
+ this.markReady("All readiness checks removed.");
68
+ }
69
+ else {
70
+ this.evaluateReadiness();
71
+ }
72
+ return true;
73
+ }
74
+ /**
75
+ * Evaluates a readiness check and records its result.
76
+ *
77
+ * Re-runs the function registered under `name` unless a replacement is
78
+ * supplied, in which case the replacement is stored and used from then on.
31
79
  */
32
80
  async updateCheck(name, check) {
33
- const startTime = Date.now();
81
+ if (check !== undefined) {
82
+ this.checkFns.set(name, check);
83
+ }
84
+ const fn = this.checkFns.get(name);
85
+ if (fn === undefined) {
86
+ throw new RuntimeStateError(`Readiness check "${name}" is not registered.`);
87
+ }
88
+ await this.evaluateCheck(name, fn);
89
+ this.evaluateReadiness();
90
+ }
91
+ /**
92
+ * Re-evaluates every registered check.
93
+ */
94
+ async runChecks() {
95
+ // Overlapping runs would interleave their writes into `checks`;
96
+ // callers that arrive mid-run join the run already in flight.
97
+ if (this.running) {
98
+ return this.running;
99
+ }
100
+ this.running = (async () => {
101
+ try {
102
+ await Promise.all([...this.checkFns].map(([name, fn]) => this.evaluateCheck(name, fn)));
103
+ this.evaluateReadiness();
104
+ }
105
+ finally {
106
+ this.running = undefined;
107
+ }
108
+ })();
109
+ return this.running;
110
+ }
111
+ /**
112
+ * Whether any readiness check is registered.
113
+ */
114
+ hasChecks() {
115
+ return this.checkFns.size > 0;
116
+ }
117
+ /**
118
+ * Runs a single check and records its result and duration.
119
+ */
120
+ async evaluateCheck(name, fn) {
121
+ const startedAt = Date.now();
34
122
  try {
35
- const result = await check();
123
+ const result = await this.withCheckTimeout(name, fn);
36
124
  this.checks.set(name, {
37
125
  name,
38
126
  ready: result,
39
127
  lastCheckedAt: new Date(),
128
+ durationMs: Date.now() - startedAt,
40
129
  });
41
130
  }
42
- catch {
131
+ catch (error) {
43
132
  this.checks.set(name, {
44
133
  name,
45
134
  ready: false,
46
135
  lastCheckedAt: new Date(),
47
- message: "Check threw an error",
136
+ durationMs: Date.now() - startedAt,
137
+ message: error instanceof Error
138
+ ? `Check threw an error: ${error.message}`
139
+ : "Check threw an error",
48
140
  });
49
141
  }
50
- this.evaluateReadiness();
142
+ }
143
+ /**
144
+ * Runs a check under a timeout, clearing the timer either way.
145
+ */
146
+ async withCheckTimeout(name, fn) {
147
+ if (this.checkTimeout <= 0) {
148
+ return fn();
149
+ }
150
+ let timer;
151
+ try {
152
+ return await Promise.race([
153
+ Promise.resolve(fn()),
154
+ new Promise((_, reject) => {
155
+ timer = setTimeout(() => {
156
+ reject(new Error(`Readiness check "${name}" did not settle within ${this.checkTimeout}ms.`));
157
+ }, this.checkTimeout);
158
+ timer.unref?.();
159
+ }),
160
+ ]);
161
+ }
162
+ finally {
163
+ if (timer !== undefined) {
164
+ clearTimeout(timer);
165
+ }
166
+ }
51
167
  }
52
168
  /**
53
169
  * 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: () => boolean | Promise<boolean>;
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): void;
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
- await runtime.start();
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
- const result = {};
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 _status;
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
  */