sidekiq-unique-jobs 7.1.19 → 7.1.20

Sign up to get free protection for your applications and to get access to all the features.

Potentially problematic release.


This version of sidekiq-unique-jobs might be problematic. Click here for more details.

checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 5432e71679519bcfbc3605de7c156e0820cf2c463ee9a5d458c1b59bd7c63fec
4
- data.tar.gz: ecd548ff2add944949acc25341d92e2f74aee5256978d32ee74180ba1eacbd66
3
+ metadata.gz: 2a112ea37ca98a7909abf3b536e5d5f2b147e3a40f7749bf3c7d819c259d069e
4
+ data.tar.gz: a3f34c72a78723c0dd441d005ae0300662183ddbe24cde430e7714587feccbd3
5
5
  SHA512:
6
- metadata.gz: 926bde9f4894aba3806723c1d75faffdf8bde86514b37f69b4156ca12b3dd64228d6eb768a03f521d119ebb42f50bcfbe87392d788f54a6e49b233565743dcb4
7
- data.tar.gz: 28d14de13123d83b6d948d8453a901efe0ae1667ebc0d6a444e702371579528eccb4ac42c298aa2eb425c23b402c155cc58f553def21cba9c7a6d46757a167e2
6
+ metadata.gz: 0a6d73f2beade75f9b0261a65ff3be37dfe0fe35c6ff3550635d3b8c634f1ad80c646c36be63c304806ef4f4f471eb0bb56ad641714ed48a53a14ee1d9f1a1aa
7
+ data.tar.gz: 93f518d9743445c8b844032dbcd8e583a88909b7e3bed9b88807ce3e3e337d2bdf101b8b413e8610705a22aae98747c8fa63549a2b001adc9800903577ad3694
data/CHANGELOG.md CHANGED
@@ -1,5 +1,14 @@
1
1
  # Changelog
2
2
 
3
+ ## [v7.1.19](https://github.com/mhenrixon/sidekiq-unique-jobs/tree/v7.1.19) (2022-04-09)
4
+
5
+ [Full Changelog](https://github.com/mhenrixon/sidekiq-unique-jobs/compare/v7.1.18...v7.1.19)
6
+
7
+ **Fixed bugs:**
8
+
9
+ - concurrent-ruby 1.1.10 spikes volume of jobs [\#701](https://github.com/mhenrixon/sidekiq-unique-jobs/issues/701)
10
+ - Reimplement the entire TimerTask as it was [\#702](https://github.com/mhenrixon/sidekiq-unique-jobs/pull/702) ([mhenrixon](https://github.com/mhenrixon))
11
+
3
12
  ## [v7.1.18](https://github.com/mhenrixon/sidekiq-unique-jobs/tree/v7.1.18) (2022-04-05)
4
13
 
5
14
  [Full Changelog](https://github.com/mhenrixon/sidekiq-unique-jobs/compare/v7.1.17...v7.1.18)
data/README.md CHANGED
@@ -123,9 +123,11 @@ Before v7, the middleware was configured automatically. Since some people report
123
123
 
124
124
  *NOTE* if you want to use the reaper you also need to configure the server middleware.
125
125
 
126
- [A full example](https://github.com/mhenrixon/sidekiq-unique-jobs/blob/master/myapp/config/initializers/sidekiq.rb#L12)
126
+ The following shows how to modify your `config/initializers/sidekiq.rb` file to use the middleware. [Here is a full example.](https://github.com/mhenrixon/sidekiq-unique-jobs/blob/master/myapp/config/initializers/sidekiq.rb#L12)
127
127
 
128
128
  ```ruby
129
+ require "sidekiq-unique-jobs"
130
+
129
131
  Sidekiq.configure_server do |config|
130
132
  config.redis = { url: ENV["REDIS_URL"], driver: :hiredis }
131
133
 
@@ -110,13 +110,7 @@ module SidekiqUniqueJobs
110
110
  # @return [Hash]
111
111
  #
112
112
  def timer_task_options
113
- timer_task_options = { run_now: true, execution_interval: reaper_interval }
114
-
115
- if VersionCheck.satisfied?(::Concurrent::VERSION, "< 1.1.10")
116
- timer_task_options[:timeout_interval] = reaper_timeout
117
- end
118
-
119
- timer_task_options
113
+ { run_now: true, execution_interval: reaper_interval }
120
114
  end
121
115
 
122
116
  #
@@ -133,13 +127,6 @@ module SidekiqUniqueJobs
133
127
  SidekiqUniqueJobs.config.reaper_interval
134
128
  end
135
129
 
136
- #
137
- # @see SidekiqUniqueJobs::Config#reaper_timeout
138
- #
139
- def reaper_timeout
140
- SidekiqUniqueJobs.config.reaper_timeout
141
- end
142
-
143
130
  #
144
131
  # A context to use for all log entries
145
132
  #
@@ -11,6 +11,8 @@ module SidekiqUniqueJobs
11
11
  #
12
12
  # rubocop:disable Metrics/ClassLength
13
13
  class RubyReaper < Reaper
14
+ include SidekiqUniqueJobs::Timing
15
+
14
16
  #
15
17
  # @return [String] the suffix for :RUN locks
16
18
  RUN_SUFFIX = ":RUN"
@@ -30,6 +32,16 @@ module SidekiqUniqueJobs
30
32
  # @return [Redis::SortedSet] the Sidekiq RetrySet
31
33
  attr_reader :retried
32
34
 
35
+ #
36
+ # @!attribute [r] start_time
37
+ # @return [Integer] The timestamp this execution started represented as integer
38
+ attr_reader :start_time
39
+
40
+ #
41
+ # @!attribute [r] timeout_ms
42
+ # @return [Integer] The allowed ms before timeout
43
+ attr_reader :timeout_ms
44
+
33
45
  #
34
46
  # Initialize a new instance of DeleteOrphans
35
47
  #
@@ -37,9 +49,11 @@ module SidekiqUniqueJobs
37
49
  #
38
50
  def initialize(conn)
39
51
  super(conn)
40
- @digests = SidekiqUniqueJobs::Digests.new
41
- @scheduled = Redis::SortedSet.new(SCHEDULE)
42
- @retried = Redis::SortedSet.new(RETRY)
52
+ @digests = SidekiqUniqueJobs::Digests.new
53
+ @scheduled = Redis::SortedSet.new(SCHEDULE)
54
+ @retried = Redis::SortedSet.new(RETRY)
55
+ @start_time = time_source.call
56
+ @timeout_ms = SidekiqUniqueJobs.config.reaper_timeout * 1000
43
57
  end
44
58
 
45
59
  #
@@ -60,7 +74,7 @@ module SidekiqUniqueJobs
60
74
  #
61
75
  # @return [Array<String>] an array of orphaned digests
62
76
  #
63
- def orphans # rubocop:disable Metrics/MethodLength
77
+ def orphans # rubocop:disable Metrics/MethodLength, Metrics/CyclomaticComplexity
64
78
  page = 0
65
79
  per = reaper_count * 2
66
80
  orphans = []
@@ -68,12 +82,14 @@ module SidekiqUniqueJobs
68
82
 
69
83
  while results.size.positive?
70
84
  results.each do |digest|
85
+ break if timeout?
71
86
  next if belongs_to_job?(digest)
72
87
 
73
88
  orphans << digest
74
89
  break if orphans.size >= reaper_count
75
90
  end
76
91
 
92
+ break if timeout?
77
93
  break if orphans.size >= reaper_count
78
94
 
79
95
  page += 1
@@ -83,6 +99,14 @@ module SidekiqUniqueJobs
83
99
  orphans
84
100
  end
85
101
 
102
+ def timeout?
103
+ elapsed_ms >= timeout_ms
104
+ end
105
+
106
+ def elapsed_ms
107
+ time_source.call - start_time
108
+ end
109
+
86
110
  #
87
111
  # Checks if the digest has a matching job.
88
112
  # 1. It checks the scheduled set
@@ -26,9 +26,7 @@ module SidekiqUniqueJobs
26
26
  # Should the task experience an unrecoverable crash only the task thread will
27
27
  # crash. This makes the `TimerTask` very fault tolerant. Additionally, the
28
28
  # `TimerTask` thread can respond to the success or failure of the task,
29
- # performing logging or ancillary operations. `TimerTask` can also be
30
- # configured with a timeout value allowing it to kill a task that runs too
31
- # long.
29
+ # performing logging or ancillary operations.
32
30
  #
33
31
  # One other advantage of `TimerTask` is that it forces the business logic to
34
32
  # be completely decoupled from the concurrency logic. The business logic can
@@ -49,9 +47,7 @@ module SidekiqUniqueJobs
49
47
  # {http://ruby-doc.org/stdlib-2.0/libdoc/observer/rdoc/Observable.html
50
48
  # Observable} module. On execution the `TimerTask` will notify the observers
51
49
  # with three arguments: time of execution, the result of the block (or nil on
52
- # failure), and any raised exceptions (or nil on success). If the timeout
53
- # interval is exceeded the observer will receive a `Concurrent::TimeoutError`
54
- # object as the third argument.
50
+ # failure), and any raised exceptions (or nil on success).
55
51
  #
56
52
  # @!macro copy_options
57
53
  #
@@ -60,20 +56,18 @@ module SidekiqUniqueJobs
60
56
  # task.execute
61
57
  #
62
58
  # task.execution_interval #=> 60 (default)
63
- # task.timeout_interval #=> 30 (default)
64
59
  #
65
60
  # # wait 60 seconds...
66
61
  # #=> 'Boom!'
67
62
  #
68
63
  # task.shutdown #=> true
69
64
  #
70
- # @example Configuring `:execution_interval` and `:timeout_interval`
71
- # task = Concurrent::TimerTask.new(execution_interval: 5, timeout_interval: 5) do
65
+ # @example Configuring `:execution_interval`
66
+ # task = Concurrent::TimerTask.new(execution_interval: 5) do
72
67
  # puts 'Boom!'
73
68
  # end
74
69
  #
75
70
  # task.execution_interval #=> 5
76
- # task.timeout_interval #=> 5
77
71
  #
78
72
  # @example Immediate execution with `:run_now`
79
73
  # task = Concurrent::TimerTask.new(run_now: true){ puts 'Boom!' }
@@ -116,15 +110,13 @@ module SidekiqUniqueJobs
116
110
  # def update(time, result, ex)
117
111
  # if result
118
112
  # print "(#{time}) Execution successfully returned #{result}\n"
119
- # elsif ex.is_a?(Concurrent::TimeoutError)
120
- # print "(#{time}) Execution timed out\n"
121
113
  # else
122
114
  # print "(#{time}) Execution failed with error #{ex}\n"
123
115
  # end
124
116
  # end
125
117
  # end
126
118
  #
127
- # task = Concurrent::TimerTask.new(execution_interval: 1, timeout_interval: 1){ 42 }
119
+ # task = Concurrent::TimerTask.new(execution_interval: 1){ 42 }
128
120
  # task.add_observer(TaskObserver.new)
129
121
  # task.execute
130
122
  # sleep 4
@@ -134,7 +126,7 @@ module SidekiqUniqueJobs
134
126
  # #=> (2013-10-13 19:09:00 -0400) Execution successfully returned 42
135
127
  # task.shutdown
136
128
  #
137
- # task = Concurrent::TimerTask.new(execution_interval: 1, timeout_interval: 1){ sleep }
129
+ # task = Concurrent::TimerTask.new(execution_interval: 1){ sleep }
138
130
  # task.add_observer(TaskObserver.new)
139
131
  # task.execute
140
132
  #
@@ -154,7 +146,7 @@ module SidekiqUniqueJobs
154
146
  #
155
147
  # @see http://ruby-doc.org/stdlib-2.0/libdoc/observer/rdoc/Observable.html
156
148
  # @see http://docs.oracle.com/javase/7/docs/api/java/util/TimerTask.html
157
- class TimerTask < Concurrent::RubyExecutorService # rubocop:disable Metrics/ClassLength
149
+ class TimerTask < Concurrent::RubyExecutorService
158
150
  include Concurrent::Concern::Dereferenceable
159
151
  include Concurrent::Concern::Observable
160
152
 
@@ -170,8 +162,6 @@ module SidekiqUniqueJobs
170
162
  # @param [Hash] opts the options defining task execution.
171
163
  # @option opts [Integer] :execution_interval number of seconds between
172
164
  # task executions (default: EXECUTION_INTERVAL)
173
- # @option opts [Integer] :timeout_interval number of seconds a task can
174
- # run before it is considered to have failed (default: TIMEOUT_INTERVAL)
175
165
  # @option opts [Boolean] :run_now Whether to run the task immediately
176
166
  # upon instantiation or to wait until the first # execution_interval
177
167
  # has passed (default: false)
@@ -233,7 +223,7 @@ module SidekiqUniqueJobs
233
223
  # task = Concurrent::TimerTask.execute(execution_interval: 10){ print "Hello World\n" }
234
224
  # task.running? #=> true
235
225
  def self.execute(opts = {}, &task)
236
- SidekiqUniqueJobs::TimerTask.new(opts, &task).execute
226
+ TimerTask.new(opts, &task).execute
237
227
  end
238
228
 
239
229
  # @!attribute [rw] execution_interval
@@ -252,22 +242,6 @@ module SidekiqUniqueJobs
252
242
  synchronize { @execution_interval = value }
253
243
  end
254
244
 
255
- # @!attribute [rw] timeout_interval
256
- # @return [Fixnum] Number of seconds the task can run before it is
257
- # considered to have failed.
258
- def timeout_interval
259
- synchronize { @timeout_interval }
260
- end
261
-
262
- # @!attribute [rw] timeout_interval
263
- # @return [Fixnum] Number of seconds the task can run before it is
264
- # considered to have failed.
265
- def timeout_interval=(value)
266
- raise ArgumentError, "must be greater than zero" if (value = value.to_f) <= 0.0
267
-
268
- synchronize { @timeout_interval = value }
269
- end
270
-
271
245
  private :post, :<<
272
246
 
273
247
  private
@@ -276,12 +250,13 @@ module SidekiqUniqueJobs
276
250
  set_deref_options(opts)
277
251
 
278
252
  self.execution_interval = opts[:execution] || opts[:execution_interval] || EXECUTION_INTERVAL
279
- self.timeout_interval = opts[:timeout] || opts[:timeout_interval] || TIMEOUT_INTERVAL
280
- @run_now = opts[:now] || opts[:run_now]
281
- @executor = Concurrent::RubySingleThreadExecutor.new
282
- @running = Concurrent::AtomicBoolean.new(false)
283
- @task = task
284
- @value = nil
253
+ if opts[:timeout] || opts[:timeout_interval]
254
+ warn "TimeTask timeouts are now ignored as these were not able to be implemented correctly"
255
+ end
256
+ @run_now = opts[:now] || opts[:run_now]
257
+ @executor = Concurrent::SafeTaskExecutor.new(task)
258
+ @running = Concurrent::AtomicBoolean.new(false)
259
+ @value = nil
285
260
 
286
261
  self.observers = Concurrent::Collection::CopyOnNotifyObserverSet.new
287
262
  end
@@ -306,52 +281,19 @@ module SidekiqUniqueJobs
306
281
  end
307
282
 
308
283
  # @!visibility private
309
- def execute_task(completion) # rubocop:disable Metrics/MethodLength
284
+ def execute_task(completion)
310
285
  return nil unless @running.true?
311
286
 
312
- timeout_task = -> { timeout_task(completion) }
313
-
314
- Concurrent::ScheduledTask.execute(
315
- timeout_interval,
316
- args: [completion],
317
- &timeout_task
318
- )
319
- @thread_completed = Concurrent::Event.new
320
-
321
- @value = @reason = nil
322
- @executor.post do
323
- @value = @task.call(self)
324
- rescue Exception => ex # rubocop:disable Lint/RescueException
325
- @reason = ex
326
- ensure
327
- @thread_completed.set
328
- end
329
-
330
- @thread_completed.wait
331
-
287
+ _success, value, reason = @executor.execute(self)
332
288
  if completion.try?
289
+ self.value = value
333
290
  schedule_next_task
334
291
  time = Time.now
335
292
  observers.notify_observers do
336
- [time, value, @reason]
293
+ [time, self.value, reason]
337
294
  end
338
295
  end
339
296
  nil
340
297
  end
341
-
342
- # @!visibility private
343
- def timeout_task(completion)
344
- return unless @running.true?
345
- return unless completion.try?
346
-
347
- @executor.kill
348
- @executor.wait_for_termination
349
- @executor = Concurrent::RubySingleThreadExecutor.new
350
-
351
- @thread_completed.set
352
-
353
- schedule_next_task
354
- observers.notify_observers(Time.now, nil, Concurrent::TimeoutError.new)
355
- end
356
298
  end
357
299
  end
@@ -3,5 +3,5 @@
3
3
  module SidekiqUniqueJobs
4
4
  #
5
5
  # @return [String] the current SidekiqUniqueJobs version
6
- VERSION = "7.1.19"
6
+ VERSION = "7.1.20"
7
7
  end
@@ -17,7 +17,7 @@ COMMIT_CHANGELOG_CMD = "git commit -a -m 'Update changelog'"
17
17
  desc "Generate a Changelog"
18
18
  task :changelog do
19
19
  sh("git checkout main")
20
- sh(*CHANGELOG_CMD.push(ENV["CHANGELOG_GITHUB_TOKEN"]))
20
+ sh(*CHANGELOG_CMD.push(ENV.fetch("CHANGELOG_GITHUB_TOKEN", nil)))
21
21
  sh(ADD_CHANGELOG_CMD)
22
22
  sh(COMMIT_CHANGELOG_CMD)
23
23
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: sidekiq-unique-jobs
3
3
  version: !ruby/object:Gem::Version
4
- version: 7.1.19
4
+ version: 7.1.20
5
5
  platform: ruby
6
6
  authors:
7
7
  - Mikael Henriksson
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2022-04-09 00:00:00.000000000 Z
11
+ date: 2022-04-22 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: brpoplpush-redis_script