@amalgm/shell 0.1.163 → 0.1.164-main.34182745507
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/PURPOSE.md +68 -6
- package/README.md +58 -11
- package/config/releases/trust/runtime/main.root.json +84 -0
- package/config/releases/trust/runtime/preview.root.json +84 -0
- package/dist/boot.js +28 -20
- package/dist/boot.js.map +1 -1
- package/dist/cli.js +7 -1
- package/dist/cli.js.map +1 -1
- package/dist/content-cache-index.js +2 -2
- package/dist/content-cache-index.js.map +1 -1
- package/dist/detection/runtime.js +2 -2
- package/dist/detection/runtime.js.map +1 -1
- package/dist/entity-apply-host.js +2 -2
- package/dist/entity-apply-host.js.map +1 -1
- package/dist/entity-apply-store.d.ts +2 -1
- package/dist/entity-apply-store.js +52 -37
- package/dist/entity-apply-store.js.map +1 -1
- package/dist/installation/lease.js +2 -2
- package/dist/installation/lease.js.map +1 -1
- package/dist/installation/ownership.js +2 -2
- package/dist/installation/ownership.js.map +1 -1
- package/dist/machine-host.d.ts +1 -0
- package/dist/machine-host.js +56 -31
- package/dist/machine-host.js.map +1 -1
- package/dist/process-lifecycle.d.ts +1 -3
- package/dist/process-lifecycle.js +10 -0
- package/dist/process-lifecycle.js.map +1 -1
- package/dist/pty-host.d.ts +1 -1
- package/dist/pty-host.js +70 -21
- package/dist/pty-host.js.map +1 -1
- package/dist/service/cli.js +50 -9
- package/dist/service/cli.js.map +1 -1
- package/dist/service/control.d.ts +10 -1
- package/dist/service/control.js +1 -1
- package/dist/service/control.js.map +1 -1
- package/dist/service/keepalive.d.ts +10 -3
- package/dist/service/keepalive.js +267 -29
- package/dist/service/keepalive.js.map +1 -1
- package/dist/service/recovery.d.ts +27 -0
- package/dist/service/recovery.js +58 -0
- package/dist/service/recovery.js.map +1 -0
- package/dist/service/systemd-unit.d.ts +7 -0
- package/dist/service/systemd-unit.js +43 -0
- package/dist/service/systemd-unit.js.map +1 -0
- package/dist/service/systemd.d.ts +1 -5
- package/dist/service/systemd.js +9 -31
- package/dist/service/systemd.js.map +1 -1
- package/dist/service/windows-action.d.ts +9 -0
- package/dist/service/windows-action.js +55 -0
- package/dist/service/windows-action.js.map +1 -0
- package/dist/service/windows-task.d.ts +1 -8
- package/dist/service/windows-task.js +4 -40
- package/dist/service/windows-task.js.map +1 -1
- package/dist/service/windows.js +3 -3
- package/dist/service/windows.js.map +1 -1
- package/dist/sqlite.d.ts +4 -0
- package/dist/sqlite.js +16 -0
- package/dist/sqlite.js.map +1 -0
- package/dist/updates/artifacts.d.ts +40 -0
- package/dist/updates/artifacts.js +299 -0
- package/dist/updates/artifacts.js.map +1 -0
- package/dist/updates/bootstrap.d.ts +48 -0
- package/dist/updates/bootstrap.js +384 -0
- package/dist/updates/bootstrap.js.map +1 -0
- package/dist/updates/controller.d.ts +66 -0
- package/dist/updates/controller.js +322 -0
- package/dist/updates/controller.js.map +1 -0
- package/dist/updates/isolated-command-lifetime.d.ts +1 -0
- package/dist/updates/isolated-command-lifetime.js +63 -0
- package/dist/updates/isolated-command-lifetime.js.map +1 -0
- package/dist/updates/store.d.ts +41 -0
- package/dist/updates/store.js +80 -0
- package/dist/updates/store.js.map +1 -0
- package/dist/updates/trust.d.ts +20 -0
- package/dist/updates/trust.js +138 -0
- package/dist/updates/trust.js.map +1 -0
- package/dist/user-ground-host.d.ts +1 -1
- package/dist/user-ground-host.js +3 -3
- package/dist/user-ground-host.js.map +1 -1
- package/dist/watching/host.js +4 -2
- package/dist/watching/host.js.map +1 -1
- package/dist/workspace-add-staging.js +2 -2
- package/dist/workspace-add-staging.js.map +1 -1
- package/examinations/fixtures/machine-control-plane.js +57 -0
- package/examinations/fixtures/private-wire-authority.js +1065 -0
- package/examinations/native-service.mjs +92 -0
- package/examinations/network-view.mjs +202 -0
- package/examinations/runtime-upgrade.native-test.mjs +198 -0
- package/npm-shrinkwrap.json +2104 -191
- package/package.json +94 -13
|
@@ -3,17 +3,19 @@ import { randomBytes, randomUUID, timingSafeEqual } from 'node:crypto';
|
|
|
3
3
|
import { closeSync, fstatSync, openSync, renameSync, rmSync, writeSync } from 'node:fs';
|
|
4
4
|
import { createServer } from 'node:http';
|
|
5
5
|
import { join } from 'node:path';
|
|
6
|
-
import {
|
|
6
|
+
import { CHILD_HEALTH_POLICY, CHILD_RESTART_POLICY, readyDeadlineMs } from '@amalgm/core/supervision';
|
|
7
7
|
import { runtimeBindingsMatch } from '@amalgm/core/binding';
|
|
8
8
|
import { atomicJson, ensurePrivateDir } from '../filesystem.js';
|
|
9
9
|
import { acquireProcessLease } from '../installation/lease.js';
|
|
10
|
-
import { readRegistration } from './registration.js';
|
|
10
|
+
import { currentLauncher, readRegistration } from './registration.js';
|
|
11
11
|
import { controllerLeaseFile, controllerStateFile } from './control.js';
|
|
12
|
+
import { RuntimeRecovery } from './recovery.js';
|
|
13
|
+
import { RuntimeUpdates } from '../updates/controller.js';
|
|
12
14
|
export const STOP_GRACE_MS = 25_000;
|
|
13
15
|
export const LOG_LIMIT_BYTES = 8 * 1024 * 1024;
|
|
14
|
-
/** One leased controller supervises one runtime over IPC.
|
|
15
|
-
*
|
|
16
|
-
export async function runKeepalive(identity) {
|
|
16
|
+
/** One leased controller supervises one runtime over IPC. The optional policy
|
|
17
|
+
* lets process examinations use short clocks; the CLI always uses Core defaults. */
|
|
18
|
+
export async function runKeepalive(identity, policy = {}) {
|
|
17
19
|
const registration = readRegistration(identity);
|
|
18
20
|
if (!registration)
|
|
19
21
|
throw new Error('This environment has no runtime service registration.');
|
|
@@ -21,37 +23,78 @@ export async function runKeepalive(identity) {
|
|
|
21
23
|
const lease = acquireProcessLease(controllerLeaseFile(identity));
|
|
22
24
|
if (!lease)
|
|
23
25
|
return 0; // A concurrent start binds to the existing owner.
|
|
24
|
-
|
|
26
|
+
try {
|
|
27
|
+
return await runOwnedController(identity, registration, policy);
|
|
28
|
+
}
|
|
29
|
+
finally {
|
|
30
|
+
lease.close();
|
|
31
|
+
}
|
|
32
|
+
}
|
|
33
|
+
async function runOwnedController(identity, registration, policy) {
|
|
34
|
+
const restartPolicy = policy.restart ?? CHILD_RESTART_POLICY;
|
|
35
|
+
const healthPolicy = policy.health ?? CHILD_HEALTH_POLICY;
|
|
36
|
+
const recovery = new RuntimeRecovery(identity, restartPolicy);
|
|
37
|
+
let log;
|
|
38
|
+
try {
|
|
39
|
+
log = openRotatingLog(join(identity.serviceDir, 'service.log'), LOG_LIMIT_BYTES);
|
|
40
|
+
}
|
|
41
|
+
catch (error) {
|
|
42
|
+
recovery.close();
|
|
43
|
+
throw error;
|
|
44
|
+
}
|
|
25
45
|
let child = null;
|
|
26
46
|
let stopping = false;
|
|
27
47
|
let wake = null;
|
|
28
48
|
let killTimer;
|
|
49
|
+
let closeMonitor = () => { };
|
|
50
|
+
let updates = null;
|
|
51
|
+
let runtimePaused = false;
|
|
52
|
+
let runtimeReady = false;
|
|
53
|
+
let starts = 0;
|
|
54
|
+
let replacing = false;
|
|
29
55
|
let state = {
|
|
30
56
|
binding: identity.binding, user: identity.user, instanceId: randomUUID(), pid: process.pid,
|
|
57
|
+
bootstrapPid: process.connected ? process.ppid : null,
|
|
31
58
|
port: 0, token: randomBytes(32).toString('base64url'), childPid: null, restarts: 0,
|
|
59
|
+
phase: 'starting', recovery: recovery.state,
|
|
32
60
|
};
|
|
33
61
|
const publish = (patch) => {
|
|
34
|
-
state = { ...state, ...patch };
|
|
62
|
+
state = { ...state, ...patch, recovery: recovery.state, update: updates?.status ?? null };
|
|
35
63
|
atomicJson(controllerStateFile(identity), state);
|
|
36
64
|
};
|
|
37
|
-
const
|
|
38
|
-
if (stopping)
|
|
39
|
-
return;
|
|
40
|
-
stopping = true;
|
|
65
|
+
const drainChild = () => {
|
|
41
66
|
if (child && child.exitCode === null && child.signalCode === null) {
|
|
42
67
|
const owned = child;
|
|
43
68
|
if (owned.connected)
|
|
44
69
|
owned.send({ type: 'amalgm-shutdown' }, () => { });
|
|
45
70
|
else
|
|
46
71
|
owned.kill('SIGTERM');
|
|
72
|
+
if (killTimer)
|
|
73
|
+
return;
|
|
47
74
|
killTimer = setTimeout(() => {
|
|
48
75
|
if (owned.exitCode === null && owned.signalCode === null)
|
|
49
76
|
owned.kill('SIGKILL');
|
|
50
|
-
}, STOP_GRACE_MS);
|
|
77
|
+
}, policy.stopGraceMs ?? STOP_GRACE_MS);
|
|
51
78
|
killTimer.unref();
|
|
52
79
|
}
|
|
80
|
+
};
|
|
81
|
+
const stop = () => {
|
|
82
|
+
if (stopping)
|
|
83
|
+
return;
|
|
84
|
+
stopping = true;
|
|
85
|
+
drainChild();
|
|
53
86
|
wake?.();
|
|
54
87
|
};
|
|
88
|
+
const parentMessage = (value) => {
|
|
89
|
+
if (!value || typeof value !== 'object')
|
|
90
|
+
return;
|
|
91
|
+
const message = value;
|
|
92
|
+
if (message.type === 'amalgm-shutdown')
|
|
93
|
+
stop();
|
|
94
|
+
else if (message.type === 'amalgm-health' && typeof message.nonce === 'string' && !stopping) {
|
|
95
|
+
process.send?.({ type: 'amalgm-health', nonce: message.nonce }, () => { });
|
|
96
|
+
}
|
|
97
|
+
};
|
|
55
98
|
const server = createServer((request, response) => {
|
|
56
99
|
const actual = Buffer.from(request.headers.authorization || '');
|
|
57
100
|
const expected = Buffer.from(`Bearer ${state.token}`);
|
|
@@ -60,7 +103,7 @@ export async function runKeepalive(identity) {
|
|
|
60
103
|
return;
|
|
61
104
|
}
|
|
62
105
|
if (request.method === 'GET' && request.url === '/status'
|
|
63
|
-
|| request.method === 'POST' && request.url === '/stop') {
|
|
106
|
+
|| request.method === 'POST' && (request.url === '/stop' || request.url === '/retry')) {
|
|
64
107
|
// A valid token proves access to this endpoint, not that the caller
|
|
65
108
|
// selected this owner. Mutation admission must prove both before effects.
|
|
66
109
|
if (request.method === 'POST') {
|
|
@@ -78,6 +121,11 @@ export async function runKeepalive(identity) {
|
|
|
78
121
|
return;
|
|
79
122
|
}
|
|
80
123
|
}
|
|
124
|
+
if (request.url === '/retry' && !stopping && recovery.state.parked) {
|
|
125
|
+
recovery.retry();
|
|
126
|
+
publish({ phase: 'starting' });
|
|
127
|
+
wake?.();
|
|
128
|
+
}
|
|
81
129
|
response.writeHead(200, { 'content-type': 'application/json', 'cache-control': 'no-store' });
|
|
82
130
|
response.end(JSON.stringify({ ...state, token: '' }));
|
|
83
131
|
if (request.url === '/stop')
|
|
@@ -88,7 +136,12 @@ export async function runKeepalive(identity) {
|
|
|
88
136
|
});
|
|
89
137
|
process.once('SIGTERM', stop);
|
|
90
138
|
process.once('SIGINT', stop);
|
|
91
|
-
|
|
139
|
+
process.once('disconnect', stop);
|
|
140
|
+
process.on('message', parentMessage);
|
|
141
|
+
const wait = (milliseconds) => new Promise((resolve) => {
|
|
142
|
+
const timer = milliseconds === undefined ? undefined : setTimeout(resolve, milliseconds);
|
|
143
|
+
wake = () => { clearTimeout(timer); resolve(); };
|
|
144
|
+
}).finally(() => { wake = null; });
|
|
92
145
|
try {
|
|
93
146
|
await new Promise((resolve, reject) => {
|
|
94
147
|
server.once('error', reject);
|
|
@@ -98,8 +151,72 @@ export async function runKeepalive(identity) {
|
|
|
98
151
|
if (!address || typeof address === 'string')
|
|
99
152
|
throw new Error('The controller did not receive a local address.');
|
|
100
153
|
publish({ port: address.port });
|
|
154
|
+
if (RuntimeUpdates.enabled(identity)) {
|
|
155
|
+
updates = new RuntimeUpdates(identity, {
|
|
156
|
+
packageRoot: currentLauncher().packageRoot,
|
|
157
|
+
pause: async () => {
|
|
158
|
+
runtimePaused = true;
|
|
159
|
+
if (child) {
|
|
160
|
+
const draining = childExit(child);
|
|
161
|
+
drainChild();
|
|
162
|
+
await draining;
|
|
163
|
+
}
|
|
164
|
+
runtimeReady = false;
|
|
165
|
+
},
|
|
166
|
+
start: async () => {
|
|
167
|
+
const before = starts;
|
|
168
|
+
runtimePaused = false;
|
|
169
|
+
if (recovery.state.parked)
|
|
170
|
+
recovery.retry(); // Core already authorized this distinct update generation.
|
|
171
|
+
wake?.();
|
|
172
|
+
const deadline = Date.now() + recovery.delayMs + readyDeadlineMs(healthPolicy);
|
|
173
|
+
while (!runtimeReady) {
|
|
174
|
+
if (stopping || Date.now() >= deadline || starts > before && child === null)
|
|
175
|
+
throw new Error('The authorized runtime generation did not become ready');
|
|
176
|
+
await new Promise(resolve => setTimeout(resolve, 50));
|
|
177
|
+
}
|
|
178
|
+
},
|
|
179
|
+
probe: async () => {
|
|
180
|
+
if (!child || !runtimeReady)
|
|
181
|
+
throw new Error('The authorized runtime generation is not running');
|
|
182
|
+
await probeRuntime(child, healthPolicy.timeoutMs);
|
|
183
|
+
},
|
|
184
|
+
replace: () => { replacing = true; stop(); },
|
|
185
|
+
changed: () => { publish({}); wake?.(); },
|
|
186
|
+
log: reason => log.write(`${JSON.stringify({ event: 'runtime-update', reason })}\n`),
|
|
187
|
+
});
|
|
188
|
+
runtimePaused = !updates.permitsOrdinaryRuntime;
|
|
189
|
+
updates.start();
|
|
190
|
+
}
|
|
191
|
+
process.send?.({ type: 'amalgm-ready' }, () => { });
|
|
101
192
|
while (!stopping) {
|
|
102
|
-
|
|
193
|
+
if (runtimePaused) {
|
|
194
|
+
publish({ phase: 'parked' });
|
|
195
|
+
await wait();
|
|
196
|
+
continue;
|
|
197
|
+
}
|
|
198
|
+
if (recovery.state.parked) {
|
|
199
|
+
publish({ phase: 'parked' });
|
|
200
|
+
await wait();
|
|
201
|
+
continue;
|
|
202
|
+
}
|
|
203
|
+
const delayMs = recovery.delayMs;
|
|
204
|
+
if (delayMs > 0) {
|
|
205
|
+
publish({ phase: 'backoff' });
|
|
206
|
+
const retryAt = Date.now() + delayMs;
|
|
207
|
+
while (!stopping && !runtimePaused && Date.now() < retryAt)
|
|
208
|
+
await wait(retryAt - Date.now());
|
|
209
|
+
if (stopping)
|
|
210
|
+
break;
|
|
211
|
+
if (runtimePaused || recovery.state.parked)
|
|
212
|
+
continue;
|
|
213
|
+
}
|
|
214
|
+
const generation = randomUUID();
|
|
215
|
+
recovery.begin(generation);
|
|
216
|
+
starts++;
|
|
217
|
+
publish({ phase: 'starting' });
|
|
218
|
+
const launcher = updates ? currentLauncher() : registration;
|
|
219
|
+
child = spawn(launcher.node, [launcher.bin, ...registration.run_args], {
|
|
103
220
|
cwd: identity.home, env: process.env,
|
|
104
221
|
stdio: ['ignore', 'pipe', 'pipe', 'ipc'], windowsHide: true,
|
|
105
222
|
});
|
|
@@ -107,52 +224,173 @@ export async function runKeepalive(identity) {
|
|
|
107
224
|
child.stdout?.on('data', (chunk) => log.write(chunk));
|
|
108
225
|
child.stderr?.on('data', (chunk) => log.write(chunk));
|
|
109
226
|
publish({ childPid: child.pid ?? null });
|
|
227
|
+
let failure = null;
|
|
228
|
+
const monitored = monitorRuntime(child, healthPolicy, restartPolicy.stableAfterMs, {
|
|
229
|
+
ready: () => { if (!stopping) {
|
|
230
|
+
runtimeReady = true;
|
|
231
|
+
publish({ phase: 'running' });
|
|
232
|
+
} },
|
|
233
|
+
healthy: () => { if (!stopping) {
|
|
234
|
+
recovery.healthy(generation);
|
|
235
|
+
publish({});
|
|
236
|
+
} },
|
|
237
|
+
failed: (reason) => { if (!stopping) {
|
|
238
|
+
failure = reason;
|
|
239
|
+
drainChild();
|
|
240
|
+
} },
|
|
241
|
+
});
|
|
242
|
+
closeMonitor = monitored.close;
|
|
110
243
|
const outcome = await exiting;
|
|
244
|
+
closeMonitor();
|
|
111
245
|
child = null;
|
|
246
|
+
runtimeReady = false;
|
|
247
|
+
if (updates && !updates.permitsOrdinaryRuntime)
|
|
248
|
+
runtimePaused = true;
|
|
112
249
|
if (killTimer)
|
|
113
250
|
clearTimeout(killTimer);
|
|
114
|
-
|
|
251
|
+
killTimer = undefined;
|
|
252
|
+
recovery.exited(generation, stopping ? null : failure ?? outcome.error ?? `Runtime exited (${outcome.signal ?? outcome.code})`);
|
|
253
|
+
publish({ childPid: null, phase: stopping ? 'stopping' : recovery.state.parked ? 'parked' : 'backoff' });
|
|
115
254
|
if (stopping)
|
|
116
255
|
break;
|
|
117
|
-
const now = Date.now();
|
|
118
|
-
crashes = [...recentCrashes(crashes, now), now];
|
|
119
|
-
const delayMs = restartDelayMs(crashes.length);
|
|
120
256
|
publish({ restarts: state.restarts + 1 });
|
|
121
|
-
log.write(`${JSON.stringify({ event: 'runtime-exited', ...outcome,
|
|
122
|
-
await new Promise((resolve) => {
|
|
123
|
-
const timer = setTimeout(resolve, delayMs);
|
|
124
|
-
wake = () => { clearTimeout(timer); resolve(); };
|
|
125
|
-
});
|
|
126
|
-
wake = null;
|
|
257
|
+
log.write(`${JSON.stringify({ event: 'runtime-exited', ...outcome, recovery: recovery.state })}\n`);
|
|
127
258
|
}
|
|
128
259
|
return 0;
|
|
129
260
|
}
|
|
130
261
|
finally {
|
|
262
|
+
const requestedStop = stopping;
|
|
263
|
+
closeMonitor();
|
|
131
264
|
stop();
|
|
132
265
|
if (child && child.exitCode === null && child.signalCode === null)
|
|
133
266
|
await childExit(child);
|
|
267
|
+
await updates?.close();
|
|
134
268
|
if (killTimer)
|
|
135
269
|
clearTimeout(killTimer);
|
|
136
270
|
process.off('SIGTERM', stop);
|
|
137
271
|
process.off('SIGINT', stop);
|
|
272
|
+
process.off('disconnect', stop);
|
|
273
|
+
process.off('message', parentMessage);
|
|
138
274
|
server.closeAllConnections();
|
|
139
275
|
await new Promise((resolve) => { if (server.listening)
|
|
140
276
|
server.close(() => resolve());
|
|
141
277
|
else
|
|
142
278
|
resolve(); });
|
|
143
279
|
rmSync(controllerStateFile(identity), { force: true });
|
|
144
|
-
|
|
145
|
-
|
|
280
|
+
try {
|
|
281
|
+
log.close();
|
|
282
|
+
}
|
|
283
|
+
finally {
|
|
284
|
+
recovery.close();
|
|
285
|
+
}
|
|
286
|
+
if (requestedStop && process.connected)
|
|
287
|
+
process.send?.({ type: replacing ? 'amalgm-controller-replace' : 'amalgm-controller-stop' }, () => { });
|
|
146
288
|
}
|
|
147
289
|
}
|
|
290
|
+
/** A fresh generation-owned challenge supplies probation evidence; an old
|
|
291
|
+
* cached status or controller heartbeat cannot prove runtime health. */
|
|
292
|
+
function probeRuntime(child, timeoutMs) {
|
|
293
|
+
return new Promise((resolve, reject) => {
|
|
294
|
+
const nonce = randomUUID();
|
|
295
|
+
const close = () => { clearTimeout(timer); child.off('message', message); child.off('exit', exited); };
|
|
296
|
+
const exited = () => { close(); reject(new Error('Runtime exited during its health examination')); };
|
|
297
|
+
const message = (value) => {
|
|
298
|
+
const reply = value;
|
|
299
|
+
if (reply?.type === 'amalgm-health' && reply.nonce === nonce) {
|
|
300
|
+
close();
|
|
301
|
+
resolve();
|
|
302
|
+
}
|
|
303
|
+
};
|
|
304
|
+
const timer = setTimeout(() => { close(); reject(new Error('Runtime probation health timed out')); }, timeoutMs);
|
|
305
|
+
child.on('message', message);
|
|
306
|
+
child.once('exit', exited);
|
|
307
|
+
if (child.connected)
|
|
308
|
+
child.send({ type: 'amalgm-health', nonce }, () => { });
|
|
309
|
+
else
|
|
310
|
+
exited();
|
|
311
|
+
});
|
|
312
|
+
}
|
|
148
313
|
function childExit(child) {
|
|
149
314
|
if (child.exitCode !== null || child.signalCode !== null)
|
|
150
315
|
return Promise.resolve({ code: child.exitCode, signal: child.signalCode });
|
|
151
316
|
return new Promise((resolve) => {
|
|
152
|
-
|
|
153
|
-
|
|
317
|
+
// Only a failed spawn has no process to drain. A later IPC/kill error is
|
|
318
|
+
// not evidence of exit and cannot authorize a replacement beside the child.
|
|
319
|
+
const error = (cause) => {
|
|
320
|
+
if (child.pid === undefined) {
|
|
321
|
+
child.off('exit', exited);
|
|
322
|
+
child.off('error', error);
|
|
323
|
+
resolve({ code: 1, signal: null, error: cause.message });
|
|
324
|
+
}
|
|
325
|
+
};
|
|
326
|
+
const exited = (code, signal) => { child.off('error', error); resolve({ code, signal }); };
|
|
327
|
+
child.on('error', error);
|
|
328
|
+
child.once('exit', exited);
|
|
154
329
|
});
|
|
155
330
|
}
|
|
331
|
+
/** Probe only the owned IPC channel, with one outstanding request. Ready plus
|
|
332
|
+
* sustained responses earns a fresh allowance; uptime alone never does. */
|
|
333
|
+
function monitorRuntime(child, health, stableAfterMs, effects) {
|
|
334
|
+
let ready = false;
|
|
335
|
+
let closed = false;
|
|
336
|
+
let stable = false;
|
|
337
|
+
let healthySince = null;
|
|
338
|
+
let failures = 0;
|
|
339
|
+
let nonce = null;
|
|
340
|
+
let probeTimer;
|
|
341
|
+
let timeout;
|
|
342
|
+
const startup = setTimeout(() => fail('Runtime did not become ready before its startup deadline'), readyDeadlineMs(health));
|
|
343
|
+
const close = () => {
|
|
344
|
+
closed = true;
|
|
345
|
+
clearTimeout(startup);
|
|
346
|
+
clearTimeout(probeTimer);
|
|
347
|
+
clearTimeout(timeout);
|
|
348
|
+
child.off('message', message);
|
|
349
|
+
};
|
|
350
|
+
const fail = (reason) => { if (!closed) {
|
|
351
|
+
close();
|
|
352
|
+
effects.failed(reason);
|
|
353
|
+
} };
|
|
354
|
+
const probe = () => {
|
|
355
|
+
if (closed)
|
|
356
|
+
return;
|
|
357
|
+
nonce = randomUUID();
|
|
358
|
+
timeout = setTimeout(() => {
|
|
359
|
+
nonce = null;
|
|
360
|
+
healthySince = null;
|
|
361
|
+
if (++failures >= health.maxFailures)
|
|
362
|
+
fail('Runtime IPC health checks stopped responding');
|
|
363
|
+
else
|
|
364
|
+
probeTimer = setTimeout(probe, health.intervalMs);
|
|
365
|
+
}, health.timeoutMs);
|
|
366
|
+
if (child.connected)
|
|
367
|
+
child.send({ type: 'amalgm-health', nonce }, () => { });
|
|
368
|
+
};
|
|
369
|
+
const message = (value) => {
|
|
370
|
+
if (closed || !value || typeof value !== 'object')
|
|
371
|
+
return;
|
|
372
|
+
const reply = value;
|
|
373
|
+
if (reply.type === 'amalgm-ready' && !ready) {
|
|
374
|
+
ready = true;
|
|
375
|
+
clearTimeout(startup);
|
|
376
|
+
effects.ready();
|
|
377
|
+
probe();
|
|
378
|
+
}
|
|
379
|
+
else if (reply.type === 'amalgm-health' && nonce && reply.nonce === nonce) {
|
|
380
|
+
clearTimeout(timeout);
|
|
381
|
+
nonce = null;
|
|
382
|
+
failures = 0;
|
|
383
|
+
healthySince ??= performance.now();
|
|
384
|
+
if (!stable && performance.now() - healthySince >= stableAfterMs) {
|
|
385
|
+
stable = true;
|
|
386
|
+
effects.healthy();
|
|
387
|
+
}
|
|
388
|
+
probeTimer = setTimeout(probe, health.intervalMs);
|
|
389
|
+
}
|
|
390
|
+
};
|
|
391
|
+
child.on('message', message);
|
|
392
|
+
return { close };
|
|
393
|
+
}
|
|
156
394
|
/** Two bounded log files; even a single oversized write obeys the limit. */
|
|
157
395
|
export function openRotatingLog(file, limitBytes) {
|
|
158
396
|
let fd = openSync(file, 'a');
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"keepalive.js","sourceRoot":"","sources":["../../src/service/keepalive.ts"],"names":[],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"keepalive.js","sourceRoot":"","sources":["../../src/service/keepalive.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
import { type ChildRestartPolicy } from '@amalgm/core/supervision';
|
|
2
|
+
import type { ServiceIdentity } from './registration.js';
|
|
3
|
+
export interface RecoveryState {
|
|
4
|
+
readonly attempts: number;
|
|
5
|
+
readonly maxAttempts: number;
|
|
6
|
+
readonly generation: string | null;
|
|
7
|
+
readonly lastFailure: string | null;
|
|
8
|
+
readonly lastHealthyGeneration: string | null;
|
|
9
|
+
readonly lastHealthyAt: string | null;
|
|
10
|
+
readonly parked: boolean;
|
|
11
|
+
}
|
|
12
|
+
/** Only the controller holding the installation lease opens this journal.
|
|
13
|
+
* Charge Core's allowance before the host effect: even death during spawn
|
|
14
|
+
* cannot turn controller replacement into a fresh recovery budget. */
|
|
15
|
+
export declare class RuntimeRecovery {
|
|
16
|
+
readonly policy: ChildRestartPolicy;
|
|
17
|
+
private readonly database;
|
|
18
|
+
readonly maxAttempts: number;
|
|
19
|
+
constructor(identity: ServiceIdentity, policy?: ChildRestartPolicy);
|
|
20
|
+
get state(): RecoveryState;
|
|
21
|
+
get delayMs(): number;
|
|
22
|
+
begin(generation: string): void;
|
|
23
|
+
healthy(generation: string): void;
|
|
24
|
+
exited(generation: string, failure: string | null): void;
|
|
25
|
+
retry(): void;
|
|
26
|
+
close(): void;
|
|
27
|
+
}
|
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
import { CHILD_RESTART_POLICY } from '@amalgm/core/supervision';
|
|
2
|
+
import { join } from 'node:path';
|
|
3
|
+
import { openFileDatabase } from '../sqlite.js';
|
|
4
|
+
/** Only the controller holding the installation lease opens this journal.
|
|
5
|
+
* Charge Core's allowance before the host effect: even death during spawn
|
|
6
|
+
* cannot turn controller replacement into a fresh recovery budget. */
|
|
7
|
+
export class RuntimeRecovery {
|
|
8
|
+
policy;
|
|
9
|
+
database;
|
|
10
|
+
maxAttempts;
|
|
11
|
+
constructor(identity, policy = CHILD_RESTART_POLICY) {
|
|
12
|
+
this.policy = policy;
|
|
13
|
+
this.maxAttempts = policy.maxRestarts + 1;
|
|
14
|
+
this.database = openFileDatabase(join(identity.serviceDir, 'recovery.sqlite'));
|
|
15
|
+
try {
|
|
16
|
+
this.database.pragma('synchronous = FULL');
|
|
17
|
+
this.database.exec(`CREATE TABLE IF NOT EXISTS recovery (
|
|
18
|
+
id INTEGER PRIMARY KEY CHECK (id = 1),
|
|
19
|
+
attempts INTEGER NOT NULL CHECK (attempts >= 0),
|
|
20
|
+
generation TEXT, lastFailure TEXT, lastHealthyGeneration TEXT, lastHealthyAt TEXT
|
|
21
|
+
);
|
|
22
|
+
INSERT OR IGNORE INTO recovery (id, attempts) VALUES (1, 0);
|
|
23
|
+
UPDATE recovery SET generation = NULL,
|
|
24
|
+
lastFailure = 'Controller exited before its runtime drained'
|
|
25
|
+
WHERE generation IS NOT NULL;`);
|
|
26
|
+
}
|
|
27
|
+
catch (error) {
|
|
28
|
+
this.database.close();
|
|
29
|
+
throw error;
|
|
30
|
+
}
|
|
31
|
+
}
|
|
32
|
+
get state() {
|
|
33
|
+
const row = this.database.prepare('SELECT attempts, generation, lastFailure, lastHealthyGeneration, lastHealthyAt FROM recovery WHERE id = 1').get();
|
|
34
|
+
return { ...row, maxAttempts: this.maxAttempts, parked: row.generation === null && row.attempts >= this.maxAttempts };
|
|
35
|
+
}
|
|
36
|
+
get delayMs() {
|
|
37
|
+
const { attempts } = this.state;
|
|
38
|
+
return attempts === 0 ? 0 : Math.min(this.policy.initialDelayMs * 2 ** (attempts - 1), this.policy.maxDelayMs);
|
|
39
|
+
}
|
|
40
|
+
begin(generation) {
|
|
41
|
+
const result = this.database.prepare('UPDATE recovery SET attempts = attempts + 1, generation = ? WHERE id = 1 AND generation IS NULL AND attempts < ?').run(generation, this.maxAttempts);
|
|
42
|
+
if (result.changes !== 1)
|
|
43
|
+
throw new Error('The runtime recovery allowance is exhausted or a generation is still owned.');
|
|
44
|
+
}
|
|
45
|
+
healthy(generation) {
|
|
46
|
+
this.database.prepare('UPDATE recovery SET attempts = 0, lastFailure = NULL, lastHealthyGeneration = ?, lastHealthyAt = ? WHERE id = 1 AND generation = ?')
|
|
47
|
+
.run(generation, new Date().toISOString(), generation);
|
|
48
|
+
}
|
|
49
|
+
exited(generation, failure) {
|
|
50
|
+
this.database.prepare('UPDATE recovery SET generation = NULL, lastFailure = COALESCE(?, lastFailure) WHERE id = 1 AND generation = ?')
|
|
51
|
+
.run(failure?.slice(0, 1_024) ?? null, generation);
|
|
52
|
+
}
|
|
53
|
+
retry() {
|
|
54
|
+
this.database.prepare('UPDATE recovery SET attempts = 0, lastFailure = NULL WHERE id = 1 AND generation IS NULL AND attempts >= ?').run(this.maxAttempts);
|
|
55
|
+
}
|
|
56
|
+
close() { this.database.close(); }
|
|
57
|
+
}
|
|
58
|
+
//# sourceMappingURL=recovery.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"recovery.js","sourceRoot":"","sources":["../../src/service/recovery.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,oBAAoB,EAA2B,MAAM,0BAA0B,CAAC;AACzF,OAAO,EAAE,IAAI,EAAE,MAAM,WAAW,CAAC;AACjC,OAAO,EAAE,gBAAgB,EAAE,MAAM,cAAc,CAAC;AAahD;;sEAEsE;AACtE,MAAM,OAAO,eAAe;IAIsB;IAH/B,QAAQ,CAAC;IACjB,WAAW,CAAS;IAE7B,YAAY,QAAyB,EAAW,SAA6B,oBAAoB;QAAjD,WAAM,GAAN,MAAM,CAA2C;QAC/F,IAAI,CAAC,WAAW,GAAG,MAAM,CAAC,WAAW,GAAG,CAAC,CAAC;QAC1C,IAAI,CAAC,QAAQ,GAAG,gBAAgB,CAAC,IAAI,CAAC,QAAQ,CAAC,UAAU,EAAE,iBAAiB,CAAC,CAAC,CAAC;QAC/E,IAAI,CAAC;YACH,IAAI,CAAC,QAAQ,CAAC,MAAM,CAAC,oBAAoB,CAAC,CAAC;YAC3C,IAAI,CAAC,QAAQ,CAAC,IAAI,CAAC;;;;;;;;sCAQa,CAAC,CAAC;QACpC,CAAC;QAAC,OAAO,KAAK,EAAE,CAAC;YAAC,IAAI,CAAC,QAAQ,CAAC,KAAK,EAAE,CAAC;YAAC,MAAM,KAAK,CAAC;QAAC,CAAC;IACzD,CAAC;IAED,IAAI,KAAK;QACP,MAAM,GAAG,GAAG,IAAI,CAAC,QAAQ,CAAC,OAAO,CAAC,2GAA2G,CAAC,CAAC,GAAG,EAAmD,CAAC;QACtM,OAAO,EAAE,GAAG,GAAG,EAAE,WAAW,EAAE,IAAI,CAAC,WAAW,EAAE,MAAM,EAAE,GAAG,CAAC,UAAU,KAAK,IAAI,IAAI,GAAG,CAAC,QAAQ,IAAI,IAAI,CAAC,WAAW,EAAE,CAAC;IACxH,CAAC;IAED,IAAI,OAAO;QACT,MAAM,EAAE,QAAQ,EAAE,GAAG,IAAI,CAAC,KAAK,CAAC;QAChC,OAAO,QAAQ,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC,IAAI,CAAC,MAAM,CAAC,cAAc,GAAG,CAAC,IAAI,CAAC,QAAQ,GAAG,CAAC,CAAC,EAAE,IAAI,CAAC,MAAM,CAAC,UAAU,CAAC,CAAC;IACjH,CAAC;IAED,KAAK,CAAC,UAAkB;QACtB,MAAM,MAAM,GAAG,IAAI,CAAC,QAAQ,CAAC,OAAO,CAAC,kHAAkH,CAAC,CAAC,GAAG,CAAC,UAAU,EAAE,IAAI,CAAC,WAAW,CAAC,CAAC;QAC3L,IAAI,MAAM,CAAC,OAAO,KAAK,CAAC;YAAE,MAAM,IAAI,KAAK,CAAC,6EAA6E,CAAC,CAAC;IAC3H,CAAC;IAED,OAAO,CAAC,UAAkB;QACxB,IAAI,CAAC,QAAQ,CAAC,OAAO,CAAC,oIAAoI,CAAC;aACxJ,GAAG,CAAC,UAAU,EAAE,IAAI,IAAI,EAAE,CAAC,WAAW,EAAE,EAAE,UAAU,CAAC,CAAC;IAC3D,CAAC;IAED,MAAM,CAAC,UAAkB,EAAE,OAAsB;QAC/C,IAAI,CAAC,QAAQ,CAAC,OAAO,CAAC,+GAA+G,CAAC;aACnI,GAAG,CAAC,OAAO,EAAE,KAAK,CAAC,CAAC,EAAE,KAAK,CAAC,IAAI,IAAI,EAAE,UAAU,CAAC,CAAC;IACvD,CAAC;IAED,KAAK;QACH,IAAI,CAAC,QAAQ,CAAC,OAAO,CAAC,4GAA4G,CAAC,CAAC,GAAG,CAAC,IAAI,CAAC,WAAW,CAAC,CAAC;IAC5J,CAAC;IAED,KAAK,KAAW,IAAI,CAAC,QAAQ,CAAC,KAAK,EAAE,CAAC,CAAC,CAAC;CACzC"}
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
/** systemd directives have distinct grammars; this module owns their encoding. */
|
|
2
|
+
export interface SystemdUnitInput {
|
|
3
|
+
readonly command: readonly string[];
|
|
4
|
+
readonly environment: Readonly<Record<string, string>>;
|
|
5
|
+
readonly workingDirectory: string;
|
|
6
|
+
}
|
|
7
|
+
export declare function renderSystemdUnit(input: SystemdUnitInput): string;
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
/** Quoted words use C escapes followed by systemd's percent-specifier expansion. */
|
|
2
|
+
function word(value) {
|
|
3
|
+
if (value.includes('\0'))
|
|
4
|
+
throw new Error('A service argument or environment value cannot contain NUL');
|
|
5
|
+
return `"${value.replace(/[\x01-\x1f\x7f"\\%]/g, (character) => {
|
|
6
|
+
if (character === '%')
|
|
7
|
+
return '%%';
|
|
8
|
+
if (character === '"' || character === '\\')
|
|
9
|
+
return `\\${character}`;
|
|
10
|
+
return `\\x${character.charCodeAt(0).toString(16).padStart(2, '0')}`;
|
|
11
|
+
})}"`;
|
|
12
|
+
}
|
|
13
|
+
export function renderSystemdUnit(input) {
|
|
14
|
+
if (!input.command.length || !input.command[0].startsWith('/'))
|
|
15
|
+
throw new Error('A service requires an absolute executable');
|
|
16
|
+
if (!input.workingDirectory.startsWith('/'))
|
|
17
|
+
throw new Error('A service requires an absolute working directory');
|
|
18
|
+
// systemd trims WorkingDirectory again when serializing its execution context.
|
|
19
|
+
// GNU env changes directory from literal argv, then execs the same owned PID.
|
|
20
|
+
const command = ['/usr/bin/env', '--chdir', input.workingDirectory, '--', ...input.command];
|
|
21
|
+
const env = Object.entries(input.environment).map(([key, value]) => {
|
|
22
|
+
if (!/^[A-Za-z_][A-Za-z0-9_]*$/.test(key))
|
|
23
|
+
throw new Error('Invalid service environment name');
|
|
24
|
+
return `Environment=${word(`${key}=${value}`)}`;
|
|
25
|
+
}).join('\n');
|
|
26
|
+
return `[Unit]
|
|
27
|
+
Description=Amalgm always-on runtime
|
|
28
|
+
StartLimitIntervalSec=0
|
|
29
|
+
|
|
30
|
+
[Service]
|
|
31
|
+
Type=exec
|
|
32
|
+
${env}
|
|
33
|
+
ExecStart=:${command.map(word).join(' ')}
|
|
34
|
+
Restart=on-failure
|
|
35
|
+
RestartSec=5
|
|
36
|
+
KillMode=mixed
|
|
37
|
+
TimeoutStopSec=30
|
|
38
|
+
|
|
39
|
+
[Install]
|
|
40
|
+
WantedBy=default.target
|
|
41
|
+
`;
|
|
42
|
+
}
|
|
43
|
+
//# sourceMappingURL=systemd-unit.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"systemd-unit.js","sourceRoot":"","sources":["../../src/service/systemd-unit.ts"],"names":[],"mappings":"AAOA,oFAAoF;AACpF,SAAS,IAAI,CAAC,KAAa;IACzB,IAAI,KAAK,CAAC,QAAQ,CAAC,IAAI,CAAC;QAAE,MAAM,IAAI,KAAK,CAAC,4DAA4D,CAAC,CAAC;IACxG,OAAO,IAAI,KAAK,CAAC,OAAO,CAAC,sBAAsB,EAAE,CAAC,SAAS,EAAE,EAAE;QAC7D,IAAI,SAAS,KAAK,GAAG;YAAE,OAAO,IAAI,CAAC;QACnC,IAAI,SAAS,KAAK,GAAG,IAAI,SAAS,KAAK,IAAI;YAAE,OAAO,KAAK,SAAS,EAAE,CAAC;QACrE,OAAO,MAAM,SAAS,CAAC,UAAU,CAAC,CAAC,CAAC,CAAC,QAAQ,CAAC,EAAE,CAAC,CAAC,QAAQ,CAAC,CAAC,EAAE,GAAG,CAAC,EAAE,CAAC;IACvE,CAAC,CAAC,GAAG,CAAC;AACR,CAAC;AAED,MAAM,UAAU,iBAAiB,CAAC,KAAuB;IACvD,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,MAAM,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC,UAAU,CAAC,GAAG,CAAC;QAAE,MAAM,IAAI,KAAK,CAAC,2CAA2C,CAAC,CAAC;IAC7H,IAAI,CAAC,KAAK,CAAC,gBAAgB,CAAC,UAAU,CAAC,GAAG,CAAC;QAAE,MAAM,IAAI,KAAK,CAAC,kDAAkD,CAAC,CAAC;IACjH,+EAA+E;IAC/E,8EAA8E;IAC9E,MAAM,OAAO,GAAG,CAAC,cAAc,EAAE,SAAS,EAAE,KAAK,CAAC,gBAAgB,EAAE,IAAI,EAAE,GAAG,KAAK,CAAC,OAAO,CAAC,CAAC;IAC5F,MAAM,GAAG,GAAG,MAAM,CAAC,OAAO,CAAC,KAAK,CAAC,WAAW,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,GAAG,EAAE,KAAK,CAAC,EAAE,EAAE;QACjE,IAAI,CAAC,0BAA0B,CAAC,IAAI,CAAC,GAAG,CAAC;YAAE,MAAM,IAAI,KAAK,CAAC,kCAAkC,CAAC,CAAC;QAC/F,OAAO,eAAe,IAAI,CAAC,GAAG,GAAG,IAAI,KAAK,EAAE,CAAC,EAAE,CAAC;IAClD,CAAC,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;IACd,OAAO;;;;;;EAMP,GAAG;aACQ,OAAO,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC;;;;;;;;CAQvC,CAAC;AACF,CAAC"}
|
|
@@ -1,9 +1,5 @@
|
|
|
1
1
|
import { type ServiceOwner } from "./adapter.js";
|
|
2
|
-
export
|
|
3
|
-
readonly command: readonly string[];
|
|
4
|
-
readonly environment: Readonly<Record<string, string>>;
|
|
5
|
-
readonly workingDirectory: string;
|
|
6
|
-
}): string;
|
|
2
|
+
export { renderSystemdUnit } from './systemd-unit.js';
|
|
7
3
|
/** Does this login have a user manager to talk to? Containers and bare SSH often do not. */
|
|
8
4
|
export declare function userSystemdAvailable(): boolean;
|
|
9
5
|
export declare const systemdOwner: ServiceOwner;
|