import { DatabaseSync } from "node:sqlite"; import { assert, assertEquals } from "@std/assert"; import { Cause, Deferred, Effect, Exit, Fiber, Option, Schema } from "effect"; import { CatalogFailure, InvalidOrder, StoreFailure } from "./contracts.ts"; import { makeIntegrationDriver } from "./integration_driver.ts"; import { submit } from "./workflow.ts"; const request = { sku: "book", quantity: 2 }; const run = (effect: Effect.Effect) => Effect.runPromise(effect.pipe(Effect.timeout("5 seconds"))); const failure = (exit: Exit.Exit): E => { assert(Exit.isFailure(exit)); const error = Cause.findErrorOption(exit.cause); assert(Option.isSome(error)); return error.value; }; interface Fixture { readonly databasePath: string; readonly catalogUrl: string; readonly requests: URL[]; readonly rows: () => unknown[]; } async function withFixture( body: (fixture: Fixture) => Promise, options: { readonly handler?: (request: Request) => Response | Promise; readonly columns?: string; } = {}, ) { // cwd is the isolated directory supplied by the outer slow-test harness. const dir = await Deno.makeTempDir({ dir: ".", prefix: "sqlite-" }); const databasePath = `${Deno.cwd()}/${dir}/orders.sqlite`; const database = new DatabaseSync(databasePath); try { database.exec(`create table orders (${ options.columns ?? "sku TEXT NOT NULL, quantity INTEGER NOT NULL, total INTEGER NOT NULL" })`); } finally { database.close(); } const requests: URL[] = []; const server = Deno.serve({ hostname: "127.0.0.1", port: 0, onListen: () => {}, }, (request) => { requests.push(new URL(request.url)); return options.handler?.(request) ?? Response.json({ price: 12 }); }); try { await body({ databasePath, catalogUrl: `http://127.0.0.1:${server.addr.port}/`, requests, rows: () => { // Reopen the file independently; no recording-driver state is consulted. const reopened = new DatabaseSync(databasePath); try { return reopened.prepare("select sku, quantity, total from orders") .all().map((row) => ({ ...row })); } finally { reopened.close(); } }, }); } finally { await server.shutdown(); await Deno.remove(dir, { recursive: true }); } } Deno.test("HTTP/SQLite workflow persists bound values and closes the leased connection", async () => { await withFixture(async (fixture) => { const driver = makeIntegrationDriver(fixture); const input = { sku: "book' ; -- / ?", quantity: 2 }; const expected = { ...input, total: 24 }; assertEquals( await run(submit(input).pipe(Effect.provide(driver.layer))), expected, ); assertEquals(fixture.rows(), [expected]); assertEquals(fixture.requests[0]?.pathname, "/price"); assertEquals(fixture.requests[0]?.searchParams.get("sku"), input.sku); assertEquals(driver.events, [ `quote:${input.sku}`, "leased:1", "begin", "write", "commit", "closed", ]); assertEquals(driver.active.size, 0); }); }); Deno.test("HTTP/SQLite invalid schema and domain input performs no external calls", async () => { await withFixture(async (fixture) => { const driver = makeIntegrationDriver(fixture); for (const input of [{}, { sku: "book", quantity: 1.5 }]) { const error = failure( await run(Effect.exit( submit(input).pipe(Effect.provide(driver.layer)), )), ); assert(error instanceof Schema.SchemaError); } for ( const input of [{ sku: "", quantity: 2 }, { sku: "book", quantity: 0 }] ) { const error = failure( await run(Effect.exit( submit(input).pipe(Effect.provide(driver.layer)), )), ); assert(error instanceof InvalidOrder); } assertEquals([fixture.requests.length, driver.leases, driver.active.size], [ 0, 0, 0, ]); assertEquals(fixture.rows(), []); }); }); Deno.test("HTTP/SQLite rejects malformed, non-success and invalid catalog responses before storage", async () => { const responses = [ () => new Response("{broken", { headers: { "content-type": "application/json" }, }), () => new Response("unavailable", { status: 503 }), () => Response.json({ price: "12" }), () => Response.json({ price: 1.5 }), () => Response.json({ price: -1 }), () => Response.json({ price: 100001 }), ]; for (const [index, response] of responses.entries()) { await withFixture(async (fixture) => { const driver = makeIntegrationDriver(fixture); const error = failure( await run(Effect.exit( submit(request).pipe(Effect.provide(driver.layer)), )), ); assert( index < 4 ? error instanceof CatalogFailure : error instanceof InvalidOrder, ); assertEquals( [fixture.requests.length, driver.leases, driver.active.size], [1, 0, 0], ); assertEquals(fixture.rows(), []); }, { handler: response }); } }); Deno.test("HTTP/SQLite permanent CHECK failure rolls back without retry and closes the connection", async () => { await withFixture(async (fixture) => { const driver = makeIntegrationDriver(fixture); const error = failure( await run(Effect.exit( submit(request).pipe(Effect.provide(driver.layer)), )), ); assert(error instanceof StoreFailure); assertEquals([error.kind, error.stage], ["Permanent", "write"]); assertEquals(driver.leases, 1); assertEquals(driver.events.slice(-3), ["write", "rollback", "closed"]); assertEquals(driver.active.size, 0); assertEquals(fixture.rows(), []); }, { columns: "sku TEXT, quantity INTEGER CHECK(quantity < 2), total INTEGER", }); }); Deno.test("HTTP/SQLite invalid returned row rolls back an actual inserted row", async () => { let inserted = false; await withFixture(async (fixture) => { const driver = makeIntegrationDriver({ ...fixture, afterWrite: () => Effect.sync(() => { inserted = true; }), }); const error = failure( await run(Effect.exit( submit(request).pipe(Effect.provide(driver.layer)), )), ); assert(error instanceof StoreFailure); assertEquals([error.kind, error.stage], ["Permanent", "row"]); assert(inserted); assertEquals(driver.events.slice(-3), ["write", "rollback", "closed"]); assertEquals([driver.leases, driver.active.size], [1, 0]); assertEquals(fixture.rows(), []); // SQLite's TEXT affinity returns "24" after insertion, rejected by StoreLive. }, { columns: "sku TEXT, quantity INTEGER, total TEXT" }); }); Deno.test("HTTP/SQLite cancellation aborts a known pending catalog request without acquiring storage", async () => { const entered = Promise.withResolvers(); const respond = Promise.withResolvers(); await withFixture(async (fixture) => { const driver = makeIntegrationDriver(fixture); try { await run(Effect.gen(function* () { const fiber = yield* Effect.forkChild( submit(request).pipe(Effect.provide(driver.layer)), ); yield* Effect.promise(() => entered.promise); yield* Fiber.interrupt(fiber); const exit = yield* Fiber.await(fiber); assert(Exit.isFailure(exit) && Cause.hasInterruptsOnly(exit.cause)); assert(driver.events.includes("http:aborted")); assertEquals([ fixture.requests.length, driver.leases, driver.active.size, ], [1, 0, 0]); assertEquals(fixture.rows(), []); })); } finally { // Release the server handler even when an assertion fails; shutdown joins it. respond.resolve(Response.json({ price: 12 })); } }, { handler: () => { entered.resolve(); return respond.promise; }, }); }); Deno.test("HTTP/SQLite cancellation after a real INSERT awaits rollback and connection close", async () => { await withFixture(async (fixture) => { const inserted = Deferred.makeUnsafe(); const driver = makeIntegrationDriver({ ...fixture, afterWrite: () => Deferred.succeed(inserted, undefined).pipe( Effect.andThen(Effect.never), ), }); await run(Effect.gen(function* () { const fiber = yield* Effect.forkChild( submit(request).pipe(Effect.provide(driver.layer)), ); yield* Deferred.await(inserted); assertEquals(driver.active.size, 1); // A second connection sees no uncommitted row while the transaction is open. assertEquals(fixture.rows(), []); yield* Fiber.interrupt(fiber); const exit = yield* Fiber.await(fiber); assert(Exit.isFailure(exit) && Cause.hasInterruptsOnly(exit.cause)); assertEquals(driver.events.slice(-3), ["write", "rollback", "closed"]); assertEquals([driver.leases, driver.active.size], [1, 0]); assertEquals(fixture.rows(), []); })); }); });