packages feed

courier 0.1.1.1 → 0.1.1.2

raw patch · 5 files changed

+90/−20 lines, 5 filesPVP: major bump suggested

API removals or changes: PVP suggests a major version bump

API changes (from Hackage documentation)

- Control.Concurrent.Mailbox: instance Eq (Mailbox m)
- Network.Endpoints: boundEndpointNames :: Endpoint -> TVar (Set Name)
- Network.Endpoints: endpointInbound :: Endpoint -> Mailbox Message
- Network.Endpoints: endpointOutbound :: Endpoint -> Mailbox Envelope
- Network.Endpoints: envelopeMessage :: Envelope -> Message
- Network.Endpoints: instance Constructor C1_0Name
- Network.Endpoints: instance Datatype D1Name
- Network.Endpoints: instance Eq Envelope
- Network.Endpoints: instance Eq Name
- Network.Endpoints: instance Exception BindException
- Network.Endpoints: instance Generic Name
- Network.Endpoints: instance Ord Name
- Network.Endpoints: instance Serialize Name
- Network.Endpoints: instance Show BindException
- Network.Endpoints: instance Show Envelope
- Network.Endpoints: instance Show Name
- Network.Endpoints: instance Typeable BindException
- Network.Endpoints: messageDestination :: Envelope -> Name
- Network.Endpoints: messageOrigin :: Envelope -> Maybe Name
- Network.RPC: instance Constructor C1_0RPCMessageType
- Network.RPC: instance Constructor C1_0RequestId
- Network.RPC: instance Constructor C1_1RPCMessageType
- Network.RPC: instance Datatype D1RPCMessageType
- Network.RPC: instance Datatype D1RequestId
- Network.RPC: instance Enum RPCMessageType
- Network.RPC: instance Eq RPCMessageType
- Network.RPC: instance Eq Request
- Network.RPC: instance Eq RequestId
- Network.RPC: instance Eq Response
- Network.RPC: instance Generic RPCMessageType
- Network.RPC: instance Generic RequestId
- Network.RPC: instance Serialize RPCMessageType
- Network.RPC: instance Serialize Request
- Network.RPC: instance Serialize RequestId
- Network.RPC: instance Serialize Response
- Network.RPC: instance Show RPCMessageType
- Network.RPC: instance Show Request
- Network.RPC: instance Show RequestId
- Network.RPC: instance Show Response
- Network.RPC: requestArgs :: Request -> Message
- Network.RPC: requestCaller :: Request -> Name
- Network.RPC: requestId :: Request -> RequestId
- Network.RPC: requestMethod :: Request -> Method
- Network.RPC: responseFrom :: Response -> Name
- Network.RPC: responseId :: Response -> RequestId
- Network.RPC: responseValue :: Response -> Message
- Network.Transport: bind :: Transport -> Endpoint -> Name -> IO Binding
- Network.Transport: bindingName :: Binding -> Name
- Network.Transport: connect :: Transport -> Endpoint -> Name -> IO Connection
- Network.Transport: disconnect :: Connection -> IO ()
- Network.Transport: dispatch :: Transport -> Endpoint -> IO Dispatcher
- Network.Transport: instance Exception TransportException
- Network.Transport: instance Show TransportException
- Network.Transport: instance Typeable TransportException
- Network.Transport: shutdown :: Transport -> IO ()
- Network.Transport: stop :: Dispatcher -> IO ()
- Network.Transport: unbind :: Binding -> IO ()
- Network.Transport.Sockets: connectionDestination :: SocketConnection -> TMVar Name
- Network.Transport.Sockets: disconnectSocket :: SocketConnection -> IO ()
- Network.Transport.Sockets: instance Constructor C1_0SocketMessage
- Network.Transport.Sockets: instance Constructor C1_1SocketMessage
- Network.Transport.Sockets: instance Datatype D1SocketMessage
- Network.Transport.Sockets: instance Exception ResolverException
- Network.Transport.Sockets: instance Generic SocketMessage
- Network.Transport.Sockets: instance Serialize SocketMessage
- Network.Transport.Sockets: instance Show ResolverException
- Network.Transport.Sockets: instance Typeable ResolverException
- Network.Transport.Sockets: receiveSocketMessage :: SocketConnection -> IO Message
- Network.Transport.Sockets: sendSocketMessage :: SocketConnection -> Message -> IO ()
+ Control.Concurrent.Mailbox: instance GHC.Classes.Eq (Control.Concurrent.Mailbox.Mailbox m)
+ Network.Endpoints: [boundEndpointNames] :: Endpoint -> TVar (Set Name)
+ Network.Endpoints: [endpointInbound] :: Endpoint -> Mailbox Message
+ Network.Endpoints: [endpointOutbound] :: Endpoint -> Mailbox Envelope
+ Network.Endpoints: [envelopeMessage] :: Envelope -> Message
+ Network.Endpoints: [messageDestination] :: Envelope -> Name
+ Network.Endpoints: [messageOrigin] :: Envelope -> Maybe Name
+ Network.Endpoints: instance Data.Serialize.Serialize Network.Endpoints.Name
+ Network.Endpoints: instance GHC.Classes.Eq Network.Endpoints.Envelope
+ Network.Endpoints: instance GHC.Classes.Eq Network.Endpoints.Name
+ Network.Endpoints: instance GHC.Classes.Ord Network.Endpoints.Name
+ Network.Endpoints: instance GHC.Exception.Exception Network.Endpoints.BindException
+ Network.Endpoints: instance GHC.Generics.Constructor Network.Endpoints.C1_0Name
+ Network.Endpoints: instance GHC.Generics.Datatype Network.Endpoints.D1Name
+ Network.Endpoints: instance GHC.Generics.Generic Network.Endpoints.Name
+ Network.Endpoints: instance GHC.Show.Show Network.Endpoints.BindException
+ Network.Endpoints: instance GHC.Show.Show Network.Endpoints.Envelope
+ Network.Endpoints: instance GHC.Show.Show Network.Endpoints.Name
+ Network.RPC: [requestArgs] :: Request -> Message
+ Network.RPC: [requestCaller] :: Request -> Name
+ Network.RPC: [requestId] :: Request -> RequestId
+ Network.RPC: [requestMethod] :: Request -> Method
+ Network.RPC: [responseFrom] :: Response -> Name
+ Network.RPC: [responseId] :: Response -> RequestId
+ Network.RPC: [responseValue] :: Response -> Message
+ Network.RPC: handleAll :: Endpoint -> Name -> (Method -> Message -> IO Message) -> IO HandleSite
+ Network.RPC: hearAll :: Endpoint -> Name -> IO (Method, Message, Reply Message)
+ Network.RPC: hearAllTimeout :: Endpoint -> Name -> Int -> IO (Maybe (Method, Message, Reply Message))
+ Network.RPC: instance Data.Serialize.Serialize Network.RPC.RPCMessageType
+ Network.RPC: instance Data.Serialize.Serialize Network.RPC.Request
+ Network.RPC: instance Data.Serialize.Serialize Network.RPC.RequestId
+ Network.RPC: instance Data.Serialize.Serialize Network.RPC.Response
+ Network.RPC: instance GHC.Classes.Eq Network.RPC.RPCMessageType
+ Network.RPC: instance GHC.Classes.Eq Network.RPC.Request
+ Network.RPC: instance GHC.Classes.Eq Network.RPC.RequestId
+ Network.RPC: instance GHC.Classes.Eq Network.RPC.Response
+ Network.RPC: instance GHC.Enum.Enum Network.RPC.RPCMessageType
+ Network.RPC: instance GHC.Generics.Constructor Network.RPC.C1_0RPCMessageType
+ Network.RPC: instance GHC.Generics.Constructor Network.RPC.C1_0RequestId
+ Network.RPC: instance GHC.Generics.Constructor Network.RPC.C1_1RPCMessageType
+ Network.RPC: instance GHC.Generics.Datatype Network.RPC.D1RPCMessageType
+ Network.RPC: instance GHC.Generics.Datatype Network.RPC.D1RequestId
+ Network.RPC: instance GHC.Generics.Generic Network.RPC.RPCMessageType
+ Network.RPC: instance GHC.Generics.Generic Network.RPC.RequestId
+ Network.RPC: instance GHC.Show.Show Network.RPC.RPCMessageType
+ Network.RPC: instance GHC.Show.Show Network.RPC.Request
+ Network.RPC: instance GHC.Show.Show Network.RPC.RequestId
+ Network.RPC: instance GHC.Show.Show Network.RPC.Response
+ Network.Transport: [bind] :: Transport -> Endpoint -> Name -> IO Binding
+ Network.Transport: [bindingName] :: Binding -> Name
+ Network.Transport: [connect] :: Transport -> Endpoint -> Name -> IO Connection
+ Network.Transport: [disconnect] :: Connection -> IO ()
+ Network.Transport: [dispatch] :: Transport -> Endpoint -> IO Dispatcher
+ Network.Transport: [shutdown] :: Transport -> IO ()
+ Network.Transport: [stop] :: Dispatcher -> IO ()
+ Network.Transport: [unbind] :: Binding -> IO ()
+ Network.Transport: instance GHC.Exception.Exception Network.Transport.TransportException
+ Network.Transport: instance GHC.Show.Show Network.Transport.TransportException
+ Network.Transport: withCompleteNetwork :: Transport -> [Name] -> Endpoint -> Name -> IO () -> IO ()
+ Network.Transport: withConnections :: Transport -> Endpoint -> [Name] -> IO () -> IO ()
+ Network.Transport.Sockets: [connectionDestination] :: SocketConnection -> TMVar Name
+ Network.Transport.Sockets: [disconnectSocket] :: SocketConnection -> IO ()
+ Network.Transport.Sockets: [receiveSocketMessage] :: SocketConnection -> IO Message
+ Network.Transport.Sockets: [sendSocketMessage] :: SocketConnection -> Message -> IO ()
+ Network.Transport.Sockets: instance Data.Serialize.Serialize Network.Transport.Sockets.SocketMessage
+ Network.Transport.Sockets: instance GHC.Exception.Exception Network.Transport.Sockets.ResolverException
+ Network.Transport.Sockets: instance GHC.Generics.Constructor Network.Transport.Sockets.C1_0SocketMessage
+ Network.Transport.Sockets: instance GHC.Generics.Constructor Network.Transport.Sockets.C1_1SocketMessage
+ Network.Transport.Sockets: instance GHC.Generics.Datatype Network.Transport.Sockets.D1SocketMessage
+ Network.Transport.Sockets: instance GHC.Generics.Generic Network.Transport.Sockets.SocketMessage
+ Network.Transport.Sockets: instance GHC.Show.Show Network.Transport.Sockets.ResolverException

Files

changes.md view
@@ -1,3 +1,8 @@+0.1.1.2++  * Updated README with better working example+  * Removed warning about TCP/IP transport; it's working again+   0.1.1.1  There are significant changes in this release, due to a complete rewrite of TCP connection handling, and,
courier.cabal view
@@ -1,5 +1,5 @@ name:                courier-version:             0.1.1.1+version:             0.1.1.2 synopsis:           A message-passing library for simplifying network applications description:         Inspired by Erlang's simple message-passing facilities, courier provides roughly similar                      capabilities. Applications simply create one or more endpoints,
src/Network/RPC.hs view
@@ -47,10 +47,13 @@     methodSelector,     hear,     hearTimeout,+    hearAll,+    hearAllTimeout,     Reply,      HandleSite,     handle,+    handleAll,     hangup,      Request(..),@@ -326,6 +329,12 @@                 then Just (caller,rid,args)                 else Nothing +anySelector :: Message -> Maybe (Name,RequestId,Method,Message)+anySelector msg =+  case decode msg of+    Left _ -> Nothing+    Right (Request rid caller method args) -> Just (caller,rid,method,args)+ {-| Wait for a single incoming request to invoke the indicated 'Method' on the specified 'Endpoint'. Return both the method arguments and a 'Reply' function useful for sending@@ -345,7 +354,6 @@         reply caller rid result = do             sendMessage endpoint caller $ encode $ Response rid name result - {-| Same as 'hear', except return 'Nothing' if no request received within the specified timeout (measured in microseconds), or return a 'Just' instance containing both the@@ -362,6 +370,34 @@             sendMessage endpoint caller $ encode $ Response rid name result  {-|+A variant of 'hear', except it listens for any incoming RPC request on the specified 'Endpoint'.+-}+hearAll :: Endpoint -> Name -> IO (Method,Message,Reply Message)+hearAll endpoint name = do+    (caller,rid,method,args) <- selectMessage endpoint anySelector+    return (method,args,reply caller rid)+    where+        reply caller rid result =+          sendMessage endpoint caller $ encode $ Response rid name result+        anySelector msg =+          case decode msg of+            Left _ -> Nothing+            Right (Request rid caller method args) -> Just (caller,rid,method,args)++{-|+A variant of 'hearTimeout', except it listens for any incoming RPC request on the specified 'Endpoint'+-}+hearAllTimeout :: Endpoint -> Name -> Int -> IO (Maybe (Method,Message,Reply Message))+hearAllTimeout endpoint name timeout = do+    req <- selectMessageTimeout endpoint timeout anySelector+    case req of+        Just (caller,rid,method,args) -> return $ Just (method,args, reply caller rid)+        Nothing -> return Nothing+    where+        reply caller rid result = do+            sendMessage endpoint caller $ encode $ Response rid name result++{-| A 'HandleSite' is a just reference to the actual handler of a specific method. Mostly for invoking 'hangup' on the handler, once it is no longer needed. -}@@ -373,12 +409,26 @@ -} handle :: Endpoint -> Name -> Method -> (Message -> IO Message) -> IO HandleSite handle endpoint name method fn = do-    task <- async $ handleCall+    task <- async handleCall     return $ HandleSite name task     where         handleCall = do             (args,reply) <- hear endpoint name method             result <- fn args+            reply result+            handleCall++{-|+Handle all RPCs on the specified 'Endpoint' until 'hangup' is called on the returned 'HandleSite'+-}+handleAll :: Endpoint -> Name -> (Method -> Message -> IO Message) -> IO HandleSite+handleAll endpoint name fn = do+    task <- async handleCall+    return $ HandleSite name task+    where+        handleCall = do+            (method,args,reply) <- hearAll endpoint name+            result <- fn method args             reply result             handleCall 
src/Network/Transport.hs view
@@ -69,6 +69,9 @@   withConnection3,   withConnection4, +  withConnections,+  withCompleteNetwork+ ) where  -- local imports@@ -264,25 +267,36 @@ A helper for ensuring that 2 'Connection's are maintained during execution of a function. -} withConnection2 :: Transport -> Endpoint -> Name -> Name -> IO () -> IO ()-withConnection2 transport endpoint name1 name2 fn =-  withConnection transport endpoint name1 $-    withConnection transport endpoint name2 fn+withConnection2 transport endpoint name1 name2 = withConnections transport endpoint [name1,name2]  {-| A helper for ensuring that 3 'Connection's are maintained during execution of a function. -} withConnection3 :: Transport -> Endpoint -> Name -> Name -> Name -> IO () -> IO ()-withConnection3 transport endpoint name1 name2 name3 fn =-  withConnection transport endpoint name1 $-    withConnection transport endpoint name2 $-      withConnection transport endpoint name3 fn+withConnection3 transport endpoint name1 name2 name3 = withConnections transport endpoint [name1,name2,name3]  {-| A helper for ensuring that 4 'Connection's are maintained during execution of a function. -} withConnection4 :: Transport -> Endpoint -> Name -> Name -> Name -> Name -> IO () -> IO ()-withConnection4 transport endpoint name1 name2 name3 name4 fn =-  withConnection transport endpoint name1 $-    withConnection transport endpoint name2 $-      withConnection transport endpoint name3 $-        withConnection transport endpoint name4 fn+withConnection4 transport endpoint name1 name2 name3 name4 = withConnections transport endpoint [name1,name2,name3,name4]++--+--  Various helpers+--+withConnections :: Transport -> Endpoint -> [Name] -> IO () -> IO ()+withConnections _ _ [] fn = fn+withConnections transport endpoint (destination:destinations) fn =+  withConnection transport endpoint destination $+    withConnections transport endpoint destinations fn++{-|+This is a helper designed to create a complete network, where there are+enough connections to ensure every endpoint has a connection to every other endpoint.+-}+withCompleteNetwork :: Transport -> [Name] -> Endpoint -> Name -> IO () -> IO ()+withCompleteNetwork _ [] _ _ fn = fn+withCompleteNetwork transport(destination:destinations) endpoint origin fn =+  if destination == origin+    then withConnections transport endpoint destinations fn+    else withCompleteNetwork transport destinations endpoint origin fn
src/Network/Transport/Sockets/TCP.hs view
@@ -51,7 +51,7 @@   vPeers <- newTVar M.empty   mailboxes <- newTVar M.empty   return Transport {-    bind = tcpBind mailboxes family resolver,+    bind = tcpBind mailboxes family resolver vPeers,     dispatch = dispatcher mailboxes,     connect =  socketConnect mailboxes $ tcpConnect family resolver,     shutdown = tcpShutdown vPeers@@ -81,9 +81,8 @@ tcpSocketResolver6 :: Name -> IO [NS.SockAddr] tcpSocketResolver6 = socketResolver6 NS.Stream -tcpBind :: Mailboxes -> NS.Family -> Resolver -> Endpoint -> Name -> IO Binding-tcpBind mailboxes family resolver endpoint name = do-  vConnections <- atomically $ newTVar M.empty+tcpBind :: Mailboxes -> NS.Family -> Resolver -> SocketConnections -> Endpoint -> Name -> IO Binding+tcpBind mailboxes family resolver vConnections endpoint name = do   listener <- async $ tcpListen mailboxes family resolver vConnections endpoint name   return Binding {     bindingName = name,@@ -102,7 +101,9 @@   connection <- tcpConnection peer   msngr <- async $ messenger mailboxes endpoint connection   let conn = Connection {-    disconnect = cancel msngr+    disconnect = do+      atomically $ modifyTVar vConnections $ M.delete peerAddress+      cancel msngr   }   maybeOldConn <- atomically $ do     connections <- readTVar vConnections