refactor: introduce Handler type synonym
This commit is contained in:
+26
-17
@@ -7,6 +7,8 @@ module Control.Actor
|
|||||||
, module Control.Actor.Network
|
, module Control.Actor.Network
|
||||||
, pass
|
, pass
|
||||||
, continue
|
, continue
|
||||||
|
, maybeContinue
|
||||||
|
, become
|
||||||
-- Demo
|
-- Demo
|
||||||
, pingActor
|
, pingActor
|
||||||
, forwardActorWithCell
|
, forwardActorWithCell
|
||||||
@@ -31,33 +33,40 @@ import Control.Monad ((<=<))
|
|||||||
import Control.Monad.Reader (MonadIO (..))
|
import Control.Monad.Reader (MonadIO (..))
|
||||||
import Unsafe.Coerce (unsafeCoerce)
|
import Unsafe.Coerce (unsafeCoerce)
|
||||||
|
|
||||||
continue :: r -> Actor u r
|
continue :: r -> Actor msg u r
|
||||||
continue x = (,) (Just x) <$> state
|
continue x = (\u -> ActorResult (Just x) u Nothing) <$> state
|
||||||
|
|
||||||
pass :: Actor u r
|
maybeContinue :: Maybe r -> Actor msg u r
|
||||||
pass = (,) Nothing <$> state
|
maybeContinue Nothing = pass
|
||||||
|
maybeContinue (Just r) = continue r
|
||||||
|
|
||||||
|
pass :: Actor msg u r
|
||||||
|
pass = (\u -> ActorResult Nothing u Nothing) <$> state
|
||||||
|
|
||||||
|
become :: Handler msg u r -> Actor msg u r
|
||||||
|
become fn = (\u -> ActorResult Nothing u (Just fn)) <$> state
|
||||||
|
|
||||||
-- Demo
|
-- Demo
|
||||||
|
|
||||||
pingActor :: String -> Actor () String
|
pingActor :: Handler String () String
|
||||||
pingActor msg = return (Just ("Hello, " <> msg <> "!"), ())
|
pingActor msg = continue ("Hello, " <> msg <> "!")
|
||||||
|
|
||||||
forwardActorWithCell :: TMVar (ActorRef String String) -> String -> Actor () String
|
forwardActorWithCell :: TMVar (ActorRef String String) -> Handler String () String
|
||||||
forwardActorWithCell cell msg = do
|
forwardActorWithCell cell msg = do
|
||||||
pingRef <- liftIO $ atomically $ readTMVar cell
|
pingRef <- liftIO $ atomically $ readTMVar cell
|
||||||
reply <- call msg pingRef
|
reply <- call msg pingRef
|
||||||
case reply of
|
case reply of
|
||||||
Nothing -> liftIO $ putStrLn "forwardActorWithCell: received empty reply!"
|
Nothing -> liftIO $ putStrLn "forwardActorWithCell: received empty reply!"
|
||||||
Just x -> liftIO $ putStrLn ("forwardActorWithCell: received reply - " <> x)
|
Just x -> liftIO $ putStrLn ("forwardActorWithCell: received reply - " <> x)
|
||||||
return (reply, ())
|
maybeContinue reply
|
||||||
|
|
||||||
repeatActor :: String -> TMVar (ActorRef String String) -> () -> Actor () String
|
repeatActor :: String -> TMVar (ActorRef String String) -> Handler () () String
|
||||||
repeatActor r cell () = do
|
repeatActor r cell () = do
|
||||||
ref <- liftIO $ atomically $ readTMVar cell
|
ref <- liftIO $ atomically $ readTMVar cell
|
||||||
(SomeActorRef self) <- getSelf
|
(SomeActorRef self) <- getSelf
|
||||||
cast r ref
|
cast r ref
|
||||||
castIn 1000 () (unsafeCoerce self)
|
castIn 1000 () (unsafeCoerce self)
|
||||||
return (Nothing, ())
|
pass
|
||||||
|
|
||||||
system :: IO ()
|
system :: IO ()
|
||||||
system = do
|
system = do
|
||||||
@@ -81,25 +90,25 @@ system = do
|
|||||||
|
|
||||||
-- Network demo
|
-- Network demo
|
||||||
|
|
||||||
newNodeActor :: NodeAddr -> Actor () NodeId
|
newNodeActor :: Handler NodeAddr () NodeId
|
||||||
newNodeActor = continue <=< liftRuntime . connect Nothing
|
newNodeActor = continue <=< liftRuntime . connect Nothing
|
||||||
|
|
||||||
-- | Actor on node 2: echo — returns whatever it received.
|
-- | Actor on node 2: echo — returns whatever it received.
|
||||||
echoActor :: String -> Actor () String
|
echoActor :: Handler String () String
|
||||||
echoActor = continue
|
echoActor = continue
|
||||||
|
|
||||||
-- | Actor on node 2: printer — side-effects only.
|
-- | Actor on node 2: printer — side-effects only.
|
||||||
printerActor :: String -> Actor () ()
|
printerActor :: Handler String () ()
|
||||||
printerActor msg = liftIO (putStrLn $ " [remote/print] " <> msg) >> pass
|
printerActor msg = liftIO (putStrLn $ " [remote/print] " <> msg) >> pass
|
||||||
|
|
||||||
-- | Trivial actor used as a stub when we only care about death notifications.
|
-- | Trivial actor used as a stub when we only care about death notifications.
|
||||||
noopActor :: () -> Actor () ()
|
noopActor :: Handler () () ()
|
||||||
noopActor _ = return (Nothing, ())
|
noopActor _ = pass
|
||||||
|
|
||||||
-- | Captures the received string into a TVar (used as a node-1 receiver actor).
|
-- | Captures the received string into a TVar (used as a node-1 receiver actor).
|
||||||
recvActorFn :: TVar (Maybe String) -> String -> Actor () ()
|
recvActorFn :: TVar (Maybe String) -> Handler String () ()
|
||||||
recvActorFn var msg =
|
recvActorFn var msg =
|
||||||
liftIO (atomically $ writeTVar var (Just msg)) >> return (Nothing, ())
|
liftIO (atomically $ writeTVar var (Just msg)) >> pass
|
||||||
|
|
||||||
-- | End-to-end networking demo.
|
-- | End-to-end networking demo.
|
||||||
--
|
--
|
||||||
|
|||||||
@@ -6,6 +6,8 @@ module Control.Actor.Core
|
|||||||
, state
|
, state
|
||||||
, getSelf
|
, getSelf
|
||||||
, Actor
|
, Actor
|
||||||
|
, ActorResult (..)
|
||||||
|
, Handler
|
||||||
, liftRuntime
|
, liftRuntime
|
||||||
, notifyOfDeath
|
, notifyOfDeath
|
||||||
, spawnActor
|
, spawnActor
|
||||||
@@ -44,6 +46,7 @@ import Control.Exception
|
|||||||
, try
|
, try
|
||||||
)
|
)
|
||||||
import Control.Monad (forM_, void)
|
import Control.Monad (forM_, void)
|
||||||
|
import Data.Maybe (fromMaybe)
|
||||||
import Control.Monad.Reader
|
import Control.Monad.Reader
|
||||||
( MonadIO (..)
|
( MonadIO (..)
|
||||||
, MonadReader (..)
|
, MonadReader (..)
|
||||||
@@ -78,7 +81,15 @@ getSelf = do
|
|||||||
Just ref -> return ref
|
Just ref -> return ref
|
||||||
Nothing -> error "getSelf: actor not found in runtime"
|
Nothing -> error "getSelf: actor not found in runtime"
|
||||||
|
|
||||||
type Actor u r = ActorM u (Maybe r, u)
|
data ActorResult msg u r = ActorResult
|
||||||
|
{ actorReply :: Maybe r
|
||||||
|
, actorState :: u
|
||||||
|
, actorBecome :: Maybe (msg -> ActorM u (ActorResult msg u r))
|
||||||
|
}
|
||||||
|
|
||||||
|
type Actor msg u r = ActorM u (ActorResult msg u r)
|
||||||
|
|
||||||
|
type Handler msg u r = msg -> Actor msg u r
|
||||||
|
|
||||||
liftRuntime :: RuntimeM a -> ActorM u a
|
liftRuntime :: RuntimeM a -> ActorM u a
|
||||||
liftRuntime = ActorM . withReaderT snd . unRuntimeM
|
liftRuntime = ActorM . withReaderT snd . unRuntimeM
|
||||||
@@ -90,7 +101,7 @@ notifyOfDeath rt dm (RemoteTarget _ peerAddr) =
|
|||||||
|
|
||||||
spawnActor ::
|
spawnActor ::
|
||||||
(Binary m, Binary r) =>
|
(Binary m, Binary r) =>
|
||||||
(m -> Actor u r) ->
|
Handler m u r ->
|
||||||
(DeathMessage -> ActorM u (SupervisorAction u)) ->
|
(DeathMessage -> ActorM u (SupervisorAction u)) ->
|
||||||
u ->
|
u ->
|
||||||
RuntimeM (ActorRef m r)
|
RuntimeM (ActorRef m r)
|
||||||
@@ -104,7 +115,7 @@ spawnActor actorFn deathFn initState = do
|
|||||||
actorState = ActorState actorId links initState
|
actorState = ActorState actorId links initState
|
||||||
actorRef = LocalRef mailbox deathQ actorState
|
actorRef = LocalRef mailbox deathQ actorState
|
||||||
|
|
||||||
let loop as = do
|
let loop fn as = do
|
||||||
event <-
|
event <-
|
||||||
atomically $
|
atomically $
|
||||||
(Left <$> readTQueue mailbox)
|
(Left <$> readTQueue mailbox)
|
||||||
@@ -113,20 +124,20 @@ spawnActor actorFn deathFn initState = do
|
|||||||
Left envelope ->
|
Left envelope ->
|
||||||
case envelope of
|
case envelope of
|
||||||
Cast msg -> do
|
Cast msg -> do
|
||||||
(_, u') <- runActorM (actorFn msg) rt as
|
ActorResult _ u' mFn <- runActorM (fn msg) rt as
|
||||||
loop as {asEnv = u'}
|
loop (fromMaybe fn mFn) as {asEnv = u'}
|
||||||
Call msg mv -> do
|
Call msg mv -> do
|
||||||
(reply, u') <- runActorM (actorFn msg) rt as
|
ActorResult reply u' mFn <- runActorM (fn msg) rt as
|
||||||
putMVar mv reply
|
putMVar mv reply
|
||||||
loop as {asEnv = u'}
|
loop (fromMaybe fn mFn) as {asEnv = u'}
|
||||||
Right dm -> do
|
Right dm -> do
|
||||||
action <- runActorM (deathFn dm) rt as
|
action <- runActorM (deathFn dm) rt as
|
||||||
case action of
|
case action of
|
||||||
Stop -> return ()
|
Stop -> return ()
|
||||||
Continue u -> loop as {asEnv = u}
|
Continue u -> loop fn as {asEnv = u}
|
||||||
|
|
||||||
tid <- liftIO $ forkIO $ do
|
tid <- liftIO $ forkIO $ do
|
||||||
result <- try @SomeException (loop actorState)
|
result <- try @SomeException (loop actorFn actorState)
|
||||||
let reason = case result of
|
let reason = case result of
|
||||||
Right () -> Normal
|
Right () -> Normal
|
||||||
Left exc -> case fromException exc of
|
Left exc -> case fromException exc of
|
||||||
|
|||||||
@@ -14,7 +14,7 @@ module Control.Actor.Network
|
|||||||
) where
|
) where
|
||||||
|
|
||||||
import Control.Actor.Core
|
import Control.Actor.Core
|
||||||
( Actor, ActorM, cast', liftRuntime, linkActorTo, spawnActor, state, stopOnDeath )
|
( Actor, ActorM, ActorResult (..), Handler, cast', liftRuntime, linkActorTo, spawnActor, state, stopOnDeath )
|
||||||
import Control.Actor.Runtime (Runtime (..), RuntimeM, newRuntime, withRuntime)
|
import Control.Actor.Runtime (Runtime (..), RuntimeM, newRuntime, withRuntime)
|
||||||
import Control.Actor.Supervision (ChildSpec (..), RestartStrategy (..), childWithRef, supervise')
|
import Control.Actor.Supervision (ChildSpec (..), RestartStrategy (..), childWithRef, supervise')
|
||||||
import Control.Actor.Transport (ConnHandle (..), Transport (..), createTCPTransport)
|
import Control.Actor.Transport (ConnHandle (..), Transport (..), createTCPTransport)
|
||||||
@@ -45,11 +45,11 @@ import Data.UUID (UUID)
|
|||||||
|
|
||||||
-- Connection actors
|
-- Connection actors
|
||||||
|
|
||||||
connActorFn :: NetworkMessage -> Actor ConnHandle ()
|
connActorFn :: Handler NetworkMessage ConnHandle ()
|
||||||
connActorFn nm = do
|
connActorFn nm = do
|
||||||
ch <- state
|
ch <- state
|
||||||
liftIO $ chSend ch (encode nm)
|
liftIO $ chSend ch (encode nm)
|
||||||
return (Nothing, ch)
|
return $ ActorResult Nothing ch Nothing
|
||||||
|
|
||||||
connDeathFn :: NodeAddr -> DeathMessage -> ActorM ConnHandle (SupervisorAction ConnHandle)
|
connDeathFn :: NodeAddr -> DeathMessage -> ActorM ConnHandle (SupervisorAction ConnHandle)
|
||||||
connDeathFn peer _ = do
|
connDeathFn peer _ = do
|
||||||
@@ -60,12 +60,12 @@ connDeathFn peer _ = do
|
|||||||
chClose ch
|
chClose ch
|
||||||
return Stop
|
return Stop
|
||||||
|
|
||||||
routerActorFn :: NodeAddr -> ByteString -> Actor () ()
|
routerActorFn :: NodeAddr -> Handler ByteString () ()
|
||||||
routerActorFn senderAddr raw = do
|
routerActorFn senderAddr raw = do
|
||||||
let nm = decode raw :: NetworkMessage
|
let nm = decode raw :: NetworkMessage
|
||||||
valid <- liftRuntime $ validateAndDispatch senderAddr nm
|
valid <- liftRuntime $ validateAndDispatch senderAddr nm
|
||||||
unless valid $ liftIO $ putStrLn "router: dropping invalid message"
|
unless valid $ liftIO $ putStrLn "router: dropping invalid message"
|
||||||
return (Nothing, ())
|
return $ ActorResult Nothing () Nothing
|
||||||
|
|
||||||
-- Connection supervision tree
|
-- Connection supervision tree
|
||||||
|
|
||||||
@@ -242,8 +242,8 @@ validateAndDispatch senderAddr nm = case nm of
|
|||||||
|
|
||||||
-- System event handler
|
-- System event handler
|
||||||
|
|
||||||
sysHandlerFn :: NetworkMessage -> Actor () ()
|
sysHandlerFn :: Handler NetworkMessage () ()
|
||||||
sysHandlerFn _ = return (Nothing, ())
|
sysHandlerFn _ = return $ ActorResult Nothing () Nothing
|
||||||
|
|
||||||
-- Node connection
|
-- Node connection
|
||||||
|
|
||||||
|
|||||||
@@ -16,7 +16,7 @@ module Control.Actor.Supervision
|
|||||||
, killSlot
|
, killSlot
|
||||||
) where
|
) where
|
||||||
|
|
||||||
import Control.Actor.Core (Actor, ActorM, liftRuntime, linkActorTo, spawnActor)
|
import Control.Actor.Core (Actor, ActorM, Handler, liftRuntime, linkActorTo, spawnActor)
|
||||||
import Control.Actor.Runtime (Runtime (..), RuntimeM, withRuntime)
|
import Control.Actor.Runtime (Runtime (..), RuntimeM, withRuntime)
|
||||||
import Control.Actor.Types
|
import Control.Actor.Types
|
||||||
import Data.Binary (Binary)
|
import Data.Binary (Binary)
|
||||||
@@ -47,7 +47,7 @@ data ChildSpec = forall m r. (Binary m, Binary r) => ChildSpec
|
|||||||
|
|
||||||
child ::
|
child ::
|
||||||
(Binary m, Binary r) =>
|
(Binary m, Binary r) =>
|
||||||
(m -> Actor u r) ->
|
Handler m u r ->
|
||||||
(DeathMessage -> ActorM u (SupervisorAction u)) ->
|
(DeathMessage -> ActorM u (SupervisorAction u)) ->
|
||||||
u ->
|
u ->
|
||||||
ChildSpec
|
ChildSpec
|
||||||
@@ -62,7 +62,7 @@ child msgFn deathFn initState =
|
|||||||
|
|
||||||
childWithRef ::
|
childWithRef ::
|
||||||
(Binary m, Binary r) =>
|
(Binary m, Binary r) =>
|
||||||
(m -> Actor u r) ->
|
Handler m u r ->
|
||||||
(DeathMessage -> ActorM u (SupervisorAction u)) ->
|
(DeathMessage -> ActorM u (SupervisorAction u)) ->
|
||||||
u ->
|
u ->
|
||||||
TMVar (ActorRef m r) ->
|
TMVar (ActorRef m r) ->
|
||||||
|
|||||||
Reference in New Issue
Block a user