{-# LANGUAGE DataKinds, FlexibleContexts, LambdaCase, OverloadedStrings #-}
module Pulsar.Core where
import Control.Exception ( throwIO )
import Control.Monad.Catch ( MonadThrow )
import Control.Monad.IO.Class
import qualified Data.Binary as B
import Data.Functor ( void )
import Data.ProtoLens.Field ( HasField )
import Data.Text ( Text )
import Lens.Family
import Proto.PulsarApi
import qualified Proto.PulsarApi_Fields as F
import Pulsar.Connection
import Pulsar.Internal.Logger
import qualified Pulsar.Protocol.Commands as P
import Pulsar.Protocol.Frame ( Payload(..)
, Response(..)
, getCommand
)
import Pulsar.Types
import UnliftIO.Chan
verifyResponse
:: (HasField a "requestId" B.Word64, Show a)
=> ReqId
-> Chan Response
-> LensLike' (Constant (Maybe a)) BaseCommand (Maybe a)
-> IO (Maybe a)
verifyResponse :: ReqId
-> Chan Response
-> LensLike' (Constant (Maybe a)) BaseCommand (Maybe a)
-> IO (Maybe a)
verifyResponse r :: ReqId
r@(ReqId req :: Word64
req) chan :: Chan Response
chan lens :: LensLike' (Constant (Maybe a)) BaseCommand (Maybe a)
lens = do
Response
resp <- Chan Response -> IO Response
forall (m :: * -> *) a. MonadIO m => Chan a -> m a
readChan Chan Response
chan
let cmd' :: Maybe a
cmd' = Response -> BaseCommand
getCommand Response
resp BaseCommand
-> LensLike' (Constant (Maybe a)) BaseCommand (Maybe a) -> Maybe a
forall s a t b. s -> FoldLike a s t a b -> a
^. LensLike' (Constant (Maybe a)) BaseCommand (Maybe a)
lens
req' :: Maybe Word64
req' = FoldLike Word64 a a Word64 Word64 -> a -> Word64
forall a s t b. FoldLike a s t a b -> s -> a
view FoldLike Word64 a a Word64 Word64
forall (f :: * -> *) s a.
(Functor f, HasField s "requestId" a) =>
LensLike' f s a
F.requestId (a -> Word64) -> Maybe a -> Maybe Word64
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> Maybe a
cmd'
rewrite :: IO ()
rewrite = Chan Response -> Response -> IO ()
forall (m :: * -> *) a. MonadIO m => Chan a -> a -> m ()
writeChan Chan Response
chan Response
resp
loop :: IO (Maybe a)
loop = ReqId
-> Chan Response
-> LensLike' (Constant (Maybe a)) BaseCommand (Maybe a)
-> IO (Maybe a)
forall a.
(HasField a "requestId" Word64, Show a) =>
ReqId
-> Chan Response
-> LensLike' (Constant (Maybe a)) BaseCommand (Maybe a)
-> IO (Maybe a)
verifyResponse ReqId
r Chan Response
chan LensLike' (Constant (Maybe a)) BaseCommand (Maybe a)
lens
checkEq :: (a, Word64) -> IO (Maybe a)
checkEq (_, rq :: Word64
rq) | Word64
rq Word64 -> Word64 -> Bool
forall a. Eq a => a -> a -> Bool
== Word64
req = Maybe a
cmd' Maybe a -> IO () -> IO (Maybe a)
forall (f :: * -> *) a b. Functor f => a -> f b -> f a
<$ Response -> IO ()
forall (m :: * -> *) a. (MonadIO m, Show a) => a -> m ()
logResponse Response
resp
| Bool
otherwise = IO ()
rewrite IO () -> IO (Maybe a) -> IO (Maybe a)
forall (m :: * -> *) a b. Monad m => m a -> m b -> m b
>> IO (Maybe a)
loop
IO (Maybe a)
-> ((a, Word64) -> IO (Maybe a))
-> Maybe (a, Word64)
-> IO (Maybe a)
forall b a. b -> (a -> b) -> Maybe a -> b
maybe IO (Maybe a)
loop (a, Word64) -> IO (Maybe a)
forall a. (a, Word64) -> IO (Maybe a)
checkEq (Maybe (a, Word64) -> IO (Maybe a))
-> Maybe (a, Word64) -> IO (Maybe a)
forall a b. (a -> b) -> a -> b
$ (,) (a -> Word64 -> (a, Word64))
-> Maybe a -> Maybe (Word64 -> (a, Word64))
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> Maybe a
cmd' Maybe (Word64 -> (a, Word64)) -> Maybe Word64 -> Maybe (a, Word64)
forall (f :: * -> *) a b. Applicative f => f (a -> b) -> f a -> f b
<*> Maybe Word64
req'
lookup :: Connection -> Chan Response -> ReqId -> Topic -> IO ()
lookup :: Connection -> Chan Response -> ReqId -> Topic -> IO ()
lookup (Conn s :: Socket
s) chan :: Chan Response
chan r :: ReqId
r@(ReqId req :: Word64
req) topic :: Topic
topic = do
BaseCommand -> IO ()
forall (m :: * -> *) a. (MonadIO m, Show a) => a -> m ()
logRequest (BaseCommand -> IO ()) -> BaseCommand -> IO ()
forall a b. (a -> b) -> a -> b
$ Word64 -> Topic -> BaseCommand
P.lookup Word64
req Topic
topic
Socket -> BaseCommand -> IO ()
forall (m :: * -> *). MonadIO m => Socket -> BaseCommand -> m ()
sendSimpleCmd Socket
s (BaseCommand -> IO ()) -> BaseCommand -> IO ()
forall a b. (a -> b) -> a -> b
$ Word64 -> Topic -> BaseCommand
P.lookup Word64
req Topic
topic
IO (Maybe CommandLookupTopicResponse) -> IO ()
forall (f :: * -> *) a. Functor f => f a -> f ()
void (IO (Maybe CommandLookupTopicResponse) -> IO ())
-> IO (Maybe CommandLookupTopicResponse) -> IO ()
forall a b. (a -> b) -> a -> b
$ ReqId
-> Chan Response
-> LensLike'
(Constant (Maybe CommandLookupTopicResponse))
BaseCommand
(Maybe CommandLookupTopicResponse)
-> IO (Maybe CommandLookupTopicResponse)
forall a.
(HasField a "requestId" Word64, Show a) =>
ReqId
-> Chan Response
-> LensLike' (Constant (Maybe a)) BaseCommand (Maybe a)
-> IO (Maybe a)
verifyResponse ReqId
r Chan Response
chan LensLike'
(Constant (Maybe CommandLookupTopicResponse))
BaseCommand
(Maybe CommandLookupTopicResponse)
forall (f :: * -> *) s a.
(Functor f, HasField s "maybe'lookupTopicResponse" a) =>
LensLike' f s a
F.maybe'lookupTopicResponse
newProducer
:: Connection -> Chan Response -> ReqId -> ProducerId -> Topic -> IO Text
newProducer :: Connection
-> Chan Response -> ReqId -> ProducerId -> Topic -> IO Text
newProducer (Conn s :: Socket
s) chan :: Chan Response
chan r :: ReqId
r@(ReqId req :: Word64
req) (PId pid :: Word64
pid) topic :: Topic
topic = do
BaseCommand -> IO ()
forall (m :: * -> *) a. (MonadIO m, Show a) => a -> m ()
logRequest (BaseCommand -> IO ()) -> BaseCommand -> IO ()
forall a b. (a -> b) -> a -> b
$ Word64 -> Word64 -> Topic -> BaseCommand
P.producer Word64
req Word64
pid Topic
topic
Socket -> BaseCommand -> IO ()
forall (m :: * -> *). MonadIO m => Socket -> BaseCommand -> m ()
sendSimpleCmd Socket
s (BaseCommand -> IO ()) -> BaseCommand -> IO ()
forall a b. (a -> b) -> a -> b
$ Word64 -> Word64 -> Topic -> BaseCommand
P.producer Word64
req Word64
pid Topic
topic
ReqId
-> Chan Response
-> LensLike'
(Constant (Maybe CommandProducerSuccess))
BaseCommand
(Maybe CommandProducerSuccess)
-> IO (Maybe CommandProducerSuccess)
forall a.
(HasField a "requestId" Word64, Show a) =>
ReqId
-> Chan Response
-> LensLike' (Constant (Maybe a)) BaseCommand (Maybe a)
-> IO (Maybe a)
verifyResponse ReqId
r Chan Response
chan LensLike'
(Constant (Maybe CommandProducerSuccess))
BaseCommand
(Maybe CommandProducerSuccess)
forall (f :: * -> *) s a.
(Functor f, HasField s "maybe'producerSuccess" a) =>
LensLike' f s a
F.maybe'producerSuccess IO (Maybe CommandProducerSuccess)
-> (Maybe CommandProducerSuccess -> IO Text) -> IO Text
forall (m :: * -> *) a b. Monad m => m a -> (a -> m b) -> m b
>>= \case
Just ps :: CommandProducerSuccess
ps -> Text -> IO Text
forall (m :: * -> *) a. Monad m => a -> m a
return (Text -> IO Text) -> Text -> IO Text
forall a b. (a -> b) -> a -> b
$ CommandProducerSuccess
ps CommandProducerSuccess
-> FoldLike
Text CommandProducerSuccess CommandProducerSuccess Text Text
-> Text
forall s a t b. s -> FoldLike a s t a b -> a
^. FoldLike
Text CommandProducerSuccess CommandProducerSuccess Text Text
forall (f :: * -> *) s a.
(Functor f, HasField s "producerName" a) =>
LensLike' f s a
F.producerName
Nothing -> Text -> IO Text
forall (m :: * -> *) a. Monad m => a -> m a
return ""
closeProducer :: Connection -> Chan Response -> ReqId -> ProducerId -> IO ()
closeProducer :: Connection -> Chan Response -> ReqId -> ProducerId -> IO ()
closeProducer (Conn s :: Socket
s) chan :: Chan Response
chan r :: ReqId
r@(ReqId req :: Word64
req) (PId pid :: Word64
pid) = do
BaseCommand -> IO ()
forall (m :: * -> *) a. (MonadIO m, Show a) => a -> m ()
logRequest (BaseCommand -> IO ()) -> BaseCommand -> IO ()
forall a b. (a -> b) -> a -> b
$ Word64 -> Word64 -> BaseCommand
P.closeProducer Word64
req Word64
pid
Socket -> BaseCommand -> IO ()
forall (m :: * -> *). MonadIO m => Socket -> BaseCommand -> m ()
sendSimpleCmd Socket
s (BaseCommand -> IO ()) -> BaseCommand -> IO ()
forall a b. (a -> b) -> a -> b
$ Word64 -> Word64 -> BaseCommand
P.closeProducer Word64
req Word64
pid
IO (Maybe CommandSuccess) -> IO ()
forall (f :: * -> *) a. Functor f => f a -> f ()
void (IO (Maybe CommandSuccess) -> IO ())
-> IO (Maybe CommandSuccess) -> IO ()
forall a b. (a -> b) -> a -> b
$ ReqId
-> Chan Response
-> LensLike'
(Constant (Maybe CommandSuccess))
BaseCommand
(Maybe CommandSuccess)
-> IO (Maybe CommandSuccess)
forall a.
(HasField a "requestId" Word64, Show a) =>
ReqId
-> Chan Response
-> LensLike' (Constant (Maybe a)) BaseCommand (Maybe a)
-> IO (Maybe a)
verifyResponse ReqId
r Chan Response
chan LensLike'
(Constant (Maybe CommandSuccess))
BaseCommand
(Maybe CommandSuccess)
forall (f :: * -> *) s a.
(Functor f, HasField s "maybe'success" a) =>
LensLike' f s a
F.maybe'success
newSubscriber
:: Connection
-> Chan Response
-> ReqId
-> ConsumerId
-> Topic
-> SubscriptionName
-> IO ()
newSubscriber :: Connection
-> Chan Response
-> ReqId
-> ConsumerId
-> Topic
-> SubscriptionName
-> IO ()
newSubscriber (Conn s :: Socket
s) chan :: Chan Response
chan r :: ReqId
r@(ReqId req :: Word64
req) (CId cid :: Word64
cid) topic :: Topic
topic subs :: SubscriptionName
subs = do
BaseCommand -> IO ()
forall (m :: * -> *) a. (MonadIO m, Show a) => a -> m ()
logRequest (BaseCommand -> IO ()) -> BaseCommand -> IO ()
forall a b. (a -> b) -> a -> b
$ Word64 -> Word64 -> Topic -> SubscriptionName -> BaseCommand
P.subscribe Word64
req Word64
cid Topic
topic SubscriptionName
subs
Socket -> BaseCommand -> IO ()
forall (m :: * -> *). MonadIO m => Socket -> BaseCommand -> m ()
sendSimpleCmd Socket
s (BaseCommand -> IO ()) -> BaseCommand -> IO ()
forall a b. (a -> b) -> a -> b
$ Word64 -> Word64 -> Topic -> SubscriptionName -> BaseCommand
P.subscribe Word64
req Word64
cid Topic
topic SubscriptionName
subs
IO (Maybe CommandSuccess) -> IO ()
forall (f :: * -> *) a. Functor f => f a -> f ()
void (IO (Maybe CommandSuccess) -> IO ())
-> IO (Maybe CommandSuccess) -> IO ()
forall a b. (a -> b) -> a -> b
$ ReqId
-> Chan Response
-> LensLike'
(Constant (Maybe CommandSuccess))
BaseCommand
(Maybe CommandSuccess)
-> IO (Maybe CommandSuccess)
forall a.
(HasField a "requestId" Word64, Show a) =>
ReqId
-> Chan Response
-> LensLike' (Constant (Maybe a)) BaseCommand (Maybe a)
-> IO (Maybe a)
verifyResponse ReqId
r Chan Response
chan LensLike'
(Constant (Maybe CommandSuccess))
BaseCommand
(Maybe CommandSuccess)
forall (f :: * -> *) s a.
(Functor f, HasField s "maybe'success" a) =>
LensLike' f s a
F.maybe'success
flow :: Connection -> ConsumerId -> IO ()
flow :: Connection -> ConsumerId -> IO ()
flow (Conn s :: Socket
s) (CId cid :: Word64
cid) = do
BaseCommand -> IO ()
forall (m :: * -> *) a. (MonadIO m, Show a) => a -> m ()
logRequest (BaseCommand -> IO ()) -> BaseCommand -> IO ()
forall a b. (a -> b) -> a -> b
$ Word64 -> BaseCommand
P.flow Word64
cid
Socket -> BaseCommand -> IO ()
forall (m :: * -> *). MonadIO m => Socket -> BaseCommand -> m ()
sendSimpleCmd Socket
s (BaseCommand -> IO ()) -> BaseCommand -> IO ()
forall a b. (a -> b) -> a -> b
$ Word64 -> BaseCommand
P.flow Word64
cid
ack :: MonadIO m => Connection -> ConsumerId -> MessageIdData -> m ()
ack :: Connection -> ConsumerId -> MessageIdData -> m ()
ack (Conn s :: Socket
s) (CId cid :: Word64
cid) msgId :: MessageIdData
msgId = do
BaseCommand -> m ()
forall (m :: * -> *) a. (MonadIO m, Show a) => a -> m ()
logRequest (BaseCommand -> m ()) -> BaseCommand -> m ()
forall a b. (a -> b) -> a -> b
$ Word64 -> MessageIdData -> BaseCommand
P.ack Word64
cid MessageIdData
msgId
Socket -> BaseCommand -> m ()
forall (m :: * -> *). MonadIO m => Socket -> BaseCommand -> m ()
sendSimpleCmd Socket
s (BaseCommand -> m ()) -> BaseCommand -> m ()
forall a b. (a -> b) -> a -> b
$ Word64 -> MessageIdData -> BaseCommand
P.ack Word64
cid MessageIdData
msgId
closeConsumer :: Connection -> Chan Response -> ReqId -> ConsumerId -> IO ()
closeConsumer :: Connection -> Chan Response -> ReqId -> ConsumerId -> IO ()
closeConsumer (Conn s :: Socket
s) _ (ReqId req :: Word64
req) (CId cid :: Word64
cid) = do
BaseCommand -> IO ()
forall (m :: * -> *) a. (MonadIO m, Show a) => a -> m ()
logRequest (BaseCommand -> IO ()) -> BaseCommand -> IO ()
forall a b. (a -> b) -> a -> b
$ Word64 -> Word64 -> BaseCommand
P.closeConsumer Word64
req Word64
cid
Socket -> BaseCommand -> IO ()
forall (m :: * -> *). MonadIO m => Socket -> BaseCommand -> m ()
sendSimpleCmd Socket
s (BaseCommand -> IO ()) -> BaseCommand -> IO ()
forall a b. (a -> b) -> a -> b
$ Word64 -> Word64 -> BaseCommand
P.closeConsumer Word64
req Word64
cid
Response
resp <- Socket -> IO Response
forall (m :: * -> *). MonadIO m => Socket -> m Response
receive Socket
s
case Response -> BaseCommand
getCommand Response
resp BaseCommand
-> LensLike'
(Constant (Maybe CommandSuccess))
BaseCommand
(Maybe CommandSuccess)
-> Maybe CommandSuccess
forall s a t b. s -> FoldLike a s t a b -> a
^. LensLike'
(Constant (Maybe CommandSuccess))
BaseCommand
(Maybe CommandSuccess)
forall (f :: * -> *) s a.
(Functor f, HasField s "maybe'success" a) =>
LensLike' f s a
F.maybe'success of
Just _ -> Response -> IO ()
forall (m :: * -> *) a. (MonadIO m, Show a) => a -> m ()
logResponse Response
resp
Nothing -> () -> IO ()
forall (m :: * -> *) a. Monad m => a -> m a
return ()
ping :: (MonadThrow m, MonadIO m) => Connection -> Chan Response -> m ()
ping :: Connection -> Chan Response -> m ()
ping (Conn s :: Socket
s) chan :: Chan Response
chan = do
BaseCommand -> m ()
forall (m :: * -> *) a. (MonadIO m, Show a) => a -> m ()
logRequest BaseCommand
P.ping
Socket -> BaseCommand -> m ()
forall (m :: * -> *). MonadIO m => Socket -> BaseCommand -> m ()
sendSimpleCmd Socket
s BaseCommand
P.ping
BaseCommand
cmd <- Response -> BaseCommand
getCommand (Response -> BaseCommand) -> m Response -> m BaseCommand
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> Chan Response -> m Response
forall (m :: * -> *) a. MonadIO m => Chan a -> m a
readChan Chan Response
chan
case BaseCommand
cmd BaseCommand
-> FoldLike
(Maybe CommandPong)
BaseCommand
BaseCommand
(Maybe CommandPong)
(Maybe CommandPong)
-> Maybe CommandPong
forall s a t b. s -> FoldLike a s t a b -> a
^. FoldLike
(Maybe CommandPong)
BaseCommand
BaseCommand
(Maybe CommandPong)
(Maybe CommandPong)
forall (f :: * -> *) s a.
(Functor f, HasField s "maybe'pong" a) =>
LensLike' f s a
F.maybe'pong of
Just p :: CommandPong
p -> CommandPong -> m ()
forall (m :: * -> *) a. (MonadIO m, Show a) => a -> m ()
logResponse CommandPong
p
Nothing -> IO () -> m ()
forall (m :: * -> *) a. MonadIO m => IO a -> m a
liftIO (IO () -> m ()) -> (IOError -> IO ()) -> IOError -> m ()
forall b c a. (b -> c) -> (a -> b) -> a -> c
. IOError -> IO ()
forall e a. Exception e => e -> IO a
throwIO (IOError -> m ()) -> IOError -> m ()
forall a b. (a -> b) -> a -> b
$ String -> IOError
userError "Failed to get PONG"
pong :: MonadIO m => Connection -> m ()
pong :: Connection -> m ()
pong (Conn s :: Socket
s) = do
BaseCommand -> m ()
forall (m :: * -> *) a. (MonadIO m, Show a) => a -> m ()
logRequest BaseCommand
P.pong
Socket -> BaseCommand -> m ()
forall (m :: * -> *). MonadIO m => Socket -> BaseCommand -> m ()
sendSimpleCmd Socket
s BaseCommand
P.pong
send
:: Connection
-> Chan Response
-> ProducerId
-> SeqId
-> PulsarMessage
-> IO ()
send :: Connection
-> Chan Response -> ProducerId -> SeqId -> PulsarMessage -> IO ()
send (Conn s :: Socket
s) chan :: Chan Response
chan (PId pid :: Word64
pid) (SeqId sid :: Word64
sid) (PulsarMessage msg :: ByteString
msg) = do
BaseCommand -> IO ()
forall (m :: * -> *) a. (MonadIO m, Show a) => a -> m ()
logRequest (BaseCommand -> IO ()) -> BaseCommand -> IO ()
forall a b. (a -> b) -> a -> b
$ Word64 -> Word64 -> BaseCommand
P.send Word64
pid Word64
sid
Socket -> BaseCommand -> MessageMetadata -> Maybe Payload -> IO ()
forall (m :: * -> *).
MonadIO m =>
Socket -> BaseCommand -> MessageMetadata -> Maybe Payload -> m ()
sendPayloadCmd Socket
s (Word64 -> Word64 -> BaseCommand
P.send Word64
pid Word64
sid) MessageMetadata
P.messageMetadata (Payload -> Maybe Payload
forall a. a -> Maybe a
Just (Payload -> Maybe Payload) -> Payload -> Maybe Payload
forall a b. (a -> b) -> a -> b
$ ByteString -> Payload
Payload ByteString
msg)
IO ()
confirmReception
where
confirmReception :: IO ()
confirmReception = do
Response
resp <- Chan Response -> IO Response
forall (m :: * -> *) a. MonadIO m => Chan a -> m a
readChan Chan Response
chan
let cmd' :: Maybe CommandSendReceipt
cmd' = Response -> BaseCommand
getCommand Response
resp BaseCommand
-> FoldLike
(Maybe CommandSendReceipt)
BaseCommand
BaseCommand
(Maybe CommandSendReceipt)
(Maybe CommandSendReceipt)
-> Maybe CommandSendReceipt
forall s a t b. s -> FoldLike a s t a b -> a
^. FoldLike
(Maybe CommandSendReceipt)
BaseCommand
BaseCommand
(Maybe CommandSendReceipt)
(Maybe CommandSendReceipt)
forall (f :: * -> *) s a.
(Functor f, HasField s "maybe'sendReceipt" a) =>
LensLike' f s a
F.maybe'sendReceipt
pid' :: Maybe Word64
pid' = FoldLike Word64 CommandSendReceipt CommandSendReceipt Word64 Word64
-> CommandSendReceipt -> Word64
forall a s t b. FoldLike a s t a b -> s -> a
view FoldLike Word64 CommandSendReceipt CommandSendReceipt Word64 Word64
forall (f :: * -> *) s a.
(Functor f, HasField s "producerId" a) =>
LensLike' f s a
F.producerId (CommandSendReceipt -> Word64)
-> Maybe CommandSendReceipt -> Maybe Word64
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> Maybe CommandSendReceipt
cmd'
sid' :: Maybe Word64
sid' = FoldLike Word64 CommandSendReceipt CommandSendReceipt Word64 Word64
-> CommandSendReceipt -> Word64
forall a s t b. FoldLike a s t a b -> s -> a
view FoldLike Word64 CommandSendReceipt CommandSendReceipt Word64 Word64
forall (f :: * -> *) s a.
(Functor f, HasField s "sequenceId" a) =>
LensLike' f s a
F.sequenceId (CommandSendReceipt -> Word64)
-> Maybe CommandSendReceipt -> Maybe Word64
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> Maybe CommandSendReceipt
cmd'
rewrite :: IO ()
rewrite = Chan Response -> Response -> IO ()
forall (m :: * -> *) a. MonadIO m => Chan a -> a -> m ()
writeChan Chan Response
chan Response
resp
loop :: IO ()
loop = IO ()
confirmReception
checkEq :: (a, Word64, Word64) -> IO ()
checkEq (_, pd :: Word64
pd, sd :: Word64
sd) | Word64
pd Word64 -> Word64 -> Bool
forall a. Eq a => a -> a -> Bool
== Word64
pid Bool -> Bool -> Bool
&& Word64
sd Word64 -> Word64 -> Bool
forall a. Eq a => a -> a -> Bool
== Word64
sid = Response -> IO ()
forall (m :: * -> *) a. (MonadIO m, Show a) => a -> m ()
logResponse Response
resp
| Bool
otherwise = IO ()
rewrite IO () -> IO () -> IO ()
forall (m :: * -> *) a b. Monad m => m a -> m b -> m b
>> IO ()
loop
IO ()
-> ((CommandSendReceipt, Word64, Word64) -> IO ())
-> Maybe (CommandSendReceipt, Word64, Word64)
-> IO ()
forall b a. b -> (a -> b) -> Maybe a -> b
maybe IO ()
loop (CommandSendReceipt, Word64, Word64) -> IO ()
forall a. (a, Word64, Word64) -> IO ()
checkEq (Maybe (CommandSendReceipt, Word64, Word64) -> IO ())
-> Maybe (CommandSendReceipt, Word64, Word64) -> IO ()
forall a b. (a -> b) -> a -> b
$ (,,) (CommandSendReceipt
-> Word64 -> Word64 -> (CommandSendReceipt, Word64, Word64))
-> Maybe CommandSendReceipt
-> Maybe (Word64 -> Word64 -> (CommandSendReceipt, Word64, Word64))
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> Maybe CommandSendReceipt
cmd' Maybe (Word64 -> Word64 -> (CommandSendReceipt, Word64, Word64))
-> Maybe Word64
-> Maybe (Word64 -> (CommandSendReceipt, Word64, Word64))
forall (f :: * -> *) a b. Applicative f => f (a -> b) -> f a -> f b
<*> Maybe Word64
pid' Maybe (Word64 -> (CommandSendReceipt, Word64, Word64))
-> Maybe Word64 -> Maybe (CommandSendReceipt, Word64, Word64)
forall (f :: * -> *) a b. Applicative f => f (a -> b) -> f a -> f b
<*> Maybe Word64
sid'