connection-pool-0.2.2: src/Data/ConnectionPool/Internal/TCP.hs
{-# LANGUAGE CPP #-}
{-# LANGUAGE DeriveDataTypeable #-}
{-# LANGUAGE DeriveGeneric #-}
{-# LANGUAGE FlexibleInstances #-}
{-# LANGUAGE MultiParamTypeClasses #-}
{-# LANGUAGE NoImplicitPrelude #-}
{-# LANGUAGE PolyKinds #-}
#ifdef KIND_POLYMORPHIC_TYPEABLE
{-# LANGUAGE StandaloneDeriving #-}
#endif
{-# LANGUAGE TypeFamilies #-}
-- |
-- Module: $HEADER$
-- Description: Family of connection pools specialized by transport protocol.
-- Copyright: (c) 2014-2016 Peter Trško
-- License: BSD3
--
-- Maintainer: peter.trsko@gmail.com
-- Stability: unstable (internal module)
-- Portability: GHC specific language extensions.
--
-- Module defines type family of connection pools that is later specialised
-- using type tags (phantom types) to specialize implementation of underlying
-- 'Internal.ConnectionPool' for various protocols.
--
-- Internal packages are here to provide access to internal definitions for
-- library writers, but they should not be used in application code.
--
-- Preferably use qualified import, e.g.:
--
-- > import qualified Data.ConnectionPool.Internal.TCP as Internal
--
-- /Module introduced in version 0.2./
module Data.ConnectionPool.Internal.TCP
( ConnectionPool(..)
, TcpClient
, createTcpClientPool
, withTcpClientConnection
, tryWithTcpClientConnection
, destroyAllTcpClientConnections
)
where
import Data.Function ((.), const)
import Data.Functor ((<$>))
import Data.Maybe (Maybe(Nothing))
import Data.Typeable (Typeable)
import GHC.Generics (Generic)
import Text.Show (Show)
import System.IO (IO)
import Network.Socket (SockAddr, Socket)
import Control.Monad.Trans.Control (MonadBaseControl)
import Data.Function.Between.Strict ((<^@~))
import Data.Streaming.Network
( AppData
, ClientSettings
)
import Data.ConnectionPool.Class
( ConnectionPoolFor
( HandlerData
, destroyAllConnections
, tryWithConnection
, withConnection
)
)
import Data.ConnectionPool.Family (ConnectionPool)
import Data.ConnectionPool.Internal.ConnectionPool
( HasConnectionPool(connectionPool)
)
import qualified Data.ConnectionPool.Internal.ConnectionPool as Internal
( ConnectionPool
, createConnectionPool
, destroyAllConnections
, tryWithConnection
, withConnection
)
import Data.ConnectionPool.Internal.HandlerParams (HandlerParams)
import qualified Data.ConnectionPool.Internal.Streaming as Internal
( acquireTcpClientConnection
, close
, fromClientSettings
, runTcpApp
)
import Data.ConnectionPool.Internal.ResourcePoolParams (ResourcePoolParams)
-- | Type tag used to specialize connection pool for TCP clients.
--
-- /Instance for 'Generic' introduced in version 0.2./
data TcpClient
deriving (Generic, Typeable)
-- | Connection pool for TCP clients.
--
-- /Definition changed in version 0.1.3 and 0.2./
-- /Instances for 'Generic' and 'Show' introduced in version 0.2./
newtype instance ConnectionPool TcpClient =
TcpConnectionPool (Internal.ConnectionPool HandlerParams Socket SockAddr)
deriving (Generic, Show)
-- | /Since version 0.2./
instance
HasConnectionPool HandlerParams Socket SockAddr (ConnectionPool TcpClient)
where
connectionPool = const TcpConnectionPool <^@~ \(TcpConnectionPool a) -> a
{-# INLINE connectionPool #-}
-- | Defined using:
--
-- @
-- 'withConnection' = 'withTcpClientConnection'
-- 'destroyAllConnections' = 'destroyAllTcpClientConnections'
-- @
--
-- /Since version 0.2./
instance ConnectionPoolFor TcpClient where
type HandlerData TcpClient = AppData
withConnection = withTcpClientConnection
{-# INLINE withConnection #-}
tryWithConnection = tryWithTcpClientConnection
{-# INLINE tryWithConnection #-}
destroyAllConnections = destroyAllTcpClientConnections
{-# INLINE destroyAllConnections #-}
-- | Create connection pool for TCP clients.
createTcpClientPool
:: ResourcePoolParams
-> ClientSettings
-> IO (ConnectionPool TcpClient)
createTcpClientPool poolParams tcpParams = TcpConnectionPool
<$> Internal.createConnectionPool handlerParams acquire release poolParams
where
acquire = Internal.acquireTcpClientConnection tcpParams
release = Internal.close
handlerParams = Internal.fromClientSettings tcpParams
{-# INLINE createTcpClientPool #-}
-- | Temporarily take a TCP connection from a pool, run client with it, and
-- return it to the pool afterwards. For details how connections are allocated
-- see 'Data.Pool.withResource'.
withTcpClientConnection
:: (MonadBaseControl io m, io ~ IO)
=> ConnectionPool TcpClient
-> (AppData -> m r)
-> m r
withTcpClientConnection (TcpConnectionPool pool) =
Internal.withConnection pool . Internal.runTcpApp Nothing
{-# INLINE withTcpClientConnection #-}
-- | Similar to 'withConnection', but only performs action if a TCP connection
-- could be taken from the pool /without blocking./ Otherwise,
-- 'tryWithResource' returns immediately with 'Nothing' (ie. the action
-- function is not called). Conversely, if a connection can be acquired from
-- the pool without blocking, the action is performed and it's result is
-- returned, wrapped in a 'Just'.
--
-- /Since version 0.2./
tryWithTcpClientConnection
:: (MonadBaseControl io m, io ~ IO)
=> ConnectionPool TcpClient
-> (AppData -> m r)
-> m (Maybe r)
tryWithTcpClientConnection (TcpConnectionPool pool) =
Internal.tryWithConnection pool . Internal.runTcpApp Nothing
{-# INLINE tryWithTcpClientConnection #-}
-- | Destroy all TCP connections that might be still open in a connection pool.
-- This is useful when one needs to release all resources at once and not to
-- wait for idle timeout to be reached.
--
-- For more details see 'Pool.destroyAllResources'.
--
-- /Since version 0.1.1.0./
destroyAllTcpClientConnections
:: ConnectionPool TcpClient
-> IO ()
destroyAllTcpClientConnections (TcpConnectionPool pool) =
Internal.destroyAllConnections pool
{-# INLINE destroyAllTcpClientConnections #-}