{-| 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