Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Would make sense to have a "addChannelClosedHandler"? #52

Closed
adinapoli opened this issue Feb 2, 2015 · 7 comments
Closed

Would make sense to have a "addChannelClosedHandler"? #52

adinapoli opened this issue Feb 2, 2015 · 7 comments

Comments

@adinapoli
Copy link
Contributor

Hi @hreinhardt ,

In production it would be nice to know and take action every time a channel is closed, for any reason. Since each channel connection is created in a separate thread, we are out of luck at the moment:

https://github.com/hreinhardt/amqp/blob/master/Network/AMQP/Internal.hs#L589

The library is rightfully using finally here, so all it would take is:

  • A function very similar to addConnectionClosedHandler, which would allow us to register new handlers
  • Call all the registered handler in the finally block, to make sure we get notified.

A perhaps even better solution would be to leverage forkFinally:

http://hackage.haskell.org/package/base-4.7.0.2/docs/Control-Concurrent.html#v:forkFinally

This would allow us to expose two new functions, addChannelClosedHandler and addChannelClosedExceptionHandler. Simply pattern matching on the result given back from forkFinally would allow us to call one group on handlers rather than the other. This would have the benefit to react differently whether the channel is closed "naturally" or if an exception caused it to be closed. Bear in mind thought that forkFinally is available from base 4.7 onwards, so a bit of CPP would be needed to support prior to 7.8.x

Do you think all of this would be an overkill?
Thanks a lot!

Alfredo

@hreinhardt
Copy link
Owner

Hi,

adding a function that's called for channel exceptions sounds like a good idea. But I'm not sure it makes sense to have another function for non-exceptional channel closes. AFAIK the only way a channel could be non-exceptionally closed is when the user calls closeChannel, in which case the user already knows the channel is about to be closed.

@adinapoli
Copy link
Contributor Author

Sounds perfectly reasonable to me!
In case I might be able to carve some time this week and issue a PR, would you be keen on reviewing and eventually merging it?

Thanks for the blazing-fast reply ;)

@hreinhardt
Copy link
Owner

Yes, I'd review and most probably merge it.

hreinhardt added a commit that referenced this issue Feb 5, 2015
@adinapoli
Copy link
Contributor Author

Now that #53 has been merged, any chance for 0.12 to hit Hackage today? 😉

@hreinhardt
Copy link
Owner

Pushed it to Hackage. I initially wanted to also remove that catch in the channelReceiver but that seems to be a bit trickier than I expected.

Thank you for your contribution! Let's hope we didn't break anything.

@adinapoli
Copy link
Contributor Author

Ha! Thank you very much! I am going to give a package a go next week, so if we did I will report back :)

@adinapoli
Copy link
Contributor Author

As a small success story, our patch seems to work, at least superficially. This is what I get from the logs inside my development environment, when the server is running but I kill the broker abruptly:

"New job = ...
"New job = ...
Rebooting the server due to 127.0.0.1:5672: Network.Connection.connectionGet: end of file
Rebooting the server due to 127.0.0.1:5672: Network.Connection.connectionGet: end of file
Rebooting the server due to 127.0.0.1:5672: Network.Connection.connectionGet: end of file
Rebooting the server due to 127.0.0.1:5672: Network.Connection.connectionGet: end of file
Rebooting the server due to 127.0.0.1:5672: Network.Connection.connectionGet: end of file
Rebooting the server due to 127.0.0.1:5672: Network.Connection.connectionGet: end of file
Rebooting the server due to 127.0.0.1:5672: Network.Connection.connectionGet: end of file
Rebooting the server due to 127.0.0.1:5672: Network.Connection.connectionGet: end of file

the message that you see, is triggered by this simple helper function:

-- We explicitly filter out the two cases where a channel can be closed gracefully;
-- 1. When it received a ThreadKilled exception
-- 2. When a user is shutting it down as part of the normal connection closing routine.
reactToChannelException :: SomeException -> IO ()
reactToChannelException (asyncExceptionFromException -> Just ThreadKilled) = return ()
reactToChannelException (fromException -> Just (ConnectionClosedException "closed by user")) = return ()
reactToChannelException ex = do
  yellow $ T.pack $ "Rebooting the server due to " <> show ex
  rebootServer

(I'm using the ViewPattern extension to make everything a bit more slick).
More testing is certainly needed, but this looks to me like a promising start :)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants