| 26 | * reports when a rollback is issued after a failed `BEGIN`. |
| 27 | */ |
| 28 | const makeHarness = (failures: { |
| 29 | readonly begin?: SqlError.SqlError | undefined |
| 30 | readonly savepoint?: SqlError.SqlError | undefined |
| 31 | } = {}) => { |
| 32 | const calls: Array<string> = [] |
| 33 | const conn: StubConnection = { id: "stub" } |
| 34 | const transactionService = Context.Service< |
| 35 | StubTransactionConnection, |
| 36 | readonly [conn: StubConnection, counter: number] |
| 37 | >(`test/SqlClient/TransactionConnection/${harnessIdCounter++}`) |
| 38 | |
| 39 | let transactionActive = false |
| 40 | const savepoints: Array<number> = [] |
| 41 | |
| 42 | const record = (name: string) => Effect.sync(() => calls.push(name)) |
| 43 | |
| 44 | const withTransaction = SqlClient.makeWithTransaction({ |
| 45 | transactionService, |
| 46 | spanAttributes: [], |
| 47 | acquireConnection: Effect.flatMap(Scope.make(), (scope) => |
| 48 | Effect.as( |
| 49 | Effect.flatMap( |
| 50 | record("acquireConnection"), |
| 51 | () => Scope.addFinalizer(scope, record("closeConnection")) |
| 52 | ), |
| 53 | [scope, conn] as const |
| 54 | )), |
| 55 | begin: () => |
| 56 | Effect.flatMap(record("begin"), () => { |
| 57 | if (failures.begin !== undefined) { |
| 58 | return Effect.fail(failures.begin) |
| 59 | } |
| 60 | transactionActive = true |
| 61 | return Effect.void |
| 62 | }), |
| 63 | savepoint: (_conn, id) => |
| 64 | Effect.flatMap(record(`savepoint(${id})`), () => { |
| 65 | if (failures.savepoint !== undefined) { |
| 66 | return Effect.fail(failures.savepoint) |
| 67 | } |
| 68 | savepoints.push(id) |
| 69 | return Effect.void |
| 70 | }), |
| 71 | commit: () => |
| 72 | Effect.flatMap(record("commit"), () => |
| 73 | transactionActive |
| 74 | ? Effect.sync(() => { |
| 75 | transactionActive = false |
| 76 | }) |
| 77 | : Effect.fail(sqlError("cannot commit - no transaction is active"))), |
| 78 | rollback: () => |
| 79 | Effect.flatMap(record("rollback"), () => |
| 80 | transactionActive |
| 81 | ? Effect.sync(() => { |
| 82 | transactionActive = false |
| 83 | }) |
| 84 | : Effect.fail(sqlError("cannot rollback - no transaction is active"))), |
| 85 | rollbackSavepoint: (_conn, id) => |