Home PreparedStatement cache invalidation when migrating table and after_create hook
Reply: 0

PreparedStatement cache invalidation when migrating table and after_create hook

Mathiou
1#
Mathiou Published in 2017-11-30 14:36:34Z

There is a bug in RoR 4 when you migrate a table: if you execute a query on this table that has already been executed and is in the prepared statement cache, you get an error.

To get around this issue without having to upgrade to RoR 5, we decided to patch the ActiveRecord#transaction method as described here.

Basically the code looks like this:

module TransactionRecoverable
  module ClassMethods
    raise "We may no longer need the monkeypatch #{__FILE__}!" if Rails::VERSION::MAJOR > 4

    def transaction(*args)
      begin
        super(*args) do
          yield
        end
      rescue PG::InFailedSqlTransaction => e
        # Raise error to parent transaction if in child transaction.  This prevents issues with dependency errors in a case where you have a transaction that spawns two child transactions, the second depending on the result of the first.  This happens because the rollback_db_transaction rolls back everything under the parent transaction NOT the current transaction.
        raise e if connection.open_transactions > 0

        connection.rollback_db_transaction
        connection.clear_cache!

        super(*args) do
          yield
        end
      end
    end
  end
end

class << ActiveRecord::Base
  prepend TransactionRecoverable::ClassMethods
end

What it does is when such an error occurs, it triggers a ROLLBACK of the current transaction in the DB and then clears the prepared statement cache. Then it re-executes the query, re-building the prepared statement cache for this query with the new table structure.

The issue we are facing now is that if the error occurs during an after_create hook, the ROLLBACK is triggered and cancels the complete DB transaction (the create and the after_create SQL statements).

But unfortunately, the only thing that is retried is the code (and therefore the SQL) in the after_create hook. So basically there is no crash but my object is not created at all...

Currently I fixed it by replacing the after_create hook with an after_commit hook but this is not very satisfactory.

Any idea how to fix this ?

You need to login account before you can post.

About| Privacy statement| Terms of Service| Advertising| Contact us| Help| Sitemap|
Processed in 0.298774 second(s) , Gzip On .

© 2016 Powered by mzan.com design MATCHINFO