| 1 | import { NodeFileSystem } from "@effect/platform-node" |
| 2 | import { SqliteClient, SqliteMigrator } from "@effect/sql-sqlite-node" |
| 3 | import { assert, describe, it } from "@effect/vitest" |
| 4 | import { Effect, FileSystem } from "effect" |
| 5 | import { Reactivity } from "effect/reactivity" |
| 6 | import * as SqlClient from "effect/sql/SqlClient" |
| 7 | import * as SqlError from "effect/sql/SqlError" |
| 8 | |
| 9 | const makeClients = Effect.gen(function*() { |
| 10 | const fs = yield* FileSystem.FileSystem |
| 11 | const dir = yield* fs.makeTempDirectoryScoped() |
| 12 | const filename = dir + "/test.db" |
| 13 | |
| 14 | return { |
| 15 | lockClient: yield* SqliteClient.make({ filename }), |
| 16 | migratorClient: yield* SqliteClient.make({ filename }) |
| 17 | } |
| 18 | }).pipe(Effect.provide([NodeFileSystem.layer, Reactivity.layer])) |
| 19 | |
| 20 | describe("SqliteMigrator", () => { |
| 21 | it.effect("fails on lock errors", () => |
| 22 | Effect.gen(function*() { |
| 23 | const { lockClient, migratorClient } = yield* makeClients |
| 24 | |
| 25 | yield* migratorClient`PRAGMA busy_timeout = 1` |
| 26 | |
| 27 | yield* SqliteMigrator.run({ |
| 28 | loader: SqliteMigrator.fromRecord({}) |
| 29 | }).pipe(Effect.provideService(SqlClient.SqlClient, migratorClient)) |
| 30 | |
| 31 | yield* Effect.acquireRelease( |
| 32 | lockClient`BEGIN IMMEDIATE`, |
| 33 | () => lockClient`ROLLBACK`.pipe(Effect.ignore) |
| 34 | ) |
| 35 | |
| 36 | const error = yield* Effect.flip( |
| 37 | SqliteMigrator.run({ |
| 38 | loader: SqliteMigrator.fromRecord({ |
| 39 | "1_test": Effect.void |
| 40 | }) |
| 41 | }).pipe(Effect.provideService(SqlClient.SqlClient, migratorClient)) |
| 42 | ) |
| 43 | |
| 44 | assert.strictEqual(error._tag, "SqlError") |
| 45 | assert(SqlError.isSqlError(error)) |
| 46 | assert.strictEqual(error.reason._tag, "LockTimeoutError") |
| 47 | })) |
| 48 | }) |