{-# LANGUAGE DeriveGeneric #-} {-# LANGUAGE DataKinds #-} {-# LANGUAGE OverloadedLabels #-} {-# LANGUAGE FlexibleContexts #-} {-# LANGUAGE OverloadedStrings #-} {-# LANGUAGE TypeApplications #-} {-# LANGUAGE TypeOperators #-} {-# LANGUAGE GADTs #-} {-# LANGUAGE DeriveGeneric #-} {-# LANGUAGE DeriveAnyClass #-} {-# LANGUAGE DerivingStrategies #-} {-# LANGUAGE ScopedTypeVariables #-} {-# LANGUAGE StandaloneDeriving #-} module Gauge.DBHelpers where import qualified Data.ByteString.Char8 as C import qualified Data.Text as T import Control.Monad ( void ) import Control.Monad.IO.Class ( liftIO ) import Control.Monad.Loops ( iterateWhile ) import GHC.Generics ( Generic ) import Test.QuickCheck import Squeal.PostgreSQL import qualified Squeal.PostgreSQL.Session.Transaction.Unsafe as Unsafe import Control.DeepSeq -- Project imports import Gauge.Schema ( Schemas ) import Gauge.Queries ( InsertUser(..) ) import Gauge.DBSetup newtype SquealPool = SquealPool {getSquealPool :: Pool (K Connection Schemas)} deriving (Generic) -- Below may be wrong - it may screw up the whole connection pool using in tests instance NFData SquealPool where rnf = rwhnf runDbErr :: SquealPool -> PQ Schemas Schemas IO b -> IO (Either SquealException b) runDbErr pool session = do liftIO . runUsingConnPool pool $ trySqueal (Unsafe.transactionally_ session) runDbWithPool :: SquealPool -> PQ Schemas Schemas IO b -> IO b runDbWithPool pool session = do errOrResult <- runDbErr pool session case errOrResult of Left err -> throwSqueal err Right result -> return result -- | Helper runUsingConnPool :: SquealPool -> PQ Schemas Schemas IO x -> IO x runUsingConnPool (SquealPool pool) = usingConnectionPool pool makePool :: C.ByteString -> IO SquealPool makePool connStr = do pool <- createConnectionPool connStr 1 0.5 10 return $ SquealPool pool initDBWithPool :: IO SquealPool initDBWithPool = do void initDB pool <- makePool connectionString return pool getRandomUser :: IO InsertUser getRandomUser = iterateWhile noEmptyEmail $ generate arbitrary where noEmptyEmail InsertUser { userEmail = userEmail } = T.length userEmail < 5