retire icon indicating copy to clipboard operation
retire copied to clipboard

Tire does not respect ROLLBACK of ActiveRecord record

Open tmaier opened this issue 13 years ago • 10 comments

When I save a record which is then rolled back, the ElasticSearch database still has the outdated entry. #343 talks also about the after_commit and after_rollback callbacks, but they're not yet supported.

https://github.com/karmi/tire/blob/master/lib/tire/model/callbacks.rb

tmaier avatar Feb 24 '13 18:02 tmaier

Hi, absolutely right. The after_commit / after_rollback hooks are ActiveRecord specific, so we must take care here. Since the callback integration is very simple, I think we can add it generally, not with a opt-in layer. I will have a look into it this week, please ping me if I slip.

karmi avatar Feb 24 '13 20:02 karmi

@tmaier Look at #640, actually, using after_commit would introduce inconsistencies between the database and the search index. This will need some more thorough thinking -- any comments, ideas?

karmi avatar Feb 26 '13 09:02 karmi

What about if we leave after_save and add a after_rollback callback, which destroys the ES entry? This would work with new records, but would create new inconsistencies when updating an existing record. Unless we cache the old entry...

tmaier avatar Feb 26 '13 09:02 tmaier

@karmi you asked me to remind you. :)

At the moment, my database also has inconsistencies, as there are records in the ES database which got rolled back (for some reason) by the Postgre Database.

tmaier avatar Mar 06 '13 17:03 tmaier

Let me add to this that having the reindexing done on after save can also lead to severe problems if the elasticsearch server cannot be reached. In our case this was happening because it could not connect to the IP address of the elasticsearch server and would just sit there and timeout. Since we were still in a transaction the whole mysql update would fail with a Lock timeout error, effectively rendering the elasticsearch server into a single point of failure.

donaldpiret avatar Mar 20 '13 03:03 donaldpiret

@donaldpiret True! But the way I see it, if you're concerned about the HTTP call inside the update_index on each save, you should have a specific indexing strategy, ie. backgrounding the index operation (Threads, Resque, Sidekiq, RabbitMQ, etc). (No argument though, that for ActiveRecord::Base models, we should fire indexing on commit, not save.)

karmi avatar Mar 20 '13 08:03 karmi

I ran into this yesterday, when a create and update_attributes got rolled back. So the entry in the database was deleted and the ElasticSearch document remained.

I was thinking the 'after_callback' would have to check the database entry and update/delete ElasticSearch accordingly.

jeremygpeterson avatar Jun 18 '13 11:06 jeremygpeterson

@jeremygpeterson See the caveat in 38492a5832160642b669630892554c74c7101f5c. I'd like to have a look into the hooks in Tire to make use of the after_commit.

karmi avatar Jun 18 '13 11:06 karmi

@karmi I see the caveat in the readme now, I didn't realize that including Tire::Model:Callbacks did not account for all possibilities on the active record model.

How can I help on this issue, keeping the database synced with ElasticSearch really matters to me. I'm not sure if <after_commit> would handle my specific error. As the rollback occurs during the creation process, but I'm open to implementing something for you to look at.

jeremygpeterson avatar Jun 18 '13 13:06 jeremygpeterson

This is how I handled the transaction when a create is rolled back.

if base.respond_to?(:after_rollback)
  index_delete = lambda {
    @destroyed = true
     tire.update_index
  }

  base.send :after_rollback, index_delete, on: :create
end

jeremygpeterson avatar Jun 22 '13 21:06 jeremygpeterson