hsnsq-0.1.2.0: src/Network/NSQ/Types.hs
{-|
Module : Network.NSQ.Types
Description : Not much to see here, just the types for the library.
-}
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
-- TODO: consider using monad-journal logger for pure code tracing
-- | Per Connection configuration such as: per nsqd state (rdy, load balance), per topic state (channel)
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 -- ^ Something went wrong with the command (IDENTIFY, SUB, PUB, MPUB, RDY, FIN, REQ, TOUCH, CLS)
| BadBody -- ^ Bad Body (IDENTIFY, MPUB)
| BadTopic -- ^ Bad Topic (most likely used disallowed characters) (SUB, PUB, MPUB)
| BadChannel -- ^ Bad channel (Like 'BadTopic' probably used an disallowed character) (SUB)
| BadMessage -- ^ Bad Message (PUB, MPUB)
| PubFailed -- ^ Publishing a message failed (PUB)
| MPubFailed -- ^ Same as 'PubFailed' (MPUB)
| FinFailed -- ^ Finish failed (Probably already finished or non-existant message-id) (FIN)
| ReqFailed -- ^ Requeue failed (REQ)
| TouchFailed -- ^ Touch failed (TOUCH)
| Unknown BS.ByteString -- ^ New unknown type of error (ANY)
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.
| Error ErrorType -- ^ 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
-- | Optional settings, if 'Disabled' then this setting will be put in the
-- json as disabled specifically vs "not being listed".
data OptionalSetting = Disabled | Custom Word64
deriving Show
-- | TLS version supported
data TLS = NoTLS | TLSV1
deriving Show
-- | For 'Deflate' its the compression level from 0-9
data Compression = NoCompression | Snappy | Deflate Word8
deriving Show
-- | The client identification
data Identification = Identification
{ clientId :: T.Text -- ^ An identifier of this consumer, something specific to this consumer
, hostname :: T.Text -- ^ Hostname of the machine the client is running on
, 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
-- | Metadata for feature negotiation, if any of the values
-- are set it will be sent to the server otherwise they will be omitted.
-- If the setting is set to 'Nothing' it will not be sent to the server,
-- and if its set to 'Just' 'Disabled' it will be sent to the server as
-- disabled explicitly.
data IdentifyMetadata = IdentifyMetadata
{ ident :: Identification -- ^ Client identification
, tls :: Maybe TLS -- ^ TLS
, compression :: Maybe Compression -- ^ Compression
, heartbeatInterval :: Maybe OptionalSetting -- ^ The time between each heartbeat (disabled = -1)
, outputBufferSize :: Maybe OptionalSetting -- ^ The size of the buffer (disabled = -1)
, outputBufferTimeout :: Maybe OptionalSetting -- ^ The timeout for the buffer (disabled = -1)
, sampleRate :: Maybe OptionalSetting -- ^ Sampling of the message will be sent to the client (disabled = 0)
, custom :: Maybe (Map.Map T.Text T.Text) -- ^ Map of possible key -> value for future protocol expansion
, customNegotiation :: Bool -- ^ Set if there are any 'custom' values to send
}
deriving Show