delayed_job_groups_plugin 0.12.0 → 0.13.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/Appraisals +1 -0
- data/CHANGELOG.md +6 -0
- data/gemfiles/rails_7.0.gemfile +1 -0
- data/lib/delayed/job_groups/errors.rb +16 -0
- data/lib/delayed/job_groups/job_group.rb +12 -2
- data/lib/delayed/job_groups/plugin.rb +7 -1
- data/lib/delayed/job_groups/railtie.rb +9 -0
- data/lib/delayed/job_groups/version.rb +1 -1
- data/lib/delayed_job_groups_plugin.rb +2 -0
- data/spec/delayed/job_groups/job_group_spec.rb +33 -1
- data/spec/spec_helper.rb +5 -3
- metadata +4 -3
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 9773f978178a522b2f7d150230d2aec54bdd5a3bd11b13a980e93ebd71a0bf8c
|
4
|
+
data.tar.gz: 9d7ae98668fc83a5d7aa516138470585dc5f711a52796c297f8c408969cb2903
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 964f5ea0c140c4d9122ed4602e2e059263f8e2ba71242aa741f079a195a8f7a39c42938380b8794f40b7ebb0b464c640ae1945c7a4174150d5299df9af381bd0
|
7
|
+
data.tar.gz: 98ff4ae8816c181e05aea9ad267d105e0d0397f3d02a50ef7fa3c61bfc9c53100d8e0a3a10aee298b512ae80a55f753f08e7407dafaabfaf6f5f40080428f600
|
data/Appraisals
CHANGED
data/CHANGELOG.md
CHANGED
@@ -1,5 +1,11 @@
|
|
1
1
|
# Changelog
|
2
2
|
|
3
|
+
## 0.13.0
|
4
|
+
- Moves `on_cancellation` logic from the before delayed job lifecycle hook to the after hook.
|
5
|
+
- Gem will now fail to load if `Delayed::Worker.destroy_failed_jobs` is set to true.
|
6
|
+
- Wrapped the job group cancel hook in a lock to prevent concurrently failing jobs from enqueueing
|
7
|
+
multiple on cancellation jobs.
|
8
|
+
|
3
9
|
## 0.12.0
|
4
10
|
- Add support for Rails 8.0.
|
5
11
|
- Drop support for Rails 6.1
|
data/gemfiles/rails_7.0.gemfile
CHANGED
@@ -0,0 +1,16 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Delayed
|
4
|
+
module JobGroups
|
5
|
+
ConfigurationError = Class.new(StandardError)
|
6
|
+
|
7
|
+
class IncompatibleWithDelayedJobError < ConfigurationError
|
8
|
+
DEFAULT_MESSAGE = 'DelayedJobGroupsPlugin is incompatible with Delayed::Job ' \
|
9
|
+
'when `destroy_failed_jobs` is set to `true`'
|
10
|
+
|
11
|
+
def initialize(msg = DEFAULT_MESSAGE)
|
12
|
+
super(msg)
|
13
|
+
end
|
14
|
+
end
|
15
|
+
end
|
16
|
+
end
|
@@ -62,8 +62,18 @@ module Delayed
|
|
62
62
|
end
|
63
63
|
|
64
64
|
def cancel
|
65
|
-
|
66
|
-
|
65
|
+
with_lock do
|
66
|
+
return if destroyed?
|
67
|
+
|
68
|
+
Delayed::Job.enqueue(on_cancellation_job, on_cancellation_job_options || {}) if on_cancellation_job
|
69
|
+
destroy
|
70
|
+
end
|
71
|
+
rescue ActiveRecord::RecordNotFound
|
72
|
+
# The first failing job to attempt cancelling the job group will enqueue the
|
73
|
+
# on cancellation job and destroy the group. Any other concurrently failing job
|
74
|
+
# in the same group can therefore silently return if the job group has already
|
75
|
+
# been destroyed.
|
76
|
+
nil
|
67
77
|
end
|
68
78
|
|
69
79
|
def check_for_completion(skip_pending_jobs_check: false)
|
@@ -17,7 +17,13 @@ module Delayed
|
|
17
17
|
end
|
18
18
|
end
|
19
19
|
|
20
|
-
|
20
|
+
# In order to allow individual jobs in the JobGroup to perform cleanup activities upon
|
21
|
+
# job failure, a JobGroups on cancellation job must be enqueued in the after failure
|
22
|
+
# delayed job lifecycle hook. If both were to be performed in the same hook, the job's
|
23
|
+
# failure hook and the on cancellation job may run at the same time since hook execution
|
24
|
+
# order is never guaranteed. This is particular important if the on cancellation job
|
25
|
+
# depends on state set in the failure hook of an individual job.
|
26
|
+
lifecycle.after(:failure) do |_worker, job|
|
21
27
|
# If a job in the job group fails, then cancel the whole job group.
|
22
28
|
# Need to check that the job group is present since another
|
23
29
|
# job may have concurrently cancelled it.
|
@@ -4,6 +4,15 @@ module Delayed
|
|
4
4
|
module JobGroups
|
5
5
|
class Railtie < ::Rails::Railtie
|
6
6
|
config.after_initialize do
|
7
|
+
|
8
|
+
# On cancellation checks are performed in the after failure delayed job lifecycle, however
|
9
|
+
# https://github.com/collectiveidea/delayed_job/blob/master/lib/delayed/worker.rb#L268 may
|
10
|
+
# delete jobs before the hook runs. This could cause a successful job in the same group to
|
11
|
+
# complete the group instead of the group being cancelled. Therefore, we must ensure that
|
12
|
+
# the Delayed::Worker.destroy_failed_jobs is set to false, guaranteeing that the group is
|
13
|
+
# never empty if failure occurs.
|
14
|
+
raise Delayed::JobGroups::IncompatibleWithDelayedJobError if Delayed::Worker.destroy_failed_jobs
|
15
|
+
|
7
16
|
Delayed::Backend::ActiveRecord::Job.include(Delayed::JobGroups::JobExtensions)
|
8
17
|
end
|
9
18
|
end
|
@@ -4,6 +4,7 @@ require 'active_support'
|
|
4
4
|
require 'active_record'
|
5
5
|
require 'delayed_job'
|
6
6
|
require 'delayed_job_active_record'
|
7
|
+
require 'delayed/job_groups/errors'
|
7
8
|
require 'delayed/job_groups/compatibility'
|
8
9
|
require 'delayed/job_groups/complete_stuck_job_groups_job'
|
9
10
|
require 'delayed/job_groups/job_extensions'
|
@@ -18,6 +19,7 @@ if defined?(Rails::Railtie)
|
|
18
19
|
else
|
19
20
|
# Do the same as in the railtie
|
20
21
|
Delayed::Backend::ActiveRecord::Job.include(Delayed::JobGroups::JobExtensions)
|
22
|
+
raise Delayed::JobGroups::IncompatibleWithDelayedJobError if Delayed::Worker.destroy_failed_jobs
|
21
23
|
end
|
22
24
|
|
23
25
|
Delayed::Worker.plugins << Delayed::JobGroups::Plugin
|
@@ -299,11 +299,28 @@ describe Delayed::JobGroups::JobGroup do
|
|
299
299
|
end
|
300
300
|
|
301
301
|
describe "#cancel" do
|
302
|
+
subject(:job_group) do
|
303
|
+
create(
|
304
|
+
:job_group,
|
305
|
+
on_completion_job: on_completion_job,
|
306
|
+
on_completion_job_options: on_completion_job_options,
|
307
|
+
on_cancellation_job: on_cancellation_job,
|
308
|
+
on_cancellation_job_options: on_cancellation_job_options,
|
309
|
+
blocked: blocked
|
310
|
+
)
|
311
|
+
end
|
312
|
+
|
302
313
|
let!(:queued_job) { Delayed::Job.create!(job_group_id: job_group.id) }
|
303
314
|
let!(:running_job) { Delayed::Job.create!(job_group_id: job_group.id, locked_at: Time.now, locked_by: 'test') }
|
315
|
+
let(:before_hook) {}
|
316
|
+
let(:on_cancellation_job) { 'dummy job' }
|
317
|
+
let(:on_cancellation_job_options) do
|
318
|
+
{ foo: 'bar' }
|
319
|
+
end
|
320
|
+
let(:cancel) { true }
|
304
321
|
|
305
322
|
before do
|
306
|
-
job_group.cancel
|
323
|
+
job_group.cancel if cancel
|
307
324
|
end
|
308
325
|
|
309
326
|
it "destroys the job group" do
|
@@ -317,6 +334,21 @@ describe Delayed::JobGroups::JobGroup do
|
|
317
334
|
it "does not destroy running jobs" do
|
318
335
|
expect(running_job).not_to have_been_destroyed
|
319
336
|
end
|
337
|
+
|
338
|
+
context "when already cancelled" do
|
339
|
+
let(:cancel) { false }
|
340
|
+
|
341
|
+
it "skips cancel block if already cancelled" do
|
342
|
+
other = Delayed::JobGroups::JobGroup.find(job_group.id)
|
343
|
+
job_group.cancel
|
344
|
+
|
345
|
+
other.cancel
|
346
|
+
other.cancel
|
347
|
+
|
348
|
+
expect(Delayed::Job)
|
349
|
+
.to have_received(:enqueue).with(on_cancellation_job, on_cancellation_job_options).once
|
350
|
+
end
|
351
|
+
end
|
320
352
|
end
|
321
353
|
|
322
354
|
describe "#failure_cancels_group?" do
|
data/spec/spec_helper.rb
CHANGED
@@ -13,6 +13,11 @@ end
|
|
13
13
|
|
14
14
|
require 'rspec/its'
|
15
15
|
require 'database_cleaner'
|
16
|
+
require 'delayed_job'
|
17
|
+
|
18
|
+
Delayed::Worker.read_ahead = 1
|
19
|
+
Delayed::Worker.destroy_failed_jobs = false
|
20
|
+
|
16
21
|
require 'delayed_job_groups_plugin'
|
17
22
|
require 'factory_bot'
|
18
23
|
require 'yaml'
|
@@ -23,9 +28,6 @@ Dir["#{spec_dir}/support/**/*.rb"].sort.each { |f| require f }
|
|
23
28
|
|
24
29
|
FileUtils.makedirs('log')
|
25
30
|
|
26
|
-
Delayed::Worker.read_ahead = 1
|
27
|
-
Delayed::Worker.destroy_failed_jobs = false
|
28
|
-
|
29
31
|
Delayed::Worker.logger = Logger.new('log/test.log')
|
30
32
|
Delayed::Worker.logger.level = Logger::DEBUG
|
31
33
|
ActiveRecord::Base.logger = Delayed::Worker.logger
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: delayed_job_groups_plugin
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.13.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Joel Turkel
|
@@ -9,7 +9,7 @@ authors:
|
|
9
9
|
autorequire:
|
10
10
|
bindir: bin
|
11
11
|
cert_chain: []
|
12
|
-
date:
|
12
|
+
date: 2025-09-24 00:00:00.000000000 Z
|
13
13
|
dependencies:
|
14
14
|
- !ruby/object:Gem::Dependency
|
15
15
|
name: activerecord
|
@@ -269,6 +269,7 @@ files:
|
|
269
269
|
- gemfiles/rails_8.0.gemfile
|
270
270
|
- lib/delayed/job_groups/compatibility.rb
|
271
271
|
- lib/delayed/job_groups/complete_stuck_job_groups_job.rb
|
272
|
+
- lib/delayed/job_groups/errors.rb
|
272
273
|
- lib/delayed/job_groups/job_extensions.rb
|
273
274
|
- lib/delayed/job_groups/job_group.rb
|
274
275
|
- lib/delayed/job_groups/plugin.rb
|
@@ -312,7 +313,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
312
313
|
- !ruby/object:Gem::Version
|
313
314
|
version: '0'
|
314
315
|
requirements: []
|
315
|
-
rubygems_version: 3.
|
316
|
+
rubygems_version: 3.4.1
|
316
317
|
signing_key:
|
317
318
|
specification_version: 4
|
318
319
|
summary: Delayed::Job job groups plugin
|