patternMinor
Haskell zmq & protobuf message forwarding
Viewed 0 times
protobufmessagezmqforwardinghaskell
Problem
I wrote a test program (and first "real" Haskell program!) that receives a zmq request on 1 socket, and forwards part of that message to another socket.
There are a 2 things I specifically don't like:
Is there any way to avoid these? Also, any other things I should fix? I would be shocked if there were no other issues.
The code:
```
module Main where
import System.ZMQ4.Monadic
import Control.Monad (forever)
import Data.ByteString.Char8 (pack, unpack)
import qualified Data.ByteString as ByteString (ByteString, concat)
import Data.ByteString.Lazy as LBS (ByteString, toChunks)
import Control.Concurrent (threadDelay)
import Text.ProtocolBuffers.WireMessage (messageGet)
import Text.ProtocolBuffers.WireMessage (messagePut)
import ProtoMsg.ForwardRequest (ForwardRequest)
import ProtoMsg.ForwardResponse
import ProtoMsg.ReqResponse (ReqResponse)
import ProtoMsg.Status
import ProtoMsg.Retort
lazyToStrictBS :: LBS.ByteString -> ByteString.ByteString
lazyToStrictBS x = ByteString.concat $ LBS.toChunks x
main :: IO ()
main =
runZMQ $ do
repSocket <- socket Rep
bind repSocket "tcp://*:9000"
pubSocket <- socket Pub
bind pubSocket "tcp://*:9001"
liftIO $ putStrLn "Ready"
forever $ do
msg <- receive repSocket
(liftIO.putStrLn.unwords) ["Received request:", unpack msg]
let repMsg = ProtoMsg.ForwardResponse.ForwardResponse {
header = ProtoMsg.ReqResponse.ReqResponse {
message_id = Nothing,
user_id = Nothing,
request_id = Nothing,
ProtoMsg.ReqResponse.status = Just ProtoMsg.Status.OK,
failure_message = Nothing
}
There are a 2 things I specifically don't like:
- I couldn't figure out a way to build a protobuf message without specifying every field. This is especially annoying for fields like
failure_message, which I had to set toNothing
- I'm not a fan of the lazyToStrictBS conversion
Is there any way to avoid these? Also, any other things I should fix? I would be shocked if there were no other issues.
The code:
```
module Main where
import System.ZMQ4.Monadic
import Control.Monad (forever)
import Data.ByteString.Char8 (pack, unpack)
import qualified Data.ByteString as ByteString (ByteString, concat)
import Data.ByteString.Lazy as LBS (ByteString, toChunks)
import Control.Concurrent (threadDelay)
import Text.ProtocolBuffers.WireMessage (messageGet)
import Text.ProtocolBuffers.WireMessage (messagePut)
import ProtoMsg.ForwardRequest (ForwardRequest)
import ProtoMsg.ForwardResponse
import ProtoMsg.ReqResponse (ReqResponse)
import ProtoMsg.Status
import ProtoMsg.Retort
lazyToStrictBS :: LBS.ByteString -> ByteString.ByteString
lazyToStrictBS x = ByteString.concat $ LBS.toChunks x
main :: IO ()
main =
runZMQ $ do
repSocket <- socket Rep
bind repSocket "tcp://*:9000"
pubSocket <- socket Pub
bind pubSocket "tcp://*:9001"
liftIO $ putStrLn "Ready"
forever $ do
msg <- receive repSocket
(liftIO.putStrLn.unwords) ["Received request:", unpack msg]
let repMsg = ProtoMsg.ForwardResponse.ForwardResponse {
header = ProtoMsg.ReqResponse.ReqResponse {
message_id = Nothing,
user_id = Nothing,
request_id = Nothing,
ProtoMsg.ReqResponse.status = Just ProtoMsg.Status.OK,
failure_message = Nothing
}
Solution
1) If you have used
could be replaced with
2) Instead of your
hprotoc to generate Haskell modules then you should be able to use defaultValue and optional fields will be assigned to Nothing by default i.e.header = ProtoMsg.ReqResponse.ReqResponse {
message_id = Nothing,
user_id = Nothing,
request_id = Nothing,
ProtoMsg.ReqResponse.status = Just ProtoMsg.Status.OK,
failure_message = Nothing
}could be replaced with
header = defaultValue {
ProtoMsg.ReqResponse.status = Just ProtoMsg.Status.OK
}2) Instead of your
lazyToStrictBS you could use the standard function toStrict in the bytestring packageCode Snippets
header = ProtoMsg.ReqResponse.ReqResponse {
message_id = Nothing,
user_id = Nothing,
request_id = Nothing,
ProtoMsg.ReqResponse.status = Just ProtoMsg.Status.OK,
failure_message = Nothing
}header = defaultValue {
ProtoMsg.ReqResponse.status = Just ProtoMsg.Status.OK
}Context
StackExchange Code Review Q#118180, answer score: 2
Revisions (0)
No revisions yet.