module Polysemy.Hasql.Interpreter.Transaction where import Hasql.Connection (Connection) import qualified Polysemy.Db.Data.DbError as DbError import Polysemy.Db.Data.DbError (DbError) import qualified Polysemy.Hasql.Effect.Database as Database import Polysemy.Hasql.Effect.Database (ConnectionSource, Database, withDatabaseUnique) import Polysemy.Hasql.Effect.Transaction (Transaction (Abort, Resource), Transactions) import Polysemy.Hasql.Statement.Transaction (beginTransaction, commitTransaction, rollbackTransaction) transactionScopeWithConnection :: Members [Database, Resource, Stop DbError] r => (Connection -> Sem (Stop DbError : r) a) -> Sem r a transactionScopeWithConnection :: forall (r :: EffectRow) a. Members '[Database, Resource, Stop DbError] r => (Connection -> Sem (Stop DbError : r) a) -> Sem r a transactionScopeWithConnection Connection -> Sem (Stop DbError : r) a use = forall (r :: EffectRow) a c b. Member Resource r => Sem r a -> (a -> Sem r c) -> (a -> Sem r b) -> Sem r b bracketOnError (forall {o}. Statement () o -> Sem r o runS (TransactionConfig -> Bool -> Statement () () beginTransaction forall a. Default a => a def Bool False)) () -> Sem r () abortTr \ () -> do forall (r :: EffectRow) a. Member Database r => (Connection -> Sem r a) -> Sem r a Database.use \ Connection connection -> forall (e :: (* -> *) -> * -> *) (r :: EffectRow) a. Member e r => Sem (e : r) a -> Sem r a subsume (Connection -> Sem (Stop DbError : r) a use Connection connection) forall (f :: * -> *) a b. Applicative f => f a -> f b -> f a <* forall {o}. Statement () o -> Sem r o runS (Bool -> Statement () () commitTransaction Bool False) where abortTr :: () -> Sem r () abortTr () _ = forall {o}. Statement () o -> Sem r o runS (Bool -> Statement () () rollbackTransaction Bool False) runS :: Statement () o -> Sem r o runS = forall (r :: EffectRow) p o. Member Database r => p -> Statement p o -> Sem r o Database.statement () transactionScope :: Members [Scoped ConnectionSource (Database !! DbError), Resource] (Stop DbError : r) => (Connection -> Sem (Stop DbError : r) a) -> Sem (Stop DbError : r) a transactionScope :: forall (r :: EffectRow) a. Members '[Scoped ConnectionSource (Database !! DbError), Resource] (Stop DbError : r) => (Connection -> Sem (Stop DbError : r) a) -> Sem (Stop DbError : r) a transactionScope Connection -> Sem (Stop DbError : r) a use = forall (r :: EffectRow). Member (Scoped ConnectionSource (Database !! DbError)) r => Maybe ConnectionTag -> InterpreterFor (Database !! DbError) r withDatabaseUnique forall a. Maybe a Nothing forall a b. (a -> b) -> a -> b $ forall err (eff :: (* -> *) -> * -> *) (r :: EffectRow). Members '[Resumable err eff, Stop err] r => InterpreterFor eff r restop @DbError @Database do forall (r :: EffectRow) a. Members '[Database, Resource, Stop DbError] r => (Connection -> Sem (Stop DbError : r) a) -> Sem r a transactionScopeWithConnection (forall (index :: Nat) (inserted :: EffectRow) (head :: EffectRow) (oldTail :: EffectRow) (tail :: EffectRow) (old :: EffectRow) (full :: EffectRow) a. (ListOfLength index head, WhenStuck index InsertAtUnprovidedIndex, old ~ Append head oldTail, tail ~ Append inserted oldTail, full ~ Append head tail, InsertAtIndex index head tail oldTail full inserted) => Sem old a -> Sem full a insertAt @1 forall b c a. (b -> c) -> (a -> b) -> a -> c . Connection -> Sem (Stop DbError : r) a use) interpretTransactions :: Members [Scoped ConnectionSource (Database !! DbError), Resource] r => InterpreterFor (Transactions Connection !! DbError) r interpretTransactions :: forall (r :: EffectRow). Members '[Scoped ConnectionSource (Database !! DbError), Resource] r => InterpreterFor (Transactions Connection !! DbError) r interpretTransactions = forall (extra :: EffectRow) param resource (effect :: (* -> *) -> * -> *) err (r :: EffectRow). KnownList extra => (forall (q :: (* -> *) -> * -> *) x. param -> (resource -> Sem (extra ++ (Stop err : Opaque q : r)) x) -> Sem (Stop err : Opaque q : r) x) -> (forall (q :: (* -> *) -> * -> *) (r0 :: EffectRow) x. resource -> effect (Sem r0) x -> Tactical effect (Sem r0) (extra ++ ('[Stop err, Opaque q] ++ r)) x) -> InterpreterFor (Scoped param effect !! err) r interpretScopedResumableWithH @'[] (forall a b. a -> b -> a const forall (r :: EffectRow) a. Members '[Scoped ConnectionSource (Database !! DbError), Resource] (Stop DbError : r) => (Connection -> Sem (Stop DbError : r) a) -> Sem (Stop DbError : r) a transactionScope) \ Connection conn -> \case Transaction Connection (Sem r0) x Resource -> forall (f :: * -> *) a (e :: (* -> *) -> * -> *) (m :: * -> *) (r :: EffectRow). Functor f => a -> Sem (WithTactics e f m r) (f a) pureT Connection conn Transaction Connection (Sem r0) x Abort -> forall e (r :: EffectRow) a. Member (Stop e) r => e -> Sem r a stop (Text -> DbError DbError.Query Text "aborted by user")