@namzu/sandbox 14.0.0 → 15.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.
Files changed (99) hide show
  1. package/CHANGELOG.md +838 -0
  2. package/README.md +310 -14
  3. package/dist/backends/aci-standby-pool/index.d.ts.map +1 -1
  4. package/dist/backends/aci-standby-pool/index.js +13 -1
  5. package/dist/backends/aci-standby-pool/index.js.map +1 -1
  6. package/dist/backends/docker/index.d.ts.map +1 -1
  7. package/dist/backends/docker/index.js +19 -1
  8. package/dist/backends/docker/index.js.map +1 -1
  9. package/dist/backends/firecracker/index.d.ts.map +1 -1
  10. package/dist/backends/firecracker/index.js +12 -2
  11. package/dist/backends/firecracker/index.js.map +1 -1
  12. package/dist/backends/firecracker/protocol.d.ts +459 -8
  13. package/dist/backends/firecracker/protocol.d.ts.map +1 -1
  14. package/dist/backends/firecracker/protocol.js +136 -0
  15. package/dist/backends/firecracker/protocol.js.map +1 -1
  16. package/dist/backends/firecracker/transport.d.ts +539 -6
  17. package/dist/backends/firecracker/transport.d.ts.map +1 -1
  18. package/dist/backends/firecracker/transport.js +1171 -24
  19. package/dist/backends/firecracker/transport.js.map +1 -1
  20. package/dist/backends/kubernetes/egress-policy.d.ts +1088 -11
  21. package/dist/backends/kubernetes/egress-policy.d.ts.map +1 -1
  22. package/dist/backends/kubernetes/egress-policy.js +2173 -29
  23. package/dist/backends/kubernetes/egress-policy.js.map +1 -1
  24. package/dist/backends/kubernetes/identity.d.ts +193 -0
  25. package/dist/backends/kubernetes/identity.d.ts.map +1 -0
  26. package/dist/backends/kubernetes/identity.js +147 -0
  27. package/dist/backends/kubernetes/identity.js.map +1 -0
  28. package/dist/backends/kubernetes/index.d.ts +678 -33
  29. package/dist/backends/kubernetes/index.d.ts.map +1 -1
  30. package/dist/backends/kubernetes/index.js +1180 -95
  31. package/dist/backends/kubernetes/index.js.map +1 -1
  32. package/dist/backends/kubernetes/ingress-policy.d.ts +375 -0
  33. package/dist/backends/kubernetes/ingress-policy.d.ts.map +1 -0
  34. package/dist/backends/kubernetes/ingress-policy.js +1050 -0
  35. package/dist/backends/kubernetes/ingress-policy.js.map +1 -0
  36. package/dist/backends/kubernetes/k8s-client.d.ts +213 -4
  37. package/dist/backends/kubernetes/k8s-client.d.ts.map +1 -1
  38. package/dist/backends/kubernetes/k8s-client.js +359 -52
  39. package/dist/backends/kubernetes/k8s-client.js.map +1 -1
  40. package/dist/backends/kubernetes/lease.d.ts +40 -14
  41. package/dist/backends/kubernetes/lease.d.ts.map +1 -1
  42. package/dist/backends/kubernetes/lease.js +68 -18
  43. package/dist/backends/kubernetes/lease.js.map +1 -1
  44. package/dist/backends/kubernetes/objects.d.ts +423 -3
  45. package/dist/backends/kubernetes/objects.d.ts.map +1 -1
  46. package/dist/backends/kubernetes/objects.js +364 -2
  47. package/dist/backends/kubernetes/objects.js.map +1 -1
  48. package/dist/backends/kubernetes/per-sandbox-policy.d.ts +219 -0
  49. package/dist/backends/kubernetes/per-sandbox-policy.d.ts.map +1 -0
  50. package/dist/backends/kubernetes/per-sandbox-policy.js +407 -0
  51. package/dist/backends/kubernetes/per-sandbox-policy.js.map +1 -0
  52. package/dist/backends/kubernetes/rbac.d.ts +153 -0
  53. package/dist/backends/kubernetes/rbac.d.ts.map +1 -0
  54. package/dist/backends/kubernetes/rbac.js +177 -0
  55. package/dist/backends/kubernetes/rbac.js.map +1 -0
  56. package/dist/backends/kubernetes/sandbox.d.ts +81 -14
  57. package/dist/backends/kubernetes/sandbox.d.ts.map +1 -1
  58. package/dist/backends/kubernetes/sandbox.js +149 -15
  59. package/dist/backends/kubernetes/sandbox.js.map +1 -1
  60. package/dist/backends/kubernetes/transport.d.ts +935 -9
  61. package/dist/backends/kubernetes/transport.d.ts.map +1 -1
  62. package/dist/backends/kubernetes/transport.js +1958 -62
  63. package/dist/backends/kubernetes/transport.js.map +1 -1
  64. package/dist/backends/kubernetes/workspace.d.ts +1149 -18
  65. package/dist/backends/kubernetes/workspace.d.ts.map +1 -1
  66. package/dist/backends/kubernetes/workspace.js +2825 -186
  67. package/dist/backends/kubernetes/workspace.js.map +1 -1
  68. package/dist/backends/remote-execution-controller.d.ts +14 -0
  69. package/dist/backends/remote-execution-controller.d.ts.map +1 -1
  70. package/dist/backends/remote-execution-controller.js.map +1 -1
  71. package/dist/index.d.ts +231 -13
  72. package/dist/index.d.ts.map +1 -1
  73. package/dist/index.js +247 -5
  74. package/dist/index.js.map +1 -1
  75. package/dist/testing/sandbox-conformance.d.ts +39 -5
  76. package/dist/testing/sandbox-conformance.d.ts.map +1 -1
  77. package/dist/testing/sandbox-conformance.js +436 -5
  78. package/dist/testing/sandbox-conformance.js.map +1 -1
  79. package/package.json +3 -3
  80. package/src/backends/aci-standby-pool/index.ts +16 -1
  81. package/src/backends/docker/index.ts +22 -1
  82. package/src/backends/firecracker/index.ts +14 -2
  83. package/src/backends/firecracker/protocol.ts +514 -6
  84. package/src/backends/firecracker/transport.ts +1492 -40
  85. package/src/backends/kubernetes/egress-policy.ts +3064 -53
  86. package/src/backends/kubernetes/identity.ts +261 -0
  87. package/src/backends/kubernetes/index.ts +1785 -127
  88. package/src/backends/kubernetes/ingress-policy.ts +1344 -0
  89. package/src/backends/kubernetes/k8s-client.ts +444 -54
  90. package/src/backends/kubernetes/lease.ts +75 -19
  91. package/src/backends/kubernetes/objects.ts +626 -6
  92. package/src/backends/kubernetes/per-sandbox-policy.ts +542 -0
  93. package/src/backends/kubernetes/rbac.ts +192 -0
  94. package/src/backends/kubernetes/sandbox.ts +218 -20
  95. package/src/backends/kubernetes/transport.ts +2733 -124
  96. package/src/backends/kubernetes/workspace.ts +4476 -222
  97. package/src/backends/remote-execution-controller.ts +14 -0
  98. package/src/index.ts +595 -14
  99. package/src/testing/sandbox-conformance.ts +540 -5
@@ -40,6 +40,32 @@
40
40
  * `CredentialError` naming the attempted verb and resource — never the
41
41
  * token, which this module never logs or embeds in any thrown message.
42
42
  *
43
+ * ## What a failure carries, and what it deliberately does not
44
+ * Everything else — a connect failure, and every non-2xx status the mapping
45
+ * above does not name — rejects with {@link KubernetesApiError}, which
46
+ * carries the verb, the path, the status where there was one, and the
47
+ * `Retry-After` the server sent with a 429 or a 503. That is METADATA and
48
+ * nothing more: there is no retry loop and no retry policy in this module.
49
+ * A retry is a decision about the OPERATION — a GET during a readiness poll
50
+ * may be repeated, a POST that may already have committed may not — and this
51
+ * client cannot tell those apart. `backends/kubernetes/index.ts` owns the
52
+ * policy, beside the acquire it serves and inside that acquire's existing
53
+ * deadline.
54
+ *
55
+ * ## Deadlines
56
+ * Every request carries its own bound
57
+ * ({@link KubernetesClientOptions.requestTimeoutMs}, default
58
+ * {@link DEFAULT_API_REQUEST_TIMEOUT_MS}) on top of whatever signal the
59
+ * caller passed, because the caller's signal is optional everywhere and
60
+ * several call sites are SHARED flights that run under whichever caller
61
+ * arrived first — one signal-less `destroy()` against an API server that
62
+ * accepted a request and never answered would otherwise pin every later
63
+ * caller joined to it. The bound covers `getToken()`, the connection and
64
+ * reading the body, on both transports, and expiry rejects with
65
+ * {@link KubernetesApiTimeoutError} rather than the generic `failed:` error
66
+ * so a caller can tell a timeout from a refusal. A caller's own abort still
67
+ * behaves exactly as it did.
68
+ *
43
69
  * ## Not in v1
44
70
  * No watch, no informers, no resourceVersion/bookmark tracking. Readiness is
45
71
  * polled by the caller with `../readiness.js`'s `OperationDeadline`, exactly
@@ -47,6 +73,16 @@
47
73
  */
48
74
  import { readFileSync } from 'node:fs';
49
75
  import https from 'node:https';
76
+ /**
77
+ * Default {@link KubernetesClientOptions.requestTimeoutMs} — 30 s.
78
+ *
79
+ * The same cap `lease.ts` already puts on a renewal PATCH, and below the
80
+ * 60 s `readyTimeoutMs` default, so a request that times out still leaves
81
+ * the readiness budget something to report with.
82
+ */
83
+ export const DEFAULT_API_REQUEST_TIMEOUT_MS = 30_000;
84
+ /** Floor for {@link KubernetesClientOptions.requestTimeoutMs} — 1 s. */
85
+ export const MIN_API_REQUEST_TIMEOUT_MS = 1_000;
50
86
  const DEFAULT_SERVICE_ACCOUNT_DIR = '/var/run/secrets/kubernetes.io/serviceaccount';
51
87
  /** 404/410 → this. A teardown path treats it as "already achieved". */
52
88
  export class KubernetesAlreadyGoneError extends Error {
@@ -72,6 +108,51 @@ export class KubernetesConflictError extends Error {
72
108
  this.name = 'KubernetesConflictError';
73
109
  }
74
110
  }
111
+ /**
112
+ * A JSON Patch the API server would not apply: 422 Unprocessable Entity.
113
+ *
114
+ * ## What the API server actually says, measured
115
+ *
116
+ * Against a real API server (v1.37.0) and the agent-sandbox `Sandbox` CRD, a
117
+ * JSON Patch whose `test` clause does not hold answers **422** with this
118
+ * body, byte for byte:
119
+ *
120
+ * ```json
121
+ * {"kind":"Status","apiVersion":"v1","metadata":{},"status":"Failure",
122
+ * "message":"the server rejected our request due to an error in our request",
123
+ * "reason":"Invalid","details":{},"code":422}
124
+ * ```
125
+ *
126
+ * A patch that is simply WRONG — a pointer into a member that does not
127
+ * exist, say — answers with exactly the same status, the same reason and the
128
+ * same message. The server does not name the operation that failed, so
129
+ * nothing this class could read off the response would tell a lost race from
130
+ * a malformed body, and a class that claimed to would be lying.
131
+ *
132
+ * So it says what it can honestly say: the patch did not apply and NOTHING
133
+ * was changed. Deciding which of the two it was belongs to the caller that
134
+ * knows what it tested — `workspace.ts` re-reads the object and compares the
135
+ * value it tested against what is stored now: changed ⇒ somebody raced it,
136
+ * unchanged ⇒ the body is wrong and the error is rethrown rather than
137
+ * retried forever.
138
+ *
139
+ * Not a {@link KubernetesConflictError}: that one is 409, which the same
140
+ * server returns for a DELETE whose `preconditions.resourceVersion` does not
141
+ * match (measured on the same cluster, with a message that DOES name the two
142
+ * versions). The two statuses mean different things and are kept apart.
143
+ */
144
+ export class KubernetesPatchNotAppliedError extends Error {
145
+ method;
146
+ resource;
147
+ status;
148
+ constructor(method, resource, status) {
149
+ super(`kubernetes ${method} ${resource} -> ${status}: the API server did not apply the JSON patch and changed nothing. It does not say which operation failed, so this is either a \`test\` clause that no longer holds — another holder wrote the object first — or a patch body that is wrong.`);
150
+ this.method = method;
151
+ this.resource = resource;
152
+ this.status = status;
153
+ this.name = 'KubernetesPatchNotAppliedError';
154
+ }
155
+ }
75
156
  /**
76
157
  * 401/403 → this. Names the attempted verb and resource only — never the
77
158
  * token, and never the response body (the API server does not echo the
@@ -90,6 +171,157 @@ export class KubernetesCredentialError extends Error {
90
171
  this.name = 'KubernetesCredentialError';
91
172
  }
92
173
  }
174
+ /**
175
+ * The request outlived {@link KubernetesClientOptions.requestTimeoutMs}.
176
+ *
177
+ * Deliberately NOT the generic `failed:` error: a caller that can tell a
178
+ * timeout from a refusal can retry an idempotent write, and one that cannot
179
+ * has to treat every failure alike. Carries the verb, the resource path and
180
+ * the bound that expired — and, like every other error in this module,
181
+ * never the bearer token.
182
+ *
183
+ * A timeout says nothing about whether the request was APPLIED, which is
184
+ * why nothing here tries to: a suspend restores the state it saw and sends
185
+ * its idempotent patch again, a create POST that landed is adopted through
186
+ * the 409 path, and a DELETE that already applied counts as done.
187
+ */
188
+ export class KubernetesApiTimeoutError extends Error {
189
+ verb;
190
+ resource;
191
+ timeoutMs;
192
+ constructor(verb, resource, timeoutMs) {
193
+ super(`kubernetes ${verb} ${resource} was still unanswered ${timeoutMs}ms after it was sent, and was given up on (apiRequestTimeoutMs). Whether the API server applied it is unknown. Raise apiRequestTimeoutMs if this cluster is genuinely this slow.`);
194
+ this.verb = verb;
195
+ this.resource = resource;
196
+ this.timeoutMs = timeoutMs;
197
+ this.name = 'KubernetesApiTimeoutError';
198
+ }
199
+ }
200
+ /**
201
+ * Every API failure this client does not already name: a connect failure, and
202
+ * every non-2xx status outside 401/403/404/409/410 (and the 422 a JSON patch
203
+ * gets).
204
+ *
205
+ * It exists because "a burst past node capacity" and "the API server is down"
206
+ * used to be the same plain `Error`, separable only by matching the message
207
+ * text a release is free to reword. The fields are the smallest set that
208
+ * makes the difference decidable by a caller:
209
+ *
210
+ * - `status` — absent for a connect failure, present for every answered one.
211
+ * - `retryAfterMs` — the `Retry-After` header the API server sends with a
212
+ * 429 (its own priority-and-fairness queue shedding load) and sometimes
213
+ * with a 503, normalised to milliseconds from either spelling the header
214
+ * allows. Absent when the server sent none, which is not the same as zero.
215
+ * - `transport` — see {@link KubernetesApiFailureTransport}.
216
+ * - `cause` — the underlying error for a connect failure.
217
+ *
218
+ * **There is no retry here.** This class is metadata; `index.ts` decides what
219
+ * is worth repeating, because only the caller knows whether the operation is
220
+ * idempotent and only the caller owns a clock to repeat it inside.
221
+ *
222
+ * The message keeps the exact wording both throw sites used before, so a host
223
+ * that logs it sees no change and only a host that inspects the type gains
224
+ * anything.
225
+ */
226
+ export class KubernetesApiError extends Error {
227
+ method;
228
+ path;
229
+ status;
230
+ retryAfterMs;
231
+ transport;
232
+ constructor(message, details) {
233
+ super(message, details.cause !== undefined ? { cause: details.cause } : undefined);
234
+ this.name = 'KubernetesApiError';
235
+ this.method = details.method;
236
+ this.path = details.path;
237
+ if (details.status !== undefined)
238
+ this.status = details.status;
239
+ if (details.retryAfterMs !== undefined)
240
+ this.retryAfterMs = details.retryAfterMs;
241
+ this.transport = details.transport;
242
+ }
243
+ }
244
+ /**
245
+ * `Retry-After`, in milliseconds, or `undefined` when the server sent none or
246
+ * sent one that cannot be read.
247
+ *
248
+ * RFC 9110 allows two spellings and the API server uses the first: a
249
+ * delta-seconds integer (`Retry-After: 1`), which is what
250
+ * priority-and-fairness sends with a 429. The HTTP-date spelling is accepted
251
+ * too, because a proxy in front of the API server may rewrite it. A date in
252
+ * the past, or a negative delta, reads as `0` — "now" — rather than being
253
+ * discarded, because the server still said to wait and the answer to "how
254
+ * long" is "no longer".
255
+ */
256
+ export function parseRetryAfterMs(header) {
257
+ if (header === undefined)
258
+ return undefined;
259
+ const raw = header.trim();
260
+ if (raw === '')
261
+ return undefined;
262
+ if (/^-?\d+$/.test(raw)) {
263
+ const seconds = Number(raw);
264
+ if (!Number.isSafeInteger(seconds))
265
+ return undefined;
266
+ return Math.max(0, seconds * 1_000);
267
+ }
268
+ const at = Date.parse(raw);
269
+ if (Number.isNaN(at))
270
+ return undefined;
271
+ return Math.max(0, at - Date.now());
272
+ }
273
+ /**
274
+ * Validate the configured bound, or supply the default.
275
+ *
276
+ * There is no disabling value, and `0` is refused rather than read as
277
+ * "unbounded": an unanswered request is not a supported configuration.
278
+ * Several call sites are single-flight promises that run under the FIRST
279
+ * caller's signal and never consult a later one's, so one hung request
280
+ * does not block one caller — it blocks every caller that joined it, on a
281
+ * handle whose state already refuses data-plane calls. A cluster with a
282
+ * genuinely slow API server raises the number.
283
+ */
284
+ export function resolveRequestTimeoutMs(value) {
285
+ if (value === undefined)
286
+ return DEFAULT_API_REQUEST_TIMEOUT_MS;
287
+ if (!Number.isSafeInteger(value) || value < MIN_API_REQUEST_TIMEOUT_MS) {
288
+ throw new Error(`kubernetes: apiRequestTimeoutMs must be an integer of at least ${MIN_API_REQUEST_TIMEOUT_MS}ms, got ${JSON.stringify(value)}. No value disables the bound: a request the API server accepted and never answered would hang its caller — and every later caller joined to the same single-flight suspend, delete or verification — until the process was killed. Raise the number instead; the default is ${DEFAULT_API_REQUEST_TIMEOUT_MS}ms.`);
289
+ }
290
+ return value;
291
+ }
292
+ /**
293
+ * Await `promise`, but give up the moment `signal` aborts, rejecting with
294
+ * that signal's reason.
295
+ *
296
+ * `getToken()` is a caller-supplied callback and `res.text()` is a body the
297
+ * peer may simply stop sending, and neither takes a signal of its own, so
298
+ * without this the bound would cover only the part of a request this module
299
+ * happens to hold a socket for. The late settlement is swallowed rather
300
+ * than left dangling: an unobserved rejection is still a rejection.
301
+ */
302
+ function settleOnAbort(promise, signal) {
303
+ if (signal.aborted) {
304
+ void promise.catch(() => { });
305
+ return Promise.reject(signal.reason);
306
+ }
307
+ return new Promise((resolve, reject) => {
308
+ let done = false;
309
+ const onAbort = () => {
310
+ done = true;
311
+ reject(signal.reason);
312
+ };
313
+ signal.addEventListener('abort', onAbort, { once: true });
314
+ promise.then((value) => {
315
+ signal.removeEventListener('abort', onAbort);
316
+ if (!done)
317
+ resolve(value);
318
+ }, (error) => {
319
+ signal.removeEventListener('abort', onAbort);
320
+ if (!done)
321
+ reject(error);
322
+ });
323
+ });
324
+ }
93
325
  function stripTrailingSlash(url) {
94
326
  return url.endsWith('/') ? url.slice(0, -1) : url;
95
327
  }
@@ -133,6 +365,7 @@ async function fetchRequest(url, method, headers, payload, signal) {
133
365
  return {
134
366
  status: res.status,
135
367
  contentType: res.headers.get('content-type') ?? '',
368
+ header: (name) => res.headers.get(name) ?? undefined,
136
369
  text: () => res.text(),
137
370
  };
138
371
  }
@@ -165,6 +398,10 @@ function httpsRequest(url, method, headers, payload, ca, signal) {
165
398
  resolve({
166
399
  status: res.statusCode ?? 0,
167
400
  contentType: Array.isArray(ct) ? (ct[0] ?? '') : (ct ?? ''),
401
+ header: (name) => {
402
+ const value = res.headers[name];
403
+ return Array.isArray(value) ? value[0] : value;
404
+ },
168
405
  text: async () => Buffer.concat(chunks).toString('utf8'),
169
406
  });
170
407
  });
@@ -177,66 +414,136 @@ function httpsRequest(url, method, headers, payload, ca, signal) {
177
414
  });
178
415
  }
179
416
  /**
180
- * `PATCH` always carries a JSON MERGE patch body (RFC 7386) — never
417
+ * `PATCH` carries a JSON MERGE patch body (RFC 7386) unless the caller asked
418
+ * for `json`, which sends an RFC 6902 operation list instead — never
181
419
  * server-side apply, never YAML. `POST` carries a plain JSON create body.
182
- * `GET`/`DELETE` normally carry no body; if a caller ever does pass one to
183
- * `DELETE` it is sent as plain JSON.
420
+ * `GET`/`DELETE` normally carry no body; when a caller does pass one to
421
+ * `DELETE` — a `DeleteOptions` with `preconditions` — it is sent as plain
422
+ * JSON, which is what the API server expects there.
184
423
  */
185
- function contentTypeFor(method) {
186
- return method === 'PATCH' ? 'application/merge-patch+json' : 'application/json';
424
+ function contentTypeFor(method, patchType) {
425
+ if (method !== 'PATCH')
426
+ return 'application/json';
427
+ return patchType === 'json' ? 'application/json-patch+json' : 'application/merge-patch+json';
187
428
  }
188
- export function createKubernetesClient(access) {
429
+ export function createKubernetesClient(access, options = {}) {
189
430
  const resolved = access.inCluster === true ? resolveInCluster(access) : resolveExplicit(access);
190
- async function request(method, path, body, signal) {
191
- signal?.throwIfAborted();
192
- const token = await resolved.getToken();
431
+ // Validated at construction, not at the first request: a configuration
432
+ // this module will never honour should be refused where the operator can
433
+ // still see which backend it came from.
434
+ const requestTimeoutMs = resolveRequestTimeoutMs(options.requestTimeoutMs);
435
+ async function request(method, path, body, signal, patchType = 'merge') {
193
436
  signal?.throwIfAborted();
194
- const url = `${resolved.baseUrl}${path}`;
195
- const payload = body !== undefined ? JSON.stringify(body) : undefined;
196
- const headers = {
197
- Authorization: `Bearer ${token}`,
198
- Accept: 'application/json',
199
- };
200
- if (payload !== undefined)
201
- headers['content-type'] = contentTypeFor(method);
202
- let res;
437
+ // The caller's signal is WRAPPED, never replaced: `deadline` aborts
438
+ // with the caller's own reason when the caller aborts, so every path
439
+ // below behaves exactly as it did, and with a
440
+ // KubernetesApiTimeoutError when the bound expires first. Combined by
441
+ // hand rather than with `AbortSignal.any`, which this package's
442
+ // declared Node floor (20.0) predates.
443
+ const deadlineController = new AbortController();
444
+ const deadline = deadlineController.signal;
445
+ let timedOut = false;
446
+ const timer = setTimeout(() => {
447
+ timedOut = true;
448
+ deadlineController.abort(new KubernetesApiTimeoutError(method, path, requestTimeoutMs));
449
+ }, requestTimeoutMs);
450
+ timer.unref?.();
451
+ const forwardCallerAbort = () => deadlineController.abort(signal?.reason);
452
+ signal?.addEventListener('abort', forwardCallerAbort, { once: true });
453
+ /** True while the CALLER is the one who gave up, which wins. */
454
+ const callerGaveUp = () => signal?.aborted === true;
455
+ const readBody = async (res) => await settleOnAbort(res.text(), deadline);
203
456
  try {
204
- res =
205
- resolved.ca !== undefined
206
- ? await httpsRequest(url, method, headers, payload, resolved.ca, signal)
207
- : await fetchRequest(url, method, headers, payload, signal);
208
- }
209
- catch (err) {
210
- throw new Error(`kubernetes ${method} ${path} failed: ${err instanceof Error ? err.message : String(err)}`, { cause: err });
211
- }
212
- if (res.status === 401 || res.status === 403) {
213
- await res.text();
214
- signal?.throwIfAborted();
215
- throw new KubernetesCredentialError(method, path, res.status);
216
- }
217
- if (res.status === 404 || res.status === 410) {
218
- await res.text();
219
- signal?.throwIfAborted();
220
- throw new KubernetesAlreadyGoneError(method, path, res.status);
221
- }
222
- if (res.status === 409) {
223
- await res.text();
224
- signal?.throwIfAborted();
225
- throw new KubernetesConflictError(method, path);
226
- }
227
- if (res.status < 200 || res.status >= 300) {
228
- const text = await res.text();
229
- signal?.throwIfAborted();
230
- throw new Error(`kubernetes ${method} ${path} -> ${res.status}: ${text}`);
231
- }
232
- if (res.status === 204)
457
+ // Covered by the bound at last: `getToken()` is caller code that
458
+ // takes no signal of its own, and an in-cluster token read that
459
+ // blocks on a wedged volume used to be unbounded on every request.
460
+ const token = await settleOnAbort(resolved.getToken(), deadline);
461
+ deadline.throwIfAborted();
462
+ const url = `${resolved.baseUrl}${path}`;
463
+ const payload = body !== undefined ? JSON.stringify(body) : undefined;
464
+ const headers = {
465
+ Authorization: `Bearer ${token}`,
466
+ Accept: 'application/json',
467
+ };
468
+ if (payload !== undefined)
469
+ headers['content-type'] = contentTypeFor(method, patchType);
470
+ let res;
471
+ try {
472
+ res =
473
+ resolved.ca !== undefined
474
+ ? await httpsRequest(url, method, headers, payload, resolved.ca, deadline)
475
+ : await fetchRequest(url, method, headers, payload, deadline);
476
+ }
477
+ catch (err) {
478
+ if (err instanceof KubernetesApiTimeoutError)
479
+ throw err;
480
+ // A timeout is named rather than folded into `failed:`; a
481
+ // caller's own abort still produces the wrapped error it
482
+ // always produced.
483
+ if (timedOut && !callerGaveUp()) {
484
+ throw new KubernetesApiTimeoutError(method, path, requestTimeoutMs);
485
+ }
486
+ // Same sentence it has always thrown, on a class that says which
487
+ // half failed. Nothing here decides whether to try again: see
488
+ // {@link KubernetesApiError}.
489
+ throw new KubernetesApiError(`kubernetes ${method} ${path} failed: ${err instanceof Error ? err.message : String(err)}`, { method, path, transport: 'connect', cause: err });
490
+ }
491
+ if (res.status === 401 || res.status === 403) {
492
+ await readBody(res);
493
+ deadline.throwIfAborted();
494
+ throw new KubernetesCredentialError(method, path, res.status);
495
+ }
496
+ if (res.status === 404 || res.status === 410) {
497
+ await readBody(res);
498
+ deadline.throwIfAborted();
499
+ throw new KubernetesAlreadyGoneError(method, path, res.status);
500
+ }
501
+ if (res.status === 409) {
502
+ await readBody(res);
503
+ deadline.throwIfAborted();
504
+ throw new KubernetesConflictError(method, path);
505
+ }
506
+ // Before the generic mapping, and only for the dialect that has a
507
+ // `test` clause to fail: a merge patch has no condition, so a 422
508
+ // on one is a malformed body and belongs in the generic error
509
+ // where it always was.
510
+ if (res.status === 422 && method === 'PATCH' && patchType === 'json') {
511
+ await readBody(res);
512
+ deadline.throwIfAborted();
513
+ throw new KubernetesPatchNotAppliedError(method, path, res.status);
514
+ }
515
+ if (res.status < 200 || res.status >= 300) {
516
+ // Read BEFORE the body, because `readBody` can abort out of this
517
+ // block and the header is the whole reason a caller can wait the
518
+ // length the server asked for rather than a length it invented.
519
+ // Only for the two statuses that mean "later, not never": a 400
520
+ // carrying one would be the server contradicting itself.
521
+ const retryAfterMs = res.status === 429 || res.status === 503
522
+ ? parseRetryAfterMs(res.header('retry-after'))
523
+ : undefined;
524
+ const text = await readBody(res);
525
+ deadline.throwIfAborted();
526
+ throw new KubernetesApiError(`kubernetes ${method} ${path} -> ${res.status}: ${text}`, {
527
+ method,
528
+ path,
529
+ status: res.status,
530
+ ...(retryAfterMs !== undefined ? { retryAfterMs } : {}),
531
+ transport: 'status',
532
+ });
533
+ }
534
+ if (res.status === 204)
535
+ return undefined;
536
+ if (res.contentType.includes('application/json')) {
537
+ const text = await readBody(res);
538
+ deadline.throwIfAborted();
539
+ return text.length > 0 ? JSON.parse(text) : undefined;
540
+ }
233
541
  return undefined;
234
- if (res.contentType.includes('application/json')) {
235
- const text = await res.text();
236
- signal?.throwIfAborted();
237
- return text.length > 0 ? JSON.parse(text) : undefined;
238
542
  }
239
- return undefined;
543
+ finally {
544
+ clearTimeout(timer);
545
+ signal?.removeEventListener('abort', forwardCallerAbort);
546
+ }
240
547
  }
241
548
  return {
242
549
  request,
@@ -1 +1 @@
1
- {"version":3,"file":"k8s-client.js","sourceRoot":"","sources":["../../../src/backends/kubernetes/k8s-client.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA8CG;AAEH,OAAO,EAAE,YAAY,EAAE,MAAM,SAAS,CAAA;AACtC,OAAO,KAAK,MAAM,YAAY,CAAA;AAgE9B,MAAM,2BAA2B,GAAG,+CAA+C,CAAA;AAEnF,uEAAuE;AACvE,MAAM,OAAO,0BAA2B,SAAQ,KAAK;IAE1C;IACA;IACA;IAHV,YACU,MAA4B,EAC5B,QAAgB,EAChB,MAAc;QAEvB,KAAK,CAAC,cAAc,MAAM,IAAI,QAAQ,OAAO,MAAM,gBAAgB,CAAC,CAAA;QAJ3D,WAAM,GAAN,MAAM,CAAsB;QAC5B,aAAQ,GAAR,QAAQ,CAAQ;QAChB,WAAM,GAAN,MAAM,CAAQ;QAGvB,IAAI,CAAC,IAAI,GAAG,4BAA4B,CAAA;IACzC,CAAC;CACD;AAED,2EAA2E;AAC3E,MAAM,OAAO,uBAAwB,SAAQ,KAAK;IAEvC;IACA;IAFV,YACU,MAA4B,EAC5B,QAAgB;QAEzB,KAAK,CAAC,cAAc,MAAM,IAAI,QAAQ,mBAAmB,CAAC,CAAA;QAHjD,WAAM,GAAN,MAAM,CAAsB;QAC5B,aAAQ,GAAR,QAAQ,CAAQ;QAGzB,IAAI,CAAC,IAAI,GAAG,yBAAyB,CAAA;IACtC,CAAC;CACD;AAED;;;;;GAKG;AACH,MAAM,OAAO,yBAA0B,SAAQ,KAAK;IAEzC;IACA;IACA;IAHV,YACU,IAA0B,EAC1B,QAAgB,EAChB,MAAc;QAEvB,KAAK,CAAC,0BAA0B,IAAI,IAAI,QAAQ,KAAK,MAAM,EAAE,CAAC,CAAA;QAJrD,SAAI,GAAJ,IAAI,CAAsB;QAC1B,aAAQ,GAAR,QAAQ,CAAQ;QAChB,WAAM,GAAN,MAAM,CAAQ;QAGvB,IAAI,CAAC,IAAI,GAAG,2BAA2B,CAAA;IACxC,CAAC;CACD;AAED,SAAS,kBAAkB,CAAC,GAAW;IACtC,OAAO,GAAG,CAAC,QAAQ,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,KAAK,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,GAAG,CAAA;AAClD,CAAC;AASD;;;;GAIG;AACH,SAAS,gBAAgB,CAAC,MAAiC;IAC1D,MAAM,GAAG,GAAG,MAAM,CAAC,iBAAiB,IAAI,2BAA2B,CAAA;IACnE,MAAM,IAAI,GAAG,OAAO,CAAC,GAAG,CAAC,uBAAuB,CAAA;IAChD,MAAM,IAAI,GAAG,OAAO,CAAC,GAAG,CAAC,uBAAuB,CAAA;IAChD,IAAI,IAAI,KAAK,SAAS,IAAI,IAAI,KAAK,EAAE,IAAI,IAAI,KAAK,SAAS,IAAI,IAAI,KAAK,EAAE,EAAE,CAAC;QAC5E,MAAM,IAAI,KAAK,CACd,4FAA4F,CAC5F,CAAA;IACF,CAAC;IACD,MAAM,EAAE,GAAG,YAAY,CAAC,GAAG,GAAG,SAAS,CAAC,CAAA;IACxC,MAAM,SAAS,GAAG,YAAY,CAAC,GAAG,GAAG,YAAY,EAAE,MAAM,CAAC,CAAC,IAAI,EAAE,CAAA;IACjE,OAAO;QACN,OAAO,EAAE,WAAW,IAAI,IAAI,IAAI,EAAE;QAClC,EAAE;QACF,SAAS;QACT,QAAQ,EAAE,KAAK,IAAI,EAAE,CAAC,YAAY,CAAC,GAAG,GAAG,QAAQ,EAAE,MAAM,CAAC,CAAC,IAAI,EAAE;KACjE,CAAA;AACF,CAAC;AAED,SAAS,eAAe,CAAC,MAAgC;IACxD,OAAO;QACN,OAAO,EAAE,kBAAkB,CAAC,MAAM,CAAC,MAAM,CAAC;QAC1C,EAAE,EAAE,MAAM,CAAC,EAAE;QACb,SAAS,EAAE,MAAM,CAAC,SAAS;QAC3B,QAAQ,EAAE,MAAM,CAAC,QAAQ;KACzB,CAAA;AACF,CAAC;AASD,+EAA+E;AAC/E,KAAK,UAAU,YAAY,CAC1B,GAAW,EACX,MAA4B,EAC5B,OAA+B,EAC/B,OAA2B,EAC3B,MAAoB;IAEpB,MAAM,IAAI,GAAgB,EAAE,MAAM,EAAE,OAAO,EAAE,CAAA;IAC7C,IAAI,OAAO,KAAK,SAAS;QAAE,IAAI,CAAC,IAAI,GAAG,OAAO,CAAA;IAC9C,IAAI,MAAM,KAAK,SAAS;QAAE,IAAI,CAAC,MAAM,GAAG,MAAM,CAAA;IAC9C,MAAM,GAAG,GAAG,MAAM,KAAK,CAAC,GAAG,EAAE,IAAI,CAAC,CAAA;IAClC,OAAO;QACN,MAAM,EAAE,GAAG,CAAC,MAAM;QAClB,WAAW,EAAE,GAAG,CAAC,OAAO,CAAC,GAAG,CAAC,cAAc,CAAC,IAAI,EAAE;QAClD,IAAI,EAAE,GAAG,EAAE,CAAC,GAAG,CAAC,IAAI,EAAE;KACtB,CAAA;AACF,CAAC;AAED;;;;;;;GAOG;AACH,SAAS,YAAY,CACpB,GAAW,EACX,MAA4B,EAC5B,OAA+B,EAC/B,OAA2B,EAC3B,EAAmB,EACnB,MAAoB;IAEpB,MAAM,MAAM,GAAG,IAAI,GAAG,CAAC,GAAG,CAAC,CAAA;IAC3B,OAAO,IAAI,OAAO,CAAc,CAAC,OAAO,EAAE,MAAM,EAAE,EAAE;QACnD,MAAM,GAAG,GAAG,KAAK,CAAC,OAAO,CACxB;YACC,QAAQ,EAAE,MAAM,CAAC,QAAQ;YACzB,QAAQ,EAAE,MAAM,CAAC,QAAQ;YACzB,IAAI,EAAE,MAAM,CAAC,IAAI,KAAK,EAAE,CAAC,CAAC,CAAC,MAAM,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,GAAG;YACpD,IAAI,EAAE,GAAG,MAAM,CAAC,QAAQ,GAAG,MAAM,CAAC,MAAM,EAAE;YAC1C,MAAM;YACN,OAAO;YACP,EAAE;YACF,kBAAkB,EAAE,IAAI;YACxB,GAAG,CAAC,MAAM,KAAK,SAAS,CAAC,CAAC,CAAC,EAAE,MAAM,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;SAC3C,EACD,CAAC,GAAG,EAAE,EAAE;YACP,MAAM,MAAM,GAAa,EAAE,CAAA;YAC3B,GAAG,CAAC,EAAE,CAAC,MAAM,EAAE,CAAC,KAAa,EAAE,EAAE,CAAC,MAAM,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,CAAA;YACrD,GAAG,CAAC,EAAE,CAAC,KAAK,EAAE,GAAG,EAAE;gBAClB,MAAM,EAAE,GAAG,GAAG,CAAC,OAAO,CAAC,cAAc,CAAC,CAAA;gBACtC,OAAO,CAAC;oBACP,MAAM,EAAE,GAAG,CAAC,UAAU,IAAI,CAAC;oBAC3B,WAAW,EAAE,KAAK,CAAC,OAAO,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,IAAI,EAAE,CAAC,CAAC,CAAC,CAAC,CAAC,EAAE,IAAI,EAAE,CAAC;oBAC3D,IAAI,EAAE,KAAK,IAAI,EAAE,CAAC,MAAM,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC,QAAQ,CAAC,MAAM,CAAC;iBACxD,CAAC,CAAA;YACH,CAAC,CAAC,CAAA;YACF,GAAG,CAAC,EAAE,CAAC,OAAO,EAAE,MAAM,CAAC,CAAA;QACxB,CAAC,CACD,CAAA;QACD,GAAG,CAAC,EAAE,CAAC,OAAO,EAAE,MAAM,CAAC,CAAA;QACvB,IAAI,OAAO,KAAK,SAAS;YAAE,GAAG,CAAC,KAAK,CAAC,OAAO,CAAC,CAAA;QAC7C,GAAG,CAAC,GAAG,EAAE,CAAA;IACV,CAAC,CAAC,CAAA;AACH,CAAC;AAED;;;;;GAKG;AACH,SAAS,cAAc,CAAC,MAA4B;IACnD,OAAO,MAAM,KAAK,OAAO,CAAC,CAAC,CAAC,8BAA8B,CAAC,CAAC,CAAC,kBAAkB,CAAA;AAChF,CAAC;AAED,MAAM,UAAU,sBAAsB,CAAC,MAAwB;IAC9D,MAAM,QAAQ,GAAG,MAAM,CAAC,SAAS,KAAK,IAAI,CAAC,CAAC,CAAC,gBAAgB,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,eAAe,CAAC,MAAM,CAAC,CAAA;IAE/F,KAAK,UAAU,OAAO,CACrB,MAA4B,EAC5B,IAAY,EACZ,IAAc,EACd,MAAoB;QAEpB,MAAM,EAAE,cAAc,EAAE,CAAA;QACxB,MAAM,KAAK,GAAG,MAAM,QAAQ,CAAC,QAAQ,EAAE,CAAA;QACvC,MAAM,EAAE,cAAc,EAAE,CAAA;QACxB,MAAM,GAAG,GAAG,GAAG,QAAQ,CAAC,OAAO,GAAG,IAAI,EAAE,CAAA;QACxC,MAAM,OAAO,GAAG,IAAI,KAAK,SAAS,CAAC,CAAC,CAAC,IAAI,CAAC,SAAS,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,SAAS,CAAA;QACrE,MAAM,OAAO,GAA2B;YACvC,aAAa,EAAE,UAAU,KAAK,EAAE;YAChC,MAAM,EAAE,kBAAkB;SAC1B,CAAA;QACD,IAAI,OAAO,KAAK,SAAS;YAAE,OAAO,CAAC,cAAc,CAAC,GAAG,cAAc,CAAC,MAAM,CAAC,CAAA;QAE3E,IAAI,GAAgB,CAAA;QACpB,IAAI,CAAC;YACJ,GAAG;gBACF,QAAQ,CAAC,EAAE,KAAK,SAAS;oBACxB,CAAC,CAAC,MAAM,YAAY,CAAC,GAAG,EAAE,MAAM,EAAE,OAAO,EAAE,OAAO,EAAE,QAAQ,CAAC,EAAE,EAAE,MAAM,CAAC;oBACxE,CAAC,CAAC,MAAM,YAAY,CAAC,GAAG,EAAE,MAAM,EAAE,OAAO,EAAE,OAAO,EAAE,MAAM,CAAC,CAAA;QAC9D,CAAC;QAAC,OAAO,GAAG,EAAE,CAAC;YACd,MAAM,IAAI,KAAK,CACd,cAAc,MAAM,IAAI,IAAI,YAAY,GAAG,YAAY,KAAK,CAAC,CAAC,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,GAAG,CAAC,EAAE,EAC1F,EAAE,KAAK,EAAE,GAAG,EAAE,CACd,CAAA;QACF,CAAC;QAED,IAAI,GAAG,CAAC,MAAM,KAAK,GAAG,IAAI,GAAG,CAAC,MAAM,KAAK,GAAG,EAAE,CAAC;YAC9C,MAAM,GAAG,CAAC,IAAI,EAAE,CAAA;YAChB,MAAM,EAAE,cAAc,EAAE,CAAA;YACxB,MAAM,IAAI,yBAAyB,CAAC,MAAM,EAAE,IAAI,EAAE,GAAG,CAAC,MAAM,CAAC,CAAA;QAC9D,CAAC;QACD,IAAI,GAAG,CAAC,MAAM,KAAK,GAAG,IAAI,GAAG,CAAC,MAAM,KAAK,GAAG,EAAE,CAAC;YAC9C,MAAM,GAAG,CAAC,IAAI,EAAE,CAAA;YAChB,MAAM,EAAE,cAAc,EAAE,CAAA;YACxB,MAAM,IAAI,0BAA0B,CAAC,MAAM,EAAE,IAAI,EAAE,GAAG,CAAC,MAAM,CAAC,CAAA;QAC/D,CAAC;QACD,IAAI,GAAG,CAAC,MAAM,KAAK,GAAG,EAAE,CAAC;YACxB,MAAM,GAAG,CAAC,IAAI,EAAE,CAAA;YAChB,MAAM,EAAE,cAAc,EAAE,CAAA;YACxB,MAAM,IAAI,uBAAuB,CAAC,MAAM,EAAE,IAAI,CAAC,CAAA;QAChD,CAAC;QACD,IAAI,GAAG,CAAC,MAAM,GAAG,GAAG,IAAI,GAAG,CAAC,MAAM,IAAI,GAAG,EAAE,CAAC;YAC3C,MAAM,IAAI,GAAG,MAAM,GAAG,CAAC,IAAI,EAAE,CAAA;YAC7B,MAAM,EAAE,cAAc,EAAE,CAAA;YACxB,MAAM,IAAI,KAAK,CAAC,cAAc,MAAM,IAAI,IAAI,OAAO,GAAG,CAAC,MAAM,KAAK,IAAI,EAAE,CAAC,CAAA;QAC1E,CAAC;QACD,IAAI,GAAG,CAAC,MAAM,KAAK,GAAG;YAAE,OAAO,SAAS,CAAA;QACxC,IAAI,GAAG,CAAC,WAAW,CAAC,QAAQ,CAAC,kBAAkB,CAAC,EAAE,CAAC;YAClD,MAAM,IAAI,GAAG,MAAM,GAAG,CAAC,IAAI,EAAE,CAAA;YAC7B,MAAM,EAAE,cAAc,EAAE,CAAA;YACxB,OAAO,IAAI,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC,CAAE,IAAI,CAAC,KAAK,CAAC,IAAI,CAAO,CAAC,CAAC,CAAC,SAAS,CAAA;QAC7D,CAAC;QACD,OAAO,SAAS,CAAA;IACjB,CAAC;IAED,OAAO;QACN,OAAO;QACP,SAAS,EAAE,GAAG,EAAE,CAAC,QAAQ,CAAC,SAAS;KACnC,CAAA;AACF,CAAC"}
1
+ {"version":3,"file":"k8s-client.js","sourceRoot":"","sources":["../../../src/backends/kubernetes/k8s-client.ts"],"names":[],"mappings":"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"}
@@ -16,36 +16,48 @@
16
16
  *
17
17
  * One `setTimeout` chained per tick, never `setInterval`: a renewal PATCH
18
18
  * that takes longer than the interval must not queue a second one behind
19
- * it. The interval is HALF the TTL, so a single failed tick still leaves a
20
- * whole half-TTL of headroom for the next one to succeed, and it is
21
- * jittered ±10% so a hundred handles acquired in the same second do not
22
- * PATCH the API server in the same millisecond forever after.
19
+ * it. On SUCCESS the interval is HALF the TTL, jittered ±10% so a hundred
20
+ * handles acquired in the same second do not PATCH the API server in the
21
+ * same millisecond forever after.
23
22
  *
24
23
  * The timer is `unref`'d: a host process that has finished its work should
25
24
  * exit, not linger because a sandbox handle is still counting. A handle
26
25
  * nobody destroyed then expires on the cluster's clock exactly as an
27
26
  * abandoned one does, which is the behaviour the TTL exists for.
28
27
  *
28
+ * ## A failed tick does not wait for the next half-TTL
29
+ *
30
+ * Waiting a full half-TTL before retrying a FAILED renewal means one blip at
31
+ * exactly the wrong moment is a coin flip against the object's own
32
+ * `shutdownTime`: the retry and the expiry are both roughly a TTL after the
33
+ * last success, so a single failure can lose that race. A failed tick
34
+ * instead retries on capped exponential backoff — starting at one second,
35
+ * doubling, capped at whichever is smaller of thirty seconds or a
36
+ * twentieth of the TTL — so an outage around a scheduled renewal gets many
37
+ * attempts inside the window that actually matters, not one. Every success
38
+ * resets the backoff and returns the loop to the normal half-TTL cadence.
39
+ *
29
40
  * ## Every tick is bounded
30
41
  *
31
- * A renewal that FAILS is survivable — it is reported and retried with half
32
- * a TTL of headroom. A renewal that HANGS is not: the next tick is scheduled
42
+ * A renewal that FAILS is survivable — it is reported and retried on a
43
+ * short backoff. A renewal that HANGS is not: the next tick is scheduled
33
44
  * only after the current one settles, so a PATCH that never answers parks
34
45
  * the loop forever, reports nothing, and lets the lease expire in silence —
35
46
  * precisely the defect this file exists to close, moved onto the failure
36
47
  * path. An API server that accepts a connection and then never responds is
37
48
  * an ordinary cluster event, so each PATCH runs under its own deadline: it
38
49
  * aborts the request through the signal the client already takes, and an
39
- * expiry is then just another reported failure that retries on the next
40
- * tick.
50
+ * expiry is then just another reported failure that retries on backoff.
41
51
  *
42
52
  * ## What each outcome means
43
53
  *
44
- * - Success → the object's expiry moves a full TTL into the future.
54
+ * - Success → the object's expiry moves a full TTL into the future, the
55
+ * backoff resets, and the next tick is a half-TTL away again.
45
56
  * - Any error, a tick that ran out of time included → reported to
46
- * `onRenewalError` and RETRIED on the next tick. A transient API blip
47
- * must not tear down a working sandbox, and there is still half a TTL of
48
- * headroom.
57
+ * `onRenewalError` and RETRIED on a backoff far shorter than the
58
+ * half-TTL interval. A transient API blip must not tear down a working
59
+ * sandbox, and the loop keeps trying rather than spend the object's
60
+ * remaining headroom waiting.
49
61
  * - Already gone (404/410) → the object this handle owns no longer exists.
50
62
  * Nothing will bring it back, so the loop stops and the handle is marked
51
63
  * gone; every later call fails with a named error instead of dialing an
@@ -82,7 +94,7 @@ export interface LeaseRenewalOptions {
82
94
  * Defaults to a quarter of the interval, capped at
83
95
  * {@link MAX_RENEWAL_TIMEOUT_MS} — a fraction rather than the whole
84
96
  * interval so that a stalled API server still leaves the loop several
85
- * attempts inside the half-TTL of headroom.
97
+ * backoff-paced attempts before the next regular half-TTL tick.
86
98
  */
87
99
  readonly patchTimeoutMs?: number;
88
100
  /** Deterministic jitter for tests. Defaults to `Math.random`. */
@@ -100,7 +112,13 @@ export declare class KubernetesLeaseRenewal {
100
112
  private started;
101
113
  private readonly baseIntervalMs;
102
114
  private readonly patchTimeoutMs;
115
+ private readonly retryBackoffCapMs;
103
116
  private readonly random;
117
+ /**
118
+ * Non-gone failures since the last success (or since the loop started).
119
+ * Reset to 0 by every success; drives how far the next retry backs off.
120
+ */
121
+ private consecutiveFailures;
104
122
  constructor(options: LeaseRenewalOptions);
105
123
  /**
106
124
  * The loop is alive: it has been started and not stopped. Deliberately
@@ -112,7 +130,15 @@ export declare class KubernetesLeaseRenewal {
112
130
  get active(): boolean;
113
131
  start(): void;
114
132
  stop(): void;
115
- private schedule;
133
+ private scheduleNext;
134
+ /**
135
+ * The delay before the NEXT retry after a non-gone failure: capped
136
+ * exponential backoff from {@link RETRY_BACKOFF_FLOOR_MS}, doubling on
137
+ * every consecutive failure, ceilinged at {@link retryBackoffCapMs}.
138
+ * Called only once `consecutiveFailures` has already been incremented for
139
+ * the failure that just happened, so the first retry uses the floor.
140
+ */
141
+ private retryDelayMs;
116
142
  /** Exposed for tests: one renewal attempt plus its scheduling decision. */
117
143
  tick(): Promise<void>;
118
144
  }
@@ -1 +1 @@
1
- {"version":3,"file":"lease.d.ts","sourceRoot":"","sources":["../../../src/backends/kubernetes/lease.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAoDG;AAKH,uEAAuE;AACvE,MAAM,WAAW,mBAAmB;IACnC,uEAAuE;IACvE,QAAQ,CAAC,UAAU,EAAE,MAAM,CAAA;IAC3B;;;;;;OAMG;IACH,QAAQ,CAAC,KAAK,EAAE,CAAC,YAAY,EAAE,MAAM,EAAE,MAAM,CAAC,EAAE,WAAW,KAAK,OAAO,CAAC,IAAI,CAAC,CAAA;IAC7E,iEAAiE;IACjE,QAAQ,CAAC,MAAM,EAAE,MAAM,IAAI,CAAA;IAC3B;;;;OAIG;IACH,QAAQ,CAAC,cAAc,CAAC,EAAE,CAAC,KAAK,EAAE,OAAO,KAAK,IAAI,CAAA;IAClD;;;;OAIG;IACH,QAAQ,CAAC,UAAU,CAAC,EAAE,MAAM,CAAA;IAC5B;;;;;;OAMG;IACH,QAAQ,CAAC,cAAc,CAAC,EAAE,MAAM,CAAA;IAChC,iEAAiE;IACjE,QAAQ,CAAC,MAAM,CAAC,EAAE,MAAM,MAAM,CAAA;CAC9B;AAaD,wBAAgB,gBAAgB,CAAC,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,MAAM,GAAG,MAAM,CAI7E;AAED;;;GAGG;AACH,qBAAa,sBAAsB;IAQtB,OAAO,CAAC,QAAQ,CAAC,OAAO;IAPpC,OAAO,CAAC,KAAK,CAA2C;IACxD,OAAO,CAAC,OAAO,CAAQ;IACvB,OAAO,CAAC,OAAO,CAAQ;IACvB,OAAO,CAAC,QAAQ,CAAC,cAAc,CAAQ;IACvC,OAAO,CAAC,QAAQ,CAAC,cAAc,CAAQ;IACvC,OAAO,CAAC,QAAQ,CAAC,MAAM,CAAc;gBAER,OAAO,EAAE,mBAAmB;IAQzD;;;;;;OAMG;IACH,IAAI,MAAM,IAAI,OAAO,CAEpB;IAED,KAAK,IAAI,IAAI;IAMb,IAAI,IAAI,IAAI;IAQZ,OAAO,CAAC,QAAQ;IAahB,2EAA2E;IACrE,IAAI,IAAI,OAAO,CAAC,IAAI,CAAC;CA0B3B"}
1
+ {"version":3,"file":"lease.d.ts","sourceRoot":"","sources":["../../../src/backends/kubernetes/lease.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAgEG;AAKH,uEAAuE;AACvE,MAAM,WAAW,mBAAmB;IACnC,uEAAuE;IACvE,QAAQ,CAAC,UAAU,EAAE,MAAM,CAAA;IAC3B;;;;;;OAMG;IACH,QAAQ,CAAC,KAAK,EAAE,CAAC,YAAY,EAAE,MAAM,EAAE,MAAM,CAAC,EAAE,WAAW,KAAK,OAAO,CAAC,IAAI,CAAC,CAAA;IAC7E,iEAAiE;IACjE,QAAQ,CAAC,MAAM,EAAE,MAAM,IAAI,CAAA;IAC3B;;;;OAIG;IACH,QAAQ,CAAC,cAAc,CAAC,EAAE,CAAC,KAAK,EAAE,OAAO,KAAK,IAAI,CAAA;IAClD;;;;OAIG;IACH,QAAQ,CAAC,UAAU,CAAC,EAAE,MAAM,CAAA;IAC5B;;;;;;OAMG;IACH,QAAQ,CAAC,cAAc,CAAC,EAAE,MAAM,CAAA;IAChC,iEAAiE;IACjE,QAAQ,CAAC,MAAM,CAAC,EAAE,MAAM,MAAM,CAAA;CAC9B;AA8BD,wBAAgB,gBAAgB,CAAC,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,MAAM,GAAG,MAAM,CAI7E;AAED;;;GAGG;AACH,qBAAa,sBAAsB;IActB,OAAO,CAAC,QAAQ,CAAC,OAAO;IAbpC,OAAO,CAAC,KAAK,CAA2C;IACxD,OAAO,CAAC,OAAO,CAAQ;IACvB,OAAO,CAAC,OAAO,CAAQ;IACvB,OAAO,CAAC,QAAQ,CAAC,cAAc,CAAQ;IACvC,OAAO,CAAC,QAAQ,CAAC,cAAc,CAAQ;IACvC,OAAO,CAAC,QAAQ,CAAC,iBAAiB,CAAQ;IAC1C,OAAO,CAAC,QAAQ,CAAC,MAAM,CAAc;IACrC;;;OAGG;IACH,OAAO,CAAC,mBAAmB,CAAI;gBAEF,OAAO,EAAE,mBAAmB;IAYzD;;;;;;OAMG;IACH,IAAI,MAAM,IAAI,OAAO,CAEpB;IAED,KAAK,IAAI,IAAI;IAMb,IAAI,IAAI,IAAI;IAQZ,OAAO,CAAC,YAAY;IAapB;;;;;;OAMG;IACH,OAAO,CAAC,YAAY;IAKpB,2EAA2E;IACrE,IAAI,IAAI,OAAO,CAAC,IAAI,CAAC;CA+B3B"}