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>;
|
ask(list: { as: string; node?: string; values?: Record<string, unknown> }[]): Promise<void>;
|
||||||
failing: Error | null;
|
failing: Error | null;
|
||||||
holdsErr: Error | null;
|
holdsErr: Error | null;
|
||||||
|
/** When set, holds fails only for these consumers (holdsErr's error). */
|
||||||
|
holdsErrFor: Set<string> | null;
|
||||||
created: string[];
|
created: string[];
|
||||||
/** Every event but the first success since start, which has its own test. */
|
/** Every event but the first success since start, which has its own test. */
|
||||||
said: Said[];
|
said: Said[];
|
||||||
@@ -44,7 +46,7 @@ interface World {
|
|||||||
async function world(opts: { classify?: boolean; announce?: false; stableForMs?: number } = {}): Promise<World> {
|
async function world(opts: { classify?: boolean; announce?: false; stableForMs?: number } = {}): Promise<World> {
|
||||||
const dir = await mkdtemp(join(tmpdir(), "standing-"));
|
const dir = await mkdtemp(join(tmpdir(), "standing-"));
|
||||||
const receives = join(dir, "postgres-database.json");
|
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) => {
|
w.ask = async (list) => {
|
||||||
const given = [];
|
const given = [];
|
||||||
for (const g of list) {
|
for (const g of list) {
|
||||||
@@ -60,8 +62,8 @@ async function world(opts: { classify?: boolean; announce?: false; stableForMs?:
|
|||||||
},
|
},
|
||||||
async remove() {},
|
async remove() {},
|
||||||
async retire() {},
|
async retire() {},
|
||||||
async holds() {
|
async holds(p) {
|
||||||
if (w.holdsErr) throw w.holdsErr;
|
if (w.holdsErr && (!w.holdsErrFor || w.holdsErrFor.has(p.as))) throw w.holdsErr;
|
||||||
return true;
|
return true;
|
||||||
},
|
},
|
||||||
...(opts.classify ? { classify: () => "its-own" } : {}),
|
...(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);
|
await until(() => w.created.length === 3);
|
||||||
w.holdsErr = new Error("boom");
|
w.holdsErr = new Error("boom");
|
||||||
await until(() => w.said.filter((s) => s.event === FAILING_EVENT).length >= 3);
|
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" }]);
|
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"));
|
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")!;
|
const c = w.said.find((s) => s.event === RECOVERED_EVENT && s.body.consumer === "c")!;
|
||||||
assert.equal(c.body.why, "retired");
|
assert.equal(c.body.why, "retired");
|
||||||
|
|||||||
Reference in New Issue
Block a user