aboutsummaryrefslogtreecommitdiffstats
path: root/app/models
diff options
context:
space:
mode:
authorTeddy Wing2017-11-29 16:47:55 +0100
committerTeddy Wing2017-11-29 17:11:43 +0100
commit8e9eb5d09ec8aa482afe33c7009c9ab78fdc6ede (patch)
tree65824d2fffc97374d80718b4bb4ad88fd25ba2d3 /app/models
parentdba5ded7b591126c3ee690669afb23eec7e04522 (diff)
downloadchouette-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.rb8
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