Ctrl K
ComunidadGuías…

services/retl-runner/src/lease.test.ts

Rama newjitsu · réplica de lectura del repositorio original.

Archivo original ↗Preguntar a KiBot
import { describe, it, expect, vi } from "vitest";
import { KubernetesLease, reverseResourceName, type LeaseRequest } from "./lease";

function api() {
  let value: any;
  let version = 0;
  const calls: string[] = [];
  const call: LeaseRequest = async (method, _path, input: any) => {
    calls.push(method);
    const response = (status: number) => ({ status, body: value ? structuredClone(value) : ({} as any) });
    if (method === "GET") return response(value ? 200 : 404);
    if (method === "POST" && value) return response(409);
    if (method === "PUT" && input.metadata.resourceVersion !== value?.metadata.resourceVersion) return response(409);
    if (method === "DELETE") {
      if (
        input.preconditions.resourceVersion !== value?.metadata.resourceVersion ||
        input.preconditions.uid !== value?.metadata.uid
      )
        return response(409);
      value = undefined;
      return response(200);
    }
    value = structuredClone(input);
    value.metadata.resourceVersion = String(++version);
    value.metadata.uid = "uid";
    return response(method === "POST" ? 201 : 200);
  };
  return {
    call,
    calls,
    expire: () => {
      value.spec.renewTime = new Date(0).toISOString();
    },
    value: () => value,
  };
}
describe("Kubernetes lease", () => {
  it("serializes acquisition and renewal timestamps as Kubernetes MicroTime", async () => {
    vi.useFakeTimers();
    try {
      vi.setSystemTime(new Date("2026-09-17T14:21:51.030Z"));
      const a = api();
      const lease = new KubernetesLease(a.call, "default", "sync", "one");
      await lease.acquire();
      expect(a.value().spec.renewTime).toBe("2026-09-17T14:21:51.030000Z");
      vi.setSystemTime(new Date("2026-09-17T14:22:01.123Z"));
      await lease.renew();
      expect(a.value().spec.renewTime).toBe("2026-09-17T14:22:01.123000Z");
    } finally {
      vi.useRealTimers();
    }
  });
  it("uses Kubernetes MicroTime precision for creation, renewal and takeover", async () => {
    const a = api();
    const timestamps: string[] = [];
    const call: LeaseRequest = async (method, path, body: any) => {
      if (method === "POST" || method === "PUT") {
        const timestamp = body.spec.renewTime;
        if (!/\.\d{6}Z$/.test(timestamp)) return { status: 400, body: {} as any };
        timestamps.push(timestamp);
      }
      return a.call(method, path, body);
    };
    const first = new KubernetesLease(call, "default", "sync", "one");
    await first.acquire();
    await first.renew();
    a.expire();
    await new KubernetesLease(call, "default", "sync", "two").acquire();
    expect(timestamps).toHaveLength(3);
    for (const timestamp of timestamps) expect(Number.isFinite(Date.parse(timestamp))).toBe(true);
  });
  it("uses case-preserving deterministic names shared with syncctl", () => {
    expect(reverseResourceName("sync")).toBe("reverse-75c75efe327a8ef35a072f25117961f5");
    expect(reverseResourceName("Sync")).not.toBe(reverseResourceName("sync"));
  });
  it("CAS admits only one concurrent owner", async () => {
    const a = api();
    const results = await Promise.allSettled([
      new KubernetesLease(a.call, "default", "sync", "one").acquire(),
      new KubernetesLease(a.call, "default", "sync", "two").acquire(),
    ]);
    expect(results.filter(r => r.status === "fulfilled")).toHaveLength(1);
  });
  it("renews and releases only its live epoch", async () => {
    const a = api(),
      first = new KubernetesLease(a.call, "default", "sync", "one"),
      next = new KubernetesLease(a.call, "default", "sync", "two");
    await first.acquire();
    await first.renew();
    await expect(next.acquire()).rejects.toThrow();
    a.expire();
    await next.acquire();
    await expect(first.renew()).rejects.toThrow();
    await first.release();
    expect(a.value().spec.holderIdentity).toBe("two");
    await next.release();
    expect(a.value()).toBeUndefined();
  });
  it("cannot resurrect an expired lease even without a new owner", async () => {
    const a = api(),
      lease = new KubernetesLease(a.call, "default", "sync", "one");
    await lease.acquire();
    a.expire();
    await expect(lease.renew()).rejects.toThrow();
  });
  it("fails closed on unavailable API", async () => {
    const lease = new KubernetesLease(async () => ({ status: 503, body: {} as any }), "default", "sync", "one");
    await expect(lease.acquire()).rejects.toThrow();
  });
});