diff --git a/ts/apis/index.ts b/ts/apis/index.ts index 50d21e8..05bfd70 100644 --- a/ts/apis/index.ts +++ b/ts/apis/index.ts @@ -1316,9 +1316,9 @@ export interface ActionOptions { * returning "not found" repeatedly), stall detection short-circuits the * loop instead of waiting for the full timeout. * - * Set to `"0s"` to disable stall detection. + * Omit this option or set it to `"0s"` to disable stall detection. * - * @default "30s" + * @default disabled */ readonly stallTimeout?: undefined | string; } diff --git a/ts/retry.test.ts b/ts/retry.test.ts index 97a2cb2..e76a310 100644 --- a/ts/retry.test.ts +++ b/ts/retry.test.ts @@ -1,7 +1,7 @@ import { describe, expect, test } from "bun:test"; import { Duration } from "./duration"; import { Recorder } from "./recording"; -import { retryUntil } from "./retry"; +import { resolveStallTimeoutMs, retryUntil } from "./retry"; test("retryUntil records success flow events", async () => { const recorder = new Recorder(); @@ -69,6 +69,11 @@ test("retryUntil records timeout flow events", async () => { }); describe("stall detection", () => { + test("is opt-in so ordinary eventual convergence uses the action timeout", () => { + expect(resolveStallTimeoutMs(undefined)).toBe(0); + expect(resolveStallTimeoutMs("30s")).toBe(30_000); + }); + test("bails early when the same error repeats beyond stallTimeout", async () => { const recorder = new Recorder(); diff --git a/ts/retry.ts b/ts/retry.ts index f4dd6ce..131bdf8 100644 --- a/ts/retry.ts +++ b/ts/retry.ts @@ -22,9 +22,9 @@ export interface RetryOptions { * returning "not found" 1,500 times), stall detection short-circuits the * loop instead of waiting for the full timeout. * - * Set to `0` or `"0s"` to disable stall detection. + * Omit this option or set it to `0` / `"0s"` to disable stall detection. * - * @default "30s" + * @default disabled */ stallTimeout?: undefined | string | Duration; @@ -60,16 +60,16 @@ function errorFingerprint(err: unknown): string { return String(err).slice(0, 200); } -const DEFAULT_STALL_TIMEOUT_MS = 30_000; - /** * Resolves the stall-timeout option. * * Returns `0` when stall detection is disabled (value is `0` / `"0s"` / `"0"`). */ -function resolveStallTimeoutMs(value: undefined | string | Duration): number { +export function resolveStallTimeoutMs( + value: undefined | string | Duration +): number { if (value === undefined) { - return DEFAULT_STALL_TIMEOUT_MS; + return 0; } if (typeof value === "number" && value === 0) { return 0; diff --git a/ts/scenario/use-cluster.test.ts b/ts/scenario/use-cluster.test.ts index aeef63d..52d24b1 100644 --- a/ts/scenario/use-cluster.test.ts +++ b/ts/scenario/use-cluster.test.ts @@ -272,9 +272,7 @@ describe("resolveCluster", () => { kind: "Cluster", metadata: { name: "workload-2", namespace: "capi-system" }, status: { - v1beta2: { - conditions: [{ type: "Available", status: "True" }], - }, + conditions: [{ type: "Available", status: "True" }], }, }); kubectl.onGet(() => readyYaml); diff --git a/ts/scenario/use-cluster.ts b/ts/scenario/use-cluster.ts index 3acb88b..6a5c044 100644 --- a/ts/scenario/use-cluster.ts +++ b/ts/scenario/use-cluster.ts @@ -124,10 +124,7 @@ export async function resolveCluster( | undefined; targetType = "Ready"; } else if (version === "v1beta2") { - const v1beta2 = status["v1beta2"] as - | Record - | undefined; - conditions = v1beta2?.["conditions"] as + conditions = status["conditions"] as | Array> | undefined; targetType = "Available";