@theford/runly 0.0.0-stage → 0.20.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 +202 -0
  2. package/README.md +157 -2
  3. package/dist/cli/client.d.ts +80 -0
  4. package/dist/cli/client.js +294 -0
  5. package/dist/cli/client.js.map +1 -0
  6. package/dist/cli/daemon-unit.d.ts +58 -0
  7. package/dist/cli/daemon-unit.js +289 -0
  8. package/dist/cli/daemon-unit.js.map +1 -0
  9. package/dist/cli/index.d.ts +2 -0
  10. package/dist/cli/index.js +1482 -0
  11. package/dist/cli/index.js.map +1 -0
  12. package/dist/cli/install.d.ts +9 -0
  13. package/dist/cli/install.js +53 -0
  14. package/dist/cli/install.js.map +1 -0
  15. package/dist/cli/logs.d.ts +43 -0
  16. package/dist/cli/logs.js +232 -0
  17. package/dist/cli/logs.js.map +1 -0
  18. package/dist/cli/tether.d.ts +3 -0
  19. package/dist/cli/tether.js +65 -0
  20. package/dist/cli/tether.js.map +1 -0
  21. package/dist/cli/watchdog.d.ts +1 -0
  22. package/dist/cli/watchdog.js +81 -0
  23. package/dist/cli/watchdog.js.map +1 -0
  24. package/dist/core/builds.d.ts +20 -0
  25. package/dist/core/builds.js +93 -0
  26. package/dist/core/builds.js.map +1 -0
  27. package/dist/core/caller-env.d.ts +17 -0
  28. package/dist/core/caller-env.js +77 -0
  29. package/dist/core/caller-env.js.map +1 -0
  30. package/dist/core/diagnostics.d.ts +68 -0
  31. package/dist/core/diagnostics.js +34 -0
  32. package/dist/core/diagnostics.js.map +1 -0
  33. package/dist/core/env-vars.d.ts +35 -0
  34. package/dist/core/env-vars.js +32 -0
  35. package/dist/core/env-vars.js.map +1 -0
  36. package/dist/core/events.d.ts +10 -0
  37. package/dist/core/events.js +42 -0
  38. package/dist/core/events.js.map +1 -0
  39. package/dist/core/exec.d.ts +22 -0
  40. package/dist/core/exec.js +84 -0
  41. package/dist/core/exec.js.map +1 -0
  42. package/dist/core/journal.d.ts +227 -0
  43. package/dist/core/journal.js +395 -0
  44. package/dist/core/journal.js.map +1 -0
  45. package/dist/core/logs.d.ts +56 -0
  46. package/dist/core/logs.js +259 -0
  47. package/dist/core/logs.js.map +1 -0
  48. package/dist/core/manifest.d.ts +292 -0
  49. package/dist/core/manifest.js +179 -0
  50. package/dist/core/manifest.js.map +1 -0
  51. package/dist/core/namespaces.d.ts +7 -0
  52. package/dist/core/namespaces.js +59 -0
  53. package/dist/core/namespaces.js.map +1 -0
  54. package/dist/core/paths.d.ts +31 -0
  55. package/dist/core/paths.js +65 -0
  56. package/dist/core/paths.js.map +1 -0
  57. package/dist/core/policy.d.ts +94 -0
  58. package/dist/core/policy.js +122 -0
  59. package/dist/core/policy.js.map +1 -0
  60. package/dist/core/ports.d.ts +52 -0
  61. package/dist/core/ports.js +94 -0
  62. package/dist/core/ports.js.map +1 -0
  63. package/dist/core/presets.d.ts +25 -0
  64. package/dist/core/presets.js +86 -0
  65. package/dist/core/presets.js.map +1 -0
  66. package/dist/core/procscan.d.ts +111 -0
  67. package/dist/core/procscan.js +342 -0
  68. package/dist/core/procscan.js.map +1 -0
  69. package/dist/core/retention.d.ts +97 -0
  70. package/dist/core/retention.js +322 -0
  71. package/dist/core/retention.js.map +1 -0
  72. package/dist/core/sleep.d.ts +51 -0
  73. package/dist/core/sleep.js +99 -0
  74. package/dist/core/sleep.js.map +1 -0
  75. package/dist/core/tree-ledger.d.ts +39 -0
  76. package/dist/core/tree-ledger.js +92 -0
  77. package/dist/core/tree-ledger.js.map +1 -0
  78. package/dist/core/types.d.ts +21 -0
  79. package/dist/core/types.js +6 -0
  80. package/dist/core/types.js.map +1 -0
  81. package/dist/core/units.d.ts +20 -0
  82. package/dist/core/units.js +69 -0
  83. package/dist/core/units.js.map +1 -0
  84. package/dist/core/upkeep.d.ts +90 -0
  85. package/dist/core/upkeep.js +176 -0
  86. package/dist/core/upkeep.js.map +1 -0
  87. package/dist/core/util.d.ts +46 -0
  88. package/dist/core/util.js +168 -0
  89. package/dist/core/util.js.map +1 -0
  90. package/dist/core/version.d.ts +39 -0
  91. package/dist/core/version.js +144 -0
  92. package/dist/core/version.js.map +1 -0
  93. package/dist/core/worktree.d.ts +51 -0
  94. package/dist/core/worktree.js +309 -0
  95. package/dist/core/worktree.js.map +1 -0
  96. package/dist/daemon/budget.d.ts +155 -0
  97. package/dist/daemon/budget.js +288 -0
  98. package/dist/daemon/budget.js.map +1 -0
  99. package/dist/daemon/election.d.ts +9 -0
  100. package/dist/daemon/election.js +140 -0
  101. package/dist/daemon/election.js.map +1 -0
  102. package/dist/daemon/engine.d.ts +1703 -0
  103. package/dist/daemon/engine.js +5305 -0
  104. package/dist/daemon/engine.js.map +1 -0
  105. package/dist/daemon/index.d.ts +2 -0
  106. package/dist/daemon/index.js +412 -0
  107. package/dist/daemon/index.js.map +1 -0
  108. package/dist/daemon/proxy.d.ts +108 -0
  109. package/dist/daemon/proxy.js +615 -0
  110. package/dist/daemon/proxy.js.map +1 -0
  111. package/dist/daemon/supervisor.d.ts +101 -0
  112. package/dist/daemon/supervisor.js +493 -0
  113. package/dist/daemon/supervisor.js.map +1 -0
  114. package/dist/drivers/appliances.d.ts +11 -0
  115. package/dist/drivers/appliances.js +174 -0
  116. package/dist/drivers/appliances.js.map +1 -0
  117. package/dist/drivers/datastores.d.ts +144 -0
  118. package/dist/drivers/datastores.js +775 -0
  119. package/dist/drivers/datastores.js.map +1 -0
  120. package/dist/drivers/preview.d.ts +69 -0
  121. package/dist/drivers/preview.js +605 -0
  122. package/dist/drivers/preview.js.map +1 -0
  123. package/dist/drivers/types.d.ts +70 -0
  124. package/dist/drivers/types.js +13 -0
  125. package/dist/drivers/types.js.map +1 -0
  126. package/package.json +63 -4
  127. package/schema/backlot.schema.json +549 -0
  128. package/schema/runly.schema.json +556 -0
@@ -0,0 +1,615 @@
1
+ /**
2
+ * The daemon's L4 proxy (decision 0033).
3
+ *
4
+ * Every service port of an environment has two numbers: the PUBLIC port, which
5
+ * this module listens on (127.0.0.1 and ::1) for the environment's whole life,
6
+ * and an INTERNAL port the service is started on, fresh at every start. Bytes
7
+ * are piped between the two without looking at them — no HTTP awareness, so
8
+ * WebSockets, gRPC, a database wire protocol all pass the same way.
9
+ *
10
+ * What the indirection buys:
11
+ * - the public port survives every restart (an `up` that rebuilt, reset-data,
12
+ * a quiesce and the next bind), so a URL handed out once stays good;
13
+ * - a connection that arrives while its service is (re)starting is HELD,
14
+ * bounded, and forwarded once the service is ready, instead of being refused;
15
+ * - client→server bytes and the time of the last of them are counted per
16
+ * environment and port — the activity signal idle detection reads (step 6 of
17
+ * the lifecycle work). runly's own readiness probes go to the internal port,
18
+ * so they never count.
19
+ *
20
+ * It holds no policy. The engine says when a target is starting, up (on which
21
+ * internal port) or down; the wake hook (decision 0035) lets the engine start
22
+ * a stopped service on the first connection, which is held meanwhile.
23
+ */
24
+ import { createServer, connect } from 'node:net';
25
+ import { logEvent } from '../core/events.js';
26
+ /** How long a connection may wait for its service to become ready. */
27
+ export const HOLD_MS = () => Number(process.env.BACKLOT_PROXY_HOLD_MS ?? 90_000);
28
+ /** Per-target bound on held connections, so a client retry storm cannot exhaust fds. */
29
+ const MAX_HELD = 512;
30
+ /** Client bytes kept for a replay; a request larger than this is not retried. */
31
+ const MAX_REPLAY_BYTES = 1024 * 1024;
32
+ /**
33
+ * Every connection's carried bytes together, across the daemon (0.19): 1 MB
34
+ * each times a few hundred held uploads was unbounded memory. Past this, a
35
+ * connection that would carry more is no longer retryable and keeps nothing.
36
+ */
37
+ const replayCapBytes = () => {
38
+ const v = Number(process.env.BACKLOT_PROXY_REPLAY_CAP_BYTES);
39
+ return Number.isFinite(v) && v >= 0 ? v : 64 * 1024 * 1024;
40
+ };
41
+ let carriedTotal = 0;
42
+ /** What every connection carries for a replay right now (tests, `status`). */
43
+ export const replayCarriedBytes = () => carriedTotal;
44
+ /** Give back what `carry` holds; idempotent. */
45
+ function dropCarry(carry) {
46
+ carriedTotal = Math.max(0, carriedTotal - carry.bytes);
47
+ carry.bytes = 0;
48
+ carry.chunks = [];
49
+ }
50
+ /** Resets tolerated while the target is still `up` (the supervisor has not seen the exit yet). */
51
+ const MAX_UP_RESETS = 5;
52
+ /** Relaunches one connection's delivered bytes may be carried to. */
53
+ const MAX_REPLAYS = 1;
54
+ /** HTTP methods that are safe to repeat (RFC 9110 §9.2.1/§9.2.2) — no side effect a second run could double. */
55
+ const IDEMPOTENT = /^(GET|HEAD|OPTIONS) /;
56
+ /**
57
+ * May bytes a process already received be sent to the next one? Only when the
58
+ * connection's first bytes are an HTTP request with a method that is safe to
59
+ * repeat: the dead process may have acted on what it read (charged a card,
60
+ * inserted a row) before it died, and a replay would act a second time. Any
61
+ * other request — POST, PUT, PATCH, DELETE, a database or TLS wire protocol,
62
+ * a first chunk too short to tell — is not replayed once delivered.
63
+ */
64
+ export function replayable(chunks) {
65
+ const head = Buffer.concat(chunks.length > 1 ? chunks.slice(0, 4) : chunks).subarray(0, 8).toString('latin1');
66
+ return IDEMPOTENT.test(head);
67
+ }
68
+ class Target {
69
+ envId;
70
+ key;
71
+ port;
72
+ hub;
73
+ servers = [];
74
+ state = 'down';
75
+ internalPort;
76
+ service;
77
+ clientBytes = 0;
78
+ lastActivityAt = null;
79
+ accepted = 0;
80
+ open = new Set();
81
+ waiters = [];
82
+ constructor(envId, key, port, hub) {
83
+ this.envId = envId;
84
+ this.key = key;
85
+ this.port = port;
86
+ this.hub = hub;
87
+ }
88
+ stats() {
89
+ return {
90
+ port: this.port,
91
+ service: this.service,
92
+ state: this.state,
93
+ internalPort: this.state === 'up' ? this.internalPort : undefined,
94
+ clientBytes: this.clientBytes,
95
+ lastActivityAt: this.lastActivityAt,
96
+ open: this.open.size,
97
+ held: this.waiters.length,
98
+ accepted: this.accepted,
99
+ };
100
+ }
101
+ onConnection(client) {
102
+ this.accepted++;
103
+ // Never let a peer reset crash the daemon.
104
+ client.on('error', () => client.destroy());
105
+ if (this.state === 'up' && this.internalPort !== undefined) {
106
+ this.forward(client, this.internalPort);
107
+ return;
108
+ }
109
+ if (this.state === 'down' && !this.hub.wake(this.envId, this.key)) {
110
+ client.destroy();
111
+ return;
112
+ }
113
+ this.hold(client);
114
+ }
115
+ hold(client, carry) {
116
+ if (this.waiters.length >= MAX_HELD) {
117
+ client.destroy();
118
+ return;
119
+ }
120
+ // A paused socket buffers what the client sends (and TCP backpressure
121
+ // stops it beyond that), so nothing is lost while it waits.
122
+ client.pause();
123
+ const waiter = {
124
+ socket: client,
125
+ carry,
126
+ timer: setTimeout(() => {
127
+ this.dropWaiter(waiter);
128
+ client.destroy();
129
+ }, carry ? Math.max(0, carry.deadline - Date.now()) : HOLD_MS()),
130
+ };
131
+ waiter.timer.unref();
132
+ client.once('close', () => this.dropWaiter(waiter));
133
+ this.waiters.push(waiter);
134
+ }
135
+ dropWaiter(waiter) {
136
+ clearTimeout(waiter.timer);
137
+ const i = this.waiters.indexOf(waiter);
138
+ if (i >= 0)
139
+ this.waiters.splice(i, 1);
140
+ }
141
+ /** Release every held connection: forward them, or close them when the target is not up. */
142
+ flush() {
143
+ const waiters = this.waiters;
144
+ this.waiters = [];
145
+ for (const w of waiters) {
146
+ clearTimeout(w.timer);
147
+ if (w.socket.destroyed)
148
+ continue;
149
+ if (this.state === 'up' && this.internalPort !== undefined)
150
+ this.forward(w.socket, this.internalPort, w.carry);
151
+ else
152
+ w.socket.destroy();
153
+ }
154
+ }
155
+ /**
156
+ * Pipe `client` to the service on `internalPort`.
157
+ *
158
+ * Until the service sends its first byte back, the client's bytes are also
159
+ * kept (`carry`). A service that dies in the window before the supervisor
160
+ * notices — the kernel accepted the connection, then the process exited and
161
+ * the socket was reset or closed with nothing written — looks to the client
162
+ * like a refused connect, and is retried and held the same way (decision
163
+ * 0035) when that is safe:
164
+ * - nothing of the client's reached the process (refused, or lost before
165
+ * the proxy wrote a byte upstream): always — it cannot have acted;
166
+ * - bytes reached it: only for an idempotent HTTP request (`replayable`),
167
+ * and only to ONE more process (`MAX_REPLAYS`).
168
+ * Otherwise the client sees the close or reset, as it would without a proxy
169
+ * (decision 0039, corrected in 0.18.1).
170
+ */
171
+ forward(client, internalPort, carry) {
172
+ if (!this.open.has(client)) {
173
+ this.open.add(client);
174
+ client.once('close', () => this.open.delete(client));
175
+ }
176
+ const replay = carry ?? { chunks: [], bytes: 0, ended: false, resets: 0, replays: 0, deadline: Date.now() + HOLD_MS() };
177
+ if (!carry)
178
+ client.once('close', () => dropCarry(replay));
179
+ connectInternal(internalPort, (err, upstream) => {
180
+ if (err || !upstream) {
181
+ this.refused(client, replay);
182
+ return;
183
+ }
184
+ if (client.destroyed) {
185
+ upstream.destroy();
186
+ return;
187
+ }
188
+ let answered = false;
189
+ let retryable = replay.bytes <= MAX_REPLAY_BYTES && !replay.capped;
190
+ let settled = false;
191
+ // Did any client byte reach this process? Before one did, it cannot have
192
+ // acted on the request, so a retry is not a replay.
193
+ let delivered = replay.chunks.length > 0;
194
+ // May this connection be retried if the process goes away unanswered?
195
+ const canRetry = () => !answered && retryable && (!delivered || (replay.replays < MAX_REPLAYS && replayable(replay.chunks)));
196
+ // Bytes the client sent while it waited (or before a reset) go first.
197
+ for (const chunk of replay.chunks)
198
+ upstream.write(chunk);
199
+ if (replay.ended)
200
+ upstream.end();
201
+ const onData = (chunk) => {
202
+ // Count before forwarding.
203
+ this.clientBytes += chunk.length;
204
+ this.lastActivityAt = Date.now();
205
+ this.hub.noteActivity(this.envId, this.key);
206
+ if (!answered && retryable) {
207
+ if (replay.bytes + chunk.length > MAX_REPLAY_BYTES || carriedTotal + chunk.length > replayCapBytes()) {
208
+ retryable = false;
209
+ replay.capped = true;
210
+ dropCarry(replay);
211
+ }
212
+ else {
213
+ replay.chunks.push(chunk);
214
+ replay.bytes += chunk.length;
215
+ carriedTotal += chunk.length;
216
+ }
217
+ }
218
+ delivered = true;
219
+ if (!upstream.write(chunk))
220
+ client.pause();
221
+ };
222
+ const onDrain = () => client.resume();
223
+ const onEnd = () => {
224
+ replay.ended = true;
225
+ upstream.end();
226
+ };
227
+ const onClientClose = () => upstream.destroy();
228
+ const detach = () => {
229
+ client.off('data', onData);
230
+ client.off('end', onEnd);
231
+ client.off('close', onClientClose);
232
+ upstream.off('drain', onDrain);
233
+ upstream.unpipe(client);
234
+ };
235
+ // The service went away before it said anything, and retrying is safe
236
+ // (canRetry): retry like a refusal.
237
+ const lost = () => {
238
+ if (settled)
239
+ return;
240
+ settled = true;
241
+ if (delivered)
242
+ replay.replays++;
243
+ detach();
244
+ upstream.destroy();
245
+ if (client.destroyed)
246
+ return;
247
+ client.pause();
248
+ this.refused(client, replay, true);
249
+ };
250
+ upstream.once('data', () => {
251
+ answered = true;
252
+ dropCarry(replay);
253
+ });
254
+ upstream.on('error', () => {
255
+ if (canRetry())
256
+ lost();
257
+ else
258
+ client.destroy();
259
+ });
260
+ upstream.on('drain', onDrain);
261
+ client.on('data', onData);
262
+ client.on('end', onEnd);
263
+ client.on('close', onClientClose);
264
+ upstream.pipe(client, { end: false });
265
+ // Half-closes travel on (the service's FIN ends the client's side), and
266
+ // a full close of either side ends the pair — unless the service closed
267
+ // before it said anything and retrying is safe: a lost connection, retried above.
268
+ const finish = (closed) => {
269
+ if (canRetry() && !client.destroyed) {
270
+ lost();
271
+ return;
272
+ }
273
+ if (settled)
274
+ return;
275
+ if (!client.destroyed)
276
+ client.end();
277
+ if (!closed)
278
+ return;
279
+ settled = true;
280
+ setTimeout(() => client.destroy(), 10_000).unref();
281
+ };
282
+ upstream.once('end', () => finish(false));
283
+ upstream.once('close', () => finish(true));
284
+ client.resume();
285
+ });
286
+ }
287
+ /**
288
+ * The service did not accept, or accepted and went away before answering:
289
+ * it may have just crashed, with the supervisor about to relaunch it (the
290
+ * self-restart gap, decision 0035). The connection is held — retried while
291
+ * the target still says `up`, held while it is `starting`, woken when it
292
+ * went `down` — until the hold deadline; only then is it closed. A service
293
+ * that keeps closing connections unanswered while it is `up` is believed
294
+ * after a few tries: that is its answer, not a crash.
295
+ */
296
+ refused(client, carry, reset = false) {
297
+ if (client.destroyed)
298
+ return;
299
+ if (Date.now() >= carry.deadline) {
300
+ client.destroy();
301
+ return;
302
+ }
303
+ if (this.state === 'starting') {
304
+ this.hold(client, carry);
305
+ return;
306
+ }
307
+ if (this.state === 'down') {
308
+ if (this.hub.wake(this.envId, this.key))
309
+ this.hold(client, carry);
310
+ else
311
+ client.destroy();
312
+ return;
313
+ }
314
+ if (reset && ++carry.resets > MAX_UP_RESETS) {
315
+ // Up all along and still closing on us: pass its close on.
316
+ client.end();
317
+ setTimeout(() => client.destroy(), 10_000).unref();
318
+ return;
319
+ }
320
+ setTimeout(() => {
321
+ if (client.destroyed)
322
+ return;
323
+ if (this.state === 'up' && this.internalPort !== undefined)
324
+ this.forward(client, this.internalPort, carry);
325
+ else
326
+ this.refused(client, carry);
327
+ }, 200).unref();
328
+ }
329
+ close() {
330
+ for (const s of this.servers)
331
+ s.close();
332
+ this.servers = [];
333
+ this.state = 'down';
334
+ this.flush();
335
+ for (const s of this.open)
336
+ s.destroy();
337
+ this.open.clear();
338
+ }
339
+ }
340
+ /**
341
+ * Connect to a service's internal port. A service told to listen on
342
+ * `localhost` may have bound IPv4, IPv6, or both, so try each loopback.
343
+ */
344
+ function connectInternal(port, done) {
345
+ const hosts = ['127.0.0.1', '::1'];
346
+ const attempt = (i, lastErr) => {
347
+ if (i >= hosts.length)
348
+ return done(lastErr ?? new Error('no loopback answered'));
349
+ const sock = connect({ port, host: hosts[i], allowHalfOpen: true });
350
+ const onError = (err) => {
351
+ sock.destroy();
352
+ attempt(i + 1, err);
353
+ };
354
+ sock.once('error', onError);
355
+ sock.once('connect', () => {
356
+ sock.off('error', onError);
357
+ done(null, sock);
358
+ });
359
+ };
360
+ attempt(0, null);
361
+ }
362
+ export class PortInUse extends Error {
363
+ port;
364
+ host;
365
+ constructor(port, host) {
366
+ super(`port ${port} is already in use on ${host}`);
367
+ this.port = port;
368
+ this.host = host;
369
+ }
370
+ }
371
+ /** Bind one listener; resolves false when the address family is absent (no IPv6). */
372
+ function listenOn(server, port, host) {
373
+ return new Promise((resolve, reject) => {
374
+ const onError = (err) => {
375
+ server.off('listening', onListening);
376
+ if (err.code === 'EADDRINUSE' || err.code === 'EACCES')
377
+ reject(new PortInUse(port, host));
378
+ else if (err.code === 'EADDRNOTAVAIL' || err.code === 'EAFNOSUPPORT')
379
+ resolve(false);
380
+ else
381
+ reject(err);
382
+ };
383
+ const onListening = () => {
384
+ server.off('error', onError);
385
+ resolve(true);
386
+ };
387
+ server.once('error', onError);
388
+ server.once('listening', onListening);
389
+ // exclusive: a second daemon (another state root) must collide, not share.
390
+ server.listen({ port, host, exclusive: true });
391
+ });
392
+ }
393
+ export class ProxyHub {
394
+ targets = new Map();
395
+ /**
396
+ * Internal ports handed to a start that is not `up` yet, by env/key. A port
397
+ * is probed free when it is allocated, and the service binds it seconds
398
+ * later; without this, two starts in that window were given the same port
399
+ * and one environment's public URL served the other's process.
400
+ */
401
+ reservedInternal = new Map();
402
+ wakeHook;
403
+ activityHook;
404
+ id(envId, key) {
405
+ return `${envId}\u0000${key}`;
406
+ }
407
+ /** The engine installs this (decision 0035): start a stopped service on its first connection. */
408
+ setWakeHook(hook) {
409
+ this.wakeHook = hook;
410
+ }
411
+ /** Optional observer of client bytes (idle bookkeeping lives with the caller). */
412
+ setActivityHook(hook) {
413
+ this.activityHook = hook;
414
+ }
415
+ wake(envId, key) {
416
+ try {
417
+ return this.wakeHook?.(envId, key) ?? false;
418
+ }
419
+ catch {
420
+ return false;
421
+ }
422
+ }
423
+ noteActivity(envId, key) {
424
+ this.activityHook?.(envId, key);
425
+ }
426
+ /** Where the service behind env/key listens, also while it restarts (decision 0035). */
427
+ internalPortOf(envId, key) {
428
+ return this.targets.get(this.id(envId, key))?.internalPort;
429
+ }
430
+ /** Start a target's activity clock from the journal, so a daemon restart keeps it (decision 0035). */
431
+ seedActivity(envId, key, at) {
432
+ const t = this.targets.get(this.id(envId, key));
433
+ if (t && (t.lastActivityAt === null || t.lastActivityAt < at))
434
+ t.lastActivityAt = at;
435
+ }
436
+ /** The last client byte per port key of an environment (null = none yet). */
437
+ activity(envId) {
438
+ const out = {};
439
+ for (const t of this.targets.values())
440
+ if (t.envId === envId)
441
+ out[t.key] = t.lastActivityAt;
442
+ return out;
443
+ }
444
+ /** Every env id with a listener (doctor's stale-listener check, decision 0037). */
445
+ envIds() {
446
+ return new Set([...this.targets.values()].map((t) => t.envId));
447
+ }
448
+ /** Is the public listener for this env/key currently held, on this port? */
449
+ holds(envId, key, port) {
450
+ const t = this.targets.get(this.id(envId, key));
451
+ return t !== undefined && t.port === port && t.servers.length > 0;
452
+ }
453
+ /** Every public port this daemon is listening on. */
454
+ heldPorts() {
455
+ const out = new Set();
456
+ for (const t of this.targets.values())
457
+ if (t.servers.length > 0)
458
+ out.add(t.port);
459
+ return out;
460
+ }
461
+ /** Every internal port currently assigned to a target (up or not) or reserved for a start, so none is handed out twice. */
462
+ assignedInternalPorts() {
463
+ const out = new Set(this.reservedInternal.values());
464
+ for (const t of this.targets.values())
465
+ if (t.internalPort !== undefined)
466
+ out.add(t.internalPort);
467
+ return out;
468
+ }
469
+ /** Hold `port` for the start of env/key until it is `up` (then the target owns it) or goes down. */
470
+ reserveInternal(envId, key, port) {
471
+ this.reservedInternal.set(this.id(envId, key), port);
472
+ }
473
+ release(id) {
474
+ this.reservedInternal.delete(id);
475
+ }
476
+ /**
477
+ * Listen on `port` for env/key (idempotent). Throws PortInUse when another
478
+ * process holds it; any previous listener for this env/key on a different
479
+ * port is closed first, and its counters carried over.
480
+ */
481
+ async listen(envId, key, port) {
482
+ const id = this.id(envId, key);
483
+ const existing = this.targets.get(id);
484
+ if (existing && existing.port === port && existing.servers.length > 0)
485
+ return;
486
+ const target = new Target(envId, key, port, this);
487
+ if (existing) {
488
+ target.clientBytes = existing.clientBytes;
489
+ target.lastActivityAt = existing.lastActivityAt;
490
+ target.accepted = existing.accepted;
491
+ target.state = existing.state;
492
+ target.internalPort = existing.internalPort;
493
+ target.service = existing.service;
494
+ }
495
+ const servers = [];
496
+ try {
497
+ for (const host of ['127.0.0.1', '::1']) {
498
+ const server = createServer({ allowHalfOpen: true, pauseOnConnect: true }, (sock) => target.onConnection(sock));
499
+ if (await listenOn(server, port, host)) {
500
+ server.on('error', (err) => logEvent({ level: 'warn', kind: 'proxy', envId, detail: `listener ${host}:${port} failed: ${err.message}` }));
501
+ servers.push(server);
502
+ }
503
+ }
504
+ if (servers.length === 0)
505
+ throw new PortInUse(port, 'loopback');
506
+ }
507
+ catch (err) {
508
+ for (const s of servers)
509
+ s.close();
510
+ throw err;
511
+ }
512
+ if (existing) {
513
+ // Move held connections too: they are waiting for the SERVICE, not the port.
514
+ target.waiters = existing.waiters;
515
+ existing.waiters = [];
516
+ existing.close();
517
+ }
518
+ target.servers = servers;
519
+ this.targets.set(id, target);
520
+ }
521
+ /** New connections are held until `up` (or dropped by `down`). */
522
+ starting(envId, key, service) {
523
+ const t = this.targets.get(this.id(envId, key));
524
+ if (!t)
525
+ return;
526
+ t.state = 'starting';
527
+ if (service)
528
+ t.service = service;
529
+ }
530
+ /** The service behind env/key is ready on `internalPort`; held connections go through. */
531
+ up(envId, key, internalPort, service) {
532
+ const t = this.targets.get(this.id(envId, key));
533
+ if (!t)
534
+ return;
535
+ t.state = 'up';
536
+ t.internalPort = internalPort;
537
+ this.reservedInternal.set(this.id(envId, key), internalPort);
538
+ if (service)
539
+ t.service = service;
540
+ t.flush();
541
+ }
542
+ /** Nothing is (or will soon be) behind env/key: held connections are closed. */
543
+ down(envId, key) {
544
+ this.release(this.id(envId, key));
545
+ const t = this.targets.get(this.id(envId, key));
546
+ if (!t)
547
+ return;
548
+ t.state = 'down';
549
+ t.internalPort = undefined;
550
+ t.flush();
551
+ }
552
+ /** A service was stopped: its targets go down unless a restart already marked them starting. */
553
+ serviceStopped(envId, service) {
554
+ for (const t of this.targets.values()) {
555
+ if (t.envId === envId && t.service === service && t.state === 'up') {
556
+ t.state = 'down';
557
+ t.internalPort = undefined;
558
+ this.release(this.id(t.envId, t.key));
559
+ t.flush();
560
+ }
561
+ }
562
+ }
563
+ /** Every `starting` target of an env that never reached `up` goes down (a failed bind). */
564
+ settle(envId) {
565
+ for (const t of this.targets.values()) {
566
+ if (t.envId === envId && t.state === 'starting') {
567
+ t.state = 'down';
568
+ t.internalPort = undefined;
569
+ this.release(this.id(t.envId, t.key));
570
+ t.flush();
571
+ }
572
+ }
573
+ }
574
+ state(envId, key) {
575
+ return this.targets.get(this.id(envId, key))?.state;
576
+ }
577
+ /** Close one env/key listener (a port key the manifest dropped). */
578
+ closeKey(envId, key) {
579
+ const id = this.id(envId, key);
580
+ this.targets.get(id)?.close();
581
+ this.targets.delete(id);
582
+ this.release(id);
583
+ }
584
+ /** The port keys this daemon holds a listener for, for one environment. */
585
+ keysOf(envId) {
586
+ return [...this.targets.values()].filter((t) => t.envId === envId).map((t) => t.key);
587
+ }
588
+ /** Release every listener of an environment (teardown). */
589
+ closeEnv(envId) {
590
+ for (const [id, t] of this.targets) {
591
+ if (t.envId === envId) {
592
+ t.close();
593
+ this.targets.delete(id);
594
+ }
595
+ }
596
+ for (const id of [...this.reservedInternal.keys()])
597
+ if (id.startsWith(`${envId}\u0000`))
598
+ this.reservedInternal.delete(id);
599
+ }
600
+ closeAll() {
601
+ for (const t of this.targets.values())
602
+ t.close();
603
+ this.targets.clear();
604
+ this.reservedInternal.clear();
605
+ }
606
+ /** Stats by port key for one environment. */
607
+ stats(envId) {
608
+ const out = {};
609
+ for (const t of this.targets.values())
610
+ if (t.envId === envId)
611
+ out[t.key] = t.stats();
612
+ return out;
613
+ }
614
+ }
615
+ //# sourceMappingURL=proxy.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"proxy.js","sourceRoot":"","sources":["../../src/daemon/proxy.ts"],"names":[],"mappings":"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"}