delayed 0.5.5 → 0.6.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/README.md +4 -0
- data/lib/delayed/runnable.rb +1 -1
- data/lib/delayed/worker.rb +9 -0
- data/spec/delayed/tasks_spec.rb +2 -2
- data/spec/helper.rb +14 -0
- data/spec/worker_spec.rb +57 -49
- metadata +2 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 6e71f18ed659d830765786daba4513f7cedfef9fb645055cd01e95af8be066b3
|
4
|
+
data.tar.gz: c3b0624ab16f81e2aa7e4296a56a4967e88e75659eca20078ad662c0cc7d37ec
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: b94b8a054612a71dc72078a0b62abf5db8a9bb305515ac75e2baeb39ab12d188eea4c168f3e774b3beebb608c821e808e2c24164a68fbdaebf894c7a566ec69e
|
7
|
+
data.tar.gz: f46b3769bc15ac507442548b1b9e810d0e70ae68a4a89eb29732c1c1b325d307eed593ab7ee49a78d6296bf69440ceb221ddb1e25e4b3237e5a723595c2903ed
|
data/README.md
CHANGED
@@ -432,6 +432,10 @@ Delayed::Worker.read_ahead = 5
|
|
432
432
|
|
433
433
|
# If a worker finds no jobs, it will sleep this number of seconds in between attempts:
|
434
434
|
Delayed::Worker.sleep_delay = 5
|
435
|
+
|
436
|
+
# Until version 1.0, the worker will not sleep at all between attemps if it finds jobs.
|
437
|
+
# This can be configured by setting the minimum reserve interval:
|
438
|
+
Delayed::Worker.min_reserve_interval = 0.5 # seconds
|
435
439
|
```
|
436
440
|
|
437
441
|
If a job fails, it will be rerun up to 25 times (with an exponential back-off). Jobs will also
|
data/lib/delayed/runnable.rb
CHANGED
data/lib/delayed/worker.rb
CHANGED
@@ -12,6 +12,7 @@ module Delayed
|
|
12
12
|
include Runnable
|
13
13
|
|
14
14
|
cattr_accessor :sleep_delay, instance_writer: false, default: 5
|
15
|
+
cattr_accessor :min_reserve_interval, instance_writer: false, default: 0
|
15
16
|
cattr_accessor :max_attempts, instance_writer: false, default: 25
|
16
17
|
cattr_accessor :max_claims, instance_writer: false, default: 5
|
17
18
|
cattr_accessor :max_run_time, instance_writer: false, default: 20.minutes
|
@@ -92,6 +93,7 @@ module Delayed
|
|
92
93
|
total = 0
|
93
94
|
|
94
95
|
while total < num
|
96
|
+
start = clock_time
|
95
97
|
jobs = reserve_jobs
|
96
98
|
break if jobs.empty?
|
97
99
|
|
@@ -107,6 +109,9 @@ module Delayed
|
|
107
109
|
pool.wait_for_termination
|
108
110
|
|
109
111
|
break if stop? # leave if we're exiting
|
112
|
+
|
113
|
+
elapsed = clock_time - start
|
114
|
+
interruptable_sleep(self.class.min_reserve_interval - elapsed)
|
110
115
|
end
|
111
116
|
|
112
117
|
[success.value, total - success.value]
|
@@ -227,5 +232,9 @@ module Delayed
|
|
227
232
|
def reload!
|
228
233
|
Rails.application.reloader.reload! if defined?(Rails.application.reloader) && Rails.application.reloader.check!
|
229
234
|
end
|
235
|
+
|
236
|
+
def clock_time
|
237
|
+
Process.clock_gettime(Process::CLOCK_MONOTONIC)
|
238
|
+
end
|
230
239
|
end
|
231
240
|
end
|
data/spec/delayed/tasks_spec.rb
CHANGED
@@ -64,7 +64,7 @@ describe 'rake' do
|
|
64
64
|
.to change { Delayed::Worker.min_priority }.from(nil).to(6)
|
65
65
|
.and change { Delayed::Worker.max_priority }.from(nil).to(8)
|
66
66
|
.and change { Delayed::Worker.queues }.from([]).to(%w(foo bar))
|
67
|
-
.and change { Delayed::Worker.sleep_delay }.from(
|
67
|
+
.and change { Delayed::Worker.sleep_delay }.from(TEST_SLEEP_DELAY).to(1)
|
68
68
|
.and change { Delayed::Worker.read_ahead }.from(5).to(3)
|
69
69
|
.and change { Delayed::Worker.max_claims }.from(5).to(3)
|
70
70
|
end
|
@@ -96,7 +96,7 @@ describe 'rake' do
|
|
96
96
|
.to change { Delayed::Worker.min_priority }.from(nil).to(6)
|
97
97
|
.and change { Delayed::Worker.max_priority }.from(nil).to(8)
|
98
98
|
.and change { Delayed::Worker.queues }.from([]).to(%w(foo))
|
99
|
-
.and change { Delayed::Worker.sleep_delay }.from(
|
99
|
+
.and change { Delayed::Worker.sleep_delay }.from(TEST_SLEEP_DELAY).to(1)
|
100
100
|
.and change { Delayed::Worker.read_ahead }.from(5).to(3)
|
101
101
|
.and change { Delayed::Worker.max_claims }.from(5).to(3)
|
102
102
|
end
|
data/spec/helper.rb
CHANGED
@@ -97,6 +97,11 @@ class SingletonClass
|
|
97
97
|
include Singleton
|
98
98
|
end
|
99
99
|
|
100
|
+
# Negative values are treated as sleep(0),
|
101
|
+
# so we can use different values to test the sleep behavior:
|
102
|
+
TEST_MIN_RESERVE_INTERVAL = -10
|
103
|
+
TEST_SLEEP_DELAY = -100
|
104
|
+
|
100
105
|
RSpec.configure do |config|
|
101
106
|
config.around(:each) do |example|
|
102
107
|
aj_priority_was = ActiveJob::Base.priority
|
@@ -113,6 +118,14 @@ RSpec.configure do |config|
|
|
113
118
|
queues_was = Delayed::Worker.queues
|
114
119
|
read_ahead_was = Delayed::Worker.read_ahead
|
115
120
|
sleep_delay_was = Delayed::Worker.sleep_delay
|
121
|
+
min_reserve_interval_was = Delayed::Worker.min_reserve_interval
|
122
|
+
|
123
|
+
if Gem.loaded_specs['delayed'].version >= Gem::Version.new('1.0') && min_reserve_interval_was.zero?
|
124
|
+
raise "Min reserve interval should be nonzero in v1.0 release"
|
125
|
+
end
|
126
|
+
|
127
|
+
Delayed::Worker.sleep_delay = TEST_SLEEP_DELAY
|
128
|
+
Delayed::Worker.min_reserve_interval = TEST_MIN_RESERVE_INTERVAL
|
116
129
|
|
117
130
|
example.run
|
118
131
|
ensure
|
@@ -130,6 +143,7 @@ RSpec.configure do |config|
|
|
130
143
|
Delayed::Worker.queues = queues_was
|
131
144
|
Delayed::Worker.read_ahead = read_ahead_was
|
132
145
|
Delayed::Worker.sleep_delay = sleep_delay_was
|
146
|
+
Delayed::Worker.min_reserve_interval = min_reserve_interval_was
|
133
147
|
|
134
148
|
Delayed::Job.delete_all
|
135
149
|
end
|
data/spec/worker_spec.rb
CHANGED
@@ -1,10 +1,6 @@
|
|
1
1
|
require 'helper'
|
2
2
|
|
3
3
|
describe Delayed::Worker do
|
4
|
-
before do
|
5
|
-
described_class.sleep_delay = 0
|
6
|
-
end
|
7
|
-
|
8
4
|
describe 'start' do
|
9
5
|
it 'runs the :execute lifecycle hook' do
|
10
6
|
performances = []
|
@@ -32,62 +28,74 @@ describe Delayed::Worker do
|
|
32
28
|
allow(subject).to receive(:interruptable_sleep).and_call_original
|
33
29
|
end
|
34
30
|
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
31
|
+
around do |example|
|
32
|
+
max_claims_was = described_class.max_claims
|
33
|
+
described_class.max_claims = max_claims
|
34
|
+
example.run
|
35
|
+
ensure
|
36
|
+
described_class.max_claims = max_claims_was
|
37
|
+
end
|
39
38
|
|
40
|
-
|
39
|
+
before do
|
40
|
+
allow(Delayed::Job).to receive(:reserve).and_return((0...jobs_returned).map { job }, [])
|
41
|
+
end
|
42
|
+
|
43
|
+
let(:max_claims) { 1 }
|
44
|
+
let(:jobs_returned) { 1 }
|
45
|
+
let(:job) do
|
46
|
+
instance_double(
|
47
|
+
Delayed::Job,
|
48
|
+
id: 123,
|
49
|
+
max_run_time: 10,
|
50
|
+
name: 'MyJob',
|
51
|
+
run_at: Delayed::Job.db_time_now,
|
52
|
+
created_at: Delayed::Job.db_time_now,
|
53
|
+
priority: Delayed::Priority.interactive,
|
54
|
+
queue: 'testqueue',
|
55
|
+
attempts: 0,
|
56
|
+
invoke_job: true,
|
57
|
+
destroy: true,
|
58
|
+
)
|
59
|
+
end
|
60
|
+
|
61
|
+
it 'logs the count and sleeps only within the loop' do
|
62
|
+
subject.run!
|
63
|
+
expect(Delayed.logger).to have_received(:info).with(/1 jobs processed/)
|
64
|
+
expect(subject).to have_received(:interruptable_sleep).once.with(a_value_within(1).of(TEST_MIN_RESERVE_INTERVAL))
|
65
|
+
expect(subject).not_to have_received(:interruptable_sleep).with(TEST_SLEEP_DELAY)
|
66
|
+
end
|
67
|
+
|
68
|
+
context 'when no jobs are returned' do
|
69
|
+
let(:jobs_returned) { 0 }
|
70
|
+
|
71
|
+
it 'does not log and then sleeps only outside of the loop' do
|
41
72
|
subject.run!
|
42
73
|
expect(Delayed.logger).not_to have_received(:info)
|
43
|
-
expect(subject).to have_received(:interruptable_sleep)
|
74
|
+
expect(subject).to have_received(:interruptable_sleep).with(TEST_SLEEP_DELAY)
|
44
75
|
end
|
45
76
|
end
|
46
77
|
|
47
|
-
context 'when
|
48
|
-
|
49
|
-
|
50
|
-
described_class.max_claims = max_claims
|
51
|
-
example.run
|
52
|
-
ensure
|
53
|
-
described_class.max_claims = max_claims_was
|
54
|
-
end
|
55
|
-
|
56
|
-
before do
|
57
|
-
allow(Delayed::Job).to receive(:reserve).and_return([job], [])
|
58
|
-
end
|
59
|
-
|
60
|
-
let(:max_claims) { 1 }
|
61
|
-
let(:job) do
|
62
|
-
instance_double(
|
63
|
-
Delayed::Job,
|
64
|
-
id: 123,
|
65
|
-
max_run_time: 10,
|
66
|
-
name: 'MyJob',
|
67
|
-
run_at: Delayed::Job.db_time_now,
|
68
|
-
created_at: Delayed::Job.db_time_now,
|
69
|
-
priority: Delayed::Priority.interactive,
|
70
|
-
queue: 'testqueue',
|
71
|
-
attempts: 0,
|
72
|
-
invoke_job: true,
|
73
|
-
destroy: true,
|
74
|
-
)
|
75
|
-
end
|
78
|
+
context 'when max_claims is 3 and 3 jobs are returned' do
|
79
|
+
let(:max_claims) { 3 }
|
80
|
+
let(:jobs_returned) { 3 }
|
76
81
|
|
77
|
-
it 'logs the count and
|
82
|
+
it 'logs the count and sleeps only in the loop' do
|
78
83
|
subject.run!
|
79
|
-
expect(Delayed.logger).to have_received(:info).with(/
|
80
|
-
expect(subject).
|
84
|
+
expect(Delayed.logger).to have_received(:info).with(/3 jobs processed/)
|
85
|
+
expect(subject).to have_received(:interruptable_sleep).once.with(a_value_within(1).of(TEST_MIN_RESERVE_INTERVAL))
|
86
|
+
expect(subject).not_to have_received(:interruptable_sleep).with(TEST_SLEEP_DELAY)
|
81
87
|
end
|
88
|
+
end
|
82
89
|
|
83
|
-
|
84
|
-
|
90
|
+
context 'when max_claims is 3 and 2 jobs are returned' do
|
91
|
+
let(:max_claims) { 3 }
|
92
|
+
let(:jobs_returned) { 2 }
|
85
93
|
|
86
|
-
|
87
|
-
|
88
|
-
|
89
|
-
|
90
|
-
|
94
|
+
it 'logs the count and sleeps both in the loop and outside of the loop' do
|
95
|
+
subject.run!
|
96
|
+
expect(Delayed.logger).to have_received(:info).with(/2 jobs processed/)
|
97
|
+
expect(subject).to have_received(:interruptable_sleep).once.with(a_value_within(1).of(TEST_MIN_RESERVE_INTERVAL))
|
98
|
+
expect(subject).to have_received(:interruptable_sleep).once.with(TEST_SLEEP_DELAY)
|
91
99
|
end
|
92
100
|
end
|
93
101
|
end
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: delayed
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.6.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Nathan Griffith
|
@@ -19,7 +19,7 @@ authors:
|
|
19
19
|
autorequire:
|
20
20
|
bindir: bin
|
21
21
|
cert_chain: []
|
22
|
-
date: 2024-
|
22
|
+
date: 2024-12-18 00:00:00.000000000 Z
|
23
23
|
dependencies:
|
24
24
|
- !ruby/object:Gem::Dependency
|
25
25
|
name: activerecord
|