hsnsq-0.1.1.0: src/Network/NSQ/Types.hs
module Network.NSQ.Types
( MsgId
, Topic
, Channel
, LogName
, Message(..)
, Command(..)
-- TODO: probably don't want to export constructor here but want pattern matching
, FrameType(..)
, ErrorType(..)
, OptionalSetting(..)
, TLS(..)
, Compression(..)
, Identification(..)
, IdentifyMetadata(..)
-- Connection config/state
, NSQConnection(..)
) where
import Data.Int
import Data.Word
import Network
import qualified Data.ByteString as BS
import qualified Data.Map.Strict as Map
import qualified Data.Text as T
-- High level arch:
-- * One queue per topic/channel
-- * This queue can be feed by multiple nsqd (load balanced/nsqlookup for ex)
-- * Probably will have one set of state/config per nsqd connection and per queue/topic/channel
-- * Can probably later on provide helpers for consuming the queue
-- | Per Connection configuration
-- * Per nsqd (connection) state (rdy, load balance, etc)
-- * Per topic state (channel related info and which nsqd connection)
-- * Global? state (do we have any atm? maybe configuration?)
-- TODO: consider using monad-journal logger for pure code tracing
data NSQConnection = NSQConnection
{ server :: String
, port :: PortNumber
, logName :: LogName
, identConf :: IdentifyMetadata
}
-- | Logger Name for a connection (hslogger format)
type LogName = String
-- | Message Id, it is a 16-byte hexdecimal string encoded as ASCII
type MsgId = BS.ByteString
-- | NSQ Topic, the only allowed character in a topic is @\\.a-zA-Z0-9_-@
type Topic = T.Text
-- | NSQ Channel, the only allowed character in a channel is @\\.a-zA-Z0-9_-@
-- A channel can be marked as ephemeral by toggling the 'Bool' value to
-- true in 'Sub'
type Channel = T.Text
-- | NSQ Command
data Command = Protocol -- ^ The protocol version
| NOP -- ^ No-op, usually used in reply to a 'Heartbeat' request from the server.
| Identify IdentifyMetadata -- ^ Client Identification + possible features negotiation.
| Sub Topic Channel Bool -- ^ Subscribe to a specified 'Topic'/'Channel', use 'True' if its an ephemeral channel.
| Pub Topic BS.ByteString -- ^ Publish a message to the specified 'Topic'.
| MPub Topic [BS.ByteString] -- ^ Publish multiple messages to a specified 'Topic'.
| Rdy Word64 -- ^ Update @RDY@ state (ready to recieve messages). Number of message you can process at once.
| Fin MsgId -- ^ Finish a message.
| Req MsgId Word64 -- ^ Re-queue a message (failure to process), Timeout is in milliseconds.
| Touch MsgId -- ^ Reset the timeout for an in-flight message.
| Cls -- ^ Cleanly close the connection to the NSQ daemon.
| Command BS.ByteString -- ^ Catch-all command for future expansion/custom commands.
deriving Show
-- | Frame Type of the incoming data from the NSQ daemon.
data FrameType = FTResponse -- ^ Response to a 'Command' from the server.
| FTError -- ^ An error in response to a 'Command'.
| FTMessage -- ^ Messages.
| FTUnknown Int32 -- ^ For future extension for handling new Frame Types.
deriving Show
-- | Types of error that the server can return in response to an 'Command'
data ErrorType = Invalid
| BadBody
| BadTopic
| BadChannel
| BadMessage
| PubFailed
| MPubFailed
| FinFailed
| ReqFailed
| TouchFailed
deriving Show
-- | The message and replies back from the server.
data Message = OK -- ^ Everything is allright.
| Heartbeat -- ^ Heartbeat, reply with the 'NOP' 'Command'.
| CloseWait -- ^ Server has closed the connection.
-- TODO: BS.ByteString -> ErrorType
| Error BS.ByteString -- ^ The server sent back an error.
| Message Int64 Word16 MsgId BS.ByteString -- ^ A message to be processed. The values are: Nanosecond Timestamp, number of attempts, Message Id, and the content of the message to be processed.
| CatchAllMessage FrameType BS.ByteString -- ^ Catch-all message for future expansion. This currently includes the reply from 'Identify' if feature negotiation is set.
deriving Show
-- Feature and Identification
data OptionalSetting = Disabled | Custom Word64
deriving Show
data TLS = NoTLS | TLSV1
deriving Show
data Compression = NoCompression | Snappy | Deflate Word8
deriving Show
data Identification = Identification
{ clientId :: T.Text
, hostname :: T.Text
, shortId :: Maybe T.Text -- Deprecated in favor of client_id
, longId :: Maybe T.Text -- Deprecated in favor of hostname
, userAgent :: Maybe T.Text -- Default (client_library_name/version)
}
deriving Show
-- feature_negotiation - set automatically if anything is set
data IdentifyMetadata = IdentifyMetadata
{ ident :: Identification
, tls :: Maybe TLS
, compression :: Maybe Compression
, heartbeatInterval :: Maybe OptionalSetting -- disabled = -1
, outputBufferSize :: Maybe OptionalSetting -- disabled = -1
, outputBufferTimeout :: Maybe OptionalSetting -- disabled = -1
, sampleRate :: Maybe OptionalSetting -- disabled = 0
-- Map of possible json value for future compat
, custom :: Maybe (Map.Map T.Text T.Text)
, customNegotiation :: Bool
}
deriving Show