{-# LANGUAGE ConstraintKinds #-} {-# LANGUAGE FlexibleContexts #-} {-# LANGUAGE FlexibleInstances #-} {-# LANGUAGE OverloadedStrings #-} {-# LANGUAGE TypeFamilies #-} module Snap.Snaplet.AMQP ( initAMQP , runAmqp , mkAmqpConn , AmqpState (..) , HasAmqpConn (..) ) where import Control.Monad.State import Control.Monad.Trans.Reader import Data.Configurator import Data.Configurator.Types import Network.AMQP (Channel, Connection, openChannel, openConnection') import Network.Socket (PortNumber (..)) import Paths_snaplet_amqp import Snap.Snaplet ------------------------------------------------------------------------------- type AmqpC = (Connection, Channel) newtype AmqpState = AmqpState { amqpConn :: AmqpC } ------------------------------------------------------------------------------- class MonadIO m => HasAmqpConn m where getAmqpConn :: m AmqpC instance HasAmqpConn (Handler b AmqpState) where getAmqpConn = gets amqpConn instance MonadIO m => HasAmqpConn (ReaderT AmqpC m) where getAmqpConn = ask -- | Initialize the AMQP Snaplet. initAMQP :: SnapletInit b AmqpState initAMQP = makeSnaplet "persist" description datadir $ do c <- mkSnapletAmqpConn return $ AmqpState c where description = "Snaplet for AMQP library" datadir = Just $ liftM (++"/resources/amqp") getDataDir ------------------------------------------------------------------------------- -- | Constructs a connection in a snaplet context. mkSnapletAmqpConn :: (MonadIO (m b v), MonadSnaplet m) => m b v AmqpC mkSnapletAmqpConn = do conf <- getSnapletUserConfig mkAmqpConn conf ------------------------------------------------------------------------------- -- | Constructs a connect from Config. mkAmqpConn :: MonadIO m => Config -> m AmqpC mkAmqpConn conf = do host <- liftIO $ require conf "host" port <- liftIO $ require conf "port" vhost <- liftIO $ require conf "vhost" login <- liftIO $ require conf "login" pass <- liftIO $ require conf "password" conn <- liftIO $ openConnection' host (PortNum port) vhost login pass chan <- liftIO $ openChannel conn return (conn, chan) ------------------------------------------------------------------------------- -- | Runs an AMQP action in any monad with a HasAmqpConn instance. runAmqp :: (HasAmqpConn m) => (AmqpC -> b) -> m b runAmqp action = getAmqpConn >>= return . action