packages feed

milena 0.1.0.0 → 0.2.0.0

raw patch · 5 files changed

+200/−119 lines, 5 filesdep +resource-pooldep ~bytestringdep ~digestdep ~lensPVP ok

version bump matches the API change (PVP)

Dependencies added: resource-pool

Dependency ranges changed: bytestring, digest, lens, mtl, transformers

API changes (from Hackage documentation)

- Network.Kafka: KafkaConsumer :: KafkaState -> Handle -> KafkaConsumer
- Network.Kafka: _consumerHandle :: KafkaConsumer -> Handle
- Network.Kafka: _consumerState :: KafkaConsumer -> KafkaState
- Network.Kafka: brokerPartitionInfo :: TopicName -> Kafka [PartitionAndLeader]
- Network.Kafka: consumerHandle :: Lens' KafkaConsumer Handle
- Network.Kafka: consumerState :: Lens' KafkaConsumer KafkaState
- Network.Kafka: data KafkaConsumer
- Network.Kafka: defaultMessageAttributes :: Attributes
- Network.Kafka: defaultMessageCrc :: Crc
- Network.Kafka: defaultMessageKey :: Key
- Network.Kafka: defaultMessageMagicByte :: MagicByte
- Network.Kafka: getPartition :: [PartitionAndLeader] -> Kafka (Maybe PartitionAndLeader)
- Network.Kafka: groupMessagesToSet :: [TopicAndMessage] -> MessageSet
- Network.Kafka: makeMessage :: ByteString -> Message
- Network.Kafka: partitionAndCollate :: [TopicAndMessage] -> Kafka (Map Leader (Map TopicAndPartition [TopicAndMessage]))
- Network.Kafka: produce :: ProduceRequest -> Kafka ProduceResponse
- Network.Kafka: produceMessages :: [TopicAndMessage] -> Kafka [ProduceResponse]
- Network.Kafka: produceRequest :: RequiredAcks -> Timeout -> [(TopicAndPartition, MessageSet)] -> ProduceRequest
- Network.Kafka: send :: Leader -> [(TopicAndPartition, MessageSet)] -> Kafka ProduceResponse
+ Network.Kafka: KafkaClient :: KafkaState -> Handle -> KafkaClient
+ Network.Kafka: KafkaFailedToFetchMetadata :: KafkaClientError
+ Network.Kafka: _kafkaClientHandle :: KafkaClient -> Handle
+ Network.Kafka: _kafkaClientState :: KafkaClient -> KafkaState
+ Network.Kafka: _stateConnections :: KafkaState -> Map Broker (Pool Handle)
+ Network.Kafka: _stateTopicMetadata :: KafkaState -> Map TopicName TopicMetadata
+ Network.Kafka: data KafkaClient
+ Network.Kafka: doRequest' :: Handle -> Request -> Kafka Response
+ Network.Kafka: instance Show PartitionAndLeader
+ Network.Kafka: kafkaClientHandle :: Lens' KafkaClient Handle
+ Network.Kafka: kafkaClientState :: Lens' KafkaClient KafkaState
+ Network.Kafka: metadata' :: Handle -> MetadataRequest -> Kafka MetadataResponse
+ Network.Kafka: stateConnections :: Lens' KafkaState (Map Broker (Pool Handle))
+ Network.Kafka: stateTopicMetadata :: Lens' KafkaState (Map TopicName TopicMetadata)
+ Network.Kafka: updateAllMetadata :: Kafka ()
+ Network.Kafka: updateMetadata :: TopicName -> Kafka ()
+ Network.Kafka: updateMetadatas :: [TopicName] -> Kafka ()
+ Network.Kafka: withBrokerHandle :: Broker -> (Handle -> Kafka a) -> Kafka a
+ Network.Kafka.Producer: brokerPartitionInfo :: TopicName -> Kafka [PartitionAndLeader]
+ Network.Kafka.Producer: defaultMessageAttributes :: Attributes
+ Network.Kafka.Producer: defaultMessageCrc :: Crc
+ Network.Kafka.Producer: defaultMessageKey :: Key
+ Network.Kafka.Producer: defaultMessageMagicByte :: MagicByte
+ Network.Kafka.Producer: findMetadataOrElse :: [TopicName] -> Getting (Maybe a) KafkaClient (Maybe a) -> KafkaClientError -> Kafka a
+ Network.Kafka.Producer: getPartition :: [PartitionAndLeader] -> Kafka (Maybe PartitionAndLeader)
+ Network.Kafka.Producer: groupMessagesToSet :: [TopicAndMessage] -> MessageSet
+ Network.Kafka.Producer: makeMessage :: ByteString -> Message
+ Network.Kafka.Producer: partitionAndCollate :: [TopicAndMessage] -> Kafka (Map Leader (Map TopicAndPartition [TopicAndMessage]))
+ Network.Kafka.Producer: produce :: Handle -> ProduceRequest -> Kafka ProduceResponse
+ Network.Kafka.Producer: produceMessages :: [TopicAndMessage] -> Kafka [ProduceResponse]
+ Network.Kafka.Producer: produceRequest :: RequiredAcks -> Timeout -> [(TopicAndPartition, MessageSet)] -> ProduceRequest
+ Network.Kafka.Producer: send :: Leader -> [(TopicAndPartition, MessageSet)] -> Kafka ProduceResponse
+ Network.Kafka.Protocol: instance Ord Broker
+ Network.Kafka.Protocol: instance Ord Host
+ Network.Kafka.Protocol: instance Ord Port
- Network.Kafka: KafkaState :: KafkaString -> CorrelationId -> RequiredAcks -> Timeout -> MinBytes -> MaxBytes -> MaxWaitTime -> Map Leader Broker -> KafkaState
+ Network.Kafka: KafkaState :: KafkaString -> RequiredAcks -> Timeout -> MinBytes -> MaxBytes -> MaxWaitTime -> CorrelationId -> Map Leader Broker -> Map Broker (Pool Handle) -> Map TopicName TopicMetadata -> KafkaState
- Network.Kafka: type Kafka = StateT KafkaConsumer (EitherT KafkaClientError IO)
+ Network.Kafka: type Kafka = StateT KafkaClient (EitherT KafkaClientError IO)

Files

Network/Kafka.hs view
@@ -12,9 +12,9 @@ import Control.Monad.Trans.State import Data.ByteString.Char8 (ByteString) import Data.Monoid ((<>))+import qualified Data.Pool as Pool import Data.Serialize.Get import System.IO-import System.Random (getStdRandom, randomR) import qualified Data.ByteString.Char8 as B import qualified Data.Map as M import qualified Network@@ -23,8 +23,6 @@  data KafkaState = KafkaState { -- | Name to use as a client ID.                                _stateName :: KafkaString-                               -- | An incrementing counter of requests.-                             , _stateCorrelationId :: CorrelationId                                -- | How many acknowledgements are required for producing.                              , _stateRequiredAcks :: RequiredAcks                                -- | Time in milliseconds to wait for messages to be produced by broker.@@ -35,20 +33,26 @@                              , _stateBufferSize :: MaxBytes                                -- | Maximum time in milliseconds to wait for response.                              , _stateWaitTime :: MaxWaitTime+                               -- | An incrementing counter of requests.+                             , _stateCorrelationId :: CorrelationId                                -- | Broker cache                              , _stateBrokers :: M.Map Leader Broker+                               -- | Connection cache+                             , _stateConnections :: M.Map Broker (Pool.Pool Handle)+                               -- | Topic metadata cache+                             , _stateTopicMetadata :: M.Map TopicName TopicMetadata                              }  makeLenses ''KafkaState -data KafkaConsumer = KafkaConsumer { _consumerState :: KafkaState-                                   , _consumerHandle :: Handle-                                   }+data KafkaClient = KafkaClient { _kafkaClientState :: KafkaState+                               , _kafkaClientHandle :: Handle+                               } -makeLenses ''KafkaConsumer+makeLenses ''KafkaClient  -- | The core Kafka monad.-type Kafka = StateT KafkaConsumer (EitherT KafkaClientError IO)+type Kafka = StateT KafkaClient (EitherT KafkaClientError IO)  type KafkaAddress = (Host, Port) type KafkaClientId = KafkaString@@ -62,6 +66,7 @@                       | KafkaDeserializationError String -- TODO: cereal is Stringly typed, should use tickle                         -- | Could not find a cached broker for the found leader.                       | KafkaInvalidBroker Leader+                      | KafkaFailedToFetchMetadata                         deriving (Eq, Show)  -- | Type of response to expect, used for 'KafkaExpected' error.@@ -82,6 +87,7 @@                                              , _palPartition :: Partition                                              , _palLeader :: Leader                                              }+                                             deriving (Show)  makeLenses ''PartitionAndLeader @@ -132,31 +138,37 @@ defaultState :: KafkaClientId -> KafkaState defaultState cid =     KafkaState cid-               defaultCorrelationId                defaultRequiredAcks                defaultRequestTimeout                defaultMinBytes                defaultMaxBytes                defaultMaxWaitTime+               defaultCorrelationId                M.empty+               M.empty+               M.empty  -- | Run the underlying Kafka monad at the given leader address and initial state. runKafka :: KafkaAddress -> KafkaState -> Kafka a -> IO (Either KafkaClientError a) runKafka (h, p) s k =-    bracket (Network.connectTo (h ^. hostString) (p ^. portId)) hClose $ runEitherT . evalStateT k . KafkaConsumer s+  bracket (Network.connectTo (h ^. hostString) (p ^. portId)) hClose $ runEitherT . evalStateT k . KafkaClient s  -- | Make a request, incrementing the `_stateCorrelationId`. makeRequest :: RequestMessage -> Kafka Request makeRequest m = do-  corid <- use (consumerState . stateCorrelationId)-  consumerState . stateCorrelationId += 1-  conid <- use (consumerState . stateName)+  corid <- use (kafkaClientState . stateCorrelationId)+  kafkaClientState . stateCorrelationId += 1+  conid <- use (kafkaClientState . stateName)   return $ Request (corid, ClientId conid, m)  -- | Perform a request and deserialize the response. doRequest :: Request -> Kafka Response-doRequest r = mapStateT (bimapEitherT KafkaDeserializationError id) $ do-  h <- use consumerHandle+doRequest r = do+  h <- use kafkaClientHandle+  doRequest' h r++doRequest' :: Handle -> Request -> Kafka Response+doRequest' h r = mapStateT (bimapEitherT KafkaDeserializationError id) $ do   dataLength <- lift . EitherT $ do     B.hPut h $ requestBytes r     hFlush h@@ -167,9 +179,15 @@  -- | Send a metadata request metadata :: MetadataRequest -> Kafka MetadataResponse-metadata request =-    makeRequest (MetadataRequest request) >>= doRequest >>= expectResponse ExpectedMetadata _MetadataResponse+metadata request = do+  h <- use kafkaClientHandle+  metadata' h request +-- | Send a metadata request+metadata' :: Handle -> MetadataRequest -> Kafka MetadataResponse+metadata' handle request =+    makeRequest (MetadataRequest request) >>= doRequest' handle >>= expectResponse ExpectedMetadata _MetadataResponse+ -- | Function to give an error when the response seems wrong. expectResponse :: KafkaExpectedResponse -> Getting (Leftmost b) ResponseMessage b -> Response -> Kafka b expectResponse e p = lift . maybe (left $ KafkaExpected e) return . firstOf (responseMessage . p)@@ -180,61 +198,6 @@ protocolTime EarliestTime = Time (-2) protocolTime (OtherTime o) = o --- * Messages---- | Group messages together with the leader they should be sent to.-partitionAndCollate :: [TopicAndMessage] -> Kafka (M.Map Leader (M.Map TopicAndPartition [TopicAndMessage]))-partitionAndCollate ks = recurse ks M.empty-      where recurse [] accum = return accum-            recurse (x:xs) accum = do-              topicPartitionsList <- brokerPartitionInfo $ _tamTopic x-              pal <- getPartition topicPartitionsList-              let leader = maybe (Leader Nothing) _palLeader pal-                  tp = TopicAndPartition <$> pal ^? folded . palTopic <*> pal ^? folded . palPartition-                  b = M.singleton leader $ maybe M.empty (`M.singleton` [x]) tp-                  accum' = M.unionWith (M.unionWith (<>)) accum b-              recurse xs accum'--getPartition :: [PartitionAndLeader] -> Kafka (Maybe PartitionAndLeader)-getPartition ps =-    liftIO $ (ps' ^?) . element <$> getStdRandom (randomR (0, length ps' - 1))-        where ps' = ps ^.. folded . filtered (has $ palLeader . leaderId . _Just)---- | Create a protocol message set from a list of messages.-groupMessagesToSet :: [TopicAndMessage] -> MessageSet-groupMessagesToSet xs = MessageSet $ uncurry msm <$> zip [0..] xs-    where msm n = MessageSetMember (Offset n) . _tamMessage---- | Find a leader and partition for the topic.-brokerPartitionInfo :: TopicName -> Kafka [PartitionAndLeader]-brokerPartitionInfo t = do-  md <- metadata $ MetadataReq [t]-  let brokers = md ^.. metadataResponseFields . _1 . folded-  consumerState . stateBrokers .= foldr addBroker M.empty brokers-  return $ pal <$> md ^.. topicsMetadata . folded . partitionsMetadata . folded-      where pal d = PartitionAndLeader t (d ^. partitionId) (d ^. partitionMetadataLeader)-            addBroker b = M.insert (Leader . Just $ b ^. brokerFields . _1 . nodeId) b---- | Default: @1@-defaultMessageCrc :: Crc-defaultMessageCrc = 1---- | Default: @0@-defaultMessageMagicByte :: MagicByte-defaultMessageMagicByte = 0---- | Default: @Nothing@-defaultMessageKey :: Key-defaultMessageKey = Key Nothing---- | Default: @0@-defaultMessageAttributes :: Attributes-defaultMessageAttributes = 0---- | Construct a message from a string of bytes using default attributes.-makeMessage :: ByteString -> Message-makeMessage m = Message (defaultMessageCrc, defaultMessageMagicByte, defaultMessageAttributes, defaultMessageKey, Value (Just (KBytes m)))- -- * Fetching  -- | Default: @-1@@@ -244,9 +207,9 @@ -- | Construct a fetch request from the values in the state. fetchRequest :: Offset -> Partition -> TopicName -> Kafka FetchRequest fetchRequest o p topic = do-  wt <- use (consumerState . stateWaitTime)-  ws <- use (consumerState . stateWaitSize)-  bs <- use (consumerState . stateBufferSize)+  wt <- use (kafkaClientState . stateWaitTime)+  ws <- use (kafkaClientState . stateWaitSize)+  bs <- use (kafkaClientState . stateBufferSize)   return $ FetchReq (ordinaryConsumerId, wt, ws, [(topic, [(p, o, bs)])])  -- | Execute a fetch request and get the raw fetch response.@@ -259,37 +222,44 @@ fetchMessages fr = (fr ^.. fetchResponseFields . folded) >>= tam     where tam a = TopicAndMessage (a ^. _1) <$> a ^.. _2 . folded . _4 . messageSetMembers . folded . setMessage --- * Producing+updateMetadatas :: [TopicName] -> Kafka ()+updateMetadatas ts = do+  md <- metadata $ MetadataReq ts+  let (brokers, tmds) = (md ^.. metadataResponseBrokers . folded, md ^.. topicsMetadata . folded)+  kafkaClientState . stateBrokers %= \m -> foldr addBroker m brokers+  kafkaClientState . stateTopicMetadata %= \m -> foldr addTopicMetadata m tmds+  return ()+    where addBroker :: Broker -> M.Map Leader Broker -> M.Map Leader Broker+          addBroker b = M.insert (Leader . Just $ b ^. brokerNode . nodeId) b+          addTopicMetadata :: TopicMetadata -> M.Map TopicName TopicMetadata -> M.Map TopicName TopicMetadata+          addTopicMetadata tm = M.insert (tm ^. topicMetadataName) tm --- | Execute a produce request and get the raw preduce response.-produce :: ProduceRequest -> Kafka ProduceResponse-produce request =-    makeRequest (ProduceRequest request) >>= doRequest >>= expectResponse ExpectedProduce _ProduceResponse+updateMetadata :: TopicName -> Kafka ()+updateMetadata t = updateMetadatas [t] --- | Construct a produce request with explicit arguments.-produceRequest :: RequiredAcks -> Timeout -> [(TopicAndPartition, MessageSet)] -> ProduceRequest-produceRequest ra ti ts =-    ProduceReq (ra, ti, M.toList . M.unionsWith (<>) $ fmap f ts)-        where f (TopicAndPartition t p, i) = M.singleton t [(p, i)]+updateAllMetadata :: Kafka ()+updateAllMetadata = updateMetadatas [] --- | Send messages to partition calculated by 'partitionAndCollate'.-produceMessages :: [TopicAndMessage] -> Kafka [ProduceResponse]-produceMessages tams = do-  m <- fmap (fmap groupMessagesToSet) <$> partitionAndCollate tams-  mapM (uncurry send) $ fmap M.toList <$> M.toList m+-- | Execute a handler action, creating a new Pool and updating the connections Map if needed.+withBrokerHandle :: Broker -> (Handle -> Kafka a) -> Kafka a+withBrokerHandle broker f = do+  conns <- use (kafkaClientState . stateConnections)+  let foundPool = conns ^. at broker+  pool <- case foundPool of+    Nothing -> do+      newPool <- liftIO $ mkPool broker+      kafkaClientState . stateConnections .= (at broker ?~ newPool $ conns)+      return newPool+    Just p -> return p+  Pool.withResource pool f+    where mkPool :: Broker -> IO (Pool.Pool Handle)+          mkPool b = Pool.createPool (createHandle b) hClose 1 10 1+          createHandle b = do+            let h = b ^. brokerHost ^. hostString+                p = b ^. brokerPort ^. portId+            Network.connectTo h p --- | Execute a produce request using the values in the state.-send :: Leader -> [(TopicAndPartition, MessageSet)] -> Kafka ProduceResponse-send l ts = do-  foundBroker <- use (consumerState . stateBrokers . at l)-  broker <- lift $ maybe (left $ KafkaInvalidBroker l) right foundBroker-  requiredAcks <- use (consumerState . stateRequiredAcks)-  requestTimeout <- use (consumerState . stateRequestTimeout)-  let h' = broker ^. brokerFields . _2-      p' = broker ^. brokerFields . _3-  cstate <- use consumerState-  r <- liftIO . runKafka (h', p') cstate . produce $ produceRequest requiredAcks requestTimeout ts-  lift $ either left right r+  -- * Offsets 
+ Network/Kafka/Producer.hs view
@@ -0,0 +1,108 @@+module Network.Kafka.Producer where++import Control.Applicative+import Control.Lens+import Control.Monad.Trans (liftIO, lift)+import Control.Monad.Trans.Either+import Data.ByteString.Char8 (ByteString)+import Data.Monoid ((<>))+import System.IO+import qualified Data.Map as M+import System.Random (getStdRandom, randomR)++import Network.Kafka+import Network.Kafka.Protocol++-- * Producing++-- | Execute a produce request and get the raw preduce response.+produce :: Handle -> ProduceRequest -> Kafka ProduceResponse+produce handle request =+    makeRequest (ProduceRequest request) >>= doRequest' handle >>= expectResponse ExpectedProduce _ProduceResponse++-- | Construct a produce request with explicit arguments.+produceRequest :: RequiredAcks -> Timeout -> [(TopicAndPartition, MessageSet)] -> ProduceRequest+produceRequest ra ti ts =+    ProduceReq (ra, ti, M.toList . M.unionsWith (<>) $ fmap f ts)+        where f (TopicAndPartition t p, i) = M.singleton t [(p, i)]++-- | Send messages to partition calculated by 'partitionAndCollate'.+produceMessages :: [TopicAndMessage] -> Kafka [ProduceResponse]+produceMessages tams = do+  m <- fmap (fmap groupMessagesToSet) <$> partitionAndCollate tams+  mapM (uncurry send) $ fmap M.toList <$> M.toList m++-- | Create a protocol message set from a list of messages.+groupMessagesToSet :: [TopicAndMessage] -> MessageSet+groupMessagesToSet xs = MessageSet $ msm <$> xs+    where msm = MessageSetMember (Offset (-1)) . _tamMessage++-- | Group messages together with the leader they should be sent to.+partitionAndCollate :: [TopicAndMessage] -> Kafka (M.Map Leader (M.Map TopicAndPartition [TopicAndMessage]))+partitionAndCollate ks = recurse ks M.empty+      where recurse [] accum = return accum+            recurse (x:xs) accum = do+              topicPartitionsList <- brokerPartitionInfo $ _tamTopic x+              pal <- getPartition topicPartitionsList+              let leader = maybe (Leader Nothing) _palLeader pal+                  tp = TopicAndPartition <$> pal ^? folded . palTopic <*> pal ^? folded . palPartition+                  b = M.singleton leader $ maybe M.empty (`M.singleton` [x]) tp+                  accum' = M.unionWith (M.unionWith (<>)) accum b+              recurse xs accum'++-- | Execute a produce request using the values in the state.+send :: Leader -> [(TopicAndPartition, MessageSet)] -> Kafka ProduceResponse+send l ts = do+  let s = kafkaClientState . stateBrokers . at l+      topicNames = map (_tapTopic . fst) ts+  broker <- findMetadataOrElse topicNames s (KafkaInvalidBroker l)+  requiredAcks <- use (kafkaClientState . stateRequiredAcks)+  requestTimeout <- use (kafkaClientState . stateRequestTimeout)+  withBrokerHandle broker $ \handle -> produce handle $ produceRequest requiredAcks requestTimeout ts++-- | Find a leader and partition for the topic.+brokerPartitionInfo :: TopicName -> Kafka [PartitionAndLeader]+brokerPartitionInfo t = do+  let s = kafkaClientState . stateTopicMetadata . at t+  tmd <- findMetadataOrElse [t] s KafkaFailedToFetchMetadata+  return $ pal <$> tmd ^. partitionsMetadata+    where pal d = PartitionAndLeader t (d ^. partitionId) (d ^. partitionMetadataLeader)++findMetadataOrElse :: [TopicName] -> Getting (Maybe a) KafkaClient (Maybe a) -> KafkaClientError -> Kafka a+findMetadataOrElse ts s err = do+  maybeFound <- use s+  case maybeFound of+    Just x -> return x+    Nothing -> do+      updateMetadatas ts+      maybeFound' <- use s+      case maybeFound' of+        Just x -> return x+        Nothing -> lift $ left $ err++getPartition :: [PartitionAndLeader] -> Kafka (Maybe PartitionAndLeader)+getPartition ps =+    liftIO $ (ps' ^?) . element <$> getStdRandom (randomR (0, length ps' - 1))+        where ps' = ps ^.. folded . filtered (has $ palLeader . leaderId . _Just)++-- * Messages++-- | Default: @1@+defaultMessageCrc :: Crc+defaultMessageCrc = 1++-- | Default: @0@+defaultMessageMagicByte :: MagicByte+defaultMessageMagicByte = 0++-- | Default: @Nothing@+defaultMessageKey :: Key+defaultMessageKey = Key Nothing++-- | Default: @0@+defaultMessageAttributes :: Attributes+defaultMessageAttributes = 0++-- | Construct a message from a string of bytes using default attributes.+makeMessage :: ByteString -> Message+makeMessage m = Message (defaultMessageCrc, defaultMessageMagicByte, defaultMessageAttributes, defaultMessageKey, Value (Just (KBytes m)))
Network/Kafka/Protocol.hs view
@@ -95,10 +95,10 @@   deriving (Show, Eq, Serializable, Deserializable)  newtype MetadataResponse = MetadataResp { _metadataResponseFields :: ([Broker], [TopicMetadata]) } deriving (Show, Eq, Deserializable)-newtype Broker = Broker { _brokerFields :: (NodeId, Host, Port) } deriving (Show, Eq, Deserializable)+newtype Broker = Broker { _brokerFields :: (NodeId, Host, Port) } deriving (Show, Eq, Ord, Deserializable) newtype NodeId = NodeId { _nodeId :: Int32 } deriving (Show, Eq, Ord, Deserializable, Num)-newtype Host = Host { _hostKString :: KafkaString } deriving (Show, Eq, Deserializable, IsString)-newtype Port = Port { _portInt :: Int32 } deriving (Show, Eq, Deserializable, Num)+newtype Host = Host { _hostKString :: KafkaString } deriving (Show, Eq, Ord, Deserializable, IsString)+newtype Port = Port { _portInt :: Int32 } deriving (Show, Eq, Ord, Deserializable, Num) newtype TopicMetadata = TopicMetadata { _topicMetadataFields :: (KafkaError, TopicName, [PartitionMetadata]) } deriving (Show, Eq, Deserializable) newtype PartitionMetadata = PartitionMetadata { _partitionMetadataFields :: (KafkaError, Partition, Leader, Replicas, Isr) } deriving (Show, Eq, Deserializable) newtype Leader = Leader { _leaderId :: Maybe Int32 } deriving (Show, Eq, Ord)
milena.cabal view
@@ -4,7 +4,7 @@ -- PVP summary:      +-+------- breaking API changes --                   | | +----- non-breaking API additions --                   | | | +--- code changes with no API change-version:             0.1.0.0+version:             0.2.0.0 synopsis:            A Kafka client for Haskell. description:         Kafka client for Haskell (not recommended for production use). license:             BSD3@@ -24,24 +24,26 @@ source-repository this   type: git   location: https://github.com/tylerholien/milena.git-  tag: 0.1.0.0+  tag: 0.2.0.0  library   default-language: Haskell2010   ghc-options:         -Wall   exposed-modules:     Network.Kafka,                        Network.Kafka.Protocol-  build-depends:       base       >=4.7      && <5,-                       mtl        >=2.1      && <2.2,-                       cereal     >=0.4      && <0.5,-                       bytestring >=0.10     && <0.12,-                       network    >=2.4      && <2.7,-                       digest     >=0.0.1.0  && <0.0.2,-                       containers >=0.5      && <0.6,-                       either     >=4.3      && <4.4,-                       random     >=1.0      && <1.2,-                       transformers >=0.3    && <0.4,-                       lens       >=4.4      && <4.5+                       Network.Kafka.Producer+  build-depends:       base          >=4.7      && <5,+                       mtl           >=2.1      && <2.3,+                       cereal        >=0.4      && <0.5,+                       bytestring    >=0.10     && <0.11,+                       network       >=2.4      && <2.7,+                       digest        >=0.0.1.0  && <0.1,+                       containers    >=0.5      && <0.6,+                       either        >=4.3      && <4.4,+                       random        >=1.0      && <1.2,+                       transformers  >=0.3      && <0.5,+                       lens          >=4.4      && <4.8,+                       resource-pool >=0.2.3.2  && <0.3  test-suite test   default-language: Haskell2010
test/tests.hs view
@@ -5,6 +5,7 @@ import Data.Functor import Data.Either (isRight) import Network.Kafka+import Network.Kafka.Producer import Network.Kafka.Protocol (Leader(..)) import Test.Hspec import Test.Hspec.QuickCheck@@ -13,7 +14,7 @@ main :: IO () main = hspec $ do   let topic = "milena-test"-      run = runKafka ("localhost", 9092) $ defaultState "milena-test-client"+      run = runKafka ("kafka1.dev", 9093) $ defaultState "milena-test-client"       byteMessages = fmap (TopicAndMessage topic . makeMessage . B.pack)    describe "can talk to local Kafka server" $ do