(options: {
readonly transactionTag: Context.Tag<I, readonly [conn: S, counter: number]>
readonly spanAttributes: ReadonlyArray<readonly [string, unknown]>
readonly acquireConnection: Effect.Effect<readonly [Scope.CloseableScope | undefined, S], Error.SqlError>
readonly begin: (conn: NoInfer<S>) => Effect.Effect<void, Error.SqlError>
readonly savepoint: (conn: NoInfer<S>, id: number) => Effect.Effect<void, Error.SqlError>
readonly commit: (conn: NoInfer<S>) => Effect.Effect<void, Error.SqlError>
readonly rollback: (conn: NoInfer<S>) => Effect.Effect<void, Error.SqlError>
readonly rollbackSavepoint: (conn: NoInfer<S>, id: number) => Effect.Effect<void, Error.SqlError>
})
| 108 | |
| 109 | /** @internal */ |
| 110 | export const makeWithTransaction = <I, S>(options: { |
| 111 | readonly transactionTag: Context.Tag<I, readonly [conn: S, counter: number]> |
| 112 | readonly spanAttributes: ReadonlyArray<readonly [string, unknown]> |
| 113 | readonly acquireConnection: Effect.Effect<readonly [Scope.CloseableScope | undefined, S], Error.SqlError> |
| 114 | readonly begin: (conn: NoInfer<S>) => Effect.Effect<void, Error.SqlError> |
| 115 | readonly savepoint: (conn: NoInfer<S>, id: number) => Effect.Effect<void, Error.SqlError> |
| 116 | readonly commit: (conn: NoInfer<S>) => Effect.Effect<void, Error.SqlError> |
| 117 | readonly rollback: (conn: NoInfer<S>) => Effect.Effect<void, Error.SqlError> |
| 118 | readonly rollbackSavepoint: (conn: NoInfer<S>, id: number) => Effect.Effect<void, Error.SqlError> |
| 119 | }) => |
| 120 | <R, E, A>( |
| 121 | effect: Effect.Effect<A, E, R> |
| 122 | ): Effect.Effect<A, E | Error.SqlError, R> => |
| 123 | Effect.uninterruptibleMask((restore) => |
| 124 | Effect.useSpan( |
| 125 | "sql.transaction", |
| 126 | { kind: "client", captureStackTrace: false }, |
| 127 | (span) => |
| 128 | Effect.withFiberRuntime<A, E | Error.SqlError, R>((fiber) => { |
| 129 | for (const [key, value] of options.spanAttributes) { |
| 130 | span.attribute(key, value) |
| 131 | } |
| 132 | const context = fiber.currentContext |
| 133 | const clock = Context.get(fiber.currentDefaultServices, Clock.Clock) |
| 134 | const connOption = Context.getOption(context, options.transactionTag) |
| 135 | const conn = connOption._tag === "Some" |
| 136 | ? Effect.succeed([undefined, connOption.value[0]] as const) |
| 137 | : options.acquireConnection |
| 138 | const id = connOption._tag === "Some" ? connOption.value[1] + 1 : 0 |
| 139 | return Effect.flatMap( |
| 140 | conn, |
| 141 | ( |
| 142 | [scope, conn] |
| 143 | ) => |
| 144 | (id === 0 ? options.begin(conn) : options.savepoint(conn, id)).pipe( |
| 145 | Effect.zipRight(Effect.locally( |
| 146 | restore(effect), |
| 147 | FiberRef.currentContext, |
| 148 | Context.add(context, options.transactionTag, [conn, id]).pipe( |
| 149 | Context.add(Tracer.ParentSpan, span) |
| 150 | ) |
| 151 | )), |
| 152 | Effect.exit, |
| 153 | Effect.flatMap((exit) => { |
| 154 | let effect: Effect.Effect<void> |
| 155 | if (Exit.isSuccess(exit)) { |
| 156 | if (id === 0) { |
| 157 | span.event("db.transaction.commit", clock.unsafeCurrentTimeNanos()) |
| 158 | effect = Effect.orDie(options.commit(conn)) |
| 159 | } else { |
| 160 | span.event("db.transaction.savepoint", clock.unsafeCurrentTimeNanos()) |
| 161 | effect = Effect.void |
| 162 | } |
| 163 | } else { |
| 164 | span.event("db.transaction.rollback", clock.unsafeCurrentTimeNanos()) |
| 165 | effect = Effect.orDie( |
| 166 | id > 0 |
| 167 | ? options.rollbackSavepoint(conn, id) |
no test coverage detected
searching dependent graphs…