patterns-0.1.1: src/Network/Mom/Patterns/Basic/Client.hs
-------------------------------------------------------------------------------
-- |
-- Module : Network/Mom/Patterns/Basic/Client.hs
-- Copyright : (c) Tobias Schoofs
-- License : LGPL
-- Stability : experimental
-- Portability: portable
--
-- Client side of Client/Server
-------------------------------------------------------------------------------
module Network.Mom.Patterns.Basic.Client (
Client, clService, withClient, request, checkResult)
where
import qualified System.ZMQ as Z
import Network.Mom.Patterns.Types
import Network.Mom.Patterns.Streams
------------------------------------------------------------------------
-- | Client data type
------------------------------------------------------------------------
data Client = Client {clSock :: Z.Socket Z.Req,
clService :: Service} -- currently unused
------------------------------------------------------------------------
-- | Create a client
-- with name 'Service',
-- linking to address 'String',
-- connecting or binding the address according to 'LinkType'
-- and finally entering the action, in whose scope
-- the client lives.
------------------------------------------------------------------------
withClient :: Context ->
Service ->
String ->
LinkType ->
(Client -> IO a) -> IO a
withClient ctx srv add lt act =
Z.withSocket ctx Z.Req $ \s -> do
link lt s add []
act $ Client s srv
------------------------------------------------------------------------
-- | Request a service:
--
-- * 'Client' - The client, through which the service is requested
--
-- * 'Timeout' - Timeout in microseconds, -1 to wait eternally.
-- With timeout = 0, the function returns immediately
-- with 'Nothing'.
-- When the timeout expires, request is abandoned.
-- In this case, the result of the request
-- is Nothing.
--
-- * 'Source' - The source of the request stream;
-- the format of the request will probably comply
-- with some communication protocol,
-- as, for instance, in the majordomo pattern.
--
-- * 'SinkR' - The sink receiving the reply. The result of the sink
-- is returned as the request's overall result.
-- Note that the sink may perform different
-- actions on the segments of the resulting stream,
-- /e.g./ storing data in a database,
-- and return the number of records received.
--
-- A \'hello world\' Example:
--
-- > import qualified Data.Conduit as C
-- > import qualified Data.ByteString.Char8 as B
-- > import Network.Mom.Patterns.Basic.Client
-- > import Network.Mom.Patterns.Types
--
-- > main :: IO ()
-- > main = withContext 1 $ \ctx ->
-- > withClient ctx "test"
-- > "tcp://localhost:5555" Connect $ \c -> do
-- > mbX <- request c (-1) src snk
-- > case mbX of
-- > Nothing -> putStrLn "No Result"
-- > Just x -> putStrLn $ "Result: " ++ x
-- > where src = C.yield (B.pack "hello world")
-- > snk = do mbX <- C.await
-- > case mbX of
-- > Nothing -> return Nothing
-- > Just x -> return $ Just $ B.unpack x
------------------------------------------------------------------------
request :: Client -> Timeout -> Source -> SinkR (Maybe r) -> IO (Maybe r)
request c tmo src snk = do
runSender (clSock c) src
if tmo /= 0 then runReceiver (clSock c) tmo snk
else return Nothing
------------------------------------------------------------------------
-- | Check for a of a previously requested result;
-- use case: request with timout 0, do some work
-- and check for a result later.
-- Do not use this function without having requested the service
-- previously.
-- The parameters equal those of 'request',
-- but do not include a 'Source'.
------------------------------------------------------------------------
checkResult :: Client -> Timeout -> SinkR (Maybe r) -> IO (Maybe r)
checkResult c tmo snk | tmo == 0 = return Nothing
| otherwise = runReceiver (clSock c) tmo snk