activejob-uniqueness 0.1.2 → 0.1.3

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: ff1cfb19bc51b7eb8f4040f700650c51a47376e1ec96c84ae72b764227911f0c
4
- data.tar.gz: 3813cf68d80e7d56d828e15f179c677e49fe2f171780e25c0a6990b7b93eed76
3
+ metadata.gz: 881d2ffd39454784d884cc4049639e2e4455d854deec87217c55a95c4f4a5869
4
+ data.tar.gz: 469900d8be29af691e4efa9d883ba3d037dbbd06ac9ca7a6cf38b8cd0b2fb17d
5
5
  SHA512:
6
- metadata.gz: b616c4460d8bffe1be31226c3d18d9d3a7197fd714d680ddd636b154934ff648fb5dface28b0099b59ac865a91a5a0cec85a8230ba8d442bda6f831535405b94
7
- data.tar.gz: 938eb49268486827b8b946934838af755f7f449fc75e84f2cde8538e49af7e786edc13583a715ad86b2203a58867e324e8e580cc611d522e512ae7ed235ddae1
6
+ metadata.gz: c9907d17c12ff54e319d75253c7190a97b8114f7492e728d98b19ea94a14219722365f35e98422a3b2cd474d6aa14cb8c45bd5b7facfc68febdb541e14110c3a
7
+ data.tar.gz: a4f99ea028e1290f7742d67025b04069c0bec2912bdf4b455f0e422b91c411e8adb6e0ad2193c3b7a0067f2921cdb3b7fe7bf2ff3f251258e87b931956f96112
@@ -1,14 +1,31 @@
1
- ## Changes Between 0.1.1 and 0.1.2
1
+ # Changelog
2
+ All notable changes to this project will be documented in this file.
2
3
 
3
- Release lock for Sidekiq adapter when all Sidekiq attempts were unsuccessful or job is deleted manually from Sidekiq::Web
4
- [PR](https://github.com/veeqo/activejob-uniqueness/pull/5) by @vbyno
4
+ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/).
5
5
 
6
- ## Changes Between 0.1.0 and 0.1.1
6
+ ## [Unreleased](https://github.com/veeqo/activejob-uniqueness/compare/v0.1.3...HEAD)
7
7
 
8
- Fixed NoMethodError on `Rails.application.eager_load!` in Rails initializer
9
- ```
10
- NoMethodError: undefined method `unique' for MyJob:Class
11
- ```
12
- [PR](https://github.com/veeqo/activejob-uniqueness/pull/4)
8
+ ## [0.1.3](https://github.com/veeqo/activejob-uniqueness/compare/v0.1.2...v0.1.3) - 2020-08-17
13
9
 
14
- ## Original Release: 0.1.0
10
+ ### Fixed
11
+ - [#7](https://github.com/veeqo/activejob-uniqueness/pull/7) Fix deprecation warnings for ruby 2.7 by [@tonobo](https://github.com/tonobo)
12
+
13
+ ### Changed
14
+ - [#8](https://github.com/veeqo/activejob-uniqueness/pull/8) Use appraisal gem to control gem versions of tests matrix
15
+ - [#9](https://github.com/veeqo/activejob-uniqueness/pull/9) Refactor of Sidekiq API patch. Fixes [#6](https://github.com/veeqo/activejob-uniqueness/issues/6) Rails boot error for version 0.1.2
16
+ - [#10](https://github.com/veeqo/activejob-uniqueness/pull/10) Refactor changelog to comply with Keep a Changelog
17
+
18
+ ## [0.1.2](https://github.com/veeqo/activejob-uniqueness/compare/v0.1.1...v0.1.2) - 2020-07-30
19
+
20
+ ### Added
21
+ - [#5](https://github.com/veeqo/activejob-uniqueness/pull/5) Release lock for Sidekiq adapter by [@vbyno](https://github.com/vbyno)
22
+
23
+ ## [0.1.1](https://github.com/veeqo/activejob-uniqueness/compare/v0.1.0...v0.1.1) - 2020-07-23
24
+
25
+ ### Fixed
26
+ - [#4](https://github.com/veeqo/activejob-uniqueness/pull/4) Fix `NoMethodError` on `Rails.application.eager_load!` in Rails initializer
27
+
28
+ ## [0.1.0](https://github.com/veeqo/activejob-uniqueness/releases/tag/v0.1.0) - 2020-07-05
29
+
30
+ ### Added
31
+ - Job uniqueness for ActiveJob
data/README.md CHANGED
@@ -93,6 +93,30 @@ And then writes to `ActiveJob::Base.logger`.
93
93
 
94
94
  ### ActiveJob prior to version `6.1` will always log `Enqueued MyJob (Job ID) ...` even if the callback chain was halted. [Details](https://github.com/rails/rails/pull/37830)
95
95
 
96
+ ## Testing
97
+
98
+ Run redis server (in separate console):
99
+ ```
100
+ docker run --rm -p 6379:6379 redis
101
+ ```
102
+
103
+ Run tests with:
104
+
105
+ ```sh
106
+ bundle
107
+ rake
108
+ ```
109
+
110
+ Use [wwtd](https://github.com/grosser/wwtd) to run test matrix:
111
+ ```sh
112
+ gem install wwtd
113
+ wwtd
114
+ ```
115
+
116
+ ## Sidekiq adapter support
117
+
118
+ ActiveJob::Uniqueness patches Sidekiq API to unset locks on jobs cleanup. Starting Sidekiq 5.1 job death also triggers locks cleanup.
119
+
96
120
  ## Contributing
97
121
 
98
122
  Bug reports and pull requests are welcome on GitHub at https://github.com/veeqo/activejob-uniqueness.
@@ -7,7 +7,15 @@ require 'openssl'
7
7
  require 'active_job/uniqueness/version'
8
8
  require 'active_job/uniqueness/errors'
9
9
  require 'active_job/uniqueness/log_subscriber'
10
- require 'active_job/uniqueness/patch'
10
+ require 'active_job/uniqueness/active_job_patch'
11
+
12
+ begin
13
+ require 'sidekiq/api'
14
+ rescue LoadError
15
+ # ¯\_(ツ)_/¯
16
+ else
17
+ require 'active_job/uniqueness/sidekiq_patch'
18
+ end
11
19
 
12
20
  module ActiveJob
13
21
  module Uniqueness
@@ -16,7 +16,7 @@ module ActiveJob
16
16
  # end
17
17
  # end
18
18
  #
19
- module Patch
19
+ module ActiveJobPatch
20
20
  extend ActiveSupport::Concern
21
21
 
22
22
  class_methods do
@@ -55,7 +55,7 @@ module ActiveJob
55
55
  end
56
56
 
57
57
  def lock_strategy
58
- @lock_strategy ||= lock_strategy_class.new(lock_options.merge(lock_key: lock_key, job: self))
58
+ @lock_strategy ||= lock_strategy_class.new(**lock_options.merge(lock_key: lock_key, job: self))
59
59
  end
60
60
 
61
61
  # Override in your job class if you want to customize arguments set for a digest.
@@ -73,12 +73,7 @@ module ActiveJob
73
73
  end
74
74
 
75
75
  ActiveSupport.on_load(:active_job) do
76
- ActiveJob::Base.include ActiveJob::Uniqueness::Patch
77
-
78
- if ::ActiveJob.const_defined?(:Railtie) &&
79
- ActiveJob::Railtie.config.active_job.queue_adapter.to_sym == :sidekiq
80
- require_relative 'patch/sidekiq'
81
- end
76
+ ActiveJob::Base.include ActiveJob::Uniqueness::ActiveJobPatch
82
77
  end
83
78
  end
84
79
  end
@@ -0,0 +1,84 @@
1
+ # frozen_string_literal: true
2
+
3
+ module ActiveJob
4
+ module Uniqueness
5
+ def self.unlock_sidekiq_job!(job_data)
6
+ return unless job_data['class'] == 'ActiveJob::QueueAdapters::SidekiqAdapter::JobWrapper' # non ActiveJob jobs
7
+
8
+ job = ActiveJob::Base.deserialize(job_data.fetch('args').first)
9
+
10
+ return unless job.class.lock_strategy_class
11
+
12
+ begin
13
+ job.send(:deserialize_arguments_if_needed)
14
+ rescue ActiveJob::DeserializationError
15
+ # Most probably, GlobalID fails to locate AR record (record is deleted)
16
+ else
17
+ ActiveJob::Uniqueness.unlock!(job_class_name: job.class.name, arguments: job.arguments)
18
+ end
19
+ end
20
+
21
+ module SidekiqPatch
22
+ module SortedEntry
23
+ def delete
24
+ ActiveJob::Uniqueness.unlock_sidekiq_job!(item) if super
25
+ item
26
+ end
27
+
28
+ private
29
+
30
+ def remove_job
31
+ super do |message|
32
+ ActiveJob::Uniqueness.unlock_sidekiq_job!(Sidekiq.load_json(message))
33
+ yield message
34
+ end
35
+ end
36
+ end
37
+
38
+ module ScheduledSet
39
+ def delete(score, job_id)
40
+ entry = find_job(job_id)
41
+ ActiveJob::Uniqueness.unlock_sidekiq_job!(entry.item) if super(score, job_id)
42
+ entry
43
+ end
44
+ end
45
+
46
+ module Job
47
+ def delete
48
+ ActiveJob::Uniqueness.unlock_sidekiq_job!(item)
49
+ super
50
+ end
51
+ end
52
+
53
+ module Queue
54
+ def clear
55
+ each(&:delete)
56
+ super
57
+ end
58
+ end
59
+
60
+ module JobSet
61
+ def clear
62
+ each(&:delete)
63
+ super
64
+ end
65
+
66
+ def delete_by_value(name, value)
67
+ ActiveJob::Uniqueness.unlock_sidekiq_job!(Sidekiq.load_json(value)) if super(name, value)
68
+ end
69
+ end
70
+ end
71
+ end
72
+ end
73
+
74
+ Sidekiq::SortedEntry.prepend ActiveJob::Uniqueness::SidekiqPatch::SortedEntry
75
+ Sidekiq::ScheduledSet.prepend ActiveJob::Uniqueness::SidekiqPatch::ScheduledSet
76
+ Sidekiq::Job.prepend ActiveJob::Uniqueness::SidekiqPatch::Job
77
+ Sidekiq::Queue.prepend ActiveJob::Uniqueness::SidekiqPatch::Queue
78
+ Sidekiq::JobSet.prepend ActiveJob::Uniqueness::SidekiqPatch::JobSet
79
+
80
+ # Global death handlers are introduced in Sidekiq 5.1
81
+ # https://github.com/mperham/sidekiq/blob/e7acb124fbeb0bece0a7c3d657c39a9cc18d72c6/Changes.md#510
82
+ if Gem::Version.new(Sidekiq::VERSION) >= Gem::Version.new('5.1')
83
+ Sidekiq.death_handlers << ->(job, _ex) { ActiveJob::Uniqueness.unlock_sidekiq_job!(job) }
84
+ end
@@ -2,6 +2,6 @@
2
2
 
3
3
  module ActiveJob
4
4
  module Uniqueness
5
- VERSION = '0.1.2'
5
+ VERSION = '0.1.3'
6
6
  end
7
7
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: activejob-uniqueness
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.2
4
+ version: 0.1.3
5
5
  platform: ruby
6
6
  authors:
7
7
  - Rustam Sharshenov
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2020-07-30 00:00:00.000000000 Z
11
+ date: 2020-08-17 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: activejob
@@ -17,6 +17,9 @@ dependencies:
17
17
  - - ">="
18
18
  - !ruby/object:Gem::Version
19
19
  version: '4.2'
20
+ - - "<"
21
+ - !ruby/object:Gem::Version
22
+ version: '7'
20
23
  type: :runtime
21
24
  prerelease: false
22
25
  version_requirements: !ruby/object:Gem::Requirement
@@ -24,6 +27,9 @@ dependencies:
24
27
  - - ">="
25
28
  - !ruby/object:Gem::Version
26
29
  version: '4.2'
30
+ - - "<"
31
+ - !ruby/object:Gem::Version
32
+ version: '7'
27
33
  - !ruby/object:Gem::Dependency
28
34
  name: redlock
29
35
  requirement: !ruby/object:Gem::Requirement
@@ -45,35 +51,35 @@ dependencies:
45
51
  - !ruby/object:Gem::Version
46
52
  version: '2'
47
53
  - !ruby/object:Gem::Dependency
48
- name: bundler
54
+ name: appraisal
49
55
  requirement: !ruby/object:Gem::Requirement
50
56
  requirements:
51
- - - ">="
57
+ - - "~>"
52
58
  - !ruby/object:Gem::Version
53
- version: '0'
59
+ version: 2.3.0
54
60
  type: :development
55
61
  prerelease: false
56
62
  version_requirements: !ruby/object:Gem::Requirement
57
63
  requirements:
58
- - - ">="
64
+ - - "~>"
59
65
  - !ruby/object:Gem::Version
60
- version: '0'
66
+ version: 2.3.0
61
67
  - !ruby/object:Gem::Dependency
62
- name: pry-byebug
68
+ name: bundler
63
69
  requirement: !ruby/object:Gem::Requirement
64
70
  requirements:
65
71
  - - ">="
66
72
  - !ruby/object:Gem::Version
67
- version: '0'
73
+ version: '2.0'
68
74
  type: :development
69
75
  prerelease: false
70
76
  version_requirements: !ruby/object:Gem::Requirement
71
77
  requirements:
72
78
  - - ">="
73
79
  - !ruby/object:Gem::Version
74
- version: '0'
80
+ version: '2.0'
75
81
  - !ruby/object:Gem::Dependency
76
- name: rake
82
+ name: pry-byebug
77
83
  requirement: !ruby/object:Gem::Requirement
78
84
  requirements:
79
85
  - - ">="
@@ -107,24 +113,17 @@ executables: []
107
113
  extensions: []
108
114
  extra_rdoc_files: []
109
115
  files:
110
- - ".gitignore"
111
- - ".rspec"
112
- - ".rubocop.yml"
113
- - ".travis.yml"
114
116
  - CHANGELOG.md
115
- - Gemfile
116
117
  - LICENSE.txt
117
118
  - README.md
118
- - Rakefile
119
- - activejob-uniqueness.gemspec
120
119
  - lib/active_job/uniqueness.rb
120
+ - lib/active_job/uniqueness/active_job_patch.rb
121
121
  - lib/active_job/uniqueness/configuration.rb
122
122
  - lib/active_job/uniqueness/errors.rb
123
123
  - lib/active_job/uniqueness/lock_key.rb
124
124
  - lib/active_job/uniqueness/lock_manager.rb
125
125
  - lib/active_job/uniqueness/log_subscriber.rb
126
- - lib/active_job/uniqueness/patch.rb
127
- - lib/active_job/uniqueness/patch/sidekiq.rb
126
+ - lib/active_job/uniqueness/sidekiq_patch.rb
128
127
  - lib/active_job/uniqueness/strategies.rb
129
128
  - lib/active_job/uniqueness/strategies/base.rb
130
129
  - lib/active_job/uniqueness/strategies/until_and_while_executing.rb
data/.gitignore DELETED
@@ -1,14 +0,0 @@
1
- /.bundle/
2
- /.yardoc
3
- /_yardoc/
4
- /coverage/
5
- /doc/
6
- /pkg/
7
- /spec/reports/
8
- /tmp/
9
- /Gemfile.lock
10
- /.ruby-gemset
11
- /.ruby-version
12
-
13
- # rspec failure tracking
14
- .rspec_status
data/.rspec DELETED
@@ -1,3 +0,0 @@
1
- --format documentation
2
- --color
3
- --require spec_helper
@@ -1,38 +0,0 @@
1
- AllCops:
2
- NewCops: enable
3
-
4
- Layout/LineLength:
5
- Max: 120
6
- Exclude:
7
- - spec/**/*
8
-
9
- Layout/MultilineMethodCallIndentation:
10
- Exclude:
11
- - spec/**/*
12
-
13
- Lint/AmbiguousBlockAssociation:
14
- Exclude:
15
- - spec/**/*
16
-
17
- Metrics/AbcSize:
18
- Exclude:
19
- - spec/**/*
20
-
21
- Metrics/BlockLength:
22
- Exclude:
23
- - activejob-uniqueness.gemspec
24
- - spec/**/*
25
-
26
- Metrics/MethodLength:
27
- Exclude:
28
- - spec/**/*
29
-
30
- Style/ClassAndModuleChildren:
31
- Exclude:
32
- - spec/**/*
33
-
34
- Style/Documentation:
35
- Enabled: false
36
-
37
- Style/RescueModifier:
38
- Enabled: false
@@ -1,22 +0,0 @@
1
- ---
2
- dist: xenial
3
- language: ruby
4
- services:
5
- - redis-server
6
- cache: bundler
7
- rvm:
8
- - 2.5.8
9
- - 2.6.6
10
- - 2.7.1
11
- env:
12
- - ACTIVEJOB_VERSION="~> 4.2.11"
13
- - ACTIVEJOB_VERSION="~> 5.2.4"
14
- - ACTIVEJOB_VERSION="~> 6.0.3"
15
- - ACTIVEJOB_VERSION="~> 6.0.3" SIDEKIQ_VERSION="~> 6.0.0"
16
- jobs:
17
- exclude:
18
- - rvm: 2.7.1
19
- env: ACTIVEJOB_VERSION="~> 4.2.11"
20
-
21
- before_install: gem install bundler -v 1.17.3
22
- bundler_args: --jobs 3 --retry 3
data/Gemfile DELETED
@@ -1,15 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- source 'https://rubygems.org'
4
-
5
- git_source(:github) { |repo_name| "https://github.com/#{repo_name}" }
6
-
7
- # Specify your gem's dependencies in activejob-uniqueness.gemspec
8
- gemspec
9
-
10
- gem 'activejob', ENV.fetch('ACTIVEJOB_VERSION', '~> 4.2.11')
11
-
12
- if ENV['SIDEKIQ_VERSION']
13
- gem 'sidekiq', ENV.fetch('SIDEKIQ_VERSION')
14
- gem 'railties', ENV.fetch('ACTIVEJOB_VERSION')
15
- end
data/Rakefile DELETED
@@ -1,8 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- require 'bundler/gem_tasks'
4
- require 'rspec/core/rake_task'
5
-
6
- RSpec::Core::RakeTask.new(:spec)
7
-
8
- task default: :spec
@@ -1,36 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- lib = File.expand_path('lib', __dir__)
4
- $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
5
- require 'active_job/uniqueness/version'
6
-
7
- Gem::Specification.new do |spec|
8
- spec.name = 'activejob-uniqueness'
9
- spec.version = ActiveJob::Uniqueness::VERSION
10
- spec.authors = ['Rustam Sharshenov']
11
- spec.email = ['rustam@sharshenov.com']
12
-
13
- spec.summary = 'Ensure uniqueness of your ActiveJob jobs'
14
- spec.description = 'Ensure uniqueness of your ActiveJob jobs'
15
- spec.homepage = 'https://github.com/veeqo/activejob-uniqueness'
16
- spec.license = 'MIT'
17
-
18
- if spec.respond_to?(:metadata)
19
- spec.metadata['homepage_uri'] = spec.homepage
20
- spec.metadata['source_code_uri'] = spec.homepage
21
- spec.metadata['changelog_uri'] = 'https://github.com/veeqo/activejob-uniqueness/blob/master/CHANGELOG.md'
22
- end
23
-
24
- spec.files = Dir.chdir(File.expand_path(__dir__)) do
25
- `git ls-files -z`.split("\x0").reject { |f| f.match(%r{^(spec|\.rubocop.yml)/}) }
26
- end
27
- spec.require_paths = ['lib']
28
-
29
- spec.add_dependency 'activejob', '>= 4.2'
30
- spec.add_dependency 'redlock', '>= 1.2', '< 2'
31
-
32
- spec.add_development_dependency 'bundler'
33
- spec.add_development_dependency 'pry-byebug'
34
- spec.add_development_dependency 'rake'
35
- spec.add_development_dependency 'rspec', '~> 3.0'
36
- end
@@ -1,93 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- module ActiveJob
4
- module Uniqueness
5
- module Patch
6
- def self.delete_sidekiq_job!(job)
7
- ActiveJob::Uniqueness.unlock!(
8
- job_class_name: job.fetch('wrapped'),
9
- arguments: job.fetch('args').first.fetch('arguments')
10
- )
11
- end
12
- end
13
- end
14
- end
15
-
16
- require 'sidekiq/api'
17
-
18
- Sidekiq.configure_server do |config|
19
- config.death_handlers << ->(job, _ex) do
20
- ActiveJob::Uniqueness::Patch.delete_sidekiq_job!(job)
21
- end
22
- end
23
-
24
- module Sidekiq
25
- class SortedEntry
26
- module UniqueExtension
27
- def delete
28
- ActiveJob::Uniqueness::Patch.delete_sidekiq_job!(item) if super
29
- item
30
- end
31
-
32
- private
33
-
34
- def remove_job
35
- super do |message|
36
- ActiveJob::Uniqueness::Patch.delete_sidekiq_job!(Sidekiq.load_json(message))
37
- yield message
38
- end
39
- end
40
- end
41
-
42
- prepend UniqueExtension
43
- end
44
-
45
- class ScheduledSet
46
- module UniqueExtension
47
- def delete(score, job_id)
48
- entry = find_job(job_id)
49
- ActiveJob::Uniqueness::Patch.delete_sidekiq_job!(entry.item) if super(score, job_id)
50
- entry
51
- end
52
- end
53
-
54
- prepend UniqueExtension
55
- end
56
-
57
- class Job
58
- module UniqueExtension
59
- def delete
60
- ActiveJob::Uniqueness::Patch.delete_sidekiq_job!(item)
61
- super
62
- end
63
- end
64
-
65
- prepend UniqueExtension
66
- end
67
-
68
- class Queue
69
- module UniqueExtension
70
- def clear
71
- each(&:delete)
72
- super
73
- end
74
- end
75
-
76
- prepend UniqueExtension
77
- end
78
-
79
- class JobSet
80
- module UniqueExtension
81
- def clear
82
- each(&:delete)
83
- super
84
- end
85
-
86
- def delete_by_value(name, value)
87
- ActiveJob::Uniqueness::Patch.delete_sidekiq_job!(Sidekiq.load_json(value)) if super(name, value)
88
- end
89
- end
90
-
91
- prepend UniqueExtension
92
- end
93
- end