Skip to content

Commit 044d954

Browse files
committed
Move transaction related functions to a separate module
Extract `begin`, `commit` and `rollback` that can be used separately from `withTransaction`.
1 parent 5d3be54 commit 044d954

File tree

4 files changed

+86
-43
lines changed

4 files changed

+86
-43
lines changed

MODULE.md

Lines changed: 43 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -135,25 +135,6 @@ withClient :: forall eff a. ConnectionInfo -> (Client -> Aff (db :: DB | eff) a)
135135
Takes a Client from the connection pool, runs the given function with
136136
the client and returns the results.
137137

138-
#### `withTransaction`
139-
140-
``` purescript
141-
withTransaction :: forall eff a. (Client -> Aff (db :: DB | eff) a) -> Client -> Aff (db :: DB | eff) a
142-
```
143-
144-
Runs an asynchronous action in a database transaction. The transaction
145-
will be rolled back if the computation fails and committed otherwise.
146-
147-
Here the first insert will be rolled back:
148-
149-
```purescript
150-
moneyTransfer :: forall e. (Client -> Aff e Unit) -> Client -> Aff e Unit
151-
moneyTransfer = withTransaction $ \c -> do
152-
execute_ (Query "insert into accounts ...") c
153-
throwError $ error "Something went wrong"
154-
execute_ (Query "insert into accounts ...") c
155-
```
156-
157138
#### `end`
158139

159140
``` purescript
@@ -215,4 +196,47 @@ instance isSqlValueMaybe :: (IsSqlValue a) => IsSqlValue (Maybe a)
215196

216197

217198

199+
## Module Database.Postgres.Transaction
200+
201+
#### `withTransaction`
202+
203+
``` purescript
204+
withTransaction :: forall eff a. (Client -> Aff (db :: DB | eff) a) -> Client -> Aff (db :: DB | eff) a
205+
```
206+
207+
Runs an asynchronous action in a database transaction. The transaction
208+
will be rolled back if the computation fails and committed otherwise.
209+
210+
Here the first insert will be rolled back:
211+
212+
```purescript
213+
moneyTransfer :: forall e. (Client -> Aff e Unit) -> Client -> Aff e Unit
214+
moneyTransfer = withTransaction $ \c -> do
215+
execute_ (Query "insert into accounts ...") c
216+
throwError $ error "Something went wrong"
217+
execute_ (Query "insert into accounts ...") c
218+
```
219+
220+
#### `begin`
221+
222+
``` purescript
223+
begin :: forall eff. Client -> Aff (db :: DB | eff) Unit
224+
```
225+
226+
227+
#### `commit`
228+
229+
``` purescript
230+
commit :: forall eff. Client -> Aff (db :: DB | eff) Unit
231+
```
232+
233+
234+
#### `rollback`
235+
236+
``` purescript
237+
rollback :: forall eff. Client -> Aff (db :: DB | eff) Unit
238+
```
239+
240+
241+
218242

src/Database/Postgres.purs

Lines changed: 0 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,6 @@ module Database.Postgres
1414
, queryOne, queryOne_
1515
, withConnection
1616
, withClient
17-
, withTransaction
1817
) where
1918

2019
import Control.Alt
@@ -132,27 +131,6 @@ withClient :: forall eff a
132131
-> Aff (db :: DB | eff) a
133132
withClient info p = runFn2 _withClient (mkConnectionString info) p
134133

135-
-- | Runs an asynchronous action in a database transaction. The transaction
136-
-- | will be rolled back if the computation fails and committed otherwise.
137-
-- |
138-
-- | Here the first insert will be rolled back:
139-
-- |
140-
-- | ```purescript
141-
-- | moneyTransfer :: forall e. (Client -> Aff e Unit) -> Client -> Aff e Unit
142-
-- | moneyTransfer = withTransaction $ \c -> do
143-
-- | execute_ (Query "insert into accounts ...") c
144-
-- | throwError $ error "Something went wrong"
145-
-- | execute_ (Query "insert into accounts ...") c
146-
-- | ```
147-
withTransaction :: forall eff a. (Client -> Aff (db :: DB | eff) a) -> Client -> Aff (db :: DB | eff) a
148-
withTransaction act client = do
149-
execute_ (Query "BEGIN TRANSACTION") client
150-
res <- attempt (act client)
151-
either rollback commit res
152-
where
153-
rollback err = execute_ (Query "ROLLBACK") client *> throwError err
154-
commit v = execute_ (Query "COMMIT") client *> pure v
155-
156134
liftError :: forall e a. ForeignError -> Aff e a
157135
liftError err = throwError $ error (show err)
158136

Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
module Database.Postgres.Transaction where
2+
3+
import Control.Apply ((*>))
4+
import Control.Monad.Aff
5+
import Control.Monad.Error.Class (throwError)
6+
import Data.Either
7+
8+
import Database.Postgres
9+
import Database.Postgres.SqlValue
10+
11+
-- | Runs an asynchronous action in a database transaction. The transaction
12+
-- | will be rolled back if the computation fails and committed otherwise.
13+
-- |
14+
-- | Here the first insert will be rolled back:
15+
-- |
16+
-- | ```purescript
17+
-- | moneyTransfer :: forall e. (Client -> Aff e Unit) -> Client -> Aff e Unit
18+
-- | moneyTransfer = withTransaction $ \c -> do
19+
-- | execute_ (Query "insert into accounts ...") c
20+
-- | throwError $ error "Something went wrong"
21+
-- | execute_ (Query "insert into accounts ...") c
22+
-- | ```
23+
withTransaction :: forall eff a. (Client -> Aff (db :: DB | eff) a) -> Client -> Aff (db :: DB | eff) a
24+
withTransaction act client = do
25+
begin client
26+
res <- attempt (act client)
27+
either rollback_ commit_ res
28+
where
29+
rollback_ err = rollback client *> throwError err
30+
commit_ v = commit client *> pure v
31+
32+
begin :: forall eff. Client -> Aff (db :: DB | eff) Unit
33+
begin = execute_ (Query "BEGIN TRANSACTION")
34+
35+
commit :: forall eff. Client -> Aff (db :: DB | eff) Unit
36+
commit = execute_ (Query "COMMIT")
37+
38+
rollback :: forall eff. Client -> Aff (db :: DB | eff) Unit
39+
rollback = execute_ (Query "ROLLBACK")

test/Main.purs

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,5 @@
11
module Test.Main where
22

3-
import Database.Postgres
4-
import Database.Postgres.SqlValue
53
import Debug.Trace
64
import Control.Monad.Eff
75
import Control.Monad.Eff.Class
@@ -18,6 +16,10 @@ import Data.Foreign.Class
1816
import Data.Foreign.Index
1917
import Control.Monad.Aff
2018

19+
import Database.Postgres
20+
import Database.Postgres.SqlValue
21+
import Database.Postgres.Transaction
22+
2123
main = runAff (trace <<< show) (const $ trace "All ok") $ do
2224
liftEff <<< trace $ "connecting to " <> mkConnectionString connectionInfo <> "..."
2325
exampleUsingWithConnection

0 commit comments

Comments
 (0)