diff --git a/.rubocop.yml b/.rubocop.yml index 138e863b..48e569cc 100644 --- a/.rubocop.yml +++ b/.rubocop.yml @@ -1,11 +1,19 @@ +# Load the rubocop-rspec gem +require: rubocop-rspec + +Rails: + Enabled: true AllCops: - RunRailsCops: true + Exclude: + - lib/**/templates/* + - vendor/**/* ################# # [i] Overrides # ################# -CollectionMethods: +Style/CollectionMethods: + Enabled: true # Mapping from undesired method to desired_method # e.g. to use `detect` over `find`: # @@ -13,34 +21,31 @@ CollectionMethods: # PreferredMethods: # find: detect PreferredMethods: - collect: 'map' - collect!: 'map!' reduce: 'inject' - find_all: 'select' find: 'detect' + each_with_index: 'each.with_index' -# Multi-line method chaining should be done with leading dots. -DotPosition: - EnforcedStyle: trailing +Style/EmptyMethod: + EnforcedStyle: expanded # Align ends correctly. EndAlignment: - AlignWith: variable - -IfUnlessModifier: - MaxLineLength: 75 + EnforcedStyleAlignWith: variable LineLength: - Max: 200 + Max: 120 SignalException: EnforcedStyle: only_raise SpaceInsideBlockBraces: - SpaceBeforeBlockParameters: false + SpaceBeforeBlockParameters: true SpaceInsideHashLiteralBraces: - EnforcedStyle: no_space + EnforcedStyle: space + +BracesAroundHashParameters: + EnforcedStyle: context_dependent StringLiterals: EnforcedStyle: double_quotes @@ -48,44 +53,99 @@ StringLiterals: ################# # Disabled cops # ################# -AbcSize: +Metrics/ClassLength: + Enabled: false + +Metrics/CyclomaticComplexity: + Enabled: false + +Metrics/MethodLength: Enabled: false -ClassAndModuleChildren: +Style/ClassAndModuleChildren: Enabled: false -ClassLength: +Style/Documentation: Enabled: false -CyclomaticComplexity: +Style/EachWithObject: Enabled: false -Documentation: +Style/FormatString: + Enabled: false + +Style/Lambda: + Enabled: false + +Style/NegatedIf: + Enabled: false + +Style/PercentLiteralDelimiters: + PreferredDelimiters: + "%w": "[]" + "%W": "[]" + "%i": "[]" + "%I": "[]" + +Style/Semicolon: Enabled: false -EachWithObject: +Style/SingleLineBlockParams: Enabled: false -FormatString: +Style/WordArray: Enabled: false -Lambda: +# HABTM still has a place. +# http://collectiveidea.com/blog/archives/2014/08/11/has_and_belongs_to_many-isnt-dead/ +Rails/HasAndBelongsToMany: Enabled: false -MethodLength: +# enforces using the class name in a describe block (e.g. `describe TestedClass do`) +RSpec/DescribeClass: Enabled: false -NegatedIf: +# enforces using the described_class variablea (`described_class` instead of MyClass) +RSpec/DescribedClass: + Enabled: false + +# RSpec examples are ok if they're long. +# Explicitness is better than cleverness in tests. +RSpec/ExampleLength: + Enabled: false + +# enforces using either `expect` or `allow` for stubs. Since they do differnet things, +# we should let the developer decide which to use +RSpec/MessageExpectation: + Enabled: false + +# enforces having only one `expect` per test +RSpec/MultipleExpectations: + Enabled: false + +# enforces rules about how many nested `describe` blocks are allowed +RSpec/NestedGroups: + Enabled: false + +# enforces rules about using `it` or `describe` block methods instead of `feature` or `scenario` +Capybara/FeatureMethods: + Enabled: false + +################### +# Local overrides # +################### + +Rails/ApplicationRecord: Enabled: false -Semicolon: +Rails/SkipsModelValidations: Enabled: false -SingleLineBlockParams: +Security/YAMLLoad: Enabled: false -TrailingComma: +Style/FormatStringToken: Enabled: false -WordArray: +Style/NumericPredicate: Enabled: false diff --git a/.travis.yml b/.travis.yml index 4b649387..88be7086 100644 --- a/.travis.yml +++ b/.travis.yml @@ -4,25 +4,27 @@ branches: - master before_script: - mysql -e 'create database delayed_job_test;' + - mysql --version - psql -c 'create database delayed_job_test;' -U postgres -script: bundle exec rspec +script: bundle exec $COMMAND env: global: - JRUBY_OPTS="$JRUBY_OPTS -Xcli.debug=true --debug" + - COMMAND=rspec gemfile: # Supported - gemfiles/mysql2/4-2.gemfile - - gemfiles/mysql2/5-0.gemfile - gemfiles/mysql2/5-1.gemfile + - gemfiles/mysql2/5-2.gemfile - gemfiles/postgresql/4-2.gemfile - - gemfiles/postgresql/5-0.gemfile - gemfiles/postgresql/5-1.gemfile + - gemfiles/postgresql/5-2.gemfile - gemfiles/sqlite3/4-2.gemfile - - gemfiles/sqlite3/5-0.gemfile - gemfiles/sqlite3/5-1.gemfile + - gemfiles/sqlite3/5-2.gemfile rvm: # Supported - - 2.2.7 - - 2.3.4 - - 2.4.1 + - 2.2.10 + - 2.3.7 + - 2.4.4 - jruby-9.1.8.0 jdk: oraclejdk8 @@ -42,75 +44,112 @@ matrix: gemfile: gemfiles/mysql2/5-1.gemfile - rvm: jruby-9.1.8.0 gemfile: gemfiles/postgresql/5-1.gemfile + - rvm: jruby-9.1.8.0 + gemfile: gemfiles/mysql2/5-2.gemfile + - rvm: jruby-9.1.8.0 + gemfile: gemfiles/postgresql/5-2.gemfile + - rvm: jruby-9.1.8.0 + gemfile: gemfiles/sqlite3/5-2.gemfile include: # + # Rubocop + # + - rvm: 2.5.1 + gemfile: Gemfile + env: + - COMMAND=rubocop + # # The future # + # MRI 2.5.1 + - rvm: 2.5.1 + gemfile: gemfiles/mysql2/5-1.gemfile + - rvm: 2.5.1 + gemfile: gemfiles/postgresql/5-1.gemfile + - rvm: 2.5.1 + gemfile: gemfiles/sqlite3/5-1.gemfile + - rvm: 2.5.1 + gemfile: gemfiles/mysql2/5-2.gemfile + - rvm: 2.5.1 + gemfile: gemfiles/postgresql/5-2.gemfile + - rvm: 2.5.1 + gemfile: gemfiles/sqlite3/5-2.gemfile # Active Record head - - gemfile: gemfiles/mysql2/master.gemfile - rvm: 2.4.1 - - gemfile: gemfiles/postgresql/master.gemfile - rvm: 2.4.1 - - gemfile: gemfiles/sqlite3/master.gemfile - rvm: 2.4.1 + - rvm: 2.5.1 + gemfile: gemfiles/mysql2/master.gemfile + - rvm: 2.5.1 + gemfile: gemfiles/postgresql/master.gemfile + - rvm: 2.5.1 + gemfile: gemfiles/sqlite3/master.gemfile # MRI Ruby head - rvm: ruby-head - gemfile: gemfiles/mysql2/5-1.gemfile + gemfile: gemfiles/mysql2/5-2.gemfile - rvm: ruby-head - gemfile: gemfiles/postgresql/5-1.gemfile + gemfile: gemfiles/postgresql/5-2.gemfile - rvm: ruby-head - gemfile: gemfiles/sqlite3/5-1.gemfile + gemfile: gemfiles/sqlite3/5-2.gemfile # JRuby head - rvm: jruby-head - gemfile: gemfiles/mysql2/5-1.gemfile + gemfile: gemfiles/mysql2/5-2.gemfile - rvm: jruby-head - gemfile: gemfiles/postgresql/5-1.gemfile + gemfile: gemfiles/postgresql/5-2.gemfile - rvm: jruby-head - gemfile: gemfiles/sqlite3/5-1.gemfile + gemfile: gemfiles/sqlite3/5-2.gemfile # # The past # # EOL Active Record - - gemfile: gemfiles/mysql2/3-0.gemfile - rvm: 2.2.7 - - gemfile: gemfiles/mysql2/3-1.gemfile - rvm: 2.2.7 - - gemfile: gemfiles/mysql2/3-2.gemfile - rvm: 2.2.7 - - gemfile: gemfiles/mysql2/4-0.gemfile - rvm: 2.3.4 - - gemfile: gemfiles/mysql2/4-1.gemfile - rvm: 2.3.4 - - gemfile: gemfiles/postgresql/3-0.gemfile - rvm: 2.2.7 - - gemfile: gemfiles/postgresql/3-1.gemfile - rvm: 2.2.7 - - gemfile: gemfiles/postgresql/3-2.gemfile - rvm: 2.2.7 - - gemfile: gemfiles/postgresql/4-0.gemfile - rvm: 2.3.4 - - gemfile: gemfiles/postgresql/4-1.gemfile - rvm: 2.3.4 - - gemfile: gemfiles/sqlite3/3-0.gemfile - rvm: 2.2.7 - - gemfile: gemfiles/sqlite3/3-1.gemfile - rvm: 2.2.7 - - gemfile: gemfiles/sqlite3/3-2.gemfile - rvm: 2.2.7 - - gemfile: gemfiles/sqlite3/4-0.gemfile - rvm: 2.3.4 - - gemfile: gemfiles/sqlite3/4-1.gemfile - rvm: 2.3.4 + # Rails 3.2 was maintained longer and is ruby 2.2 compatible + - rvm: 2.2.10 + gemfile: gemfiles/mysql2/3-2.gemfile + - rvm: 2.2.10 + gemfile: gemfiles/postgresql/3-2.gemfile + - rvm: 2.2.10 + gemfile: gemfiles/sqlite3/3-2.gemfile + # Rails <= 4.0 was only compatible with ruby 2.0 + # The test were running, but there are known incompatibilites + - rvm: 2.0.0-p648 + gemfile: gemfiles/mysql2/3-0.gemfile + - rvm: 2.0.0-p648 + gemfile: gemfiles/mysql2/3-1.gemfile + - rvm: 2.0.0-p648 + gemfile: gemfiles/postgresql/3-0.gemfile + - rvm: 2.0.0-p648 + gemfile: gemfiles/postgresql/3-1.gemfile + - rvm: 2.0.0-p648 + gemfile: gemfiles/sqlite3/3-0.gemfile + - rvm: 2.0.0-p648 + gemfile: gemfiles/sqlite3/3-1.gemfile + - rvm: 2.0.0-p648 + gemfile: gemfiles/mysql2/4-0.gemfile + - rvm: 2.0.0-p648 + gemfile: gemfiles/postgresql/4-0.gemfile + - rvm: 2.0.0-p648 + gemfile: gemfiles/sqlite3/4-0.gemfile + # Rails 4.1 was only compatible with ruby 2.1 + - rvm: 2.1.9 + gemfile: gemfiles/mysql2/4-1.gemfile + - rvm: 2.1.9 + gemfile: gemfiles/postgresql/4-1.gemfile + - rvm: 2.1.9 + gemfile: gemfiles/sqlite3/4-1.gemfile + # Rails 5.0 was EOL with the release of 5.2 + - rvm: 2.4.4 + gemfile: gemfiles/mysql2/5-0.gemfile + - rvm: 2.4.4 + gemfile: gemfiles/postgresql/5-0.gemfile + - rvm: 2.4.4 + gemfile: gemfiles/sqlite3/5-0.gemfile # # The parallel dimension # # Rubinius - - gemfile: gemfiles/mysql2/5-1.gemfile - rvm: rbx-2 - - gemfile: gemfiles/postgresql/5-1.gemfile - rvm: rbx-2 - - gemfile: gemfiles/sqlite3/5-1.gemfile - rvm: rbx-2 + - rvm: rbx-2 + gemfile: gemfiles/mysql2/5-1.gemfile + - rvm: rbx-2 + gemfile: gemfiles/postgresql/5-1.gemfile + - rvm: rbx-2 + gemfile: gemfiles/sqlite3/5-1.gemfile sudo: false diff --git a/Gemfile b/Gemfile index 4ba62fec..6a063649 100644 --- a/Gemfile +++ b/Gemfile @@ -4,22 +4,21 @@ gem "rake" group :test do platforms :jruby do - gem 'activerecord-jdbcmysql-adapter', git: 'https://github.com/jruby/activerecord-jdbc-adapter', branch: 'rails-5' - - gem 'activerecord-jdbcpostgresql-adapter', git: 'https://github.com/jruby/activerecord-jdbc-adapter', branch: 'rails-5' - - gem 'activerecord-jdbcsqlite3-adapter', git: 'https://github.com/jruby/activerecord-jdbc-adapter', branch: 'rails-5' + gem "activerecord-jdbcmysql-adapter" + gem "activerecord-jdbcpostgresql-adapter" + gem "activerecord-jdbcsqlite3-adapter" end platforms :ruby, :mswin, :mingw do - gem 'mysql2', '~> 0.4.5' - gem "pg" + gem "mysql2", "~> 0.4.5" + gem "pg", "~> 0.18" gem "sqlite3" end gem "coveralls", require: false gem "rspec", ">= 3" - gem "rubocop", ">= 0.23" + gem "rubocop" + gem "rubocop-rspec" gem "simplecov", require: false end diff --git a/README.md b/README.md index 29598222..7e87f786 100644 --- a/README.md +++ b/README.md @@ -1,7 +1,7 @@ **If you're viewing this at https://github.com/collectiveidea/delayed_job_active_record, you're reading the documentation for the master branch. [View documentation for the latest release -(4.1.2).](https://github.com/collectiveidea/delayed_job_active_record/tree/v4.1.2)** +(4.1.3).](https://github.com/collectiveidea/delayed_job_active_record/tree/v4.1.3)** # DelayedJob ActiveRecord Backend diff --git a/Rakefile b/Rakefile index d854d6fd..b8d3c778 100644 --- a/Rakefile +++ b/Rakefile @@ -3,7 +3,7 @@ Bundler::GemHelper.install_tasks require "rspec/core/rake_task" -ADAPTERS = %w(mysql2 postgresql sqlite3) +ADAPTERS = %w[mysql2 postgresql sqlite3].freeze ADAPTERS.each do |adapter| desc "Run RSpec code examples for #{adapter} adapter" diff --git a/delayed_job_active_record.gemspec b/delayed_job_active_record.gemspec index fffc38ce..f0c5f348 100644 --- a/delayed_job_active_record.gemspec +++ b/delayed_job_active_record.gemspec @@ -1,14 +1,14 @@ Gem::Specification.new do |spec| - spec.add_dependency "activerecord", [">= 3.0", "< 5.2"] + spec.add_dependency "activerecord", [">= 3.0", "< 5.3"] spec.add_dependency "delayed_job", [">= 3.0", "< 5"] spec.authors = ["Brian Ryckbost", "Matt Griffin", "Erik Michaels-Ober"] spec.description = "ActiveRecord backend for Delayed::Job, originally authored by Tobias Lütke" spec.email = ["bryckbost@gmail.com", "matt@griffinonline.org", "sferik@gmail.com"] - spec.files = %w(CONTRIBUTING.md LICENSE.md README.md delayed_job_active_record.gemspec) + Dir["lib/**/*.rb"] + spec.files = %w[CONTRIBUTING.md LICENSE.md README.md delayed_job_active_record.gemspec] + Dir["lib/**/*.rb"] spec.homepage = "http://github.com/collectiveidea/delayed_job_active_record" spec.licenses = ["MIT"] spec.name = "delayed_job_active_record" spec.require_paths = ["lib"] spec.summary = "ActiveRecord backend for DelayedJob" - spec.version = "4.1.2" + spec.version = "4.1.3" end diff --git a/gemfiles/mysql2/3-0.gemfile b/gemfiles/mysql2/3-0.gemfile index 19f3831c..836d9985 100644 --- a/gemfiles/mysql2/3-0.gemfile +++ b/gemfiles/mysql2/3-0.gemfile @@ -1,21 +1,15 @@ -source 'https://rubygems.org' +source "https://rubygems.org" -gem 'rake' +gem "rake" group :test do - platforms :jruby do - gem 'activerecord-jdbcmysql-adapter' - end + gem "activerecord-mysql2-adapter" - platforms :ruby, :mswin, :mingw do - gem 'activerecord-mysql2-adapter' - end + gem "coveralls", require: false + gem "rspec", ">= 2.11" + gem "simplecov", require: false - gem 'coveralls', :require => false - gem 'rspec', '>= 2.11' - gem 'simplecov', :require => false - - gem 'activerecord', "~> 3.0.0" + gem "activerecord", "~> 3.0.0" end -gemspec :path => "../../" +gemspec path: "../../" diff --git a/gemfiles/mysql2/3-1.gemfile b/gemfiles/mysql2/3-1.gemfile index a88d0791..5eb7ed81 100644 --- a/gemfiles/mysql2/3-1.gemfile +++ b/gemfiles/mysql2/3-1.gemfile @@ -1,22 +1,13 @@ -source 'https://rubygems.org' +source "https://rubygems.org" -gem 'rake' +gem "rake" -group :test do - platforms :jruby do - gem 'activerecord-jdbcmysql-adapter' - end +gem "mysql2", "~> 0.3.10" - platforms :ruby, :mswin, :mingw do - gem 'mysql2', '~> 0.3.10' - gem 'activerecord-mysql2-adapter' - end +gem "coveralls", require: false +gem "rspec", ">= 2.11" +gem "simplecov", require: false - gem 'coveralls', :require => false - gem 'rspec', '>= 2.11' - gem 'simplecov', :require => false +gem "activerecord", "~> 3.1.0" - gem 'activerecord', "~> 3.1.0" -end - -gemspec :path => "../../" +gemspec path: "../../" diff --git a/gemfiles/mysql2/3-2.gemfile b/gemfiles/mysql2/3-2.gemfile index 2d60846d..2fd7011f 100644 --- a/gemfiles/mysql2/3-2.gemfile +++ b/gemfiles/mysql2/3-2.gemfile @@ -1,22 +1,13 @@ -source 'https://rubygems.org' +source "https://rubygems.org" -gem 'rake' +gem "rake" -group :test do - platforms :jruby do - gem 'activerecord-jdbcmysql-adapter' - end +gem "mysql2", "~> 0.3.10" - platforms :ruby, :mswin, :mingw do - gem 'mysql2', '~> 0.3.10' - gem 'activerecord-mysql2-adapter' - end +gem "coveralls", require: false +gem "rspec", ">= 2.11" +gem "simplecov", require: false - gem 'coveralls', :require => false - gem 'rspec', '>= 2.11' - gem 'simplecov', :require => false +gem "activerecord", "~> 3.2.0" - gem 'activerecord', "~> 3.2.0" -end - -gemspec :path => "../../" +gemspec path: "../../" diff --git a/gemfiles/mysql2/4-0.gemfile b/gemfiles/mysql2/4-0.gemfile index 6a781b8f..a7720eb1 100644 --- a/gemfiles/mysql2/4-0.gemfile +++ b/gemfiles/mysql2/4-0.gemfile @@ -1,22 +1,13 @@ -source 'https://rubygems.org' +source "https://rubygems.org" -gem 'rake' +gem "rake" -group :test do - platforms :jruby do - gem 'activerecord-jdbcmysql-adapter' - end +gem "mysql2", "~> 0.3.10" - platforms :ruby, :mswin, :mingw do - gem 'mysql2', '~> 0.3.10' - gem 'activerecord-mysql2-adapter' - end +gem "coveralls", require: false +gem "rspec", ">= 2.11" +gem "simplecov", require: false - gem 'coveralls', :require => false - gem 'rspec', '>= 2.11' - gem 'simplecov', :require => false +gem "activerecord", "~> 4.0.0" - gem 'activerecord', "~> 4.0.0" -end - -gemspec :path => "../../" +gemspec path: "../../" diff --git a/gemfiles/mysql2/4-1.gemfile b/gemfiles/mysql2/4-1.gemfile index f4c9aa7c..6f204a0e 100644 --- a/gemfiles/mysql2/4-1.gemfile +++ b/gemfiles/mysql2/4-1.gemfile @@ -1,22 +1,13 @@ -source 'https://rubygems.org' +source "https://rubygems.org" -gem 'rake' +gem "rake" -group :test do - platforms :jruby do - gem 'activerecord-jdbcmysql-adapter' - end +gem "mysql2", "~> 0.3.13" - platforms :ruby, :mswin, :mingw do - gem 'mysql2', '~> 0.3.13' - gem 'activerecord-mysql2-adapter' - end +gem "coveralls", require: false +gem "rspec", ">= 2.11" +gem "simplecov", require: false - gem 'coveralls', :require => false - gem 'rspec', '>= 2.11' - gem 'simplecov', :require => false +gem "activerecord", "~> 4.1.0" - gem 'activerecord', "~> 4.1.0" -end - -gemspec :path => "../../" +gemspec path: "../../" diff --git a/gemfiles/mysql2/4-2.gemfile b/gemfiles/mysql2/4-2.gemfile index 24e9459e..7e633d79 100644 --- a/gemfiles/mysql2/4-2.gemfile +++ b/gemfiles/mysql2/4-2.gemfile @@ -1,21 +1,21 @@ -source 'https://rubygems.org' +source "https://rubygems.org" -gem 'rake' +gem "rake" group :test do platforms :jruby do - gem 'activerecord-jdbcmysql-adapter' + gem "activerecord-jdbcmysql-adapter", "< 50.0" end platforms :ruby, :mswin, :mingw do - gem 'mysql2', '>= 0.3.13', '< 0.5' + gem "mysql2", ">= 0.3.13", "< 0.5" end - gem 'coveralls', :require => false - gem 'rspec', '>= 2.11' - gem 'simplecov', :require => false + gem "coveralls", require: false + gem "rspec", ">= 2.11" + gem "simplecov", require: false - gem 'activerecord', "~> 4.2.0" + gem "activerecord", "~> 4.2.0" end -gemspec :path => "../../" +gemspec path: "../../" diff --git a/gemfiles/mysql2/5-0.gemfile b/gemfiles/mysql2/5-0.gemfile index 6026756a..4c7d7d7d 100644 --- a/gemfiles/mysql2/5-0.gemfile +++ b/gemfiles/mysql2/5-0.gemfile @@ -1,21 +1,21 @@ -source 'https://rubygems.org' +source "https://rubygems.org" -gem 'rake' +gem "rake" group :test do platforms :jruby do - gem 'activerecord-jdbcmysql-adapter', git: 'https://github.com/jruby/activerecord-jdbc-adapter', branch: 'rails-5' + gem "activerecord-jdbcmysql-adapter" end platforms :ruby, :mswin, :mingw do - gem 'mysql2' + gem "mysql2" end - gem 'coveralls', :require => false - gem 'rspec', '>= 2.11' - gem 'simplecov', :require => false + gem "coveralls", require: false + gem "rspec", ">= 2.11" + gem "simplecov", require: false - gem 'activerecord', "~> 5.0.0" + gem "activerecord", "~> 5.0.0" end -gemspec :path => "../../" +gemspec path: "../../" diff --git a/gemfiles/mysql2/5-1.gemfile b/gemfiles/mysql2/5-1.gemfile index bdec7686..249d3d2e 100644 --- a/gemfiles/mysql2/5-1.gemfile +++ b/gemfiles/mysql2/5-1.gemfile @@ -1,21 +1,21 @@ -source 'https://rubygems.org' +source "https://rubygems.org" -gem 'rake' +gem "rake" group :test do platforms :jruby do - gem 'activerecord-jdbcmysql-adapter', git: 'https://github.com/jruby/activerecord-jdbc-adapter', branch: 'rails-5' + gem "activerecord-jdbcmysql-adapter" end platforms :ruby, :mswin, :mingw do - gem 'mysql2' + gem "mysql2" end - gem 'coveralls', :require => false - gem 'rspec', '>= 2.11' - gem 'simplecov', :require => false + gem "coveralls", require: false + gem "rspec", ">= 2.11" + gem "simplecov", require: false - gem 'activerecord', "~> 5.1.0" + gem "activerecord", "~> 5.1.0" end -gemspec :path => "../../" +gemspec path: "../../" diff --git a/gemfiles/mysql2/5-2.gemfile b/gemfiles/mysql2/5-2.gemfile new file mode 100644 index 00000000..ff77e119 --- /dev/null +++ b/gemfiles/mysql2/5-2.gemfile @@ -0,0 +1,21 @@ +source "https://rubygems.org" + +gem "rake" + +group :test do + platforms :jruby do + gem "activerecord-jdbcmysql-adapter" + end + + platforms :ruby, :mswin, :mingw do + gem "mysql2" + end + + gem "coveralls", require: false + gem "rspec", ">= 2.11" + gem "simplecov", require: false + + gem "activerecord", "~> 5.2.0" +end + +gemspec path: "../../" diff --git a/gemfiles/mysql2/master.gemfile b/gemfiles/mysql2/master.gemfile index 3c25e298..65659451 100644 --- a/gemfiles/mysql2/master.gemfile +++ b/gemfiles/mysql2/master.gemfile @@ -1,21 +1,21 @@ -source 'https://rubygems.org' +source "https://rubygems.org" -gem 'rake' +gem "rake" group :test do platforms :jruby do - gem 'activerecord-jdbcmysql-adapter', git: 'https://github.com/jruby/activerecord-jdbc-adapter', branch: 'rails-5' + gem "activerecord-jdbcmysql-adapter" end platforms :ruby, :mswin, :mingw do - gem 'mysql2' + gem "mysql2" end - gem 'coveralls', :require => false - gem 'rspec', '>= 2.11' - gem 'simplecov', :require => false + gem "coveralls", require: false + gem "rspec", ">= 2.11" + gem "simplecov", require: false - gem 'activerecord', github: 'rails' + gem "activerecord", github: "rails" end -gemspec :path => '../../' +gemspec path: "../../" diff --git a/gemfiles/postgresql/3-0.gemfile b/gemfiles/postgresql/3-0.gemfile index 58a1c112..b46ce039 100644 --- a/gemfiles/postgresql/3-0.gemfile +++ b/gemfiles/postgresql/3-0.gemfile @@ -1,21 +1,15 @@ -source 'https://rubygems.org' +source "https://rubygems.org" -gem 'rake' +gem "rake" group :test do - platforms :jruby do - gem 'activerecord-jdbcpostgresql-adapter' - end + gem "pg", "~> 0.18" - platforms :ruby, :mswin, :mingw do - gem 'pg' - end + gem "coveralls", require: false + gem "rspec", ">= 2.11" + gem "simplecov", require: false - gem 'coveralls', :require => false - gem 'rspec', '>= 2.11' - gem 'simplecov', :require => false - - gem 'activerecord', "~> 3.0.0" + gem "activerecord", "~> 3.0.0" end -gemspec :path => "../../" +gemspec path: "../../" diff --git a/gemfiles/postgresql/3-1.gemfile b/gemfiles/postgresql/3-1.gemfile index 70f55e0c..4fb54b95 100644 --- a/gemfiles/postgresql/3-1.gemfile +++ b/gemfiles/postgresql/3-1.gemfile @@ -1,21 +1,15 @@ -source 'https://rubygems.org' +source "https://rubygems.org" -gem 'rake' +gem "rake" group :test do - platforms :jruby do - gem 'activerecord-jdbcpostgresql-adapter' - end + gem "pg", "~> 0.18" - platforms :ruby, :mswin, :mingw do - gem 'pg' - end + gem "coveralls", require: false + gem "rspec", ">= 2.11" + gem "simplecov", require: false - gem 'coveralls', :require => false - gem 'rspec', '>= 2.11' - gem 'simplecov', :require => false - - gem 'activerecord', "~> 3.1.0" + gem "activerecord", "~> 3.1.0" end -gemspec :path => "../../" +gemspec path: "../../" diff --git a/gemfiles/postgresql/3-2.gemfile b/gemfiles/postgresql/3-2.gemfile index ec77b087..e6ce602e 100644 --- a/gemfiles/postgresql/3-2.gemfile +++ b/gemfiles/postgresql/3-2.gemfile @@ -1,21 +1,15 @@ -source 'https://rubygems.org' +source "https://rubygems.org" -gem 'rake' +gem "rake" group :test do - platforms :jruby do - gem 'activerecord-jdbcpostgresql-adapter' - end + gem "pg", "~> 0.18" - platforms :ruby, :mswin, :mingw do - gem 'pg' - end + gem "coveralls", require: false + gem "rspec", ">= 2.11" + gem "simplecov", require: false - gem 'coveralls', :require => false - gem 'rspec', '>= 2.11' - gem 'simplecov', :require => false - - gem 'activerecord', "~> 3.2.0" + gem "activerecord", "~> 3.2.0" end -gemspec :path => "../../" +gemspec path: "../../" diff --git a/gemfiles/postgresql/4-0.gemfile b/gemfiles/postgresql/4-0.gemfile index c192aed2..31fba425 100644 --- a/gemfiles/postgresql/4-0.gemfile +++ b/gemfiles/postgresql/4-0.gemfile @@ -1,21 +1,15 @@ -source 'https://rubygems.org' +source "https://rubygems.org" -gem 'rake' +gem "rake" group :test do - platforms :jruby do - gem 'activerecord-jdbcpostgresql-adapter' - end + gem "pg", "~> 0.18" - platforms :ruby, :mswin, :mingw do - gem 'pg' - end + gem "coveralls", require: false + gem "rspec", ">= 2.11" + gem "simplecov", require: false - gem 'coveralls', :require => false - gem 'rspec', '>= 2.11' - gem 'simplecov', :require => false - - gem 'activerecord', "~> 4.0.0" + gem "activerecord", "~> 4.0.0" end -gemspec :path => "../../" +gemspec path: "../../" diff --git a/gemfiles/postgresql/4-1.gemfile b/gemfiles/postgresql/4-1.gemfile index af265cd6..278501c1 100644 --- a/gemfiles/postgresql/4-1.gemfile +++ b/gemfiles/postgresql/4-1.gemfile @@ -1,21 +1,15 @@ -source 'https://rubygems.org' +source "https://rubygems.org" -gem 'rake' +gem "rake" group :test do - platforms :jruby do - gem 'activerecord-jdbcpostgresql-adapter' - end + gem "pg", "~> 0.18" - platforms :ruby, :mswin, :mingw do - gem 'pg' - end + gem "coveralls", require: false + gem "rspec", ">= 2.11" + gem "simplecov", require: false - gem 'coveralls', :require => false - gem 'rspec', '>= 2.11' - gem 'simplecov', :require => false - - gem 'activerecord', "~> 4.1.0" + gem "activerecord", "~> 4.1.0" end -gemspec :path => "../../" +gemspec path: "../../" diff --git a/gemfiles/postgresql/4-2.gemfile b/gemfiles/postgresql/4-2.gemfile index eb042e60..047833e4 100644 --- a/gemfiles/postgresql/4-2.gemfile +++ b/gemfiles/postgresql/4-2.gemfile @@ -1,21 +1,21 @@ -source 'https://rubygems.org' +source "https://rubygems.org" -gem 'rake' +gem "rake" group :test do platforms :jruby do - gem 'activerecord-jdbcpostgresql-adapter' + gem "activerecord-jdbcpostgresql-adapter", "< 50.0" end platforms :ruby, :mswin, :mingw do - gem 'pg' + gem "pg", "~> 0.18" end - gem 'coveralls', :require => false - gem 'rspec', '>= 2.11' - gem 'simplecov', :require => false + gem "coveralls", require: false + gem "rspec", ">= 2.11" + gem "simplecov", require: false - gem 'activerecord', "~> 4.2.0" + gem "activerecord", "~> 4.2.0" end -gemspec :path => "../../" +gemspec path: "../../" diff --git a/gemfiles/postgresql/5-0.gemfile b/gemfiles/postgresql/5-0.gemfile index ac3732f9..3c71ef69 100644 --- a/gemfiles/postgresql/5-0.gemfile +++ b/gemfiles/postgresql/5-0.gemfile @@ -1,21 +1,21 @@ -source 'https://rubygems.org' +source "https://rubygems.org" -gem 'rake' +gem "rake" group :test do platforms :jruby do - gem 'activerecord-jdbcpostgresql-adapter', git: 'https://github.com/jruby/activerecord-jdbc-adapter', branch: 'rails-5' + gem "activerecord-jdbcpostgresql-adapter" end platforms :ruby, :mswin, :mingw do - gem 'pg' + gem "pg", "~> 0.18" end - gem 'coveralls', :require => false - gem 'rspec', '>= 2.11' - gem 'simplecov', :require => false + gem "coveralls", require: false + gem "rspec", ">= 2.11" + gem "simplecov", require: false - gem 'activerecord', "~> 5.0.0" + gem "activerecord", "~> 5.0.0" end -gemspec :path => "../../" +gemspec path: "../../" diff --git a/gemfiles/postgresql/5-1.gemfile b/gemfiles/postgresql/5-1.gemfile index 6b80728e..34e0c203 100644 --- a/gemfiles/postgresql/5-1.gemfile +++ b/gemfiles/postgresql/5-1.gemfile @@ -1,21 +1,21 @@ -source 'https://rubygems.org' +source "https://rubygems.org" -gem 'rake' +gem "rake" group :test do platforms :jruby do - gem 'activerecord-jdbcpostgresql-adapter', git: 'https://github.com/jruby/activerecord-jdbc-adapter', branch: 'rails-5' + gem "activerecord-jdbcpostgresql-adapter" end platforms :ruby, :mswin, :mingw do - gem 'pg' + gem "pg", "~> 0.18" end - gem 'coveralls', :require => false - gem 'rspec', '>= 2.11' - gem 'simplecov', :require => false + gem "coveralls", require: false + gem "rspec", ">= 2.11" + gem "simplecov", require: false - gem 'activerecord', "~> 5.1.0" + gem "activerecord", "~> 5.1.0" end -gemspec :path => "../../" +gemspec path: "../../" diff --git a/gemfiles/postgresql/5-2.gemfile b/gemfiles/postgresql/5-2.gemfile new file mode 100644 index 00000000..e95902c7 --- /dev/null +++ b/gemfiles/postgresql/5-2.gemfile @@ -0,0 +1,21 @@ +source "https://rubygems.org" + +gem "rake" + +group :test do + platforms :jruby do + gem "activerecord-jdbcpostgresql-adapter" + end + + platforms :ruby, :mswin, :mingw do + gem "pg", "~> 0.18" + end + + gem "coveralls", require: false + gem "rspec", ">= 2.11" + gem "simplecov", require: false + + gem "activerecord", "~> 5.2.0" +end + +gemspec path: "../../" diff --git a/gemfiles/postgresql/master.gemfile b/gemfiles/postgresql/master.gemfile index ade52b13..7ac422ba 100644 --- a/gemfiles/postgresql/master.gemfile +++ b/gemfiles/postgresql/master.gemfile @@ -1,21 +1,21 @@ -source 'https://rubygems.org' +source "https://rubygems.org" -gem 'rake' +gem "rake" group :test do platforms :jruby do - gem 'activerecord-jdbcpostgresql-adapter', git: 'https://github.com/jruby/activerecord-jdbc-adapter', branch: 'rails-5' + gem "activerecord-jdbcpostgresql-adapter" end platforms :ruby, :mswin, :mingw do - gem 'pg' + gem "pg", "~> 0.18" end - gem 'coveralls', :require => false - gem 'rspec', '>= 2.11' - gem 'simplecov', :require => false + gem "coveralls", require: false + gem "rspec", ">= 2.11" + gem "simplecov", require: false - gem 'activerecord', github: 'rails' + gem "activerecord", github: "rails" end -gemspec :path => "../../" +gemspec path: "../../" diff --git a/gemfiles/sqlite3/3-0.gemfile b/gemfiles/sqlite3/3-0.gemfile index 4b36e699..71b10b4e 100644 --- a/gemfiles/sqlite3/3-0.gemfile +++ b/gemfiles/sqlite3/3-0.gemfile @@ -1,21 +1,15 @@ -source 'https://rubygems.org' +source "https://rubygems.org" -gem 'rake' +gem "rake" group :test do - platforms :jruby do - gem 'activerecord-jdbcsqlite3-adapter' - end + gem "sqlite3" - platforms :ruby, :mswin, :mingw do - gem 'sqlite3' - end + gem "coveralls", require: false + gem "rspec", ">= 2.11" + gem "simplecov", require: false - gem 'coveralls', :require => false - gem 'rspec', '>= 2.11' - gem 'simplecov', :require => false - - gem 'activerecord', "~> 3.0.0" + gem "activerecord", "~> 3.0.0" end -gemspec :path => "../../" +gemspec path: "../../" diff --git a/gemfiles/sqlite3/3-1.gemfile b/gemfiles/sqlite3/3-1.gemfile index c27298ec..0099efad 100644 --- a/gemfiles/sqlite3/3-1.gemfile +++ b/gemfiles/sqlite3/3-1.gemfile @@ -1,21 +1,15 @@ -source 'https://rubygems.org' +source "https://rubygems.org" -gem 'rake' +gem "rake" group :test do - platforms :jruby do - gem 'activerecord-jdbcsqlite3-adapter' - end + gem "sqlite3" - platforms :ruby, :mswin, :mingw do - gem 'sqlite3' - end + gem "coveralls", require: false + gem "rspec", ">= 2.11" + gem "simplecov", require: false - gem 'coveralls', :require => false - gem 'rspec', '>= 2.11' - gem 'simplecov', :require => false - - gem 'activerecord', "~> 3.1.0" + gem "activerecord", "~> 3.1.0" end -gemspec :path => "../../" +gemspec path: "../../" diff --git a/gemfiles/sqlite3/3-2.gemfile b/gemfiles/sqlite3/3-2.gemfile index 974eba26..bb3394ea 100644 --- a/gemfiles/sqlite3/3-2.gemfile +++ b/gemfiles/sqlite3/3-2.gemfile @@ -1,21 +1,15 @@ -source 'https://rubygems.org' +source "https://rubygems.org" -gem 'rake' +gem "rake" group :test do - platforms :jruby do - gem 'activerecord-jdbcsqlite3-adapter' - end + gem "sqlite3" - platforms :ruby, :mswin, :mingw do - gem 'sqlite3' - end + gem "coveralls", require: false + gem "rspec", ">= 2.11" + gem "simplecov", require: false - gem 'coveralls', :require => false - gem 'rspec', '>= 2.11' - gem 'simplecov', :require => false - - gem 'activerecord', "~> 3.2.0" + gem "activerecord", "~> 3.2.0" end -gemspec :path => "../../" +gemspec path: "../../" diff --git a/gemfiles/sqlite3/4-0.gemfile b/gemfiles/sqlite3/4-0.gemfile index 15109853..ba3e3327 100644 --- a/gemfiles/sqlite3/4-0.gemfile +++ b/gemfiles/sqlite3/4-0.gemfile @@ -1,21 +1,15 @@ -source 'https://rubygems.org' +source "https://rubygems.org" -gem 'rake' +gem "rake" group :test do - platforms :jruby do - gem 'activerecord-jdbcsqlite3-adapter' - end + gem "sqlite3" - platforms :ruby, :mswin, :mingw do - gem 'sqlite3' - end + gem "coveralls", require: false + gem "rspec", ">= 2.11" + gem "simplecov", require: false - gem 'coveralls', :require => false - gem 'rspec', '>= 2.11' - gem 'simplecov', :require => false - - gem 'activerecord', "~> 4.0.0" + gem "activerecord", "~> 4.0.0" end -gemspec :path => "../../" +gemspec path: "../../" diff --git a/gemfiles/sqlite3/4-1.gemfile b/gemfiles/sqlite3/4-1.gemfile index 37cb391c..94a01013 100644 --- a/gemfiles/sqlite3/4-1.gemfile +++ b/gemfiles/sqlite3/4-1.gemfile @@ -1,21 +1,15 @@ -source 'https://rubygems.org' +source "https://rubygems.org" -gem 'rake' +gem "rake" group :test do - platforms :jruby do - gem 'activerecord-jdbcsqlite3-adapter' - end + gem "sqlite3" - platforms :ruby, :mswin, :mingw do - gem 'sqlite3' - end + gem "coveralls", require: false + gem "rspec", ">= 2.11" + gem "simplecov", require: false - gem 'coveralls', :require => false - gem 'rspec', '>= 2.11' - gem 'simplecov', :require => false - - gem 'activerecord', "~> 4.1.0" + gem "activerecord", "~> 4.1.0" end -gemspec :path => "../../" +gemspec path: "../../" diff --git a/gemfiles/sqlite3/4-2.gemfile b/gemfiles/sqlite3/4-2.gemfile index 2de1fe6a..a2ae2f44 100644 --- a/gemfiles/sqlite3/4-2.gemfile +++ b/gemfiles/sqlite3/4-2.gemfile @@ -1,21 +1,21 @@ -source 'https://rubygems.org' +source "https://rubygems.org" -gem 'rake' +gem "rake" group :test do platforms :jruby do - gem 'activerecord-jdbcsqlite3-adapter' + gem "activerecord-jdbcsqlite3-adapter", "< 50.0" end platforms :ruby, :mswin, :mingw do - gem 'sqlite3' + gem "sqlite3" end - gem 'coveralls', :require => false - gem 'rspec', '>= 2.11' - gem 'simplecov', :require => false + gem "coveralls", require: false + gem "rspec", ">= 2.11" + gem "simplecov", require: false - gem 'activerecord', "~> 4.2.0" + gem "activerecord", "~> 4.2.0" end -gemspec :path => "../../" +gemspec path: "../../" diff --git a/gemfiles/sqlite3/5-0.gemfile b/gemfiles/sqlite3/5-0.gemfile index 4c2137ac..bc6e076c 100644 --- a/gemfiles/sqlite3/5-0.gemfile +++ b/gemfiles/sqlite3/5-0.gemfile @@ -1,21 +1,21 @@ -source 'https://rubygems.org' +source "https://rubygems.org" -gem 'rake' +gem "rake" group :test do platforms :jruby do - gem 'activerecord-jdbcsqlite3-adapter', git: 'https://github.com/jruby/activerecord-jdbc-adapter', branch: 'rails-5' + gem "activerecord-jdbcsqlite3-adapter" end platforms :ruby, :mswin, :mingw do - gem 'sqlite3' + gem "sqlite3" end - gem 'coveralls', :require => false - gem 'rspec', '>= 2.11' - gem 'simplecov', :require => false + gem "coveralls", require: false + gem "rspec", ">= 2.11" + gem "simplecov", require: false - gem 'activerecord', "~> 5.0.0" + gem "activerecord", "~> 5.0.0" end -gemspec :path => "../../" +gemspec path: "../../" diff --git a/gemfiles/sqlite3/5-1.gemfile b/gemfiles/sqlite3/5-1.gemfile index 8f51461b..4c803830 100644 --- a/gemfiles/sqlite3/5-1.gemfile +++ b/gemfiles/sqlite3/5-1.gemfile @@ -1,21 +1,21 @@ -source 'https://rubygems.org' +source "https://rubygems.org" -gem 'rake' +gem "rake" group :test do platforms :jruby do - gem 'activerecord-jdbcsqlite3-adapter', git: 'https://github.com/jruby/activerecord-jdbc-adapter', branch: 'rails-5' + gem "activerecord-jdbcsqlite3-adapter" end platforms :ruby, :mswin, :mingw do - gem 'sqlite3' + gem "sqlite3" end - gem 'coveralls', :require => false - gem 'rspec', '>= 2.11' - gem 'simplecov', :require => false + gem "coveralls", require: false + gem "rspec", ">= 2.11" + gem "simplecov", require: false - gem 'activerecord', "~> 5.1.0" + gem "activerecord", "~> 5.1.0" end -gemspec :path => "../../" +gemspec path: "../../" diff --git a/gemfiles/sqlite3/5-2.gemfile b/gemfiles/sqlite3/5-2.gemfile new file mode 100644 index 00000000..6dc5a0a0 --- /dev/null +++ b/gemfiles/sqlite3/5-2.gemfile @@ -0,0 +1,21 @@ +source "https://rubygems.org" + +gem "rake" + +group :test do + platforms :jruby do + gem "activerecord-jdbcsqlite3-adapter" + end + + platforms :ruby, :mswin, :mingw do + gem "sqlite3" + end + + gem "coveralls", require: false + gem "rspec", ">= 2.11" + gem "simplecov", require: false + + gem "activerecord", "~> 5.2.0" +end + +gemspec path: "../../" diff --git a/gemfiles/sqlite3/master.gemfile b/gemfiles/sqlite3/master.gemfile index 868fe561..afd2bf9a 100644 --- a/gemfiles/sqlite3/master.gemfile +++ b/gemfiles/sqlite3/master.gemfile @@ -1,21 +1,21 @@ -source 'https://rubygems.org' +source "https://rubygems.org" -gem 'rake' +gem "rake" group :test do platforms :jruby do - gem 'activerecord-jdbcsqlite3-adapter', git: 'https://github.com/jruby/activerecord-jdbc-adapter', branch: 'rails-5' + gem "activerecord-jdbcsqlite3-adapter" end platforms :ruby, :mswin, :mingw do - gem 'sqlite3' + gem "sqlite3" end - gem 'coveralls', :require => false - gem 'rspec', '>= 2.11' - gem 'simplecov', :require => false + gem "coveralls", require: false + gem "rspec", ">= 2.11" + gem "simplecov", require: false - gem 'activerecord', github: 'rails' + gem "activerecord", github: "rails" end -gemspec :path => "../../" +gemspec path: "../../" diff --git a/lib/delayed/backend/active_record.rb b/lib/delayed/backend/active_record.rb index 5de99696..b69fd050 100644 --- a/lib/delayed/backend/active_record.rb +++ b/lib/delayed/backend/active_record.rb @@ -10,7 +10,9 @@ def initialize end def reserve_sql_strategy=(val) - raise ArgumentError, "allowed values are :optimized_sql or :default_sql" unless val == :optimized_sql || val == :default_sql + if !(val == :optimized_sql || val == :default_sql) + raise ArgumentError, "allowed values are :optimized_sql or :default_sql" + end @reserve_sql_strategy = val end end @@ -34,6 +36,9 @@ class Job < ::ActiveRecord::Base end scope :by_priority, lambda { order("priority ASC, run_at ASC") } + scope :min_priority, lambda { where("priority >= ?", Worker.min_priority) if Worker.min_priority } + scope :max_priority, lambda { where("priority <= ?", Worker.max_priority) if Worker.max_priority } + scope :for_queues, lambda { |queues = Worker.queues| where(queue: queues) if Array(queues).any? } before_save :set_default_run_at @@ -45,7 +50,12 @@ def self.set_delayed_job_table_name set_delayed_job_table_name def self.ready_to_run(worker_name, max_run_time) - where("(run_at <= ? AND (locked_at IS NULL OR locked_at < ?) OR locked_by = ?) AND failed_at IS NULL", db_time_now, db_time_now - max_run_time, worker_name) + where( + "(run_at <= ? AND (locked_at IS NULL OR locked_at < ?) OR locked_by = ?) AND failed_at IS NULL", + db_time_now, + db_time_now - max_run_time, + worker_name + ) end def self.before_fork @@ -61,15 +71,13 @@ def self.clear_locks!(worker_name) where(locked_by: worker_name).update_all(locked_by: nil, locked_at: nil) end - def self.reserve(worker, max_run_time = Worker.max_run_time) # rubocop:disable CyclomaticComplexity - # scope to filter to records that are "ready to run" - ready_scope = ready_to_run(worker.name, max_run_time) - - # scope to filter to the single next eligible job - ready_scope = ready_scope.where("priority >= ?", Worker.min_priority) if Worker.min_priority - ready_scope = ready_scope.where("priority <= ?", Worker.max_priority) if Worker.max_priority - ready_scope = ready_scope.where(queue: Worker.queues) if Worker.queues.any? - ready_scope = ready_scope.by_priority + def self.reserve(worker, max_run_time = Worker.max_run_time) + ready_scope = + ready_to_run(worker.name, max_run_time) + .min_priority + .max_priority + .for_queues + .by_priority reserve_with_scope(ready_scope, worker, db_time_now) end @@ -88,41 +96,12 @@ def self.reserve_with_scope(ready_scope, worker, now) def self.reserve_with_scope_using_optimized_sql(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 - 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 "PostgreSQL", "PostGIS" + reserve_with_scope_using_optimized_postgres(ready_scope, worker, now) 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 - 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 + reserve_with_scope_using_optimized_mysql(ready_scope, worker, now) when "MSSQL", "Teradata" - # 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" - quoted_table_name = connection.quote_table_name(table_name) - sql = ["UPDATE #{quoted_table_name} SET locked_at = ?, locked_by = ? WHERE id IN (#{subquery_sql})", now, worker.name] - count = connection.execute(sanitize_sql(sql)) - return nil if count == 0 - # MSSQL JDBC doesn't support OUTPUT INSERTED.* for returning a result set, so query locked row - where(locked_at: now, locked_by: worker.name, failed_at: nil).first + reserve_with_scope_using_optimized_mssql(ready_scope, worker, now) # Fallback for unknown / other DBMS else reserve_with_scope_using_default_sql(ready_scope, worker, now) @@ -137,6 +116,48 @@ def self.reserve_with_scope_using_default_sql(ready_scope, worker, now) end end + def self.reserve_with_scope_using_optimized_postgres(ready_scope, worker, now) + # 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 + quoted_name = connection.quote_table_name(table_name) + subquery = ready_scope.limit(1).lock(true).select("id").to_sql + sql = "UPDATE #{quoted_name} SET locked_at = ?, locked_by = ? WHERE id IN (#{subquery}) RETURNING *" + reserved = find_by_sql([sql, now, worker.name]) + reserved[0] + end + + def self.reserve_with_scope_using_optimized_mysql(ready_scope, worker, now) + # 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 + end + + def self.reserve_with_scope_using_optimized_mssql(ready_scope, worker, now) + # 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" + quoted_table_name = connection.quote_table_name(table_name) + sql = "UPDATE #{quoted_table_name} SET locked_at = ?, locked_by = ? WHERE id IN (#{subquery_sql})" + count = connection.execute(sanitize_sql([sql, now, worker.name])) + return nil if count == 0 + # MSSQL JDBC doesn't support OUTPUT INSERTED.* for returning a result set, so query locked row + where(locked_at: now, locked_by: worker.name, failed_at: nil).first + end + # Get the current time (GMT or local depending on DB) # Note: This does not ping the DB to get the time, so all your clients # must have syncronized clocks. @@ -146,7 +167,7 @@ def self.db_time_now elsif ::ActiveRecord::Base.default_timezone == :utc Time.now.utc else - Time.now + Time.now # rubocop:disable Rails/TimeZone end end diff --git a/lib/generators/delayed_job/active_record_generator.rb b/lib/generators/delayed_job/active_record_generator.rb index ea4057ed..3370f06b 100644 --- a/lib/generators/delayed_job/active_record_generator.rb +++ b/lib/generators/delayed_job/active_record_generator.rb @@ -22,9 +22,7 @@ def self.next_migration_number(dirname) private def migration_version - if ActiveRecord::VERSION::MAJOR >= 5 - "[#{ActiveRecord::VERSION::MAJOR}.#{ActiveRecord::VERSION::MINOR}]" - end + "[#{ActiveRecord::VERSION::MAJOR}.#{ActiveRecord::VERSION::MINOR}]" if ActiveRecord::VERSION::MAJOR >= 5 end end end diff --git a/lib/generators/delayed_job/upgrade_generator.rb b/lib/generators/delayed_job/upgrade_generator.rb index c4425f16..2383f5ac 100644 --- a/lib/generators/delayed_job/upgrade_generator.rb +++ b/lib/generators/delayed_job/upgrade_generator.rb @@ -7,7 +7,11 @@ module DelayedJob class UpgradeGenerator < ActiveRecordGenerator def create_migration_file - migration_template "upgrade_migration.rb", "db/migrate/add_queue_to_delayed_jobs.rb", migration_version: migration_version + migration_template( + "upgrade_migration.rb", + "db/migrate/add_queue_to_delayed_jobs.rb", + migration_version: migration_version + ) end end end diff --git a/spec/.rubocop.yml b/spec/.rubocop.yml new file mode 100644 index 00000000..6c897e4d --- /dev/null +++ b/spec/.rubocop.yml @@ -0,0 +1,14 @@ +inherit_from: + - ../.rubocop.yml + +Lint/AmbiguousBlockAssociation: + Enabled: false + +Metrics/BlockLength: + Enabled: false + +RSpec/ContextWording: + Enabled: false + +RSpec/FilePath: + Enabled: false \ No newline at end of file diff --git a/spec/delayed/backend/active_record_spec.rb b/spec/delayed/backend/active_record_spec.rb index ad055f37..dd7bad96 100644 --- a/spec/delayed/backend/active_record_spec.rb +++ b/spec/delayed/backend/active_record_spec.rb @@ -6,27 +6,31 @@ describe "configuration" do describe "reserve_sql_strategy" do + let(:configuration) { Delayed::Backend::ActiveRecord.configuration } + it "allows :optimized_sql" do - Delayed::Backend::ActiveRecord.configuration.reserve_sql_strategy = :optimized_sql - expect(Delayed::Backend::ActiveRecord.configuration.reserve_sql_strategy).to eq(:optimized_sql) + configuration.reserve_sql_strategy = :optimized_sql + expect(configuration.reserve_sql_strategy).to eq(:optimized_sql) end it "allows :default_sql" do - Delayed::Backend::ActiveRecord.configuration.reserve_sql_strategy = :default_sql - expect(Delayed::Backend::ActiveRecord.configuration.reserve_sql_strategy).to eq(:default_sql) + configuration.reserve_sql_strategy = :default_sql + expect(configuration.reserve_sql_strategy).to eq(:default_sql) end it "raises an argument error on invalid entry" do - expect { Delayed::Backend::ActiveRecord.configuration.reserve_sql_strategy = :invald }.to raise_error(ArgumentError) + expect { configuration.reserve_sql_strategy = :invald }.to raise_error(ArgumentError) end end end describe "reserve_with_scope" do - let(:worker) { double(name: "worker01", read_ahead: 1) } - let(:scope) { double(limit: limit, where: double(update_all: nil)) } - let(:limit) { double(job: job, update_all: nil) } - let(:job) { double(id: 1) } + let(:relation_class) { Delayed::Job.limit(1).class } + let(:worker) { instance_double(Delayed::Worker, name: "worker01", read_ahead: 1) } + let(:limit) { instance_double(relation_class, update_all: 0) } + let(:where) { instance_double(relation_class, update_all: 0) } + let(:scope) { instance_double(relation_class, limit: limit, where: where) } + let(:job) { instance_double(Delayed::Job, id: 1) } before do allow(Delayed::Backend::ActiveRecord::Job.connection).to receive(:adapter_name).at_least(:once).and_return(dbms) @@ -40,8 +44,9 @@ let(:dbms) { "MySQL" } it "uses the optimized sql version" do - expect(Delayed::Backend::ActiveRecord::Job).to_not receive(:reserve_with_scope_using_default_sql) - Delayed::Backend::ActiveRecord::Job.reserve_with_scope(scope, worker, Time.now) + allow(Delayed::Backend::ActiveRecord::Job).to receive(:reserve_with_scope_using_default_sql) + Delayed::Backend::ActiveRecord::Job.reserve_with_scope(scope, worker, Time.current) + expect(Delayed::Backend::ActiveRecord::Job).not_to have_received(:reserve_with_scope_using_default_sql) end end @@ -49,8 +54,9 @@ let(:dbms) { "OtherDB" } it "uses the plain sql version" do - expect(Delayed::Backend::ActiveRecord::Job).to receive(:reserve_with_scope_using_default_sql).once - Delayed::Backend::ActiveRecord::Job.reserve_with_scope(scope, worker, Time.now) + allow(Delayed::Backend::ActiveRecord::Job).to receive(:reserve_with_scope_using_default_sql) + Delayed::Backend::ActiveRecord::Job.reserve_with_scope(scope, worker, Time.current) + expect(Delayed::Backend::ActiveRecord::Job).to have_received(:reserve_with_scope_using_default_sql).once end end end @@ -60,8 +66,9 @@ let(:reserve_sql_strategy) { :default_sql } it "uses the plain sql version" do - expect(Delayed::Backend::ActiveRecord::Job).to receive(:reserve_with_scope_using_default_sql).once - Delayed::Backend::ActiveRecord::Job.reserve_with_scope(scope, worker, Time.now) + allow(Delayed::Backend::ActiveRecord::Job).to receive(:reserve_with_scope_using_default_sql) + Delayed::Backend::ActiveRecord::Job.reserve_with_scope(scope, worker, Time.current) + expect(Delayed::Backend::ActiveRecord::Job).to have_received(:reserve_with_scope_using_default_sql).once end end end @@ -73,8 +80,8 @@ end it "returns time in current time zone if set" do - Time.zone = "Eastern Time (US & Canada)" - expect(%(EST EDT)).to include(Delayed::Job.db_time_now.zone) + Time.zone = "Arizona" + expect(Delayed::Job.db_time_now.zone).to eq("MST") end it "returns UTC time if that is the AR default" do @@ -84,16 +91,17 @@ end it "returns local time if that is the AR default" do - Time.zone = "Central Time (US & Canada)" + Time.zone = "Arizona" ActiveRecord::Base.default_timezone = :local - expect(%w(CST CDT)).to include(Delayed::Backend::ActiveRecord::Job.db_time_now.zone) + expect(Delayed::Backend::ActiveRecord::Job.db_time_now.zone).to eq("MST") end end describe "after_fork" do it "calls reconnect on the connection" do - expect(ActiveRecord::Base).to receive(:establish_connection) + allow(ActiveRecord::Base).to receive(:establish_connection) Delayed::Backend::ActiveRecord::Job.after_fork + expect(ActiveRecord::Base).to have_received(:establish_connection) end end @@ -112,12 +120,15 @@ end after do - Delayed::Backend::ActiveRecord::Job.send(:attr_accessible, *Delayed::Backend::ActiveRecord::Job.new.attributes.keys) + Delayed::Backend::ActiveRecord::Job.send( + :attr_accessible, + *Delayed::Backend::ActiveRecord::Job.new.attributes.keys + ) end it "is still accessible" do job = Delayed::Backend::ActiveRecord::Job.enqueue payload_object: EnqueueJobMod.new - expect(Delayed::Backend::ActiveRecord::Job.find(job.id).handler).to_not be_blank + expect(Delayed::Backend::ActiveRecord::Job.find(job.id).handler).not_to be_blank end end end diff --git a/spec/helper.rb b/spec/helper.rb index 63484664..80f3c280 100644 --- a/spec/helper.rb +++ b/spec/helper.rb @@ -1,10 +1,12 @@ require "simplecov" require "coveralls" -SimpleCov.formatter = SimpleCov::Formatter::MultiFormatter.new([ - SimpleCov::Formatter::HTMLFormatter, - Coveralls::SimpleCov::Formatter -]) +SimpleCov.formatter = SimpleCov::Formatter::MultiFormatter.new( + [ + SimpleCov::Formatter::HTMLFormatter, + Coveralls::SimpleCov::Formatter + ] +) SimpleCov.start do add_filter "/spec/" @@ -24,7 +26,8 @@ Delayed::Worker.logger = Logger.new("/tmp/dj.log") ENV["RAILS_ENV"] = "test" -db_adapter, gemfile = ENV["ADAPTER"], ENV["BUNDLE_GEMFILE"] +db_adapter = ENV["ADAPTER"] +gemfile = ENV["BUNDLE_GEMFILE"] db_adapter ||= gemfile && gemfile[%r{gemfiles/(.*?)/}] && $1 # rubocop:disable PerlBackrefs db_adapter ||= "sqlite3" @@ -36,22 +39,21 @@ migration_template = File.open("lib/generators/delayed_job/templates/migration.rb") # need to eval the template with the migration_version intact -migration_context = Class.new do - def get_binding - binding - end +migration_context = + Class.new do + def my_binding + binding + end - private + private - def migration_version - if ActiveRecord::VERSION::MAJOR >= 5 - "[#{ActiveRecord::VERSION::MAJOR}.#{ActiveRecord::VERSION::MINOR}]" + def migration_version + "[#{ActiveRecord::VERSION::MAJOR}.#{ActiveRecord::VERSION::MINOR}]" if ActiveRecord::VERSION::MAJOR >= 5 end end -end -migration_ruby = ERB.new(migration_template.read).result(migration_context.new.get_binding) -eval(migration_ruby) +migration_ruby = ERB.new(migration_template.read).result(migration_context.new.my_binding) +eval(migration_ruby) # rubocop:disable Security/Eval ActiveRecord::Schema.define do CreateDelayedJobs.up @@ -73,8 +75,8 @@ def tell text end - def whatever(n, _) - tell * n + def whatever(number) + tell * number end default_scope { where(scoped: true) }