natskell-0.0.0.1: client/API.hs
-- | Capability record for the NATS client surface.
module API
(
Client (..)
, MsgView (..)
, PublishOption
, SubscribeOption
, withSubscriptionExpiry
, withPayload
, withReplyCallback
, withHeaders
) where
import qualified Data.ByteString as BS
import Data.Time.Clock (NominalDiffTime)
import Lib.CallOption (CallOption)
import Publish.Config (PublishConfig)
import Subscription.Types (SubscribeConfig (..))
import qualified Types.Msg as Msg
import Types.Msg (Headers, Payload, SID, Subject)
-- | Client capabilities for publishing, subscribing, and lifecycle control.
data Client = Client
{ publish :: Subject -> [PublishOption] -> IO ()
-- ^ Publish a message, optionally overriding publish options.
, subscribe :: Subject -> [SubscribeOption] -> (Maybe MsgView -> IO ()) -> IO SID
-- ^ Subscribe to a subject and handle delivered messages.
, request :: Subject -> [SubscribeOption] -> (Maybe MsgView -> IO ()) -> IO SID
-- ^ Subscribe with request semantics and auto-unsubscribe after a reply.
, unsubscribe :: SID -> IO ()
-- ^ Unsubscribe from a subscription by SID.
, ping :: IO () -> IO ()
-- ^ Send a ping and run the callback when a pong arrives.
, flush :: IO ()
-- ^ Flush buffered writes to the server.
, reset :: IO ()
-- ^ Reset the client connection state.
, close :: IO ()
-- ^ Close the client connection and release resources.
}
-- | MsgView represents a MSG in the NATS protocol.
data MsgView = MsgView
{ -- | The subject of the message.
subject :: BS.ByteString
-- | The SID (subscription ID) of the message.
, sid :: BS.ByteString
-- | The replyTo subject, if any.
, replyTo :: Maybe BS.ByteString
-- | The payload of the message, if any.
, payload :: Maybe BS.ByteString
-- | Headers associated with the message, if any.
, headers :: Maybe [(BS.ByteString, BS.ByteString)]
}
deriving (Eq, Show)
type PublishOption = CallOption PublishConfig
type SubscribeOption = CallOption SubscribeConfig
-- | withSubscriptionExpiry sets the reply subscription expiry in seconds.
-- Default: no expiry (reply subscriptions stay open until unsubscribe).
--
-- __Examples:__
--
-- @
-- {-# LANGUAGE OverloadedStrings #-}
--
-- subscribe client \"events.created\" [withSubscriptionExpiry 2] print
-- @
withSubscriptionExpiry :: NominalDiffTime -> SubscribeOption
withSubscriptionExpiry expirySeconds cfg = cfg { expiry = Just expirySeconds }
-- | withPayload is used to set the payload for a publish operation.
-- Default: no payload.
--
-- __Examples:__
--
-- @
-- {-# LANGUAGE OverloadedStrings #-}
--
-- publish client \"updates\" [withPayload \"hello\"]
-- @
withPayload :: Payload -> PublishOption
withPayload payload (_, callback, headers) = (Just payload, callback, headers)
-- | withReplyCallback is used to set a callback for a reply to a publish operation.
-- Default: no reply subscription; publishes are fire-and-forget.
--
-- __Examples:__
--
-- @
-- {-# LANGUAGE OverloadedStrings #-}
--
-- publish client \"service.echo\" [withReplyCallback print]
-- @
withReplyCallback :: (Maybe MsgView -> IO ()) -> PublishOption
withReplyCallback callback (payload, _, headers) =
(payload, Just (callback . fmap (\msg -> MsgView
{ subject = Msg.subject msg
, sid = Msg.sid msg
, replyTo = Msg.replyTo msg
, payload = Msg.payload msg
, headers = Msg.headers msg
})), headers)
-- | withHeaders is used to set headers for a publish operation.
-- Default: no headers.
--
-- __Examples:__
--
-- @
-- {-# LANGUAGE OverloadedStrings #-}
--
-- publish client \"updates\" [withHeaders [(\"source\", \"test\")]]
-- @
withHeaders :: Headers -> PublishOption
withHeaders headers (payload, callback, _) = (payload, callback, Just headers)