1import { NodeFileSystem } from "@effect/platform-node"
2import { SqliteClient, SqliteMigrator } from "@effect/sql-sqlite-node"
3import { assert, describe, it } from "@effect/vitest"
4import { Effect, FileSystem } from "effect"
5import { Reactivity } from "effect/reactivity"
6import * as SqlClient from "effect/sql/SqlClient"
7import * as SqlError from "effect/sql/SqlError"
8
9const 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
20describe("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})