mirror of
https://github.com/morluto/rea.git
synced 2026-11-12 09:52:27 +00:00
fix(kuna): retain failed inventory admission as result
This commit is contained in:
1 parent
c4e3e48574
commit
2aa5ba836d
2 files changed
+113
-5
No files matched your search
@@ -24,6 +24,7 @@ import {
|
||||
type RetainedResourceScope,
|
||||
} from "../application/AnalysisProvider.js";
|
||||
import { AnalysisError } from "../domain/analysisErrorBase.js";
|
||||
import { ConfigurationError } from "../domain/configurationErrors.js";
|
||||
import {
|
||||
AnalysisCancelledError,
|
||||
AnalysisCapabilityUnavailableError,
|
||||
@@ -2405,10 +2406,18 @@ export class KunaSessionClient implements AnalysisClient {
|
||||
// The session owns the shared run; each caller only stops waiting.
|
||||
const run = this.#listInventory(installation);
|
||||
this.#inventory = run;
|
||||
void run.then((listed) => {
|
||||
// A failed listing is retried by the next request.
|
||||
if (!listed.ok && this.#inventory === run) this.#inventory = undefined;
|
||||
});
|
||||
void run.then(
|
||||
(listed) => {
|
||||
// A failed listing is retried by the next request.
|
||||
if (!listed.ok && this.#inventory === run)
|
||||
this.#inventory = undefined;
|
||||
},
|
||||
() => {
|
||||
// Unexpected rejections remain visible to waiters but cannot poison
|
||||
// the shared cache or create a second unhandled rejection.
|
||||
if (this.#inventory === run) this.#inventory = undefined;
|
||||
},
|
||||
);
|
||||
}
|
||||
return waitFor(this.#inventory, options.signal, "list_procedures");
|
||||
}
|
||||
@@ -2427,11 +2436,24 @@ export class KunaSessionClient implements AnalysisClient {
|
||||
if (this.#reader !== undefined) return ok(this.#reader.project.inventory);
|
||||
const exported = await this.#exportInventory;
|
||||
if (exported !== undefined) return ok(exported);
|
||||
if (this.#session.signal.aborted)
|
||||
return err(
|
||||
new AnalysisCancelledError("list_procedures", {
|
||||
cause: this.#session.signal.reason,
|
||||
}),
|
||||
);
|
||||
let deadline: KunaDeadline;
|
||||
try {
|
||||
deadline = kunaFunctionDeadline(installation.configuration);
|
||||
} catch (cause: unknown) {
|
||||
if (cause instanceof ConfigurationError) return err(cause);
|
||||
throw cause;
|
||||
}
|
||||
const run = await this.#commands.run({
|
||||
installation,
|
||||
arguments: (input) => ["functions", input, "--json"],
|
||||
operation: "list_procedures",
|
||||
deadline: kunaFunctionDeadline(installation.configuration),
|
||||
deadline,
|
||||
outputBytes: KUNA_INVENTORY_OUTPUT_BYTES,
|
||||
signal: this.#session.signal,
|
||||
});
|
||||
|
||||
@@ -0,0 +1,86 @@
|
||||
import { expect, it as test } from "vitest";
|
||||
import { runWithAnalysisOperationSnapshot } from "../../../../src/domain/analysisOperationSnapshot.js";
|
||||
import { session } from "./kunaSessionFixture.js";
|
||||
|
||||
const it = test.skipIf(process.platform === "win32");
|
||||
|
||||
it("retries inventory after a reset exposes an invalid function deadline", async () => {
|
||||
const snapshot = {
|
||||
revision: 1,
|
||||
overrides: { "kuna.function_timeout_ms": 1000 },
|
||||
} as const;
|
||||
const fixture = await runWithAnalysisOperationSnapshot(snapshot, () =>
|
||||
session(
|
||||
"rea-kuna-deadline-inventory-",
|
||||
{},
|
||||
{ REA_KUNA_TIMEOUT_MS: "invalid" },
|
||||
),
|
||||
);
|
||||
const client = runWithAnalysisOperationSnapshot(snapshot, () =>
|
||||
fixture.open(),
|
||||
);
|
||||
try {
|
||||
const ready = await runWithAnalysisOperationSnapshot(snapshot, () =>
|
||||
client.execute("health", {}),
|
||||
);
|
||||
expect(ready.ok).toBe(true);
|
||||
const refused = await client.execute("list_procedures", {});
|
||||
expect(refused).toMatchObject({
|
||||
ok: false,
|
||||
error: { _tag: "ConfigurationError" },
|
||||
});
|
||||
const retried = await runWithAnalysisOperationSnapshot(snapshot, () =>
|
||||
client.execute(
|
||||
"list_procedures",
|
||||
{},
|
||||
{ signal: AbortSignal.timeout(3000) },
|
||||
),
|
||||
);
|
||||
expect(retried).toMatchObject({ ok: true });
|
||||
} finally {
|
||||
await client.close();
|
||||
}
|
||||
});
|
||||
|
||||
it.each([
|
||||
["list_strings", {}],
|
||||
["procedure_callers", { procedure: "main" }],
|
||||
["xrefs", { address: "0x1000" }],
|
||||
] as const)(
|
||||
"retries %s after a reset exposes an invalid project deadline",
|
||||
async (operation, parameters) => {
|
||||
const snapshot = {
|
||||
revision: 1,
|
||||
overrides: { "kuna.project_timeout_ms": 1000 },
|
||||
} as const;
|
||||
const fixture = await runWithAnalysisOperationSnapshot(snapshot, () =>
|
||||
session(
|
||||
"rea-kuna-deadline-query-",
|
||||
{},
|
||||
{ REA_KUNA_PROJECT_TIMEOUT_MS: "invalid" },
|
||||
),
|
||||
);
|
||||
const client = runWithAnalysisOperationSnapshot(snapshot, () =>
|
||||
fixture.open(),
|
||||
);
|
||||
try {
|
||||
const ready = await runWithAnalysisOperationSnapshot(snapshot, () =>
|
||||
client.execute("health", {}),
|
||||
);
|
||||
expect(ready.ok).toBe(true);
|
||||
const refused = await client.execute(operation, parameters);
|
||||
expect(refused).toMatchObject({
|
||||
ok: false,
|
||||
error: { _tag: "ConfigurationError" },
|
||||
});
|
||||
const retried = await runWithAnalysisOperationSnapshot(snapshot, () =>
|
||||
client.execute(operation, parameters, {
|
||||
signal: AbortSignal.timeout(3000),
|
||||
}),
|
||||
);
|
||||
expect(retried).toMatchObject({ ok: true });
|
||||
} finally {
|
||||
await client.close();
|
||||
}
|
||||
},
|
||||
);
|
||||
Reference in new issue
Block a user