( effect: Effect<A, E, R> )
| 14526 | * @since 4.0.0 |
| 14527 | */ |
| 14528 | export const tx = <A, E, R>( |
| 14529 | effect: Effect<A, E, R> |
| 14530 | ): Effect<A, E, Exclude<R, Transaction>> => |
| 14531 | withFiber((fiber) => { |
| 14532 | let state = Context.getOrUndefined(fiber.context, Transaction) |
| 14533 | if (state) { |
| 14534 | return effect as Effect<A, E, Exclude<R, Transaction>> |
| 14535 | } |
| 14536 | // Create transaction state only at the outermost boundary |
| 14537 | state = { journal: new Map(), retry: false } |
| 14538 | let result: Exit.Exit<A, E> | undefined |
| 14539 | return uninterruptibleMask((restore) => |
| 14540 | flatMap( |
| 14541 | whileLoop({ |
| 14542 | while: () => !result, |
| 14543 | body: constant( |
| 14544 | restore(effect).pipe( |
| 14545 | provideService(Transaction, state), |
| 14546 | tapCause(() => { |
| 14547 | if (!state.retry) return void_ |
| 14548 | return restore(awaitPendingTransaction(state)) |
| 14549 | }), |
| 14550 | exit |
| 14551 | ) |
| 14552 | ), |
| 14553 | step(exit: Exit.Exit<A, E>) { |
| 14554 | if (state.retry || !isTransactionConsistent(state)) { |
| 14555 | return clearTransaction(state) |
| 14556 | } |
| 14557 | if (Exit.isSuccess(exit)) { |
| 14558 | commitTransaction(fiber, state) |
| 14559 | } else { |
| 14560 | clearTransaction(state) |
| 14561 | } |
| 14562 | result = exit |
| 14563 | } |
| 14564 | }), |
| 14565 | () => result! |
| 14566 | ) |
| 14567 | ) |
| 14568 | }) |
| 14569 | |
| 14570 | const isTransactionConsistent = (state: Transaction["Service"]) => { |
| 14571 | for (const [ref, { version }] of state.journal) { |
nothing calls this directly
no test coverage detected