1

I have a Rails 5.2.3 (MRI 2.5.5) app hosted on Heroku. I've added some cleanup code inside an ensure block, so that it runs when the app receives the SIGTERM for its daily restart. The cleanup code involves a simple update on an ActiveRecord object. The ensure block runs as expected, but the database transaction itself always rolls back.

The transaction inside ensure works fine during normal operations, but I cannot get it to complete after it has received a SIGTERM. I'm going by what's shown in Heroku's docs.

begin
  ## Do some work...
ensure
  ## Runs (not exclusively) after SIGTERM...
  ## ...except for ActiveRecord update/create etc!

I couldn't find any error message to go by.

flavio
  • 87
  • 2
  • 8
  • Something is making your transaction to rollback. Maybe the record is just not valid or a `before_save` callback is returning false. Double check the validations and the `before_` callbacks. You could use method like `update_column` or `update_all` or the like if you need to skip validations and callbacks. – arieljuod Apr 10 '19 at 04:25
  • The transaction runs without issues, as part of the normal `ensure` process. The problem is, when `ensure` is running _after_ having received SIGTERM, that's when the transaction fails. I even tried creating a new record by typing manual, valid, values, and it didn't work. – flavio Apr 10 '19 at 04:30
  • 1
    This might be a possible explanation: https://stackoverflow.com/questions/548048/activerecordstatementinvalid-when-process-receives-sigterm - once your app receive SIGTERM, it ActiveRecord will throw StatementInvalid and roll back the transaction. What you might do is put your cleanup code inside `Signal.trap`: https://apidock.com/ruby/Signal/trap/class – Dmitry Frenkel Apr 10 '19 at 05:43
  • Thanks! So I guess even though the `ensure` block is running, that `SignalException` is not being necessarily caught, so it falls through to ActiveRecord to catch and re-raise. As a solution for now, I ended up making a separate object to manage these sensitive pending transactions, and run them inside an `at_exit` block. – flavio Apr 10 '19 at 18:48

0 Answers0