activejob-uniqueness 0.3.2 → 0.4.0
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 +4 -4
- data/CHANGELOG.md +14 -3
- data/README.md +26 -0
- data/lib/active_job/uniqueness/active_job_patch.rb +4 -1
- data/lib/active_job/uniqueness/configuration.rb +13 -0
- data/lib/active_job/uniqueness/lock_manager.rb +7 -1
- data/lib/active_job/uniqueness/strategies/base.rb +16 -1
- data/lib/active_job/uniqueness/version.rb +1 -1
- data/lib/generators/active_job/uniqueness/templates/config/initializers/active_job_uniqueness.rb +7 -0
- metadata +5 -5
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: cd76f286ed7e6482860247e9b98b754dc1b73a381fcd2579d73e469da95d0200
|
4
|
+
data.tar.gz: 866f0949c68745c168217cbc70b10c65799f70aa372902dbd145781726217acd
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 5cb9299a82cc40a9fca3df73c771cf553ead9393b11eca505afea5e55fe3023722db67d509528d0886db66e64569ba1caea04622ebde3ca365df1d768f04d2f4
|
7
|
+
data.tar.gz: 205d78f3c41721bce16c16d991204423fe5429b23c1d6fad48eb1a4ac7f775057f7e15192e8d1c32c97fc0c2c4af60a1584d6a666c253df71e1acce9ba02e5fa
|
data/CHANGELOG.md
CHANGED
@@ -3,15 +3,26 @@ All notable changes to this project will be documented in this file.
|
|
3
3
|
|
4
4
|
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/).
|
5
5
|
|
6
|
-
## [Unreleased](https://github.com/veeqo/activejob-uniqueness/compare/v0.
|
6
|
+
## [Unreleased](https://github.com/veeqo/activejob-uniqueness/compare/v0.4.0...HEAD)
|
7
|
+
|
8
|
+
|
9
|
+
## [0.4.0](https://github.com/veeqo/activejob-uniqueness/compare/v0.3.2...v0.4.0) - 2024-12-07
|
10
|
+
|
11
|
+
### Added
|
12
|
+
|
13
|
+
- [#86](https://github.com/veeqo/activejob-uniqueness/pull/86) Add Rails 8.0 rc1 support by[@sharshenov](https://github.com/sharshenov)
|
14
|
+
- [#78](https://github.com/veeqo/activejob-uniqueness/pull/78) Add on_redis_connection_error config to adjust to new redlock behaviour by[@nduitz](https://github.com/nduitz)
|
15
|
+
|
16
|
+
### Changed
|
17
|
+
- [#82](https://github.com/veeqo/activejob-uniqueness/pull/82) Optimize bulk unlocking [@sharshenov](https://github.com/sharshenov)
|
7
18
|
|
8
19
|
## [0.3.2](https://github.com/veeqo/activejob-uniqueness/compare/v0.3.1...v0.3.2) - 2024-08-16
|
9
20
|
|
10
21
|
### Added
|
11
|
-
- [#80](https://github.com/veeqo/activejob-uniqueness/pull/80) Add rails 7.2 support by [viralpraxis]
|
22
|
+
- [#80](https://github.com/veeqo/activejob-uniqueness/pull/80) Add rails 7.2 support by [@viralpraxis](https://github.com/viralpraxis)
|
12
23
|
|
13
24
|
### Changed
|
14
|
-
- [#74](https://github.com/veeqo/activejob-uniqueness/pull/74) Fix log subscriber by [@shahidkhaliq]
|
25
|
+
- [#74](https://github.com/veeqo/activejob-uniqueness/pull/74) Fix log subscriber by [@shahidkhaliq](https://github.com/shahidkhaliq)
|
15
26
|
|
16
27
|
## [0.3.1](https://github.com/veeqo/activejob-uniqueness/compare/v0.3.0...v0.3.1) - 2023-10-30
|
17
28
|
|
data/README.md
CHANGED
@@ -43,6 +43,19 @@ To override the defaults, create an initializer `config/initializers/active_job_
|
|
43
43
|
rails generate active_job:uniqueness:install
|
44
44
|
```
|
45
45
|
|
46
|
+
This gem relies on `redlock` for it's Redis connection, that means **it will not inherit global configuration of `Sidekiq`**. To configure the connection, you can use `config.redlock_servers`, for example to disable SSL verification for Redis/Key-Value cloud providers:
|
47
|
+
|
48
|
+
```ruby
|
49
|
+
ActiveJob::Uniqueness.configure do |config|
|
50
|
+
config.redlock_servers = [
|
51
|
+
RedisClient.new(
|
52
|
+
url: ENV['REDIS_URL'],
|
53
|
+
ssl_params: { verify_mode: OpenSSL::SSL::VERIFY_NONE }
|
54
|
+
)
|
55
|
+
]
|
56
|
+
end
|
57
|
+
```
|
58
|
+
|
46
59
|
## Usage
|
47
60
|
|
48
61
|
|
@@ -87,6 +100,19 @@ class MyJob < ActiveJob::Base
|
|
87
100
|
end
|
88
101
|
```
|
89
102
|
|
103
|
+
### Control redis connection errors
|
104
|
+
|
105
|
+
```ruby
|
106
|
+
class MyJob < ActiveJob::Base
|
107
|
+
# Proc gets the job instance including its arguments, and as keyword arguments the resource(lock key) `resource` and the original error `error`
|
108
|
+
unique :until_executing, on_redis_connection_error: ->(job, resource: _, error: _) { job.logger.info "Oops: #{job.arguments}" }
|
109
|
+
|
110
|
+
def perform(args)
|
111
|
+
# work
|
112
|
+
end
|
113
|
+
end
|
114
|
+
```
|
115
|
+
|
90
116
|
### Control lock key arguments
|
91
117
|
|
92
118
|
```ruby
|
@@ -27,6 +27,7 @@ module ActiveJob
|
|
27
27
|
def unique(strategy, options = {})
|
28
28
|
validate_on_conflict_action!(options[:on_conflict])
|
29
29
|
validate_on_conflict_action!(options[:on_runtime_conflict])
|
30
|
+
validate_on_redis_connection_error!(options[:on_redis_connection_error])
|
30
31
|
|
31
32
|
self.lock_strategy_class = ActiveJob::Uniqueness::Strategies.lookup(strategy)
|
32
33
|
self.lock_options = options
|
@@ -40,7 +41,9 @@ module ActiveJob
|
|
40
41
|
|
41
42
|
private
|
42
43
|
|
43
|
-
delegate :validate_on_conflict_action!,
|
44
|
+
delegate :validate_on_conflict_action!,
|
45
|
+
:validate_on_redis_connection_error!,
|
46
|
+
to: :'ActiveJob::Uniqueness.config'
|
44
47
|
end
|
45
48
|
|
46
49
|
included do
|
@@ -14,6 +14,7 @@ module ActiveJob
|
|
14
14
|
config_accessor(:lock_ttl) { 86_400 } # 1.day
|
15
15
|
config_accessor(:lock_prefix) { 'activejob_uniqueness' }
|
16
16
|
config_accessor(:on_conflict) { :raise }
|
17
|
+
config_accessor(:on_redis_connection_error) { :raise }
|
17
18
|
config_accessor(:redlock_servers) { [ENV.fetch('REDIS_URL', 'redis://localhost:6379')] }
|
18
19
|
config_accessor(:redlock_options) { { retry_count: 0 } }
|
19
20
|
config_accessor(:lock_strategies) { {} }
|
@@ -34,6 +35,18 @@ module ActiveJob
|
|
34
35
|
|
35
36
|
raise ActiveJob::Uniqueness::InvalidOnConflictAction, "Unexpected '#{action}' action on conflict"
|
36
37
|
end
|
38
|
+
|
39
|
+
def on_redis_connection_error=(action)
|
40
|
+
validate_on_redis_connection_error!(action)
|
41
|
+
|
42
|
+
config.on_redis_connection_error = action
|
43
|
+
end
|
44
|
+
|
45
|
+
def validate_on_redis_connection_error!(action)
|
46
|
+
return if action.nil? || action == :raise || action.respond_to?(:call)
|
47
|
+
|
48
|
+
raise ActiveJob::Uniqueness::InvalidOnConflictAction, "Unexpected '#{action}' action on_redis_connection_error"
|
49
|
+
end
|
37
50
|
end
|
38
51
|
end
|
39
52
|
end
|
@@ -17,11 +17,17 @@ module ActiveJob
|
|
17
17
|
true
|
18
18
|
end
|
19
19
|
|
20
|
+
DELETE_LOCKS_SCAN_COUNT = 1000
|
21
|
+
|
20
22
|
# Unlocks multiple resources by key wildcard.
|
21
23
|
def delete_locks(wildcard)
|
22
24
|
@servers.each do |server|
|
23
25
|
synced_redis_connection(server) do |conn|
|
24
|
-
|
26
|
+
cursor = 0
|
27
|
+
while cursor != '0'
|
28
|
+
cursor, keys = conn.call('SCAN', cursor, 'MATCH', wildcard, 'COUNT', DELETE_LOCKS_SCAN_COUNT)
|
29
|
+
conn.call('UNLINK', *keys) unless keys.empty?
|
30
|
+
end
|
25
31
|
end
|
26
32
|
end
|
27
33
|
|
@@ -11,12 +11,13 @@ module ActiveJob
|
|
11
11
|
|
12
12
|
delegate :lock_manager, :config, to: :'ActiveJob::Uniqueness'
|
13
13
|
|
14
|
-
attr_reader :lock_key, :lock_ttl, :on_conflict, :job
|
14
|
+
attr_reader :lock_key, :lock_ttl, :on_conflict, :on_redis_connection_error, :job
|
15
15
|
|
16
16
|
def initialize(job:)
|
17
17
|
@lock_key = job.lock_key
|
18
18
|
@lock_ttl = (job.lock_options[:lock_ttl] || config.lock_ttl).to_i * 1000 # ms
|
19
19
|
@on_conflict = job.lock_options[:on_conflict] || config.on_conflict
|
20
|
+
@on_redis_connection_error = job.lock_options[:on_redis_connection_error] || config.on_redis_connection_error
|
20
21
|
@job = job
|
21
22
|
end
|
22
23
|
|
@@ -60,6 +61,12 @@ module ActiveJob
|
|
60
61
|
|
61
62
|
handle_conflict(resource: lock_key, on_conflict: on_conflict)
|
62
63
|
abort_job
|
64
|
+
rescue RedisClient::ConnectionError => e
|
65
|
+
handle_redis_connection_error(
|
66
|
+
resource: lock_key, on_redis_connection_error:
|
67
|
+
on_redis_connection_error, error: e
|
68
|
+
)
|
69
|
+
abort_job
|
63
70
|
end
|
64
71
|
|
65
72
|
def around_enqueue(block)
|
@@ -86,6 +93,14 @@ module ActiveJob
|
|
86
93
|
end
|
87
94
|
end
|
88
95
|
|
96
|
+
def handle_redis_connection_error(resource:, on_redis_connection_error:, error:)
|
97
|
+
case on_redis_connection_error
|
98
|
+
when :raise, nil then raise error
|
99
|
+
else
|
100
|
+
on_redis_connection_error.call(job, resource: resource, error: error)
|
101
|
+
end
|
102
|
+
end
|
103
|
+
|
89
104
|
def abort_job
|
90
105
|
@job_aborted = true # ActiveJob 4.2 workaround
|
91
106
|
|
data/lib/generators/active_job/uniqueness/templates/config/initializers/active_job_uniqueness.rb
CHANGED
@@ -19,6 +19,13 @@ ActiveJob::Uniqueness.configure do |config|
|
|
19
19
|
#
|
20
20
|
# config.on_conflict = :raise
|
21
21
|
|
22
|
+
# Default action on redis connection error. Can be set per job.
|
23
|
+
# Allowed values are
|
24
|
+
# :raise - raises ActiveJob::Uniqueness::JobNotUnique
|
25
|
+
# proc - custom Proc. For example, ->(job, resource: _, error: _) { job.logger.info("Job already in queue: #{job.class.name} #{job.arguments.inspect} (#{job.job_id})") }
|
26
|
+
#
|
27
|
+
# config.on_redis_connection_error = :raise
|
28
|
+
|
22
29
|
# Digest method for lock keys generating. Expected to have `hexdigest` class method.
|
23
30
|
#
|
24
31
|
# config.digest_method = OpenSSL::Digest::MD5
|
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.
|
4
|
+
version: 0.4.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Rustam Sharshenov
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2024-
|
11
|
+
date: 2024-12-07 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: activejob
|
@@ -19,7 +19,7 @@ dependencies:
|
|
19
19
|
version: '4.2'
|
20
20
|
- - "<"
|
21
21
|
- !ruby/object:Gem::Version
|
22
|
-
version: '
|
22
|
+
version: '8.1'
|
23
23
|
type: :runtime
|
24
24
|
prerelease: false
|
25
25
|
version_requirements: !ruby/object:Gem::Requirement
|
@@ -29,7 +29,7 @@ dependencies:
|
|
29
29
|
version: '4.2'
|
30
30
|
- - "<"
|
31
31
|
- !ruby/object:Gem::Version
|
32
|
-
version: '
|
32
|
+
version: '8.1'
|
33
33
|
- !ruby/object:Gem::Dependency
|
34
34
|
name: redlock
|
35
35
|
requirement: !ruby/object:Gem::Requirement
|
@@ -187,7 +187,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
187
187
|
- !ruby/object:Gem::Version
|
188
188
|
version: '0'
|
189
189
|
requirements: []
|
190
|
-
rubygems_version: 3.
|
190
|
+
rubygems_version: 3.2.33
|
191
191
|
signing_key:
|
192
192
|
specification_version: 4
|
193
193
|
summary: Ensure uniqueness of your ActiveJob jobs
|