diff options
| author | Teddy Wing | 2017-11-29 16:47:55 +0100 | 
|---|---|---|
| committer | Teddy Wing | 2017-11-29 17:11:43 +0100 | 
| commit | 8e9eb5d09ec8aa482afe33c7009c9ab78fdc6ede (patch) | |
| tree | 65824d2fffc97374d80718b4bb4ad88fd25ba2d3 /app/models | |
| parent | dba5ded7b591126c3ee690669afb23eec7e04522 (diff) | |
| download | chouette-core-8e9eb5d09ec8aa482afe33c7009c9ab78fdc6ede.tar.bz2 | |
Referential: Lock `referentials` table before validation
It was possible for two identical referentials (with the same metadata)
to be created and persisted if they were created at the same time. This
is validated by the test: `spec/models/referential_spec.rb:164`.
As a heavy-handed solution to that problem, prevent two referentials
from being created at the same time by setting a lock on the
`referentials` database table before Rails validation begins. This
prevents any other referentials from being saved at the same time as the
current one. Thanks to Alban for coming up with the lock Postgres query.
The lock should be the last `before_validation` hook that gets executed,
so we put it after the other `before_validation` definitions. We want it
to be the last one because we're trying to hold the lock for as little
time as possible.
Note that we don't need to explicitly unlock the table as this will
happen automatically at the end of the transaction.
Refs #5024
Diffstat (limited to 'app/models')
| -rw-r--r-- | app/models/referential.rb | 8 | 
1 files changed, 8 insertions, 0 deletions
| diff --git a/app/models/referential.rb b/app/models/referential.rb index ee74bd9f5..a8f387122 100644 --- a/app/models/referential.rb +++ b/app/models/referential.rb @@ -192,6 +192,7 @@ class Referential < ActiveRecord::Base    before_validation :assign_line_and_stop_area_referential, :on => :create, if: :workbench    before_validation :assign_slug, :on => :create    before_validation :assign_prefix, :on => :create +  before_validation :lock_table, :on => :create    before_create :create_schema    after_create :clone_schema, if: :created_from @@ -369,4 +370,11 @@ class Referential < ActiveRecord::Base      not metadatas_overlap?    end +  private + +  def lock_table +    ActiveRecord::Base.connection.execute( +      'LOCK referentials IN ACCESS EXCLUSIVE MODE' +    ) +  end  end | 
