
Hi: I am writing a small application which receives HTTP requests, translates them to JSON, and queues the requests using RabbitMQ. I am using exceptions to handle extreme cases, such as when a client's HTTP request lacks a critical header: lookupHeader :: RequestHeaders -> HeaderName -> Text lookupHeader hs h = decodeUtf8 $ fromMaybe notFound (lookup h hs) where notFound = throw $ MissingHeader $ decodeUtf8 $ original h The problem I am running in to is that the header isn't actually looked up until I call the AMQP library's publishMsg function. If I purposely do not supply a critical header, I get the following error printed to the screen: ConnectionClosedException "ConnectionClosedException \"UNEXPECTED_FRAME - expected content header for class 60, got non content header frame instead\"" If I add the following line just above the publishMsg function (to force evaluation), my exception handler is called successfully: print $ encode req As a result, I suspect that this is due to the fact that the "throw MissingHeader" is getting captured by the AMQP library. What's the best way to deal with this situation? -- Alex

Hi.
I would suggest to separate data-extraction from request stage and
data-sending one. Create a data-structure that will represent a thing you
will want to send into RabbitMQ, and build it before you send anything.
Then catch exceptions in IO-based layer to handle exception case.
This way you won't need any evaluation tricks and will get all exceptions
during that phase.
Cheers.
12 трав. 2015 05:11 "Alex"
Hi:
I am writing a small application which receives HTTP requests, translates them to JSON, and queues the requests using RabbitMQ.
I am using exceptions to handle extreme cases, such as when a client's HTTP request lacks a critical header:
lookupHeader :: RequestHeaders -> HeaderName -> Text lookupHeader hs h = decodeUtf8 $ fromMaybe notFound (lookup h hs) where notFound = throw $ MissingHeader $ decodeUtf8 $ original h
The problem I am running in to is that the header isn't actually looked up until I call the AMQP library's publishMsg function. If I purposely do not supply a critical header, I get the following error printed to the screen:
ConnectionClosedException "ConnectionClosedException \"UNEXPECTED_FRAME - expected content header for class 60, got non content header frame instead\""
If I add the following line just above the publishMsg function (to force evaluation), my exception handler is called successfully:
print $ encode req
As a result, I suspect that this is due to the fact that the "throw MissingHeader" is getting captured by the AMQP library. What's the best way to deal with this situation?
-- Alex _______________________________________________ Beginners mailing list Beginners@haskell.org http://mail.haskell.org/cgi-bin/mailman/listinfo/beginners

On Tue, 12 May 2015 08:15:28 +0300
Kostiantyn Rybnikov
Hi.
I would suggest to separate data-extraction from request stage and data-sending one. Create a data-structure that will represent a thing you will want to send into RabbitMQ, and build it before you send anything. Then catch exceptions in IO-based layer to handle exception case.
This way you won't need any evaluation tricks and will get all exceptions during that phase.
In my case, the HTTP request is immediately parsed and a data structure representing the request is created. The request is forwarded to the AMQP code which does the following: publishMsg chan "" "the-queue" newMsg { msgDeliveryMode = Just Persistent , msgReplyTo = Just cbQueue , msgBody = encode req } where "encode req" uses aeson to transform the data structure in to JSON. I tried to make the values which comprise the request data structure strict (by prefixing them with `!'), but it does not seem to help.
Cheers. 12 трав. 2015 05:11 "Alex"
пише: Hi:
I am writing a small application which receives HTTP requests, translates them to JSON, and queues the requests using RabbitMQ.
I am using exceptions to handle extreme cases, such as when a client's HTTP request lacks a critical header:
lookupHeader :: RequestHeaders -> HeaderName -> Text lookupHeader hs h = decodeUtf8 $ fromMaybe notFound (lookup h hs) where notFound = throw $ MissingHeader $ decodeUtf8 $ original h
The problem I am running in to is that the header isn't actually looked up until I call the AMQP library's publishMsg function. If I purposely do not supply a critical header, I get the following error printed to the screen:
ConnectionClosedException "ConnectionClosedException \"UNEXPECTED_FRAME - expected content header for class 60, got non content header frame instead\""
If I add the following line just above the publishMsg function (to force evaluation), my exception handler is called successfully:
print $ encode req
As a result, I suspect that this is due to the fact that the "throw MissingHeader" is getting captured by the AMQP library. What's the best way to deal with this situation?
-- Alex _______________________________________________ Beginners mailing list Beginners@haskell.org http://mail.haskell.org/cgi-bin/mailman/listinfo/beginners
-- Alex

Your issue is related to Lazy evaluation. Your function (lookupHeader)
isn't actually evaluated before you call publishMsg or print. You need to
put seq or deepseq to overcome this, or put your exception handler in place
when your function is actually evaluated. Unfortunately, you haven't
provided the calling code, so I have no specific suggestion. Just read some
info on Lazy vs. Strict.
Parallel and Concurrent Programming in Haskell Chapter 2 [1] has a good
description (just skip "The Eval Monad, rpar, and rseq" section and
continue with deepseq).
Here is a good chapter on exception [2], if you need one.
[1]: http://chimera.labs.oreilly.com/books/1230000000929/ch02.html
[2]:
http://chimera.labs.oreilly.com/books/1230000000929/ch08.html#sec_exceptions
On Tue, May 12, 2015 at 5:11 AM Alex
Hi:
I am writing a small application which receives HTTP requests, translates them to JSON, and queues the requests using RabbitMQ.
I am using exceptions to handle extreme cases, such as when a client's HTTP request lacks a critical header:
lookupHeader :: RequestHeaders -> HeaderName -> Text lookupHeader hs h = decodeUtf8 $ fromMaybe notFound (lookup h hs) where notFound = throw $ MissingHeader $ decodeUtf8 $ original h
The problem I am running in to is that the header isn't actually looked up until I call the AMQP library's publishMsg function. If I purposely do not supply a critical header, I get the following error printed to the screen:
ConnectionClosedException "ConnectionClosedException \"UNEXPECTED_FRAME - expected content header for class 60, got non content header frame instead\""
If I add the following line just above the publishMsg function (to force evaluation), my exception handler is called successfully:
print $ encode req
As a result, I suspect that this is due to the fact that the "throw MissingHeader" is getting captured by the AMQP library. What's the best way to deal with this situation?
-- Alex _______________________________________________ Beginners mailing list Beginners@haskell.org http://mail.haskell.org/cgi-bin/mailman/listinfo/beginners

On Tue, 12 May 2015 05:24:32 +0000
Alexey Shmalko
Your issue is related to Lazy evaluation. Your function (lookupHeader) isn't actually evaluated before you call publishMsg or print. You need to put seq or deepseq to overcome this, or put your exception handler in place when your function is actually evaluated. Unfortunately, you haven't provided the calling code, so I have no specific suggestion. Just read some info on Lazy vs. Strict.
Per your suggestion, I tried out deepseq, and it doesn't seem to be working. Below is the code which sends the message to RMQ. As you've noted, `req' is not fully evaluated at this point: publishMsg chan "" "the-queue" newMsg { msgDeliveryMode = Just Persistent , msgReplyTo = Just cbQueue , msgBody = encode req } If I put this line above publishMsg, the problem still exists: _ <- return $!! req This is counter intuitive, because I would have thought that running deepseq on req would fully evaluate it to NF, but that doesn't seem to be the case.
Parallel and Concurrent Programming in Haskell Chapter 2 [1] has a good description (just skip "The Eval Monad, rpar, and rseq" section and continue with deepseq). Here is a good chapter on exception [2], if you need one.
[1]: http://chimera.labs.oreilly.com/books/1230000000929/ch02.html [2]: http://chimera.labs.oreilly.com/books/1230000000929/ch08.html#sec_exceptions
On Tue, May 12, 2015 at 5:11 AM Alex
wrote: Hi:
I am writing a small application which receives HTTP requests, translates them to JSON, and queues the requests using RabbitMQ.
I am using exceptions to handle extreme cases, such as when a client's HTTP request lacks a critical header:
lookupHeader :: RequestHeaders -> HeaderName -> Text lookupHeader hs h = decodeUtf8 $ fromMaybe notFound (lookup h hs) where notFound = throw $ MissingHeader $ decodeUtf8 $ original h
The problem I am running in to is that the header isn't actually looked up until I call the AMQP library's publishMsg function. If I purposely do not supply a critical header, I get the following error printed to the screen:
ConnectionClosedException "ConnectionClosedException \"UNEXPECTED_FRAME - expected content header for class 60, got non content header frame instead\""
If I add the following line just above the publishMsg function (to force evaluation), my exception handler is called successfully:
print $ encode req
As a result, I suspect that this is due to the fact that the "throw MissingHeader" is getting captured by the AMQP library. What's the best way to deal with this situation?
-- Alex _______________________________________________ Beginners mailing list Beginners@haskell.org http://mail.haskell.org/cgi-bin/mailman/listinfo/beginners
-- Alex

Seems, that you're putting it in the wrong place. Please, publish your code
to lpaste [1].
Hmm.... Maybe you need evaluate `encode req`?
On Tue, May 12, 2015 at 9:10 AM Alex
On Tue, 12 May 2015 05:24:32 +0000 Alexey Shmalko
wrote: Your issue is related to Lazy evaluation. Your function (lookupHeader) isn't actually evaluated before you call publishMsg or print. You need to put seq or deepseq to overcome this, or put your exception handler in place when your function is actually evaluated. Unfortunately, you haven't provided the calling code, so I have no specific suggestion. Just read some info on Lazy vs. Strict.
Per your suggestion, I tried out deepseq, and it doesn't seem to be working. Below is the code which sends the message to RMQ. As you've noted, `req' is not fully evaluated at this point:
publishMsg chan "" "the-queue" newMsg { msgDeliveryMode = Just Persistent , msgReplyTo = Just cbQueue , msgBody = encode req }
If I put this line above publishMsg, the problem still exists:
_ <- return $!! req
This is counter intuitive, because I would have thought that running deepseq on req would fully evaluate it to NF, but that doesn't seem to be the case.
Parallel and Concurrent Programming in Haskell Chapter 2 [1] has a good description (just skip "The Eval Monad, rpar, and rseq" section and continue with deepseq). Here is a good chapter on exception [2], if you need one.
[1]: http://chimera.labs.oreilly.com/books/1230000000929/ch02.html [2]:
http://chimera.labs.oreilly.com/books/1230000000929/ch08.html#sec_exceptions
On Tue, May 12, 2015 at 5:11 AM Alex
wrote: Hi:
I am writing a small application which receives HTTP requests, translates them to JSON, and queues the requests using RabbitMQ.
I am using exceptions to handle extreme cases, such as when a client's HTTP request lacks a critical header:
lookupHeader :: RequestHeaders -> HeaderName -> Text lookupHeader hs h = decodeUtf8 $ fromMaybe notFound (lookup h hs) where notFound = throw $ MissingHeader $ decodeUtf8 $ original h
The problem I am running in to is that the header isn't actually looked up until I call the AMQP library's publishMsg function. If I purposely do not supply a critical header, I get the following error printed to the screen:
ConnectionClosedException "ConnectionClosedException \"UNEXPECTED_FRAME - expected content header for class 60, got non content header frame instead\""
If I add the following line just above the publishMsg function (to force evaluation), my exception handler is called successfully:
print $ encode req
As a result, I suspect that this is due to the fact that the "throw MissingHeader" is getting captured by the AMQP library. What's the best way to deal with this situation?
-- Alex _______________________________________________ Beginners mailing list Beginners@haskell.org http://mail.haskell.org/cgi-bin/mailman/listinfo/beginners
-- Alex

On Tue, 12 May 2015 06:25:44 +0000
Alexey Shmalko
Seems, that you're putting it in the wrong place. Please, publish your code to lpaste [1].
Hmm.... Maybe you need evaluate `encode req`?
I've created a test case demonstrating the behavior which is confusing me: http://lpaste.net/132446 -- Alex

Seems you lack the proper instance of NFData for Foo
instance NFData Foo where
rnf f = foo f `deepseq` ()
With this change, keeping either line produces outer exception.
On Tue, May 12, 2015 at 10:43 AM Alex
On Tue, 12 May 2015 06:25:44 +0000 Alexey Shmalko
wrote: Seems, that you're putting it in the wrong place. Please, publish your code to lpaste [1].
Hmm.... Maybe you need evaluate `encode req`?
I've created a test case demonstrating the behavior which is confusing me:
-- Alex

On Tue, 12 May 2015 08:32:08 +0000
Alexey Shmalko
Seems you lack the proper instance of NFData for Foo
instance NFData Foo where rnf f = foo f `deepseq` ()
With this change, keeping either line produces outer exception.
Ah, as it turns out I was using deepseq 1.3, but the Generics support wasn't available until 1.4. Upgrading to 1.4 solves the issue. Thank you for your help! -- Alex
participants (3)
-
Alex
-
Alexey Shmalko
-
Kostiantyn Rybnikov