Skip to content

Commit 67e07c0

Browse files
committed
Handle pg transactions
1 parent 3f6be3b commit 67e07c0

File tree

2 files changed

+92
-133
lines changed

2 files changed

+92
-133
lines changed

src/WebRow/Selda.purs

Lines changed: 92 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -7,34 +7,36 @@ import Data.Either (Either(..))
77
import Data.Maybe (Maybe(..))
88
import Data.Symbol (SProxy(..))
99
import Data.Variant.Internal (FProxy)
10-
import Database.PostgreSQL (Connection, PGError, Query(..), execute) as PG
1110
import Database.PostgreSQL (PGError, Row0(..))
12-
import Database.PostgreSQL (class FromSQLRow, class ToSQLRow, Query, query) as PostgreSQL
11+
import Database.PostgreSQL (class FromSQLRow, class ToSQLRow, Connection, PGError, Pool, Query(..), ConnectResult, connect, execute, query) as PG
1312
import Effect.Aff (Aff)
1413
import Run (Run)
1514
import Run as Run
1615
import Run.Except (EXCEPT, throwAt)
17-
import Run.Reader (READER, askAt)
16+
import Run.State (STATE, getAt, modifyAt, putAt)
1817
import Selda (Col, FullQuery, Table)
1918
import Selda.PG.Class (class InsertRecordIntoTableReturning, BackendPGClass)
2019
import Selda.PG.Class (deleteFrom, insert, insert1, insert1_, query, query1, update) as PG.Class
2120
import Selda.Query.Class (class GenericDelete, class GenericInsert, class GenericQuery, class GenericUpdate)
2221
import Type.Row (type (+))
23-
import WebRow.Contrib.Run (AffRow)
22+
import WebRow.Contrib.Run (AffRow, EffRow)
2423

2524
type SeldaPG
2625
= ExceptT PG.PGError (ReaderT PG.Connection Aff)
2726

2827
-- | I'm not sure if this represtation is consistent.
29-
-- | I want to allow some inspection but also compile
30-
-- | those actions without coercing.
28+
-- | I want to allow some intronspection but also compile
29+
-- | those actions without coercing or experimenting with
30+
-- | `Exist` here.
3131
-- |
3232
-- | * Probably we could split query and keep `FullQuery`.
3333
-- | * We can add `∀ i o. Query i o` to `PgQueryF`.
3434
data SeldaF a
3535
= SeldaF (SeldaPG a)
36-
| PgExecuteF String (Unit a)
36+
| PgExecuteF String a
3737
| PgQueryF (PG.Connection Aff (Either PGError a))
38+
| PgOpenTransactionF a
39+
| PgCloseTransactionF a
3840

3941
derive instance functorSeldaFFunctor SeldaF
4042

@@ -50,9 +52,9 @@ type PgError r
5052
= ( pgError EXCEPT PGError | r )
5153

5254
type PgConnection r
53-
= ( pgConnection READER { conn PG.Connection, inTransaction Boolean } | r )
55+
= ( pg STATE { conn Maybe PG.ConnectResult, inTransaction Boolean, pool PG.Pool } | r )
5456

55-
_pgConnection = SProxy SProxy "pgConnection"
57+
_pg = SProxy SProxy "pg"
5658

5759
_pgError = SProxy SProxy "pgError"
5860

@@ -101,40 +103,96 @@ update ∷
101103
Table t ({ | r } Col BackendPGClass Boolean) ({ | r } { | r }) Run (Selda + eff) Unit
102104
update table cond set = Run.lift _selda (SeldaF (PG.Class.update table cond set))
103105

106+
openTransaction eff. Run (Selda + eff) Unit
107+
openTransaction = Run.lift _selda (PgOpenTransactionF unit)
108+
109+
closeTransaction eff. Run (Selda + eff) Unit
110+
closeTransaction = Run.lift _selda (PgCloseTransactionF unit)
111+
112+
withTransaction a eff. Run (Selda + eff) a Run (Selda + eff) a
113+
withTransaction block = do
114+
openTransaction
115+
r ← block
116+
closeTransaction
117+
pure r
118+
104119
pgExecute eff. String Run (Selda + eff) Unit
105-
pgExecute q = Run.lift _selda (PgExecuteF q identity)
120+
pgExecute q = Run.lift _selda (PgExecuteF q unit)
106121

107122
pgQuery
108123
eff i o.
109-
PostgreSQL.ToSQLRow i
110-
PostgreSQL.FromSQLRow o
111-
PostgreSQL.Query i o
124+
PG.ToSQLRow i
125+
PG.FromSQLRow o
126+
PG.Query i o
112127
i
113128
Run (Selda + eff) (Array o)
114-
pgQuery q i = Run.lift _selda (PgQueryF (\conn → PostgreSQL.query conn q i))
129+
pgQuery q i = Run.lift _selda (PgQueryF (\conn → PG.query conn q i))
115130

116131
run
117132
eff.
118-
Run (AffRow + PgConnection + PgError + Selda + eff)
119-
~> Run (AffRow + PgConnection + PgError + eff)
120-
run = Run.run (Run.on _selda handleSelda Run.send)
133+
Run (AffRow + EffRow + PgConnection + PgError + Selda + eff)
134+
~> Run (AffRow + EffRow + PgConnection + PgError + eff)
135+
run action = do
136+
a ← Run.run (Run.on _selda handleSelda Run.send) action
137+
getAt _pg >>= _.conn
138+
>>> case _ of
139+
Just { connection, done } → do
140+
inTransaction
141+
>>= flip when do
142+
execute "ROLLBACK TRANSACTION"
143+
modifyAt _pg _ { inTransaction = false }
144+
Run.liftEffect $ done
145+
modifyAt _pg _ { conn = Nothing }
146+
Nothing → pure unit
147+
pure a
121148
where
122-
handleSelda a. SeldaF a Run (AffRow + PgConnection + PgError + eff) a
123-
handleSelda action = do
124-
{ conn, inTransaction } ← askAt _pgConnection
125-
case action of
126-
SeldaF q → do
127-
Run.liftAff (runReaderT (runExceptT q) conn)
128-
>>= case _ of
129-
Right next → pure next
130-
Left err → throwAt _pgError err
131-
PgExecuteF q next → do
132-
(Run.liftAff $ PG.execute conn (PG.Query q) Row0)
133-
>>= case _ of
134-
Just err → throwAt _pgError err
135-
Nothing → pure (next unit)
136-
PgQueryF q → do
137-
(Run.liftAff (q conn))
149+
inTransaction = getAt _pg <#> _.inTransaction
150+
151+
conn = do
152+
pg ← getAt _pg
153+
case pg.conn of
154+
Nothing
155+
(Run.liftAff (PG.connect pg.pool))
138156
>>= case _ of
157+
Right result → do
158+
putAt _pg (pg { conn = Just result })
159+
pure result.connection
139160
Left err → throwAt _pgError err
140-
Right next → pure next
161+
Just { connection } → pure connection
162+
163+
execute q = do
164+
c ← conn
165+
(Run.liftAff $ PG.execute c (PG.Query q) Row0)
166+
>>= case _ of
167+
Just err → throwAt _pgError err
168+
Nothing → pure unit
169+
170+
handleSelda a. SeldaF a Run (AffRow + EffRow + PgConnection + PgError + eff) a
171+
handleSelda = case _ of
172+
SeldaF q → do
173+
c ← conn
174+
Run.liftAff (runReaderT (runExceptT q) c)
175+
>>= case _ of
176+
Right next → pure next
177+
Left err → throwAt _pgError err
178+
PgExecuteF q next → do
179+
execute q
180+
pure next
181+
PgQueryF q → do
182+
c ← conn
183+
(Run.liftAff (q c))
184+
>>= case _ of
185+
Left err → throwAt _pgError err
186+
Right next → pure next
187+
PgOpenTransactionF next → do
188+
inTransaction >>= not
189+
>>> flip when do
190+
execute "BEGIN TRANSACTION"
191+
modifyAt _pg _ { inTransaction = true }
192+
pure next
193+
PgCloseTransactionF next → do
194+
inTransaction
195+
>>= flip when do
196+
execute "END TRANSACTION"
197+
modifyAt _pg _ { inTransaction = false }
198+
pure next

src/WebRow/Session/DataStore/InCookie.purs

Lines changed: 0 additions & 99 deletions
This file was deleted.

0 commit comments

Comments
 (0)