Skip to content

Commit

Permalink
feat(tc): better tc impl
Browse files Browse the repository at this point in the history
  • Loading branch information
Kerry Perret committed Jan 23, 2021
1 parent 9a1b6b9 commit 5a1bd7d
Show file tree
Hide file tree
Showing 3 changed files with 30 additions and 14 deletions.
2 changes: 1 addition & 1 deletion Vp.FSharp.Sql/SqlCommand.fs
Original file line number Diff line number Diff line change
Expand Up @@ -75,7 +75,7 @@ module Vp.FSharp.Sql.SqlCommand
let command = deps.CreateCommand connection

Option.iter
(fun transaction -> command.Transaction <- transaction)
(deps.SetCommandTransaction command)
(commandDefinition.Transaction)

match commandDefinition.Text with
Expand Down
40 changes: 27 additions & 13 deletions Vp.FSharp.Sql/Transaction.fs
Original file line number Diff line number Diff line change
@@ -1,51 +1,62 @@
[<RequireQualifiedAccess>]
module Vp.FSharp.Sql.Transaction

open System.Data
open System.Threading
open System.Data.Common

open System.Threading.Tasks
open System.Transactions

open Vp.FSharp.Sql.Helpers


[<Literal>]
let DefaultIsolationLevel = IsolationLevel.ReadCommitted

let commit cancellationToken isolationLevel (connection: #DbConnection) body =
let commit cancellationToken isolationLevel
(connection: #DbConnection)
(beginTransaction: #DbConnection -> IsolationLevel -> CancellationToken -> ValueTask<#DbTransaction>)
(body: #DbConnection -> #DbTransaction -> Async<'Output>)=
async {
let wasClosed = DbConnection.isClosed connection
let! linkedToken = Async.linkedTokenSourceFrom cancellationToken
try
if wasClosed then do! DbConnection.openIfClosed linkedToken wasClosed connection
use! transaction = connection.BeginTransactionAsync(isolationLevel, linkedToken) |> Async.AwaitValueTask
let! actionResult = body connection
use! transaction = beginTransaction connection isolationLevel linkedToken |> Async.AwaitValueTask
let! actionResult = body connection transaction
do! transaction.CommitAsync(linkedToken) |> Async.AwaitTask
return actionResult
finally
DbConnection.closedIfClosed wasClosed connection
}

let notCommit cancellationToken isolationLevel (connection: #DbConnection) body =
let notCommit cancellationToken isolationLevel
(connection: #DbConnection)
(beginTransaction: #DbConnection -> IsolationLevel -> CancellationToken -> ValueTask<#DbTransaction>)
(body: #DbConnection -> #DbTransaction -> Async<'Output>) =
async {
let wasClosed = DbConnection.isClosed connection
let! linkedToken = Async.linkedTokenSourceFrom cancellationToken
try
if wasClosed then do! DbConnection.openIfClosed linkedToken wasClosed connection
use! _transaction = connection.BeginTransactionAsync(isolationLevel, linkedToken) |> Async.AwaitValueTask
let! actionResult = body connection
use! transaction = beginTransaction connection isolationLevel linkedToken |> Async.AwaitValueTask
let! actionResult = body connection transaction
return actionResult
finally
DbConnection.closedIfClosed wasClosed connection
}

let commitOnSome cancellationToken isolationLevel (connection: #DbConnection) body =
let commitOnSome cancellationToken isolationLevel
(connection: #DbConnection)
(beginTransaction: #DbConnection -> IsolationLevel -> CancellationToken -> ValueTask<#DbTransaction>)
(body: #DbConnection -> #DbTransaction -> Async<'Output option>) =
async {
let wasClosed = DbConnection.isClosed connection
let! linkedToken = Async.linkedTokenSourceFrom cancellationToken
try
if wasClosed then do! DbConnection.openIfClosed linkedToken wasClosed connection
use! transaction = connection.BeginTransactionAsync(isolationLevel, linkedToken) |> Async.AwaitValueTask
match! body connection with
use! transaction = beginTransaction connection isolationLevel linkedToken |> Async.AwaitValueTask
match! body connection transaction with
| Some some ->
do! transaction.CommitAsync(linkedToken) |> Async.AwaitTask
return Some some
Expand All @@ -55,14 +66,17 @@ let commitOnSome cancellationToken isolationLevel (connection: #DbConnection) bo
DbConnection.closedIfClosed wasClosed connection
}

let commitOnOk cancellationToken isolationLevel (connection: #DbConnection) body =
let commitOnOk cancellationToken isolationLevel
(connection: #DbConnection)
(beginTransaction: #DbConnection -> IsolationLevel -> CancellationToken -> ValueTask<#DbTransaction>)
(body: #DbConnection -> #DbTransaction -> Async<Result<'Ok, 'Error>>) =
async {
let wasClosed = DbConnection.isClosed connection
let! linkedToken = Async.linkedTokenSourceFrom cancellationToken
try
if wasClosed then do! DbConnection.openIfClosed linkedToken wasClosed connection
use! transaction = connection.BeginTransactionAsync(isolationLevel, linkedToken) |> Async.AwaitValueTask
match! body connection with
use! transaction = beginTransaction connection isolationLevel linkedToken |> Async.AwaitValueTask
match! body connection transaction with
| Ok ok ->
do! transaction.CommitAsync(linkedToken) |> Async.AwaitTask
return Ok ok
Expand Down
2 changes: 2 additions & 0 deletions Vp.FSharp.Sql/Types.fs
Original file line number Diff line number Diff line change
Expand Up @@ -115,6 +115,8 @@ type SqlDependencies<'DbConnection, 'DbCommand, 'DbParameter, 'DbDataReader, 'Db
and 'DbDataReader :> DbDataReader
and 'DbTransaction :> DbTransaction> =
{ CreateCommand: 'DbConnection -> 'DbCommand
SetCommandTransaction: 'DbCommand -> 'DbTransaction -> unit
BeginTransactionAsync: 'DbConnection -> IsolationLevel -> CancellationToken -> ValueTask<'DbTransaction>
ExecuteReaderAsync: 'DbCommand -> CancellationToken -> Task<'DbDataReader>
DbValueToParameter: string -> 'DbType -> 'DbParameter }

Expand Down

0 comments on commit 5a1bd7d

Please sign in to comment.