The standing test's runs last 0.6 of failingAfterMs of clock as well as two attempts, so a success that does not reset a run is caught; the addition test holds a thousand stable passes, so 'first pass' is proved (review of the standing test races)
This commit is contained in:
+6
-5
@@ -38,7 +38,7 @@ interface World {
|
||||
|
||||
async function world(
|
||||
names: string[],
|
||||
opts: { retire?: boolean; held?: string[]; del?: boolean; reenable?: boolean; stableForMs?: number } = {},
|
||||
opts: { retire?: boolean; held?: string[]; del?: boolean; reenable?: boolean; stableForMs?: number; stablePasses?: number } = {},
|
||||
): Promise<World> {
|
||||
const dir = await mkdtemp(join(tmpdir(), "retire-"));
|
||||
const receives = join(dir, "postgres-database.json");
|
||||
@@ -64,6 +64,7 @@ async function world(
|
||||
};
|
||||
w.p = runProviderLoop("postgres-database", adapter, {
|
||||
receives, everyMs: EVERY, node: "anchor", stableForMs: opts.stableForMs ?? 0,
|
||||
...(opts.stablePasses ? { stablePasses: opts.stablePasses } : {}),
|
||||
// Only retirement is these tests'; the standing (provisioner.failing, .recovered) is standing.test.ts's.
|
||||
announce: (event, body) => { if (event === RETIREMENT_EVENT) w.events.push(body); },
|
||||
});
|
||||
@@ -302,13 +303,13 @@ test("delete refuses an active consumer and deletes only the named retired one",
|
||||
});
|
||||
|
||||
test("an addition acts on the first pass", async () => {
|
||||
// Not gated by the stability a retirement waits for: with a hold of a minute, only a pass that acts at once creates b
|
||||
// in the time the test waits. A deadline of three intervals, as before, was a race with the scheduler under load.
|
||||
const w = await world(["a"], { stableForMs: 60_000 });
|
||||
// Not gated by the stability a retirement waits for: with a hold of a minute and a thousand passes, only a pass that
|
||||
// acts at once creates b. The deadline is a few passes, not three intervals of 10 ms: a scheduler stall must not fail it.
|
||||
const w = await world(["a"], { stableForMs: 60_000, stablePasses: 1000 });
|
||||
try {
|
||||
const before = w.created.length;
|
||||
await w.ask(["a", "b"]);
|
||||
await until(() => w.created.length > before);
|
||||
await until(() => w.created.length > before, 1000);
|
||||
assert.equal(w.created.at(-1), "b");
|
||||
} finally {
|
||||
w.done();
|
||||
|
||||
@@ -134,14 +134,14 @@ test("a consumer failed for minutes is announced, naming it, its machine and the
|
||||
test("one success between failures starts the run again", async () => {
|
||||
const w = await world();
|
||||
try {
|
||||
// Each failing run lasts two failed attempts, counted, not a slept fraction of failingAfterMs. A run the load
|
||||
// Each failing run lasts two counted failed attempts and at least 0.6 of failingAfterMs of clock (long enough that a success which did not reset the run would be announced at the second run). A run the load
|
||||
// stretched to failingAfterMs is a long run and may be announced, so only runs that stayed short are asserted.
|
||||
const run = async (values?: Record<string, unknown>): Promise<number> => {
|
||||
const start = Date.now();
|
||||
const base = w.attempts;
|
||||
w.failing = new Error("connection refused");
|
||||
await w.ask([{ as: "a", values }]);
|
||||
await until(() => w.attempts >= base + 2);
|
||||
await until(() => w.attempts >= base + 2 && Date.now() - start >= FAILING_AFTER * 0.6);
|
||||
w.failing = null;
|
||||
return Date.now() - start;
|
||||
};
|
||||
|
||||
Reference in New Issue
Block a user