From 8e9eb5d09ec8aa482afe33c7009c9ab78fdc6ede Mon Sep 17 00:00:00 2001 From: Teddy Wing Date: Wed, 29 Nov 2017 16:47:55 +0100 Subject: 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 --- app/models/referential.rb | 8 ++++++++ 1 file changed, 8 insertions(+) (limited to 'app/models/referential.rb') 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 -- cgit v1.2.3 From 6e8eada24b19f1d0b4f58da69a54278caec7429d Mon Sep 17 00:00:00 2001 From: Teddy Wing Date: Wed, 29 Nov 2017 17:08:56 +0100 Subject: Referential: Add a comment about the `lock_table` callback Make it clear in the code (not just in the commit message) that this callback must go last. Refs #5024 --- app/models/referential.rb | 3 +++ 1 file changed, 3 insertions(+) (limited to 'app/models/referential.rb') diff --git a/app/models/referential.rb b/app/models/referential.rb index a8f387122..6912f140f 100644 --- a/app/models/referential.rb +++ b/app/models/referential.rb @@ -192,7 +192,10 @@ 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 + + # Locking the table must be the last hook to minimise the duration of the lock before_validation :lock_table, :on => :create + before_create :create_schema after_create :clone_schema, if: :created_from -- cgit v1.2.3 From e90f92707abf1b2ba4d00f97e15888f6e29e8cbc Mon Sep 17 00:00:00 2001 From: Teddy Wing Date: Wed, 29 Nov 2017 17:35:44 +0100 Subject: Referential: Add comment to describe why we lock the table Refs #5024 --- app/models/referential.rb | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) (limited to 'app/models/referential.rb') diff --git a/app/models/referential.rb b/app/models/referential.rb index 6912f140f..f78b4ec9a 100644 --- a/app/models/referential.rb +++ b/app/models/referential.rb @@ -193,7 +193,9 @@ class Referential < ActiveRecord::Base before_validation :assign_slug, :on => :create before_validation :assign_prefix, :on => :create - # Locking the table must be the last hook to minimise the duration of the lock + # Lock the `referentials` table to prevent duplicate referentials from being + # created simultaneously in separate transactions. This must be the last hook + # to minimise the duration of the lock. before_validation :lock_table, :on => :create before_create :create_schema -- cgit v1.2.3 From e06f5641a074eacce3218f277b42ef5f1eb696a6 Mon Sep 17 00:00:00 2001 From: Teddy Wing Date: Wed, 29 Nov 2017 17:39:44 +0100 Subject: Referential#lock_table: Add comment about unlock Refs #5024 --- app/models/referential.rb | 2 ++ 1 file changed, 2 insertions(+) (limited to 'app/models/referential.rb') diff --git a/app/models/referential.rb b/app/models/referential.rb index f78b4ec9a..9047cc21e 100644 --- a/app/models/referential.rb +++ b/app/models/referential.rb @@ -378,6 +378,8 @@ class Referential < ActiveRecord::Base private def lock_table + # No explicit unlock is needed as it will be released at the end of the + # transaction. ActiveRecord::Base.connection.execute( 'LOCK referentials IN ACCESS EXCLUSIVE MODE' ) -- cgit v1.2.3 From 22896b02846617d6b9dd517f095ea1be676e88ba Mon Sep 17 00:00:00 2001 From: Teddy Wing Date: Wed, 29 Nov 2017 17:56:19 +0100 Subject: Referential: Use new hash syntax Convert the hash syntax in `models/referential.rb` to new Ruby hash syntax. Refs #5024 --- app/models/referential.rb | 24 ++++++++++++------------ 1 file changed, 12 insertions(+), 12 deletions(-) (limited to 'app/models/referential.rb') diff --git a/app/models/referential.rb b/app/models/referential.rb index 9047cc21e..c91007172 100644 --- a/app/models/referential.rb +++ b/app/models/referential.rb @@ -12,17 +12,17 @@ class Referential < ActiveRecord::Base validates_uniqueness_of :slug - validates_format_of :slug, :with => %r{\A[a-z][0-9a-z_]+\Z} - validates_format_of :prefix, :with => %r{\A[0-9a-zA-Z_]+\Z} - validates_format_of :upper_corner, :with => %r{\A-?[0-9]+\.?[0-9]*\,-?[0-9]+\.?[0-9]*\Z} - validates_format_of :lower_corner, :with => %r{\A-?[0-9]+\.?[0-9]*\,-?[0-9]+\.?[0-9]*\Z} + validates_format_of :slug, with: %r{\A[a-z][0-9a-z_]+\Z} + validates_format_of :prefix, with: %r{\A[0-9a-zA-Z_]+\Z} + validates_format_of :upper_corner, with: %r{\A-?[0-9]+\.?[0-9]*\,-?[0-9]+\.?[0-9]*\Z} + validates_format_of :lower_corner, with: %r{\A-?[0-9]+\.?[0-9]*\,-?[0-9]+\.?[0-9]*\Z} validate :slug_excluded_values attr_accessor :upper_corner attr_accessor :lower_corner has_one :user - has_many :api_keys, :class_name => 'Api::V1::ApiKey', :dependent => :destroy + has_many :api_keys, class_name: 'Api::V1::ApiKey', dependent: :destroy belongs_to :organisation validates_presence_of :organisation @@ -78,7 +78,7 @@ class Referential < ActiveRecord::Base errors.add(:slug,I18n.t("referentials.errors.public_excluded")) end if slug == self.class.connection_config[:username] - errors.add(:slug,I18n.t("referentials.errors.user_excluded", :user => slug)) + errors.add(:slug,I18n.t("referentials.errors.user_excluded", user: slug)) end end end @@ -141,7 +141,7 @@ class Referential < ActiveRecord::Base def self.new_from(from, functional_scope) Referential.new( - name: I18n.t("activerecord.copy", :name => from.name), + name: I18n.t("activerecord.copy", name: from.name), slug: "#{from.slug}_clone", prefix: from.prefix, time_zone: from.time_zone, @@ -189,14 +189,14 @@ class Referential < ActiveRecord::Base projection_type || "" end - 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 :assign_line_and_stop_area_referential, on: :create, if: :workbench + before_validation :assign_slug, on: :create + before_validation :assign_prefix, on: :create # Lock the `referentials` table to prevent duplicate referentials from being # created simultaneously in separate transactions. This must be the last hook # to minimise the duration of the lock. - before_validation :lock_table, :on => :create + before_validation :lock_table, on: :create before_create :create_schema after_create :clone_schema, if: :created_from @@ -281,7 +281,7 @@ class Referential < ActiveRecord::Base def detect_overlapped_referentials self.class.where(id: overlapped_referential_ids).each do |referential| - errors.add :metadatas, I18n.t("referentials.errors.overlapped_referential", :referential => referential.name) + errors.add :metadatas, I18n.t("referentials.errors.overlapped_referential", referential: referential.name) end end -- cgit v1.2.3 From 5ae238936d3c91e70709c2ec4ed8a73a6f4524dc Mon Sep 17 00:00:00 2001 From: Teddy Wing Date: Fri, 24 Nov 2017 19:18:25 +0100 Subject: Referential: Move `create_schema` to an `after_commit` The goal being to separate the creation of the database schema from the creation of the `Referential` object. Previously these were created in the same database transaction, but moving the schema to an `after_commit` puts it in a separate transaction. This change tries to mitigate a problem where two `Referential`s, created at the same time with the same data, can be saved, even though identical `Referential`s should not be allowed. By moving the schema creation to a separate transaction, we decrease the time it takes to create a `Referential`, increasing the odds of not creating two identical `Referential`s due to near-simultaneous writes. Refs #5024 Conflicts: app/models/referential.rb --- app/models/referential.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'app/models/referential.rb') diff --git a/app/models/referential.rb b/app/models/referential.rb index f89eafee8..d090a3f7c 100644 --- a/app/models/referential.rb +++ b/app/models/referential.rb @@ -200,8 +200,8 @@ class Referential < ActiveRecord::Base # to minimise the duration of the lock. before_validation :lock_table, on: :create - before_create :create_schema after_create :clone_schema, if: :created_from + after_commit :create_schema before_destroy :destroy_schema before_destroy :destroy_jobs -- cgit v1.2.3 From f858a1b3b446b973247fc1e9a44b2099f0b31c38 Mon Sep 17 00:00:00 2001 From: Teddy Wing Date: Mon, 11 Dec 2017 12:17:46 +0100 Subject: Revert "Referential: Move `create_schema` to an `after_commit`" This reverts commit 5ae238936d3c91e70709c2ec4ed8a73a6f4524dc. I was getting a bunch of test errors like this: 1) Referentials destroy should remove referential Failure/Error: Apartment::Tenant.switch!(slug) Apartment::TenantNotFound: One of the following schema(s) is invalid: "test_1" "first", "shared_extensions" # .../.gem/ruby/2.3.3/gems/apartment-1.0.2/lib/apartment/adapters/postgresql_adapter.rb:92:in `rescue in connect_to_new' # .../.gem/ruby/2.3.3/gems/apartment-1.0.2/lib/apartment/adapters/postgresql_adapter.rb:85:in `connect_to_new' # .../.gem/ruby/2.3.3/gems/apartment-1.0.2/lib/apartment/adapters/abstract_adapter.rb:84:in `switch!' # ./app/models/referential.rb:139:in `switch' # ./app/controllers/referentials_controller.rb:26:in `show' # .../.gem/ruby/2.3.3/gems/actionpack-4.2.8/lib/action_controller/metal/implicit_render.rb:4:in `send_action' # .../.gem/ruby/2.3.3/gems/actionpack-4.2.8/lib/abstract_controller/base.rb:198:in `process_action' # .../.gem/ruby/2.3.3/gems/actionpack-4.2.8/lib/action_controller/metal/rendering.rb:10:in `process_action' # .../.gem/ruby/2.3.3/gems/actionpack-4.2.8/lib/abstract_controller/callbacks.rb:20:in `block in process_action' # .../.gem/ruby/2.3.3/gems/activesupport-4.2.8/lib/active_support/callbacks.rb:117:in `call' # .../.gem/ruby/2.3.3/gems/activesupport-4.2.8/lib/active_support/callbacks.rb:555:in `block (2 levels) in compile' # .../.gem/ruby/2.3.3/gems/activesupport-4.2.8/lib/active_support/callbacks.rb:505:in `call' # .../.gem/ruby/2.3.3/gems/activesupport-4.2.8/lib/active_support/callbacks.rb:92:in `__run_callbacks__' # .../.gem/ruby/2.3.3/gems/activesupport-4.2.8/lib/active_support/callbacks.rb:778:in `_run_process_action_callbacks' # .../.gem/ruby/2.3.3/gems/activesupport-4.2.8/lib/active_support/callbacks.rb:81:in `run_callbacks' # .../.gem/ruby/2.3.3/gems/actionpack-4.2.8/lib/abstract_controller/callbacks.rb:19:in `process_action' # .../.gem/ruby/2.3.3/gems/actionpack-4.2.8/lib/action_controller/metal/rescue.rb:29:in `process_action' # .../.gem/ruby/2.3.3/gems/actionpack-4.2.8/lib/action_controller/metal/instrumentation.rb:32:in `block in process_action' # .../.gem/ruby/2.3.3/gems/activesupport-4.2.8/lib/active_support/notifications.rb:164:in `block in instrument' # .../.gem/ruby/2.3.3/gems/activesupport-4.2.8/lib/active_support/notifications/instrumenter.rb:20:in `instrument' # .../.gem/ruby/2.3.3/gems/activesupport-4.2.8/lib/active_support/notifications.rb:164:in `instrument' # .../.gem/ruby/2.3.3/gems/actionpack-4.2.8/lib/action_controller/metal/instrumentation.rb:30:in `process_action' # .../.gem/ruby/2.3.3/gems/actionpack-4.2.8/lib/action_controller/metal/params_wrapper.rb:250:in `process_action' # .../.gem/ruby/2.3.3/gems/activerecord-4.2.8/lib/active_record/railties/controller_runtime.rb:18:in `process_action' # .../.gem/ruby/2.3.3/gems/actionpack-4.2.8/lib/abstract_controller/base.rb:137:in `process' # .../.gem/ruby/2.3.3/gems/actionview-4.2.8/lib/action_view/rendering.rb:30:in `process' # .../.gem/ruby/2.3.3/gems/actionpack-4.2.8/lib/action_controller/metal.rb:196:in `dispatch' # .../.gem/ruby/2.3.3/gems/actionpack-4.2.8/lib/action_controller/metal/rack_delegation.rb:13:in `dispatch' # .../.gem/ruby/2.3.3/gems/actionpack-4.2.8/lib/action_controller/metal.rb:237:in `block in action' # .../.gem/ruby/2.3.3/gems/actionpack-4.2.8/lib/action_dispatch/routing/route_set.rb:74:in `dispatch' # .../.gem/ruby/2.3.3/gems/actionpack-4.2.8/lib/action_dispatch/routing/route_set.rb:43:in `serve' # .../.gem/ruby/2.3.3/gems/actionpack-4.2.8/lib/action_dispatch/journey/router.rb:43:in `block in serve' # .../.gem/ruby/2.3.3/gems/actionpack-4.2.8/lib/action_dispatch/journey/router.rb:30:in `each' # .../.gem/ruby/2.3.3/gems/actionpack-4.2.8/lib/action_dispatch/journey/router.rb:30:in `serve' # .../.gem/ruby/2.3.3/gems/actionpack-4.2.8/lib/action_dispatch/routing/route_set.rb:817:in `call' # .../.gem/ruby/2.3.3/gems/devise_cas_authenticatable-1.10.0/lib/devise_cas_authenticatable/single_sign_out/rack.rb:14:in `call' # .../.gem/ruby/2.3.3/gems/warden-1.2.7/lib/warden/manager.rb:36:in `block in call' # .../.gem/ruby/2.3.3/gems/warden-1.2.7/lib/warden/manager.rb:35:in `catch' # .../.gem/ruby/2.3.3/gems/warden-1.2.7/lib/warden/manager.rb:35:in `call' # .../.gem/ruby/2.3.3/gems/rack-1.6.8/lib/rack/etag.rb:24:in `call' # .../.gem/ruby/2.3.3/gems/rack-1.6.8/lib/rack/conditionalget.rb:25:in `call' # .../.gem/ruby/2.3.3/gems/rack-1.6.8/lib/rack/head.rb:13:in `call' # .../.gem/ruby/2.3.3/gems/actionpack-4.2.8/lib/action_dispatch/middleware/params_parser.rb:27:in `call' # .../.gem/ruby/2.3.3/gems/actionpack-4.2.8/lib/action_dispatch/middleware/flash.rb:260:in `call' # .../.gem/ruby/2.3.3/gems/rack-1.6.8/lib/rack/session/abstract/id.rb:225:in `context' # .../.gem/ruby/2.3.3/gems/rack-1.6.8/lib/rack/session/abstract/id.rb:220:in `call' # .../.gem/ruby/2.3.3/gems/actionpack-4.2.8/lib/action_dispatch/middleware/cookies.rb:560:in `call' # .../.gem/ruby/2.3.3/gems/activerecord-4.2.8/lib/active_record/query_cache.rb:36:in `call' # .../.gem/ruby/2.3.3/gems/activerecord-4.2.8/lib/active_record/connection_adapters/abstract/connection_pool.rb:653:in `call' # .../.gem/ruby/2.3.3/gems/actionpack-4.2.8/lib/action_dispatch/middleware/callbacks.rb:29:in `block in call' # .../.gem/ruby/2.3.3/gems/activesupport-4.2.8/lib/active_support/callbacks.rb:88:in `__run_callbacks__' # .../.gem/ruby/2.3.3/gems/activesupport-4.2.8/lib/active_support/callbacks.rb:778:in `_run_call_callbacks' # .../.gem/ruby/2.3.3/gems/activesupport-4.2.8/lib/active_support/callbacks.rb:81:in `run_callbacks' # .../.gem/ruby/2.3.3/gems/actionpack-4.2.8/lib/action_dispatch/middleware/callbacks.rb:27:in `call' # .../.gem/ruby/2.3.3/gems/actionpack-4.2.8/lib/action_dispatch/middleware/remote_ip.rb:78:in `call' # .../.gem/ruby/2.3.3/gems/actionpack-4.2.8/lib/action_dispatch/middleware/debug_exceptions.rb:17:in `call' # .../.gem/ruby/2.3.3/gems/actionpack-4.2.8/lib/action_dispatch/middleware/show_exceptions.rb:30:in `call' # .../.gem/ruby/2.3.3/gems/railties-4.2.8/lib/rails/rack/logger.rb:38:in `call_app' # .../.gem/ruby/2.3.3/gems/railties-4.2.8/lib/rails/rack/logger.rb:20:in `block in call' # .../.gem/ruby/2.3.3/gems/activesupport-4.2.8/lib/active_support/tagged_logging.rb:68:in `block in tagged' # .../.gem/ruby/2.3.3/gems/activesupport-4.2.8/lib/active_support/tagged_logging.rb:26:in `tagged' # .../.gem/ruby/2.3.3/gems/activesupport-4.2.8/lib/active_support/tagged_logging.rb:68:in `tagged' # .../.gem/ruby/2.3.3/gems/railties-4.2.8/lib/rails/rack/logger.rb:20:in `call' # .../.gem/ruby/2.3.3/gems/request_store-1.3.2/lib/request_store/middleware.rb:9:in `call' # .../.gem/ruby/2.3.3/gems/actionpack-4.2.8/lib/action_dispatch/middleware/request_id.rb:21:in `call' # .../.gem/ruby/2.3.3/gems/rack-1.6.8/lib/rack/methodoverride.rb:22:in `call' # .../.gem/ruby/2.3.3/gems/rack-1.6.8/lib/rack/runtime.rb:18:in `call' # .../.gem/ruby/2.3.3/gems/activesupport-4.2.8/lib/active_support/cache/strategy/local_cache_middleware.rb:28:in `call' # .../.gem/ruby/2.3.3/gems/rack-1.6.8/lib/rack/lock.rb:17:in `call' # .../.gem/ruby/2.3.3/gems/actionpack-4.2.8/lib/action_dispatch/middleware/static.rb:120:in `call' # .../.gem/ruby/2.3.3/gems/rack-1.6.8/lib/rack/sendfile.rb:113:in `call' # .../.gem/ruby/2.3.3/gems/railties-4.2.8/lib/rails/engine.rb:518:in `call' # .../.gem/ruby/2.3.3/gems/railties-4.2.8/lib/rails/application.rb:165:in `call' # .../.gem/ruby/2.3.3/gems/rack-1.6.8/lib/rack/urlmap.rb:66:in `block in call' # .../.gem/ruby/2.3.3/gems/rack-1.6.8/lib/rack/urlmap.rb:50:in `each' # .../.gem/ruby/2.3.3/gems/rack-1.6.8/lib/rack/urlmap.rb:50:in `call' # .../.gem/ruby/2.3.3/gems/rack-test-0.6.3/lib/rack/mock_session.rb:30:in `request' # .../.gem/ruby/2.3.3/gems/rack-test-0.6.3/lib/rack/test.rb:244:in `process_request' # .../.gem/ruby/2.3.3/gems/rack-test-0.6.3/lib/rack/test.rb:58:in `get' # .../.gem/ruby/2.3.3/gems/capybara-2.4.4/lib/capybara/rack_test/browser.rb:60:in `process' # .../.gem/ruby/2.3.3/gems/capybara-2.4.4/lib/capybara/rack_test/browser.rb:35:in `process_and_follow_redirects' # .../.gem/ruby/2.3.3/gems/capybara-2.4.4/lib/capybara/rack_test/browser.rb:21:in `visit' # .../.gem/ruby/2.3.3/gems/capybara-2.4.4/lib/capybara/rack_test/driver.rb:42:in `visit' # .../.gem/ruby/2.3.3/gems/capybara-2.4.4/lib/capybara/session.rb:227:in `visit' # .../.gem/ruby/2.3.3/gems/capybara-2.4.4/lib/capybara/dsl.rb:51:in `block (2 levels) in ' # ./spec/features/referentials_spec.rb:193:in `block (3 levels) in ' # .../.gem/ruby/2.3.3/gems/activesupport-4.2.8/lib/active_support/dependencies.rb:268:in `load' # .../.gem/ruby/2.3.3/gems/activesupport-4.2.8/lib/active_support/dependencies.rb:268:in `block in load' # .../.gem/ruby/2.3.3/gems/activesupport-4.2.8/lib/active_support/dependencies.rb:240:in `load_dependency' # .../.gem/ruby/2.3.3/gems/activesupport-4.2.8/lib/active_support/dependencies.rb:268:in `load' # .../.gem/ruby/2.3.3/gems/spring-commands-rspec-1.0.4/lib/spring/commands/rspec.rb:18:in `call' # -e:1:in `
' # ------------------ # --- Caused by: --- # ActiveRecord::StatementInvalid: # Could not find schema test_1 # .../.gem/ruby/2.3.3/gems/apartment-1.0.2/lib/apartment/adapters/postgresql_adapter.rb:86:in `connect_to_new' Couldn't figure out how to get around this. The problem is that: 1. The referential is created 2. The app tries to switch to the newly-created referential's schema 3. The schema is created But of course we can't switch to a schema that doesn't exist. After a discussion with Luc & Alban, we decided to leave out the `after_commit`. I'll be logging a benchmark of time it takes for schema creation to give us an idea of the time & performance impact of the schema creation and lock. --- app/models/referential.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'app/models/referential.rb') diff --git a/app/models/referential.rb b/app/models/referential.rb index 7aeb946c5..81bb1d6d5 100644 --- a/app/models/referential.rb +++ b/app/models/referential.rb @@ -200,8 +200,8 @@ class Referential < ActiveRecord::Base # to minimise the duration of the lock. before_validation :lock_table, on: :create + before_create :create_schema after_create :clone_schema, if: :created_from - after_commit :create_schema before_destroy :destroy_schema before_destroy :destroy_jobs -- cgit v1.2.3 From b72e4dee4766b6cf310634ff404caf589c917349 Mon Sep 17 00:00:00 2001 From: Teddy Wing Date: Mon, 11 Dec 2017 14:22:22 +0100 Subject: Referential#create_schema: Log benchmark time to create We want some measurements for how long it takes to create schemas to give us some data to decide whether to put `#create_schema` in an `after_commit` somehow (it didn't work the simple way). This at least gives us a better idea of what's going on and how our table lock is performing. Refs #5024 --- app/models/referential.rb | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) (limited to 'app/models/referential.rb') diff --git a/app/models/referential.rb b/app/models/referential.rb index 81bb1d6d5..b14ab3827 100644 --- a/app/models/referential.rb +++ b/app/models/referential.rb @@ -293,7 +293,11 @@ class Referential < ActiveRecord::Base def create_schema unless created_from - Apartment::Tenant.create slug + report = Benchmark.measure do + Apartment::Tenant.create slug + end + + Rails.logger.info("Schema create benchmark: '#{slug}'\t#{report}") Rails.logger.error( "Schema migrations count for Referential #{slug} " + Referential.connection.select_value("select count(*) from #{slug}.schema_migrations;").to_s ) end end -- cgit v1.2.3 From 55b995531b2504792dfa1b0314b5cc5b55a775ac Mon Sep 17 00:00:00 2001 From: Teddy Wing Date: Tue, 12 Dec 2017 16:56:49 +0100 Subject: Referential: Raise an error if the table lock times out Paired with Johan on this one. There's an internal timeout on our table lock. If it's reached, an `ActiveRecord::StatementInvalid` error is raised. Use a custom error instead by "overriding" `#save` with a method that raises our custom error in that case instead. This will enable us to provide a custom user-facing error in the event this happens. Refs #5024 --- app/models/referential.rb | 12 ++++++++++++ 1 file changed, 12 insertions(+) (limited to 'app/models/referential.rb') diff --git a/app/models/referential.rb b/app/models/referential.rb index b14ab3827..b44bb15c6 100644 --- a/app/models/referential.rb +++ b/app/models/referential.rb @@ -61,6 +61,18 @@ class Referential < ActiveRecord::Base scope :order_by_validity_period, ->(dir) { joins(:metadatas).order("unnest(periodes) #{dir}") } scope :order_by_lines, ->(dir) { joins(:metadatas).group("referentials.id").order("sum(array_length(referential_metadata.line_ids,1)) #{dir}") } + def save_with_table_lock_timeout + save_without_table_lock_timeout + rescue ActiveRecord::StatementInvalid => e + if e.message.include?('PG::LockNotAvailable') + raise TableLockTimeoutError.new(e) + else + raise + end + end + + alias_method_chain :save, :table_lock_timeout + def lines if metadatas.blank? workbench ? workbench.lines : associated_lines -- cgit v1.2.3 From df13a9b7b26b568b5edcea590a2e867d26580d22 Mon Sep 17 00:00:00 2001 From: Teddy Wing Date: Tue, 12 Dec 2017 17:01:49 +0100 Subject: Referential: Lock table on :update We had been locking the `referentials` table on :create, but we also want to handle :update. Paired on this with Johan. When I used: referential_2.metadatas << metadata_2 the referential was saved. To add the metadata without automatically saving the referential + metadata, Johan suggested using the nested attribute method: referential_2.metadatas_attributes = [metadata_2.attributes] This allows us to add the metadata and still use the `#save` method to lock the table. Also change the callback from `before_validation` to `before_save` because before_validation :lock_table, on: [:create, :update] didn't work. That caused an error in our `expect`, as the `be_valid` triggered the lock callback. To enable the callback on both :create and :update, use a `before_save` instead. Refs #5024 --- app/models/referential.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'app/models/referential.rb') diff --git a/app/models/referential.rb b/app/models/referential.rb index b44bb15c6..6cdab8fb7 100644 --- a/app/models/referential.rb +++ b/app/models/referential.rb @@ -210,7 +210,7 @@ class Referential < ActiveRecord::Base # Lock the `referentials` table to prevent duplicate referentials from being # created simultaneously in separate transactions. This must be the last hook # to minimise the duration of the lock. - before_validation :lock_table, on: :create + before_save :lock_table, on: [:create, :update] before_create :create_schema after_create :clone_schema, if: :created_from -- cgit v1.2.3 From 6497b23e18385121974f6cbf56d48caf897e69b1 Mon Sep 17 00:00:00 2001 From: Teddy Wing Date: Wed, 13 Dec 2017 18:28:01 +0100 Subject: Referential#save_with_table_lock_timeout: Add argument I was getting test failures like this one: 2) Workbenches show filtering filter by status should display archived referentials Failure/Error: def save_with_table_lock_timeout save_without_table_lock_timeout rescue ActiveRecord::StatementInvalid => e if e.message.include?('PG::LockNotAvailable') raise TableLockTimeoutError.new(e) else raise end ArgumentError: wrong number of arguments (given 1, expected 0) # ./app/models/referential.rb:64:in `save_with_table_lock_timeout' # .../.gem/ruby/2.3.3/gems/activerecord-4.2.8/lib/active_record/persistence.rb:241:in `update_attribute' # ./spec/features/workbenches_spec.rb:71:in `block (5 levels) in ' # .../.gem/ruby/2.3.3/gems/activesupport-4.2.8/lib/active_support/dependencies.rb:268:in `load' # .../.gem/ruby/2.3.3/gems/activesupport-4.2.8/lib/active_support/dependencies.rb:268:in `block in load' # .../.gem/ruby/2.3.3/gems/activesupport-4.2.8/lib/active_support/dependencies.rb:240:in `load_dependency' # .../.gem/ruby/2.3.3/gems/activesupport-4.2.8/lib/active_support/dependencies.rb:268:in `load' # .../.gem/ruby/2.3.3/gems/spring-commands-rspec-1.0.4/lib/spring/commands/rspec.rb:18:in `call' # .../.gem/ruby/2.3.3/gems/spring-2.0.1/lib/spring/command_wrapper.rb:38:in `call' # .../.gem/ruby/2.3.3/gems/spring-2.0.1/lib/spring/application.rb:191:in `block in serve' # .../.gem/ruby/2.3.3/gems/spring-2.0.1/lib/spring/application.rb:161:in `fork' # .../.gem/ruby/2.3.3/gems/spring-2.0.1/lib/spring/application.rb:161:in `serve' # .../.gem/ruby/2.3.3/gems/spring-2.0.1/lib/spring/application.rb:131:in `block in run' # .../.gem/ruby/2.3.3/gems/spring-2.0.1/lib/spring/application.rb:125:in `loop' # .../.gem/ruby/2.3.3/gems/spring-2.0.1/lib/spring/application.rb:125:in `run' # .../.gem/ruby/2.3.3/gems/spring-2.0.1/lib/spring/application/boot.rb:19:in `' # -e:1:in `
' Sometimes an argument gets passed to the function and sometimes it doesn't. Inspecting that argument in a debugger revealed what appeared to be an options hash: (byebug) options {:validate=>false} Add this optional argument to get past the test failures. At this point I'm not even really considering whether this is a good idea or not, I just want this to be done. Refs #5024 --- app/models/referential.rb | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'app/models/referential.rb') diff --git a/app/models/referential.rb b/app/models/referential.rb index 6cdab8fb7..3a9ef2027 100644 --- a/app/models/referential.rb +++ b/app/models/referential.rb @@ -61,8 +61,8 @@ class Referential < ActiveRecord::Base scope :order_by_validity_period, ->(dir) { joins(:metadatas).order("unnest(periodes) #{dir}") } scope :order_by_lines, ->(dir) { joins(:metadatas).group("referentials.id").order("sum(array_length(referential_metadata.line_ids,1)) #{dir}") } - def save_with_table_lock_timeout - save_without_table_lock_timeout + def save_with_table_lock_timeout(options = {}) + save_without_table_lock_timeout(options) rescue ActiveRecord::StatementInvalid => e if e.message.include?('PG::LockNotAvailable') raise TableLockTimeoutError.new(e) -- cgit v1.2.3 From 43f8c76522288a0328d520dfc753ed173fc84964 Mon Sep 17 00:00:00 2001 From: cedricnjanga Date: Tue, 19 Dec 2017 16:21:06 +0100 Subject: BusinessCalendar => PurchaseWindow belongs_to referential --- app/models/referential.rb | 4 ++++ 1 file changed, 4 insertions(+) (limited to 'app/models/referential.rb') diff --git a/app/models/referential.rb b/app/models/referential.rb index 851a33653..122af65a1 100644 --- a/app/models/referential.rb +++ b/app/models/referential.rb @@ -128,6 +128,10 @@ class Referential < ActiveRecord::Base Chouette::RoutingConstraintZone.all end + def purchase_windows + Chouette::PurchaseWindow.all + end + before_validation :define_default_attributes def define_default_attributes -- cgit v1.2.3 From e20ce60629e91c63d75701651c117177ce02aced Mon Sep 17 00:00:00 2001 From: Alban Peignier Date: Thu, 28 Dec 2017 12:16:19 +0100 Subject: Add log messages when Referential can't be created. Remove useless build_referenial invocation in ReferentialsController#create. Refs #5297 --- app/models/referential.rb | 1 + 1 file changed, 1 insertion(+) (limited to 'app/models/referential.rb') diff --git a/app/models/referential.rb b/app/models/referential.rb index 122af65a1..8db009ebd 100644 --- a/app/models/referential.rb +++ b/app/models/referential.rb @@ -282,6 +282,7 @@ class Referential < ActiveRecord::Base def detect_overlapped_referentials self.class.where(id: overlapped_referential_ids).each do |referential| + Rails.logger.info "Referential #{referential.id} #{referential.metadatas.inspect} overlaps #{metadatas.inspect}" errors.add :metadatas, I18n.t("referentials.errors.overlapped_referential", :referential => referential.name) end end -- cgit v1.2.3 From 638a1864a027226c9c0b26b01ca80a85435387f7 Mon Sep 17 00:00:00 2001 From: Alban Peignier Date: Thu, 14 Dec 2017 11:09:05 +0100 Subject: Create Merge operation. Refs #5299 --- app/models/referential.rb | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) (limited to 'app/models/referential.rb') diff --git a/app/models/referential.rb b/app/models/referential.rb index 1cdda9e6a..c77fd4e3e 100644 --- a/app/models/referential.rb +++ b/app/models/referential.rb @@ -305,8 +305,15 @@ class Referential < ActiveRecord::Base end end + attr_accessor :inline_clone def clone_schema - ReferentialCloning.create(source_referential: created_from, target_referential: self) + cloning = ReferentialCloning.new source_referential: created_from, target_referential: self + + if inline_clone + cloning.clone! + else + cloning.save! + end end def create_schema -- cgit v1.2.3 From 54c202a781a189c34390e699a19e7ebae9c03442 Mon Sep 17 00:00:00 2001 From: Alban Peignier Date: Thu, 14 Dec 2017 21:40:53 +0100 Subject: Ignore detect_overlapped_referentials when Referential is into a ReferentialSuite. Refs #5299 --- app/models/referential.rb | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) (limited to 'app/models/referential.rb') diff --git a/app/models/referential.rb b/app/models/referential.rb index c77fd4e3e..4fa353a37 100644 --- a/app/models/referential.rb +++ b/app/models/referential.rb @@ -296,7 +296,7 @@ class Referential < ActiveRecord::Base overlapped_referential_ids.present? end - validate :detect_overlapped_referentials + validate :detect_overlapped_referentials, unless: :in_referential_suite? def detect_overlapped_referentials self.class.where(id: overlapped_referential_ids).each do |referential| @@ -305,6 +305,10 @@ class Referential < ActiveRecord::Base end end + def in_referential_suite? + referential_suite_id.present? + end + attr_accessor :inline_clone def clone_schema cloning = ReferentialCloning.new source_referential: created_from, target_referential: self -- cgit v1.2.3 From 78c2b9deaefa4aa5c0ac5173055cb2cacd3d27c1 Mon Sep 17 00:00:00 2001 From: Alban Peignier Date: Sun, 17 Dec 2017 22:14:17 +0100 Subject: First try for route/stop_point and journey_pattern merge. RefsĀ #5299 --- app/models/referential.rb | 30 +++++++++++++++++++++++++++--- 1 file changed, 27 insertions(+), 3 deletions(-) (limited to 'app/models/referential.rb') diff --git a/app/models/referential.rb b/app/models/referential.rb index 4fa353a37..8087ea61e 100644 --- a/app/models/referential.rb +++ b/app/models/referential.rb @@ -144,6 +144,18 @@ class Referential < ActiveRecord::Base Chouette::PurchaseWindow.all end + def routes + Chouette::Route.all + end + + def journey_patterns + Chouette::JourneyPattern.all + end + + def stop_points + Chouette::StopPoint.all + end + before_validation :define_default_attributes def define_default_attributes @@ -151,10 +163,22 @@ class Referential < ActiveRecord::Base self.objectid_format ||= workbench.objectid_format if workbench end - def switch + def switch(&block) raise "Referential not created" if new_record? - Apartment::Tenant.switch!(slug) - self + + unless block_given? + Rails.logger.debug "Referential switch to #{slug}" + Apartment::Tenant.switch! slug + self + else + result = nil + Apartment::Tenant.switch slug do + Rails.logger.debug "Referential switch to #{slug}" + result = yield + end + Rails.logger.debug "Referential back" + result + end end def self.new_from(from, functional_scope) -- cgit v1.2.3 From 2eb7c69b115516759086acf4ba19de2ef86ebec0 Mon Sep 17 00:00:00 2001 From: Alban Peignier Date: Mon, 18 Dec 2017 12:33:14 +0100 Subject: Ignore Referential with referential_suite_id in Workbench#all_referentials. Refs #5330 --- app/models/referential.rb | 1 + 1 file changed, 1 insertion(+) (limited to 'app/models/referential.rb') diff --git a/app/models/referential.rb b/app/models/referential.rb index 8087ea61e..8391a8b00 100644 --- a/app/models/referential.rb +++ b/app/models/referential.rb @@ -61,6 +61,7 @@ class Referential < ActiveRecord::Base scope :include_metadatas_lines, ->(line_ids) { where('referential_metadata.line_ids && ARRAY[?]::bigint[]', line_ids) } scope :order_by_validity_period, ->(dir) { joins(:metadatas).order("unnest(periodes) #{dir}") } scope :order_by_lines, ->(dir) { joins(:metadatas).group("referentials.id").order("sum(array_length(referential_metadata.line_ids,1)) #{dir}") } + scope :not_in_referential_suite, -> { where referential_suite_id: nil } def save_with_table_lock_timeout(options = {}) save_without_table_lock_timeout(options) -- cgit v1.2.3 From c2ca588ec9ec70ccd77690feacd45c7aae56b355 Mon Sep 17 00:00:00 2001 From: cedricnjanga Date: Thu, 4 Jan 2018 17:49:06 +0100 Subject: Refs #5468 Change redirect after Referential#validate --- app/models/referential.rb | 2 ++ 1 file changed, 2 insertions(+) (limited to 'app/models/referential.rb') diff --git a/app/models/referential.rb b/app/models/referential.rb index 8391a8b00..1608550fb 100644 --- a/app/models/referential.rb +++ b/app/models/referential.rb @@ -155,6 +155,8 @@ class Referential < ActiveRecord::Base def stop_points Chouette::StopPoint.all + def compliance_check_sets + ComplianceCheckSet.all end before_validation :define_default_attributes -- cgit v1.2.3 From e11d23cfd4c114d1bf5fcb0c4168c8a20f218d75 Mon Sep 17 00:00:00 2001 From: cedricnjanga Date: Fri, 5 Jan 2018 15:05:27 +0100 Subject: Fix typo in referential.rb after rebase --- app/models/referential.rb | 2 ++ 1 file changed, 2 insertions(+) (limited to 'app/models/referential.rb') diff --git a/app/models/referential.rb b/app/models/referential.rb index 1608550fb..a5d5acbf9 100644 --- a/app/models/referential.rb +++ b/app/models/referential.rb @@ -155,6 +155,8 @@ class Referential < ActiveRecord::Base def stop_points Chouette::StopPoint.all + end + def compliance_check_sets ComplianceCheckSet.all end -- cgit v1.2.3 From fb9eb367b9c56c19df7f2e2301f4a417f5409d6d Mon Sep 17 00:00:00 2001 From: Robert Date: Fri, 5 Jan 2018 17:34:07 +0100 Subject: Refs: #5413@4h; Setting up db (chore) and specing desired behavior [skip-ci] - Adapted shared pundit examples to allow to check with archieved and finalised referentials - Speced desired behavior with this enhancement - finalise_referential helper in policy spec's support --- app/models/referential.rb | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) (limited to 'app/models/referential.rb') diff --git a/app/models/referential.rb b/app/models/referential.rb index a5d5acbf9..5aa360cba 100644 --- a/app/models/referential.rb +++ b/app/models/referential.rb @@ -252,6 +252,10 @@ class Referential < ActiveRecord::Base before_destroy :destroy_schema before_destroy :destroy_jobs + def in_referential_suite? + referential_suite_id.present? + end + def in_workbench? workbench_id.present? end @@ -334,9 +338,6 @@ class Referential < ActiveRecord::Base end end - def in_referential_suite? - referential_suite_id.present? - end attr_accessor :inline_clone def clone_schema -- cgit v1.2.3 From db678948aba130425b2a4651e46ea7a7cc75721e Mon Sep 17 00:00:00 2001 From: Alban Peignier Date: Mon, 8 Jan 2018 09:26:04 +0100 Subject: Avoid error into Referetial#create_schema can't read migration count --- app/models/referential.rb | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) (limited to 'app/models/referential.rb') diff --git a/app/models/referential.rb b/app/models/referential.rb index a5d5acbf9..4cddd502e 100644 --- a/app/models/referential.rb +++ b/app/models/referential.rb @@ -156,7 +156,7 @@ class Referential < ActiveRecord::Base def stop_points Chouette::StopPoint.all end - + def compliance_check_sets ComplianceCheckSet.all end @@ -356,7 +356,13 @@ class Referential < ActiveRecord::Base end Rails.logger.info("Schema create benchmark: '#{slug}'\t#{report}") - Rails.logger.error( "Schema migrations count for Referential #{slug} " + Referential.connection.select_value("select count(*) from #{slug}.schema_migrations;").to_s ) + Rails.logger.info("Schema migrations count for Referential #{slug}: #{migration_count || '-'}") + end + end + + def migration_count + if self.class.connection.table_exists?("#{slug}.schema_migrations") + self.class.connection.select_value("select count(*) from #{slug}.schema_migrations;") end end -- cgit v1.2.3 From 09e818a6a63ebe5ae08045a2c67e20ae578f640e Mon Sep 17 00:00:00 2001 From: Robert Date: Mon, 8 Jan 2018 11:47:03 +0100 Subject: Refs: #5413@0.5h; Fixed broken delegation to #archived_or_finalised? --- app/models/referential.rb | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) (limited to 'app/models/referential.rb') diff --git a/app/models/referential.rb b/app/models/referential.rb index 5aa360cba..75c1889ca 100644 --- a/app/models/referential.rb +++ b/app/models/referential.rb @@ -422,11 +422,13 @@ class Referential < ActiveRecord::Base GeoRuby::SimpleFeatures::Geometry.from_ewkt(bounds.present? ? bounds : default_bounds ).envelope end - # Archive - def archived? - archived_at != nil + # For Delegator + def archived_or_finalised? + archived_at || in_referential_suite? end + # Archive + def archive! # self.archived = true touch :archived_at -- cgit v1.2.3 From 0e91d206fd8278d0c43c34777f4a585481882b70 Mon Sep 17 00:00:00 2001 From: Robert Date: Tue, 9 Jan 2018 12:24:23 +0100 Subject: Refs: #5413@0.5h; Refactoring of #archived_or_finalised? --- app/models/referential.rb | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) (limited to 'app/models/referential.rb') diff --git a/app/models/referential.rb b/app/models/referential.rb index 75c1889ca..73d29fee4 100644 --- a/app/models/referential.rb +++ b/app/models/referential.rb @@ -252,6 +252,10 @@ class Referential < ActiveRecord::Base before_destroy :destroy_schema before_destroy :destroy_jobs + def referential_read_only? + in_referential_suite? || archived_at + end + def in_referential_suite? referential_suite_id.present? end @@ -422,11 +426,6 @@ class Referential < ActiveRecord::Base GeoRuby::SimpleFeatures::Geometry.from_ewkt(bounds.present? ? bounds : default_bounds ).envelope end - # For Delegator - def archived_or_finalised? - archived_at || in_referential_suite? - end - # Archive def archive! -- cgit v1.2.3 From 00e3beef89ac53191dc4b18bad07c9a3d1ae09c0 Mon Sep 17 00:00:00 2001 From: Luc Donnet Date: Tue, 9 Jan 2018 21:08:18 +0100 Subject: Add log to count migration when we clone or create schema --- app/models/referential.rb | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) (limited to 'app/models/referential.rb') diff --git a/app/models/referential.rb b/app/models/referential.rb index 4cddd502e..36fc2e680 100644 --- a/app/models/referential.rb +++ b/app/models/referential.rb @@ -355,11 +355,15 @@ class Referential < ActiveRecord::Base Apartment::Tenant.create slug end - Rails.logger.info("Schema create benchmark: '#{slug}'\t#{report}") - Rails.logger.info("Schema migrations count for Referential #{slug}: #{migration_count || '-'}") + check_migration_count end end + def check_migration_count + Rails.logger.info("Schema create benchmark: '#{slug}'\t#{report}") + Rails.logger.info("Schema migrations count for Referential #{slug}: #{migration_count || '-'}") + end + def migration_count if self.class.connection.table_exists?("#{slug}.schema_migrations") self.class.connection.select_value("select count(*) from #{slug}.schema_migrations;") -- cgit v1.2.3 From 197f39349dd703a99d1efb20aa3a5e5a0c567724 Mon Sep 17 00:00:00 2001 From: Luc Donnet Date: Tue, 9 Jan 2018 21:48:21 +0100 Subject: Fix argument call to log referential create and clone --- app/models/referential.rb | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'app/models/referential.rb') diff --git a/app/models/referential.rb b/app/models/referential.rb index 36fc2e680..1fd51a779 100644 --- a/app/models/referential.rb +++ b/app/models/referential.rb @@ -355,11 +355,11 @@ class Referential < ActiveRecord::Base Apartment::Tenant.create slug end - check_migration_count + check_migration_count(report) end end - def check_migration_count + def check_migration_count(report) Rails.logger.info("Schema create benchmark: '#{slug}'\t#{report}") Rails.logger.info("Schema migrations count for Referential #{slug}: #{migration_count || '-'}") end -- cgit v1.2.3 From d597c065194e84f3c350c042276480361520b3b9 Mon Sep 17 00:00:00 2001 From: Alban Peignier Date: Wed, 10 Jan 2018 18:48:18 +0100 Subject: Lock public.referentials to avoid problem with schemas. Refs #5024 --- app/models/referential.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'app/models/referential.rb') diff --git a/app/models/referential.rb b/app/models/referential.rb index 1fd51a779..75525c441 100644 --- a/app/models/referential.rb +++ b/app/models/referential.rb @@ -456,7 +456,7 @@ class Referential < ActiveRecord::Base # No explicit unlock is needed as it will be released at the end of the # transaction. ActiveRecord::Base.connection.execute( - 'LOCK referentials IN ACCESS EXCLUSIVE MODE' + 'LOCK public.referentials IN ACCESS EXCLUSIVE MODE' ) end end -- cgit v1.2.3 From 2959b21c13baa18dd2210af2b8751b906a9e2158 Mon Sep 17 00:00:00 2001 From: Alban Peignier Date: Wed, 10 Jan 2018 21:00:40 +0100 Subject: Restore Referential#archived? method. Refs #5413 --- app/models/referential.rb | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) (limited to 'app/models/referential.rb') diff --git a/app/models/referential.rb b/app/models/referential.rb index 73d29fee4..932000174 100644 --- a/app/models/referential.rb +++ b/app/models/referential.rb @@ -156,7 +156,7 @@ class Referential < ActiveRecord::Base def stop_points Chouette::StopPoint.all end - + def compliance_check_sets ComplianceCheckSet.all end @@ -253,7 +253,7 @@ class Referential < ActiveRecord::Base before_destroy :destroy_jobs def referential_read_only? - in_referential_suite? || archived_at + in_referential_suite? || archived? end def in_referential_suite? @@ -427,6 +427,9 @@ class Referential < ActiveRecord::Base end # Archive + def archived? + archived_at != nil + end def archive! # self.archived = true -- cgit v1.2.3 From 3aee5e1e5d7c54190453164b6954d685a86fcd3f Mon Sep 17 00:00:00 2001 From: Alban Peignier Date: Wed, 10 Jan 2018 21:32:57 +0100 Subject: Ignore referential_in_suite in Referential#overlapped_referential_ids (used by can_unarchive. Refs #5299 --- app/models/referential.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'app/models/referential.rb') diff --git a/app/models/referential.rb b/app/models/referential.rb index 3eb5d3283..2b7866d9f 100644 --- a/app/models/referential.rb +++ b/app/models/referential.rb @@ -323,7 +323,7 @@ class Referential < ActiveRecord::Base query = "select distinct(public.referential_metadata.referential_id) FROM public.referential_metadata, unnest(line_ids) line, LATERAL unnest(periodes) period WHERE public.referential_metadata.referential_id - IN (SELECT public.referentials.id FROM public.referentials WHERE referentials.workbench_id = #{workbench_id} and referentials.archived_at is null #{not_myself}) + IN (SELECT public.referentials.id FROM public.referentials WHERE referentials.workbench_id = #{workbench_id} and referentials.archived_at is null and referentials.referential_suite_id is null #{not_myself}) AND line in (#{line_ids.join(',')}) and (#{periods_query});" self.class.connection.select_values(query).map(&:to_i) -- cgit v1.2.3 From 4f74779e9732c5dd45bd8c3cd1ae67f74d1faa28 Mon Sep 17 00:00:00 2001 From: Alban Peignier Date: Thu, 11 Jan 2018 12:02:25 +0100 Subject: Create Referential#full_name and try to use it (to be completed). Refs #5546 --- app/models/referential.rb | 8 ++++++++ 1 file changed, 8 insertions(+) (limited to 'app/models/referential.rb') diff --git a/app/models/referential.rb b/app/models/referential.rb index 2b7866d9f..718f60ffd 100644 --- a/app/models/referential.rb +++ b/app/models/referential.rb @@ -105,6 +105,14 @@ class Referential < ActiveRecord::Base self.class.human_attribute_name(*args) end + def full_name + if in_referential_suite? + name + else + "#{self.class.model_name.human.capitalize} #{name}" + end + end + def stop_areas Chouette::StopArea.all end -- cgit v1.2.3 From 13de613c6db20e32f58ca16b5b3c58e79b5e8d70 Mon Sep 17 00:00:00 2001 From: Alban Peignier Date: Thu, 11 Jan 2018 21:43:22 +0100 Subject: Add Referential#merged_at and make Referentials archived and merged. Refs #5559 --- app/models/referential.rb | 12 ++++++++++++ 1 file changed, 12 insertions(+) (limited to 'app/models/referential.rb') diff --git a/app/models/referential.rb b/app/models/referential.rb index 718f60ffd..92931564d 100644 --- a/app/models/referential.rb +++ b/app/models/referential.rb @@ -463,6 +463,18 @@ class Referential < ActiveRecord::Base not metadatas_overlap? end + def merged? + merged_at.present? + end + + def self.not_merged + where merged_at: nil + end + + def self.mergeable + ready.not_merged.not_in_referential_suite + end + private def lock_table -- cgit v1.2.3 From b853120644819dd1ae646ea762f457836abfea09 Mon Sep 17 00:00:00 2001 From: Zog Date: Wed, 17 Jan 2018 16:57:59 +0100 Subject: Refs #5593 @1h; - Register all models that implement checksums - Add a simple rake task that updates all checksums within a given referential --- app/models/referential.rb | 40 ++++++++++++++++++++++++++++++++++++++++ 1 file changed, 40 insertions(+) (limited to 'app/models/referential.rb') diff --git a/app/models/referential.rb b/app/models/referential.rb index 92931564d..baaa354da 100644 --- a/app/models/referential.rb +++ b/app/models/referential.rb @@ -75,6 +75,46 @@ class Referential < ActiveRecord::Base alias_method_chain :save, :table_lock_timeout + if Rails.env.development? + def self.force_register_models_with_checksum + paths = Rails.application.paths['app/models'].to_a + Rails.application.railties.each do |tie| + next unless tie.respond_to? :paths + paths += tie.paths['app/models'].to_a + end + + paths.each do |path| + next unless File.directory?(path) + Dir.chdir path do + Dir['**/*.rb'].each do |src| + next if src =~ /^concerns/ + # thanks for inconsistent naming ... + if src == "route_control/zdl_stop_area.rb" + RouteControl::ZDLStopArea + next + end + Rails.logger.info "Loading #{src}" + begin + src[0..-4].classify.safe_constantize + rescue => e + Rails.logger.info "Failed: #{e.message}" + nil + end + end + end + end + end + end + + def self.register_model_with_checksum klass + @_models_with_checksum ||= [] + @_models_with_checksum << klass + end + + def self.models_with_checksum + @_models_with_checksum || [] + end + def lines if metadatas.blank? workbench ? workbench.lines : associated_lines -- cgit v1.2.3 From 5152b611d62849c7f9bac24f1708aba6a651fe75 Mon Sep 17 00:00:00 2001 From: Alban Peignier Date: Thu, 1 Feb 2018 23:51:21 +0100 Subject: Remove Referential#stop_areas to use stop_areas has_many through. Refs #5824 --- app/models/referential.rb | 4 ---- 1 file changed, 4 deletions(-) (limited to 'app/models/referential.rb') diff --git a/app/models/referential.rb b/app/models/referential.rb index baaa354da..f64db4ebf 100644 --- a/app/models/referential.rb +++ b/app/models/referential.rb @@ -153,10 +153,6 @@ class Referential < ActiveRecord::Base end end - def stop_areas - Chouette::StopArea.all - end - def access_points Chouette::AccessPoint.all end -- cgit v1.2.3 From 7e7371087b61aaf8a128d5f5f5ec6c43c06fd4ca Mon Sep 17 00:00:00 2001 From: cedricnjanga Date: Tue, 6 Feb 2018 21:52:02 -0800 Subject: Refs #5707 Add status to the application to track 'blocked objects' --- app/models/referential.rb | 1 + 1 file changed, 1 insertion(+) (limited to 'app/models/referential.rb') diff --git a/app/models/referential.rb b/app/models/referential.rb index f64db4ebf..509e0412f 100644 --- a/app/models/referential.rb +++ b/app/models/referential.rb @@ -62,6 +62,7 @@ class Referential < ActiveRecord::Base scope :order_by_validity_period, ->(dir) { joins(:metadatas).order("unnest(periodes) #{dir}") } scope :order_by_lines, ->(dir) { joins(:metadatas).group("referentials.id").order("sum(array_length(referential_metadata.line_ids,1)) #{dir}") } scope :not_in_referential_suite, -> { where referential_suite_id: nil } + scope :blocked, -> { where('ready = ? AND created_at < ?', false, 4.hours.ago) } def save_with_table_lock_timeout(options = {}) save_without_table_lock_timeout(options) -- cgit v1.2.3