-
Notifications
You must be signed in to change notification settings - Fork 1.2k
Close event connections when the server is gracefully shutting down. #383
Conversation
This will interrupt open, normal, not-long-running requests that are in the process of completing right? If so, could we add a timeout or something like that that only closes connections if they are still open after the request timeout? Would that cause 30 seconds of "downtime" where we aren't accepting new connections but waiting for old ones to close? Probably. That's less than ideal also. |
I think the real solution would be a puma or unicorn style rolling restart between processes to load up new code but the in memory event bus architecture of Dashing prevents that. |
Nope, the connections array is one maintained by the dashing rather than thin or sinatra, so it will only close the connections for the events endpoint.
Yes, this is definitely not a zero downtime restart like we get from unicorn. |
Oh schweet, |
Close event connections when the server is gracefully shutting down.
I'm on my phone and can't see it right now. I'm just in transit so |
Sorry for merging before you got to see it @pushmatrix. I can revert or fix forward based on any feedback you have though. |
So my concern here is that some users of Dashing don't use thin. I Dashing 2.0 will be a tad more agnostic for this. |
Ya, I would have done this in statly, but I thought it was more appropriate here after noticing that thin was a hard coded dependancy. I can revert and move it into statly now to make that transition easier though.
Ya, it would override the method, but then the method would never get used if they aren't using Thin. |
@@ -119,6 +120,16 @@ def protected! | |||
end | |||
end | |||
|
|||
Thin::Server.class_eval do | |||
def stop_with_connection_closing | |||
Sinatra::Application.settings.connections.each(&:close) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This didn't work when there was more than one connection, because the callback on line 74 deletes the connection from the array, which results in .each
here skipping connections. I pushed commit 55f9093 to dup the array before iterating on it here.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Dastardly mutable iterations. Nice fix.
@airhorns for review
Problem
When the TERM signal is sent to TERM, then it waits for existing connections to finish before exiting (https://github.com/macournoyer/thin/blob/v1.6.2/lib/thin/server.rb#L175). There is a 30 second timeout for most requests, but the /events endpoint uses
stream :keep_open do |out|
to keep the connection open for server sent events. As a result, a graceful shutdown can take over an hour to complete.Solution
I couldn't find a simple hook in thin to close connections when the server is shutting down, but I ended up wrapping the Thin::Server#stop method to close the event connections.
I tested manually by sending the TERM signal to the thin processes in development after visiting a page which connected to the /events endpoint. Previously this would get stuck waiting until I close the page, but now it completes quickly.