MCPcopy Create free account
hub / github.com/Effect-TS/effect / makeWithTransaction

Function makeWithTransaction

packages/effect/src/unstable/sql/SqlClient.ts:224–302  ·  view source on GitHub ↗
(options: {
  readonly transactionService: Context.Key<I, readonly [conn: S, counter: number]>
  readonly spanAttributes: ReadonlyArray<readonly [string, unknown]>
  readonly acquireConnection: Effect.Effect<readonly [Scope.Closeable | undefined, S], SqlError>
  readonly begin: (conn: NoInfer<S>) => Effect.Effect<void, SqlError>
  readonly savepoint: (conn: NoInfer<S>, id: number) => Effect.Effect<void, SqlError>
  readonly commit: (conn: NoInfer<S>) => Effect.Effect<void, SqlError>
  readonly rollback: (conn: NoInfer<S>) => Effect.Effect<void, SqlError>
  readonly rollbackSavepoint: (conn: NoInfer<S>, id: number) => Effect.Effect<void, SqlError>
})

Source from the content-addressed store, hash-verified

222 * @since 4.0.0
223 */
224export const makeWithTransaction = <I, S>(options: {
225 readonly transactionService: Context.Key<I, readonly [conn: S, counter: number]>
226 readonly spanAttributes: ReadonlyArray<readonly [string, unknown]>
227 readonly acquireConnection: Effect.Effect<readonly [Scope.Closeable | undefined, S], SqlError>
228 readonly begin: (conn: NoInfer<S>) => Effect.Effect<void, SqlError>
229 readonly savepoint: (conn: NoInfer<S>, id: number) => Effect.Effect<void, SqlError>
230 readonly commit: (conn: NoInfer<S>) => Effect.Effect<void, SqlError>
231 readonly rollback: (conn: NoInfer<S>) => Effect.Effect<void, SqlError>
232 readonly rollbackSavepoint: (conn: NoInfer<S>, id: number) => Effect.Effect<void, SqlError>
233}) => {
234 const transactionSemaphore = Context.Service<Semaphore.Semaphore>(
235 `effect/sql/SqlClient/TransactionSemaphore/${transactionSemaphoreIdCounter++}`
236 )
237 return <R, E, A>(effect: Effect.Effect<A, E, R>): Effect.Effect<A, E | SqlError, R> =>
238 Effect.uninterruptibleMask((restore) =>
239 Effect.useSpan(
240 "sql.transaction",
241 { kind: "client" },
242 (span) =>
243 Effect.withFiber<A, E | SqlError, R>((fiber) => {
244 for (const [key, value] of options.spanAttributes) {
245 span.attribute(key, value)
246 }
247 const services = fiber.context
248 const clock = fiber.getRef(Clock)
249 const connOption = Context.getOption(services, options.transactionService)
250 const conn = connOption._tag === "Some"
251 ? Effect.succeed([undefined, connOption.value[0]] as const)
252 : options.acquireConnection
253 const id = connOption._tag === "Some" ? connOption.value[1] + 1 : 0
254 const transaction = Effect.flatMap(
255 conn,
256 (
257 [scope, conn]
258 ) =>
259 (id === 0 ? options.begin(conn) : options.savepoint(conn, id)).pipe(
260 Effect.flatMap(() =>
261 Effect.onExitPrimitive(
262 Effect.provideContext(
263 restore(effect),
264 services.pipe(
265 Context.add(options.transactionService, [conn, id]),
266 Context.add(transactionSemaphore, Semaphore.makeUnsafe(1)),
267 Context.add(Tracer.ParentSpan, span)
268 )
269 ),
270 (exit) => {
271 let effect: Effect.Effect<void>
272 if (Exit.isSuccess(exit)) {
273 if (id === 0) {
274 span.event("db.transaction.commit", clock.currentTimeNanosUnsafe())
275 effect = Effect.orDie(options.commit(conn))
276 } else {
277 span.event("db.transaction.savepoint", clock.currentTimeNanosUnsafe())
278 effect = Effect.void
279 }
280 } else {
281 span.event("db.transaction.rollback", clock.currentTimeNanosUnsafe())

Callers 1

SqlClient.tsFile · 0.85

Calls 12

getRefMethod · 0.80
commitMethod · 0.80
rollbackMethod · 0.80
withPermitMethod · 0.80
getUnsafeMethod · 0.80
attributeMethod · 0.65
pipeMethod · 0.65
addMethod · 0.65
eventMethod · 0.65
closeMethod · 0.65
succeedMethod · 0.45

Tested by

no test coverage detected