ifad / chronomodel

Temporal PostgreSQL (9.4+) system with "flashback" framework for ActiveRecord (7.0+)

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

Race condition on updates in parallel with counter_cache or after_save

pzac opened this issue · comments

When a record has after_save hooks (or rails built-ins such as the counter cache) that update another object, and there are parallel updates that will affect the same object, there are regular failures with timeline consistency errors.
The entire callback chain should be wrapped in a transaction or have an exclusive lock on the dependent object.
#70 has a spec to reproduce the issue

Thanks for the report. Will fix asap.

..or deadlocks
image

Sorry for the delay. The issue emerges because Active Record counter cache issues an UPDATE on the ChronoModel view, and this in turn runs the triggers for each row in your table.

This could be fixed by overriding Active Record counter cache behaviour, to issue the update on the temporal table only, but it would be another Monkey-Patch to maintain.

Further, given it is pointless to store changes to the counter cache in the history, please disable journaling on the counter cache column by using selective journaling, i.e.:

change_table :sections, temporal: true, no_journal: %w( articles_count )

I have added a section in the README to mention the requirement.

The spec is merged in b57ff40, and passes with the relevant no_journal option.

Then we'd lose the purpose and benefit of the counter cache, but this was an example: the same happens when an after_save callback updates another parent object

Let me check in the spec whether the no_journal breaks counter cache in the history schema.

The Callbacks problem is a completely different one, that will be researched separately.