mirror of
https://github.com/morluto/rea
synced 2026-10-26 06:16:17 -04:00
6fdcac6cad
Match table metadata by stored name bytes and fold only ASCII code units for relationships, reusing parsed facts without per-trigger queries. Preserve caller paths on structured worker limits and V8 heap failures. Validated invalid UTF-8 collisions, distinct UTF-16 names and real worker transport refusal through CLI and stdio MCP. Controlled stderr covers OOM classification; actual memory exhaustion was not induced. Fixes #6795 Fixes #6607
158 lines
5.1 KiB
TypeScript
158 lines
5.1 KiB
TypeScript
import { ArtifactReaderFailure } from "../../../src/artifacts/ArtifactReader.js";
|
|
import { expect, it } from "vitest";
|
|
import { OwnedCommandFailure } from "../../../src/process/OwnedCommand.js";
|
|
import { projectAnalysisError } from "../../../src/domain/analysisErrorProjection.js";
|
|
import { sqliteDatabaseFailure } from "../../../src/sqlite/SqliteDatabaseFailures.js";
|
|
import { SQLITE_DATABASE_LIMITS } from "../../../src/sqlite/SqliteDatabaseLimits.js";
|
|
|
|
it.each([null, "owned stop unconfirmed"])(
|
|
"preserves a selected worker deadline with cleanup=%s",
|
|
(cleanup) => {
|
|
const cause = new OwnedCommandFailure(
|
|
"timeout",
|
|
"Command deadline elapsed.",
|
|
{
|
|
stdout: { text: "partial-owned-output", bytes: 20, observedBytes: 20 },
|
|
stderr: { text: "", bytes: 0, observedBytes: 0 },
|
|
exitCode: null,
|
|
signal: null,
|
|
},
|
|
cleanup,
|
|
undefined,
|
|
["pid:owned-fixture"],
|
|
);
|
|
const failure = sqliteDatabaseFailure(
|
|
cause,
|
|
"/selected.db",
|
|
"worker",
|
|
undefined,
|
|
1234,
|
|
);
|
|
expect(failure.cause).toBe(cause);
|
|
const projected = projectAnalysisError(failure);
|
|
if (cleanup === null)
|
|
expect(projected).toMatchObject({
|
|
code: "provider_timeout",
|
|
details: { timeout_ms: 1234 },
|
|
remediation: { action: expect.stringContaining("--worker-timeout-ms") },
|
|
});
|
|
else
|
|
expect(projected).toMatchObject({
|
|
code: "cleanup_incomplete",
|
|
retryable: false,
|
|
details: {
|
|
resources: ["pid:owned-fixture"],
|
|
diagnostics: {
|
|
previous_error: {
|
|
code: "provider_timeout",
|
|
details: { timeout_ms: 1234 },
|
|
remediation: {
|
|
action: expect.stringContaining("worker_timeout_ms"),
|
|
},
|
|
},
|
|
},
|
|
},
|
|
});
|
|
expect(
|
|
JSON.stringify(projected).split("partial-owned-output"),
|
|
).toHaveLength(2);
|
|
if (cleanup !== null) {
|
|
expect(failure.cleanupPrimary).toMatchObject({
|
|
_tag: "AnalysisTimeoutError",
|
|
timeoutMs: 1234,
|
|
});
|
|
failure.resolveCleanup();
|
|
const resolved = projectAnalysisError(failure);
|
|
expect(resolved).toMatchObject({
|
|
code: "provider_timeout",
|
|
details: { timeout_ms: 1234 },
|
|
});
|
|
expect(
|
|
JSON.stringify(resolved).split("partial-owned-output"),
|
|
).toHaveLength(2);
|
|
}
|
|
},
|
|
);
|
|
|
|
it("does not recommend a timer above the supported maximum", () => {
|
|
const failure = projectAnalysisError(
|
|
sqliteDatabaseFailure(
|
|
new OwnedCommandFailure("timeout", "deadline"),
|
|
"/selected.db",
|
|
"worker",
|
|
undefined,
|
|
2_147_483_647,
|
|
),
|
|
);
|
|
expect(failure.details).toMatchObject({ timeout_ms: 2_147_483_647 });
|
|
expect(failure.remediation.action).toContain("no higher worker deadline");
|
|
expect(failure.remediation.action).not.toContain("Increase");
|
|
});
|
|
|
|
it("says diagnostic capture has no runtime override", () => {
|
|
const projected = projectAnalysisError(
|
|
sqliteDatabaseFailure(
|
|
new OwnedCommandFailure("output-limit", "diagnostics exceeded"),
|
|
"/selected.db",
|
|
"worker",
|
|
),
|
|
);
|
|
expect(projected.remediation.action).toContain(
|
|
String(SQLITE_DATABASE_LIMITS.diagnosticBytes),
|
|
);
|
|
expect(projected.remediation.action).toContain("no runtime override");
|
|
expect(projected.remediation.action).toContain(
|
|
"worker_timeout_ms does not raise it",
|
|
);
|
|
});
|
|
|
|
it.each(["/selected.db", "./Database files/another.db"])(
|
|
"retains the caller-selected path %s when the owned worker reports V8 heap exhaustion",
|
|
(path) => {
|
|
const stderr =
|
|
"FATAL ERROR: Reached heap limit Allocation failed - JavaScript heap out of memory";
|
|
const cause = new OwnedCommandFailure("process", "Worker exited.", {
|
|
stdout: { text: "", bytes: 0, observedBytes: 0 },
|
|
stderr: {
|
|
text: stderr,
|
|
bytes: Buffer.byteLength(stderr),
|
|
observedBytes: Buffer.byteLength(stderr),
|
|
},
|
|
exitCode: null,
|
|
signal: "SIGABRT",
|
|
});
|
|
const failure = sqliteDatabaseFailure(cause, path, "worker");
|
|
expect(failure.cause).toBe(cause);
|
|
expect(projectAnalysisError(failure)).toMatchObject({
|
|
code: "resource_constraint",
|
|
details: {
|
|
operation: "inspect_sqlite_database",
|
|
resource: "memory",
|
|
reported_limits: { javascript_heap_bytes: 256 * 1024 * 1024 },
|
|
diagnostics: { selected_path: path },
|
|
captured_output: { stderr },
|
|
},
|
|
});
|
|
},
|
|
);
|
|
|
|
it("does not infer cancellation from a later signal when cleanup carries no cancellation fact", () => {
|
|
const controller = new AbortController();
|
|
const cause = new ArtifactReaderFailure("io", "cleanup remains owned", {
|
|
cleanup: { reason: "close failed", resources: ["/owned/reply.json"] },
|
|
});
|
|
controller.abort(new Error("later caller cancellation"));
|
|
const failure = sqliteDatabaseFailure(
|
|
cause,
|
|
"/selected.db",
|
|
"worker",
|
|
controller.signal,
|
|
);
|
|
expect(failure.cleanupIncomplete).toBe(true);
|
|
expect(failure.cleanupPrimary).toBeUndefined();
|
|
expect(projectAnalysisError(failure)).toMatchObject({
|
|
code: "cleanup_incomplete",
|
|
details: { resources: ["/owned/reply.json"] },
|
|
});
|
|
});
|