activejob-uniqueness 0.1.2 → 0.1.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
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