The standing test keeps c failing alone after its ask is dropped, so its only recovery is its retirement: clearing every failure at once raced the loop's read of the new list under load (issue 1126; the hidden failure of try-1793042418286545971, issue 1901)
This commit is contained in:
@@ -34,6 +34,8 @@ interface World {
|
||||
ask(list: { as: string; node?: string; values?: Record<string, unknown> }[]): Promise<void>;
|
||||
failing: Error | null;
|
||||
holdsErr: Error | null;
|
||||
/** When set, holds fails only for these consumers (holdsErr's error). */
|
||||
holdsErrFor: Set<string> | null;
|
||||
created: string[];
|
||||
/** Every event but the first success since start, which has its own test. */
|
||||
said: Said[];
|
||||
@@ -44,7 +46,7 @@ interface World {
|
||||
async function world(opts: { classify?: boolean; announce?: false; stableForMs?: number } = {}): Promise<World> {
|
||||
const dir = await mkdtemp(join(tmpdir(), "standing-"));
|
||||
const receives = join(dir, "postgres-database.json");
|
||||
const w = { dir, failing: null, holdsErr: null, created: [], said: [], all: [] } as unknown as World;
|
||||
const w = { dir, failing: null, holdsErr: null, holdsErrFor: null, created: [], said: [], all: [] } as unknown as World;
|
||||
w.ask = async (list) => {
|
||||
const given = [];
|
||||
for (const g of list) {
|
||||
@@ -60,8 +62,8 @@ async function world(opts: { classify?: boolean; announce?: false; stableForMs?:
|
||||
},
|
||||
async remove() {},
|
||||
async retire() {},
|
||||
async holds() {
|
||||
if (w.holdsErr) throw w.holdsErr;
|
||||
async holds(p) {
|
||||
if (w.holdsErr && (!w.holdsErrFor || w.holdsErrFor.has(p.as))) throw w.holdsErr;
|
||||
return true;
|
||||
},
|
||||
...(opts.classify ? { classify: () => "its-own" } : {}),
|
||||
@@ -197,9 +199,11 @@ test("a failing consumer the mesh stopped asking for is said recovered when it i
|
||||
await until(() => w.created.length === 3);
|
||||
w.holdsErr = new Error("boom");
|
||||
await until(() => w.said.filter((s) => s.event === FAILING_EVENT).length >= 3);
|
||||
// c is no longer asked for while it is still failing; the others then recover.
|
||||
// c is no longer asked for while it is still failing; the others then recover. c keeps failing, so its only way
|
||||
// to be said recovered is its retirement: clearing every failure at once raced the loop's read of the new list
|
||||
// under load (a pass before that read recovered c as an ordinary recovery, with no why).
|
||||
await w.ask([{ as: "a" }, { as: "b" }]);
|
||||
w.holdsErr = null;
|
||||
w.holdsErrFor = new Set(["c"]);
|
||||
await until(() => w.said.some((s) => s.event === RECOVERED_EVENT && s.body.consumer === "c"));
|
||||
const c = w.said.find((s) => s.event === RECOVERED_EVENT && s.body.consumer === "c")!;
|
||||
assert.equal(c.body.why, "retired");
|
||||
|
||||
Reference in New Issue
Block a user