shard-crystal-db/src/db/begin_transaction.cr

40 lines
1.2 KiB
Crystal

module DB
module BeginTransaction
# Creates a transaction from the current context.
# If is expected that either `Transaction#commit` or `Transaction#rollback`
# are called explicitly to release the context.
abstract def begin_transaction : Transaction
# yields a transaction from the current context.
# Query the database through `Transaction#connection` object.
# If an exception is thrown within the block a rollback is performed.
# The exception thrown is bubbled unless it is a `DB::Rollback`.
# From the yielded object `Transaction#commit` or `Transaction#rollback`
# can be called explicitly.
# Returns the value of the block.
def transaction(& : Transaction -> T) : T? forall T
rollback = false
# TODO: Cast to workaround crystal-lang/crystal#9483
# begin_transaction returns a Tx where Tx < Transaction
tx = begin_transaction.as(Transaction)
begin
res = yield tx
rescue DB::Rollback
rollback = true
res
rescue e
rollback = true
raise e
ensure
unless tx.closed?
if rollback
tx.rollback
else
tx.commit
end
end
end
end
end
end