----------------------------------------------------------------------------- -- | -- Module : Control.Distributed.Process.Execution.Exchange -- Copyright : (c) Tim Watson 2012 - 2014 -- License : BSD3 (see the file LICENSE) -- -- Maintainer : Tim Watson -- Stability : experimental -- Portability : non-portable (requires concurrency) -- -- [Message Exchanges] -- -- The concept of a /message exchange/ is borrowed from the world of -- messaging and enterprise integration. The /exchange/ acts like a kind of -- mailbox, accepting inputs from /producers/ and forwarding these messages -- to one or more /consumers/, depending on the implementation's semantics. -- -- This module provides some basic types of message exchange and exposes an API -- for defining your own custom /exchange types/. -- -- [Broadcast Exchanges] -- -- The broadcast exchange type, started via 'broadcastExchange', forward their -- inputs to all registered consumers (as the name suggests). This exchange type -- is highly optimised for local (intra-node) traffic and provides two different -- kinds of client binding, one which causes messages to be delivered directly -- to the client's mailbox (viz 'bindToBroadcaster'), the other providing a -- separate stream of messages that can be obtained using the @expect@ and -- @receiveX@ family of messaging primitives (and thus composed with other forms -- of input selection, such as typed channels and selective reads on the process -- mailbox). -- -- /Important:/ When a @ProcessId@ is registered via 'bindToBroadcaster', only -- the payload of the 'Message' (i.e., the underlying @Serializable@ datum) is -- forwarded to the consumer, /not/ the whole 'Message' itself. -- -- [Router Exchanges] -- -- The /router/ API provides a means to selectively route messages to one or -- more clients, depending on the content of the 'Message'. Two modes of binding -- (and client selection) are provided out of the box, one of which matches the -- message 'key', the second of which matches on a name and value from the -- 'headers'. Alternative mechanisms for content based routing can be derived -- by modifying the 'BindingSelector' expression passed to 'router' -- -- See 'messageKeyRouter' and 'headerContentRouter' for the built-in routing -- exchanges, and 'router' for the extensible routing API. -- -- [Custom Exchange Types] -- -- Both the /broadcast/ and /router/ exchanges are implemented as custom -- /exchange types/. The mechanism for defining custom exchange behaviours -- such as these is very simple. Raw exchanges are started by evaluating -- 'startExchange' with a specific 'ExchangeType' record. This type is -- parameterised by the internal /state/ it holds, and defines two API callbacks -- in its 'configureEx' and 'routeEx' fields. The former is evaluated whenever a -- client process evaluates 'configureExchange', the latter whenever a client -- evaluates 'post' or 'postMessage'. The 'configureEx' callback takes a raw -- @Message@ (from "Control.Distributed.Process") and is responsible for -- decoding the message and updating its own state (if required). It is via -- this callback that custom exchange types can receive information about -- clients and handle it in their own way. The 'routeEx' callback is evaluated -- with the exchange type's own internal state and the 'Message' originally -- sent to the exchange process (via 'post') and is responsible for delivering -- the message to its clients in whatever way makes sense for that exchange -- type. -- ----------------------------------------------------------------------------- module Control.Distributed.Process.Execution.Exchange ( -- * Fundamental API Exchange() , Message(..) -- * Starting/Running an Exchange , startExchange , startSupervised , startSupervisedRef , runExchange -- * Client Facing API , post , postMessage , configureExchange , createMessage -- * Broadcast Exchange , broadcastExchange , broadcastExchangeT , broadcastClient , bindToBroadcaster , BroadcastExchange -- * Routing (Content Based) , HeaderName , Binding(..) , Bindable , BindingSelector , RelayType(..) -- * Starting a Router , router , supervisedRouter -- * Routing (Publishing) API , route , routeMessage -- * Routing via message/binding keys , messageKeyRouter , bindKey -- * Routing via message headers , headerContentRouter , bindHeader -- * Defining Custom Exchange Types , ExchangeType(..) , applyHandlers ) where import Control.Distributed.Process.Execution.Exchange.Broadcast ( broadcastExchange , broadcastExchangeT , broadcastClient , bindToBroadcaster , BroadcastExchange ) import Control.Distributed.Process.Execution.Exchange.Internal ( Exchange() , Message(..) , ExchangeType(..) , startExchange , startSupervised , startSupervisedRef , runExchange , post , postMessage , configureExchange , createMessage , applyHandlers ) import Control.Distributed.Process.Execution.Exchange.Router ( HeaderName , Binding(..) , Bindable , BindingSelector , RelayType(..) , router , supervisedRouter , route , routeMessage , messageKeyRouter , bindKey , headerContentRouter , bindHeader )