17

I'd like to have some cleanup code run when Rails is shutting down - is that possible? My situation is that I have a few threads in the background (I'm using jruby and calling into java) that live for the life of the process and I need to let them know to shut themselves down

Thanks!

Marc W
  • 19,083
  • 4
  • 59
  • 71
Stuart
  • 323
  • 2
  • 6

3 Answers3

21

Probably should just use the Ruby exit handler, which is a Kernel method:

$ irb
>> at_exit do
?>   puts 'bye...'
>> end
=> #<Proc:0xb79a87e4@(irb):1>
>> exit
bye...
$ 
DigitalRoss
  • 143,651
  • 25
  • 248
  • 329
  • As long as JRuby itself has a lifecycle corresponding to the underlying application server, then you can put it anywhere it will get run at least once. A good place would be to register the exit handler in whatever piece of Ruby code fires off those background threads in the first place. – DigitalRoss Oct 23 '09 at 02:12
  • (If it does get called more than once the exit handlers will run more than once, however, so don't call it 30,000 times. :-) – DigitalRoss Oct 23 '09 at 02:14
  • @Stuart: did you ever implement this? if so, how did it go and where did you put it? – efleming Jul 18 '11 at 16:30
  • Thanks to DigitalRoss for the code hint and Radar for right file. @efleming I implemented this after 10 years of giving the solution and 8 years of asking about it :-P – SriramK89 Mar 14 '19 at 12:41
11

Within the context of a Rails Application, the best place to put such a file is in config/initializers. In my app, I needed to Flush the Redis/Sidekiq queue whenever the development or test environments shut down. This works perfectly.

config/initializers/at_exit.rb

at_exit do
  begin
    puts 'Flushing Redis...'
    Redis.new.flushall
  rescue => e
    puts "There was an #{e.to_s} while flushing redis..."
  ensure
    puts 'Done Flushing Redis!'
  end
end unless Rails.env.production?
danielricecodes
  • 3,446
  • 21
  • 23
0

Be aware that you must not use Signal.trap because it does redefine what was set. There is a trick to call previous trap:

$prev_trap = Signal.trap("TERM") do
  $prev_trap&.call
  graceful_shutdown
end

However Rails initializators are executed before app server starts, e.g. Puma redefines most of the signal traps throwing away what was defined. Therefore do not use this, it might work maybe for webrick but not in production environmentální.

So the only reasonable option is what was already recommended by folks: at_exit in an initializer.

lzap
  • 16,417
  • 12
  • 71
  • 108