-
Notifications
You must be signed in to change notification settings - Fork 39
/
Copy pathtryaction.hs
70 lines (54 loc) · 2.16 KB
/
tryaction.hs
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
{-# LANGUAGE FlexibleInstances #-}
{-# LANGUAGE GADTs #-}
{-# LANGUAGE QuasiQuotes #-}
{-# LANGUAGE StandaloneDeriving #-}
{-# LANGUAGE TemplateHaskell #-}
{-# LANGUAGE TypeFamilies #-}
module Main where
import Control.Exception.Safe
import Control.Monad.IO.Class
import Control.Monad.Trans.Class
import Control.Monad.Trans.Except
import Database.Groundhog.Core
import Database.Groundhog.Sqlite
import Database.Groundhog.TH
data Customer = Customer {customerName :: String, customerPhone :: String} deriving (Show)
data TestException = TestException
deriving (Show)
instance Exception TestException
mkPersist
defaultCodegenConfig
[groundhog|
- entity: Customer # Name of the datatype
constructors:
- name: Customer
uniques:
- name: PhoneConstraint
fields: [ customerPhone ]
|]
migration :: PersistBackendConn conn => Action conn ()
migration = runMigration $ do
migrate (undefined :: Customer)
insertCustomer :: (MonadIO m, PersistBackendConn conn) => Customer -> TryAction TestException m conn (Key Customer BackendSpecific)
insertCustomer = insert
insertFails :: (MonadIO m, PersistBackendConn conn) => TryAction TestException m conn (Key Customer BackendSpecific)
insertFails = do
janeKey <- insert $ Customer "Jane Doe" "987654321"
-- Some logic leads to exception
lift $ throwE TestException
pure janeKey
main = withSqliteConn ":memory:" $ \conn -> do
-- create tables
runDbConn migration conn >>= liftIO . print
let customer = Customer "John Doe" "0123456789"
-- Use runTryDbConn to run a TryAction.
-- Insert that is successful
runTryDbConn (insertCustomer customer) conn >>= liftIO . print
-- Insert that fails because of the unique condition
runTryDbConn (insertCustomer customer) conn >>= liftIO . print
-- Insert that fails because of the exception
runTryDbConn insertFails conn >>= liftIO . print
-- Use runTryDbConn' to run an Action and catch the exception if it fails
runTryDbConn' (insert customer) conn >>= liftIO . print
-- Select all customers confirms that the failing TryActions and Action were rolled back
runDbConn (select CondEmpty) conn >>= liftIO . (print :: [Customer] -> IO ())