diff --git a/.rubocop.yml b/.rubocop.yml index 066eb004..138e863b 100644 --- a/.rubocop.yml +++ b/.rubocop.yml @@ -1,9 +1,5 @@ AllCops: RunRailsCops: true - Include: - - 'Gemfile' - - 'Rakefile' - - 'delayed_job_active_record.gemspec' ################# # [i] Overrides # @@ -52,6 +48,9 @@ StringLiterals: ################# # Disabled cops # ################# +AbcSize: + Enabled: false + ClassAndModuleChildren: Enabled: false diff --git a/lib/delayed/backend/active_record.rb b/lib/delayed/backend/active_record.rb index d495f225..6f912251 100644 --- a/lib/delayed/backend/active_record.rb +++ b/lib/delayed/backend/active_record.rb @@ -58,22 +58,30 @@ def self.reserve_with_scope(ready_scope, worker, now) case connection.adapter_name when "PostgreSQL" # Custom SQL required for PostgreSQL because postgres does not support UPDATE...LIMIT - # This locks the single record 'FOR UPDATE' in the subquery (http://www.postgresql.org/docs/9.0/static/sql-select.html#SQL-FOR-UPDATE-SHARE) - # Note: active_record would attempt to generate UPDATE...LIMIT like sql for postgres if we use a .limit() filter, but it would not use - # 'FOR UPDATE' and we would have many locking conflicts + # This locks the single record 'FOR UPDATE' in the subquery + # http://www.postgresql.org/docs/9.0/static/sql-select.html#SQL-FOR-UPDATE-SHARE + # Note: active_record would attempt to generate UPDATE...LIMIT like + # SQL for Postgres if we use a .limit() filter, but it would not + # use 'FOR UPDATE' and we would have many locking conflicts quoted_table_name = connection.quote_table_name(table_name) subquery_sql = ready_scope.limit(1).lock(true).select("id").to_sql reserved = find_by_sql(["UPDATE #{quoted_table_name} SET locked_at = ?, locked_by = ? WHERE id IN (#{subquery_sql}) RETURNING *", now, worker.name]) reserved[0] when "MySQL", "Mysql2" - #removing the millisecond precision from now(time object),mysql 5.6.4 onwards millisecond precision exists, but the datetime object created doesn't have precision, so discarded while updating. But during the where clause, for mysql(>=5.6.4), it queries with precision as well. So removing the precision - now = now.change(:usec => 0) - # This works on MySQL and possibly some other DBs that support UPDATE...LIMIT. It uses separate queries to lock and return the job + # Removing the millisecond precision from now(time object) + # MySQL 5.6.4 onwards millisecond precision exists, but the + # datetime object created doesn't have precision, so discarded + # while updating. But during the where clause, for mysql(>=5.6.4), + # it queries with precision as well. So removing the precision + now = now.change(usec: 0) + # This works on MySQL and possibly some other DBs that support + # UPDATE...LIMIT. It uses separate queries to lock and return the job count = ready_scope.limit(1).update_all(locked_at: now, locked_by: worker.name) return nil if count == 0 where(locked_at: now, locked_by: worker.name, failed_at: nil).first when "MSSQL", "Teradata" - # The MSSQL driver doesn't generate a limit clause when update_all is called directly + # The MSSQL driver doesn't generate a limit clause when update_all + # is called directly subsubquery_sql = ready_scope.limit(1).to_sql # select("id") doesn't generate a subquery, so force a subquery subquery_sql = "SELECT id FROM (#{subsubquery_sql}) AS x" diff --git a/spec/helper.rb b/spec/helper.rb index de7a0bc8..e8ca265d 100644 --- a/spec/helper.rb +++ b/spec/helper.rb @@ -2,8 +2,8 @@ require "coveralls" SimpleCov.formatter = SimpleCov::Formatter::MultiFormatter[ - SimpleCov::Formatter::HTMLFormatter, - Coveralls::SimpleCov::Formatter + SimpleCov::Formatter::HTMLFormatter, + Coveralls::SimpleCov::Formatter ] SimpleCov.start do @@ -33,7 +33,7 @@ ActiveRecord::Base.logger = Delayed::Worker.logger ActiveRecord::Migration.verbose = false -require 'generators/delayed_job/templates/migration' +require "generators/delayed_job/templates/migration" ActiveRecord::Schema.define do CreateDelayedJobs.up