testAWaitIsSaidOnceAgainOnlyWhenItChangesAndWhenItEnds

tcmts.cli.budget.test.testAWaitIsSaidOnceAgainOnlyWhenItChangesAndWhenItEnds · #uqndyeyg · term

import { slotWaits } from "#codebase/tcmts/cli/budget";
import type { SlotHolder } from "#codebase/tcmts/cli/budget";
import { fakePool, holding } from "#codebase/tcmts/cli/budget/test";
import assert from "node:assert/strict";

export const testAWaitIsSaidOnceAgainOnlyWhenItChangesAndWhenItEnds = async () => {
  let t = 0;
  const said: string[] = [];
  const waits = slotWaits(
    (l) => said.push(l),
    () => t,
  );
  const { pool, takes } = fakePool();
  const own = "tcm test of /x/codebase on session/me";
  const a = holding(4001, "tcm test of /x/codebase on session/a");
  const b = holding(4002, "tcm test of /x/codebase on session/b");
  const c = holding(4003, "tcm test of /y/other/codebase on session/c");
  const look = (holders: SlotHolder[], ahead: number, i = 0) =>
    takes[i]!.onWait({ holders, ahead, want: 1, size: 3 });
  const first = waits.take(pool, own);
  // said when it starts, with what sets how many
  look([a, a, b], 3);
  assert.deepEqual(said, [
    "waiting for a slot: 3 of 3 in use (2 by session/a, 1 by session/b), 3 ahead in line (TCM_SLOTS sets how many)",
  ]);
  // the same, or a little more ahead, or a change within the minute: nothing
  t = 10_000;
  look([a, a, b], 3);
  t = 40_000;
  look([a, a, b], 4);
  look([a, a, c], 4);
  t = 70_000;
  look([a, a, b], 4);
  assert.equal(said.length, 1);
  // who holds them changes, after a minute: said, briefly
  t = 80_000;
  look([a, a, c], 4);
  assert.equal(
    said[1],
    "still waiting for a slot after 1m20s: 3 of 3 in use (2 by session/a, 1 by session/c of …/other/codebase), 4 ahead in line",
  );
  // nothing changing: said again after five minutes
  t = 300_000;
  look([a, a, c], 4);
  assert.equal(said.length, 2);
  t = 380_000;
  look([a, a, c], 4);
  assert.match(said[2]!, /^still waiting for a slot after 6m20s: /);
  // and when it ends, how long it took
  t = 390_000;
  takes[0]!.give();
  await first;
  assert.equal(said[3], "got a slot after 6m30s");
  assert.equal(waits.waited(), 390_000);
  // two takes waiting at once are one wait; a wait soon after another, the same as before, isn't said
  t = 400_000;
  const second = waits.take(pool, own);
  const third = waits.take(pool, own);
  look([a, a, c], 4, 1);
  t = 405_000;
  look([a, a, c], 4, 2);
  takes[1]!.give();
  await second;
  t = 410_000;
  takes[2]!.give();
  await third;
  assert.equal(said.length, 4);
  assert.equal(waits.waited(), 400_000);
  // a take that didn't wait isn't counted
  const quick = waits.take(pool, own);
  t = 500_000;
  takes[3]!.give();
  await quick;
  assert.equal(waits.waited(), 400_000);
}

uses