delayed 0.1.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 +7 -0
- data/LICENSE +20 -0
- data/README.md +560 -0
- data/Rakefile +35 -0
- data/lib/delayed.rb +72 -0
- data/lib/delayed/active_job_adapter.rb +65 -0
- data/lib/delayed/backend/base.rb +166 -0
- data/lib/delayed/backend/job_preparer.rb +43 -0
- data/lib/delayed/exceptions.rb +14 -0
- data/lib/delayed/job.rb +250 -0
- data/lib/delayed/lifecycle.rb +85 -0
- data/lib/delayed/message_sending.rb +65 -0
- data/lib/delayed/monitor.rb +134 -0
- data/lib/delayed/performable_mailer.rb +22 -0
- data/lib/delayed/performable_method.rb +47 -0
- data/lib/delayed/plugin.rb +15 -0
- data/lib/delayed/plugins/connection.rb +13 -0
- data/lib/delayed/plugins/instrumentation.rb +39 -0
- data/lib/delayed/priority.rb +164 -0
- data/lib/delayed/psych_ext.rb +135 -0
- data/lib/delayed/railtie.rb +7 -0
- data/lib/delayed/runnable.rb +46 -0
- data/lib/delayed/serialization/active_record.rb +18 -0
- data/lib/delayed/syck_ext.rb +42 -0
- data/lib/delayed/tasks.rb +40 -0
- data/lib/delayed/worker.rb +233 -0
- data/lib/delayed/yaml_ext.rb +10 -0
- data/lib/delayed_job.rb +1 -0
- data/lib/delayed_job_active_record.rb +1 -0
- data/lib/generators/delayed/generator.rb +7 -0
- data/lib/generators/delayed/migration_generator.rb +28 -0
- data/lib/generators/delayed/next_migration_version.rb +14 -0
- data/lib/generators/delayed/templates/migration.rb +22 -0
- data/spec/autoloaded/clazz.rb +6 -0
- data/spec/autoloaded/instance_clazz.rb +5 -0
- data/spec/autoloaded/instance_struct.rb +6 -0
- data/spec/autoloaded/struct.rb +7 -0
- data/spec/database.yml +25 -0
- data/spec/delayed/active_job_adapter_spec.rb +267 -0
- data/spec/delayed/job_spec.rb +953 -0
- data/spec/delayed/monitor_spec.rb +276 -0
- data/spec/delayed/plugins/instrumentation_spec.rb +49 -0
- data/spec/delayed/priority_spec.rb +154 -0
- data/spec/delayed/serialization/active_record_spec.rb +15 -0
- data/spec/delayed/tasks_spec.rb +116 -0
- data/spec/helper.rb +196 -0
- data/spec/lifecycle_spec.rb +77 -0
- data/spec/message_sending_spec.rb +149 -0
- data/spec/performable_mailer_spec.rb +68 -0
- data/spec/performable_method_spec.rb +123 -0
- data/spec/psych_ext_spec.rb +94 -0
- data/spec/sample_jobs.rb +117 -0
- data/spec/worker_spec.rb +235 -0
- data/spec/yaml_ext_spec.rb +48 -0
- metadata +326 -0
@@ -0,0 +1,15 @@
|
|
1
|
+
require "helper"
|
2
|
+
|
3
|
+
describe ActiveRecord do
|
4
|
+
it "loads classes with non-default primary key" do
|
5
|
+
expect {
|
6
|
+
YAML.load(Story.create.to_yaml)
|
7
|
+
}.not_to raise_error
|
8
|
+
end
|
9
|
+
|
10
|
+
it "loads classes even if not in default scope" do
|
11
|
+
expect {
|
12
|
+
YAML.load(Story.create(scoped: false).to_yaml)
|
13
|
+
}.not_to raise_error
|
14
|
+
end
|
15
|
+
end
|
@@ -0,0 +1,116 @@
|
|
1
|
+
require 'helper'
|
2
|
+
|
3
|
+
describe 'rake' do
|
4
|
+
let(:runnable) { instance_double(Delayed::Runnable, start: true) }
|
5
|
+
|
6
|
+
before do
|
7
|
+
Rake::Task.clear
|
8
|
+
Rake::Task.define_task(:environment)
|
9
|
+
load 'lib/delayed/tasks.rb'
|
10
|
+
|
11
|
+
allow(ENV).to receive(:[]).and_call_original
|
12
|
+
allow(ENV).to receive(:key?).and_call_original
|
13
|
+
end
|
14
|
+
|
15
|
+
def stub_env(key, value)
|
16
|
+
allow(ENV).to receive(:[]).with(key).and_return(value)
|
17
|
+
allow(ENV).to receive(:key?).with(key).and_return(true)
|
18
|
+
end
|
19
|
+
|
20
|
+
describe 'delayed:work' do
|
21
|
+
before do
|
22
|
+
allow(Delayed::Worker).to receive(:new).and_return(runnable)
|
23
|
+
end
|
24
|
+
|
25
|
+
it 'starts a worker' do
|
26
|
+
Rake.application.invoke_task 'delayed:work'
|
27
|
+
expect(runnable).to have_received(:start)
|
28
|
+
end
|
29
|
+
|
30
|
+
context 'when configurations are set manually' do
|
31
|
+
before do
|
32
|
+
Delayed::Worker.min_priority = 99
|
33
|
+
Delayed::Worker.max_priority = 101
|
34
|
+
Delayed::Worker.queues = %w(a b c)
|
35
|
+
Delayed::Worker.sleep_delay = 1.5
|
36
|
+
Delayed::Worker.read_ahead = 100
|
37
|
+
Delayed::Worker.max_claims = 10
|
38
|
+
end
|
39
|
+
|
40
|
+
it 'does not override them' do
|
41
|
+
Rake.application.invoke_task('delayed:work')
|
42
|
+
|
43
|
+
expect(Delayed::Worker.min_priority).to eq 99
|
44
|
+
expect(Delayed::Worker.max_priority).to eq 101
|
45
|
+
expect(Delayed::Worker.queues).to eq %w(a b c)
|
46
|
+
expect(Delayed::Worker.sleep_delay).to eq 1.5
|
47
|
+
expect(Delayed::Worker.read_ahead).to eq 100
|
48
|
+
expect(Delayed::Worker.max_claims).to eq 10
|
49
|
+
end
|
50
|
+
end
|
51
|
+
|
52
|
+
context 'when environment variables are set' do
|
53
|
+
before do
|
54
|
+
stub_env('MIN_PRIORITY', '6')
|
55
|
+
stub_env('MAX_PRIORITY', '8')
|
56
|
+
stub_env('QUEUES', 'foo,bar')
|
57
|
+
stub_env('SLEEP_DELAY', '1')
|
58
|
+
stub_env('READ_AHEAD', '3')
|
59
|
+
stub_env('MAX_CLAIMS', '3')
|
60
|
+
end
|
61
|
+
|
62
|
+
it 'sets the worker config' do
|
63
|
+
expect { Rake.application.invoke_task('delayed:work') }
|
64
|
+
.to change { Delayed::Worker.min_priority }.from(nil).to(6)
|
65
|
+
.and change { Delayed::Worker.max_priority }.from(nil).to(8)
|
66
|
+
.and change { Delayed::Worker.queues }.from([]).to(%w(foo bar))
|
67
|
+
.and change { Delayed::Worker.sleep_delay }.from(5).to(1)
|
68
|
+
.and change { Delayed::Worker.read_ahead }.from(5).to(3)
|
69
|
+
.and change { Delayed::Worker.max_claims }.from(5).to(3)
|
70
|
+
end
|
71
|
+
end
|
72
|
+
end
|
73
|
+
|
74
|
+
describe 'delayed:monitor' do
|
75
|
+
before do
|
76
|
+
allow(Delayed::Monitor).to receive(:new).and_return(runnable)
|
77
|
+
end
|
78
|
+
|
79
|
+
it 'starts a monitor' do
|
80
|
+
Rake.application.invoke_task 'delayed:monitor'
|
81
|
+
expect(runnable).to have_received(:start)
|
82
|
+
end
|
83
|
+
|
84
|
+
context 'when environment variables are set' do
|
85
|
+
before do
|
86
|
+
stub_env('MIN_PRIORITY', '6')
|
87
|
+
stub_env('MAX_PRIORITY', '8')
|
88
|
+
stub_env('QUEUE', 'foo')
|
89
|
+
stub_env('SLEEP_DELAY', '1')
|
90
|
+
stub_env('READ_AHEAD', '3')
|
91
|
+
stub_env('MAX_CLAIMS', '3')
|
92
|
+
end
|
93
|
+
|
94
|
+
it 'sets the worker config' do
|
95
|
+
expect { Rake.application.invoke_task('delayed:monitor') }
|
96
|
+
.to change { Delayed::Worker.min_priority }.from(nil).to(6)
|
97
|
+
.and change { Delayed::Worker.max_priority }.from(nil).to(8)
|
98
|
+
.and change { Delayed::Worker.queues }.from([]).to(%w(foo))
|
99
|
+
.and change { Delayed::Worker.sleep_delay }.from(5).to(1)
|
100
|
+
.and change { Delayed::Worker.read_ahead }.from(5).to(3)
|
101
|
+
.and change { Delayed::Worker.max_claims }.from(5).to(3)
|
102
|
+
end
|
103
|
+
end
|
104
|
+
end
|
105
|
+
|
106
|
+
describe 'jobs:work' do
|
107
|
+
before do
|
108
|
+
allow(Delayed::Worker).to receive(:new).and_return(runnable)
|
109
|
+
end
|
110
|
+
|
111
|
+
it 'starts a worker' do
|
112
|
+
Rake.application.invoke_task 'jobs:work'
|
113
|
+
expect(runnable).to have_received(:start)
|
114
|
+
end
|
115
|
+
end
|
116
|
+
end
|
data/spec/helper.rb
ADDED
@@ -0,0 +1,196 @@
|
|
1
|
+
require 'rspec'
|
2
|
+
require 'timecop'
|
3
|
+
|
4
|
+
require 'action_mailer'
|
5
|
+
require 'active_job'
|
6
|
+
require 'active_record'
|
7
|
+
|
8
|
+
require 'delayed'
|
9
|
+
require 'sample_jobs'
|
10
|
+
|
11
|
+
require 'rake'
|
12
|
+
|
13
|
+
if ENV['DEBUG_LOGS']
|
14
|
+
Delayed.logger = Logger.new($stdout)
|
15
|
+
else
|
16
|
+
require 'tempfile'
|
17
|
+
|
18
|
+
tf = Tempfile.new('dj.log')
|
19
|
+
Delayed.logger = Logger.new(tf.path)
|
20
|
+
tf.unlink
|
21
|
+
end
|
22
|
+
ENV['RAILS_ENV'] = 'test'
|
23
|
+
|
24
|
+
db_adapter = ENV["ADAPTER"]
|
25
|
+
gemfile = ENV["BUNDLE_GEMFILE"]
|
26
|
+
db_adapter ||= gemfile && gemfile[%r{gemfiles/(.*?)/}] && $1 # rubocop:disable Style/PerlBackrefs
|
27
|
+
db_adapter ||= "sqlite3"
|
28
|
+
|
29
|
+
config = YAML.load(ERB.new(File.read("spec/database.yml")).result)
|
30
|
+
ActiveRecord::Base.establish_connection config[db_adapter]
|
31
|
+
ActiveRecord::Base.logger = Delayed.logger
|
32
|
+
ActiveRecord::Migration.verbose = false
|
33
|
+
|
34
|
+
# MySQL 5.7 no longer supports null default values for the primary key
|
35
|
+
# Override the default primary key type in Rails <= 4.0
|
36
|
+
# https://stackoverflow.com/a/34555109
|
37
|
+
if db_adapter == "mysql2"
|
38
|
+
types = if defined?(ActiveRecord::ConnectionAdapters::AbstractMysqlAdapter)
|
39
|
+
# ActiveRecord 3.2+
|
40
|
+
ActiveRecord::ConnectionAdapters::AbstractMysqlAdapter::NATIVE_DATABASE_TYPES
|
41
|
+
else
|
42
|
+
# ActiveRecord < 3.2
|
43
|
+
ActiveRecord::ConnectionAdapters::Mysql2Adapter::NATIVE_DATABASE_TYPES
|
44
|
+
end
|
45
|
+
types[:primary_key] = types[:primary_key].sub(" DEFAULT NULL", "")
|
46
|
+
end
|
47
|
+
|
48
|
+
migration_template = File.open("lib/generators/delayed/templates/migration.rb")
|
49
|
+
|
50
|
+
# need to eval the template with the migration_version intact
|
51
|
+
migration_context =
|
52
|
+
Class.new do
|
53
|
+
def my_binding
|
54
|
+
binding
|
55
|
+
end
|
56
|
+
|
57
|
+
private
|
58
|
+
|
59
|
+
def migration_version
|
60
|
+
"[#{ActiveRecord::VERSION::MAJOR}.#{ActiveRecord::VERSION::MINOR}]" if ActiveRecord::VERSION::MAJOR >= 5
|
61
|
+
end
|
62
|
+
end
|
63
|
+
|
64
|
+
migration_ruby = ERB.new(migration_template.read).result(migration_context.new.my_binding)
|
65
|
+
eval(migration_ruby) # rubocop:disable Security/Eval
|
66
|
+
|
67
|
+
ActiveRecord::Schema.define do
|
68
|
+
if table_exists?(:delayed_jobs)
|
69
|
+
# `if_exists: true` was only added in Rails 5
|
70
|
+
drop_table :delayed_jobs
|
71
|
+
end
|
72
|
+
|
73
|
+
CreateDelayedJobs.up
|
74
|
+
|
75
|
+
create_table :stories, primary_key: :story_id, force: true do |table|
|
76
|
+
table.string :text
|
77
|
+
table.boolean :scoped, default: true
|
78
|
+
end
|
79
|
+
end
|
80
|
+
|
81
|
+
class Story < ActiveRecord::Base
|
82
|
+
self.primary_key = :story_id
|
83
|
+
|
84
|
+
def tell
|
85
|
+
text
|
86
|
+
end
|
87
|
+
|
88
|
+
def whatever(number)
|
89
|
+
tell * number
|
90
|
+
end
|
91
|
+
default_scope { where(scoped: true) }
|
92
|
+
|
93
|
+
handle_asynchronously :whatever
|
94
|
+
end
|
95
|
+
|
96
|
+
class SingletonClass
|
97
|
+
include Singleton
|
98
|
+
end
|
99
|
+
|
100
|
+
RSpec.configure do |config|
|
101
|
+
config.around(:each) do |example|
|
102
|
+
aj_priority_was = ActiveJob::Base.priority
|
103
|
+
aj_queue_name_was = ActiveJob::Base.queue_name
|
104
|
+
default_priority_was = Delayed::Worker.default_priority
|
105
|
+
default_queue_name_was = Delayed::Worker.default_queue_name
|
106
|
+
delay_jobs_was = Delayed::Worker.delay_jobs
|
107
|
+
destroy_failed_jobs_was = Delayed::Worker.destroy_failed_jobs
|
108
|
+
max_attempts_was = Delayed::Worker.max_attempts
|
109
|
+
max_claims_was = Delayed::Worker.max_claims
|
110
|
+
max_priority_was = Delayed::Worker.max_priority
|
111
|
+
max_run_time_was = Delayed::Worker.max_run_time
|
112
|
+
min_priority_was = Delayed::Worker.min_priority
|
113
|
+
queues_was = Delayed::Worker.queues
|
114
|
+
read_ahead_was = Delayed::Worker.read_ahead
|
115
|
+
sleep_delay_was = Delayed::Worker.sleep_delay
|
116
|
+
|
117
|
+
example.run
|
118
|
+
ensure
|
119
|
+
ActiveJob::Base.priority = aj_priority_was
|
120
|
+
ActiveJob::Base.queue_name = aj_queue_name_was
|
121
|
+
Delayed::Worker.default_priority = default_priority_was
|
122
|
+
Delayed::Worker.default_queue_name = default_queue_name_was
|
123
|
+
Delayed::Worker.delay_jobs = delay_jobs_was
|
124
|
+
Delayed::Worker.destroy_failed_jobs = destroy_failed_jobs_was
|
125
|
+
Delayed::Worker.max_attempts = max_attempts_was
|
126
|
+
Delayed::Worker.max_claims = max_claims_was
|
127
|
+
Delayed::Worker.max_priority = max_priority_was
|
128
|
+
Delayed::Worker.max_run_time = max_run_time_was
|
129
|
+
Delayed::Worker.min_priority = min_priority_was
|
130
|
+
Delayed::Worker.queues = queues_was
|
131
|
+
Delayed::Worker.read_ahead = read_ahead_was
|
132
|
+
Delayed::Worker.sleep_delay = sleep_delay_was
|
133
|
+
|
134
|
+
Delayed::Job.delete_all
|
135
|
+
end
|
136
|
+
|
137
|
+
config.expect_with :rspec do |c|
|
138
|
+
c.syntax = :expect
|
139
|
+
end
|
140
|
+
end
|
141
|
+
|
142
|
+
# Add this directory so the ActiveSupport autoloading works
|
143
|
+
ActiveSupport::Dependencies.autoload_paths << File.dirname(__FILE__)
|
144
|
+
|
145
|
+
RSpec::Matchers.define :emit_notification do |expected_event_name|
|
146
|
+
attr_reader :actual, :expected
|
147
|
+
|
148
|
+
def supports_block_expectations?
|
149
|
+
true
|
150
|
+
end
|
151
|
+
|
152
|
+
chain :with_payload, :expected_payload
|
153
|
+
chain :with_value, :expected_value
|
154
|
+
diffable
|
155
|
+
|
156
|
+
match do |block|
|
157
|
+
@expected = { event_name: expected_event_name, payload: expected_payload, value: expected_value }
|
158
|
+
@actuals = []
|
159
|
+
callback = ->(name, _started, _finished, _unique_id, payload) do
|
160
|
+
@actuals << { event_name: name, payload: payload.except(:value), value: payload[:value] }
|
161
|
+
end
|
162
|
+
|
163
|
+
ActiveSupport::Notifications.subscribed(callback, expected_event_name, &block)
|
164
|
+
|
165
|
+
unless expected_payload
|
166
|
+
@actuals.each { |a| a.delete(:payload) }
|
167
|
+
@expected.delete(:payload)
|
168
|
+
end
|
169
|
+
|
170
|
+
@actual = @actuals.select { |a| values_match?(@expected.except(:value), a.except(:value)) }
|
171
|
+
@expected = [@expected]
|
172
|
+
values_match?(@expected, @actual)
|
173
|
+
end
|
174
|
+
|
175
|
+
failure_message do
|
176
|
+
<<~MSG
|
177
|
+
Expected the code block to emit:
|
178
|
+
#{@expected.first.inspect}
|
179
|
+
|
180
|
+
But instead, the following were emitted:
|
181
|
+
#{(@actual.presence || @actuals).map(&:inspect).join("\n ")}
|
182
|
+
MSG
|
183
|
+
end
|
184
|
+
end
|
185
|
+
|
186
|
+
def current_adapter
|
187
|
+
ENV.fetch('ADAPTER', 'sqlite3')
|
188
|
+
end
|
189
|
+
|
190
|
+
def current_database
|
191
|
+
if current_adapter == 'sqlite3'
|
192
|
+
a_string_ending_with('tmp/database.sqlite')
|
193
|
+
else
|
194
|
+
'delayed_job_test'
|
195
|
+
end
|
196
|
+
end
|
@@ -0,0 +1,77 @@
|
|
1
|
+
require 'helper'
|
2
|
+
|
3
|
+
describe Delayed::Lifecycle do
|
4
|
+
let(:lifecycle) { described_class.new }
|
5
|
+
let(:callback) { lambda { |*_args| } }
|
6
|
+
let(:arguments) { [1] }
|
7
|
+
let(:behavior) { double(Object, before!: nil, after!: nil, inside!: nil) }
|
8
|
+
let(:wrapped_block) { proc { behavior.inside! } }
|
9
|
+
|
10
|
+
describe 'before callbacks' do
|
11
|
+
before(:each) do
|
12
|
+
lifecycle.before(:enqueue, &callback)
|
13
|
+
end
|
14
|
+
|
15
|
+
it 'enqueues before wrapped block' do
|
16
|
+
expect(callback).to receive(:call).with(*arguments).ordered
|
17
|
+
expect(behavior).to receive(:inside!).ordered
|
18
|
+
lifecycle.run_callbacks :enqueue, *arguments, &wrapped_block
|
19
|
+
end
|
20
|
+
end
|
21
|
+
|
22
|
+
describe 'after callbacks' do
|
23
|
+
before(:each) do
|
24
|
+
lifecycle.after(:enqueue, &callback)
|
25
|
+
end
|
26
|
+
|
27
|
+
it 'enqueues after wrapped block' do
|
28
|
+
expect(behavior).to receive(:inside!).ordered
|
29
|
+
expect(callback).to receive(:call).with(*arguments).ordered
|
30
|
+
lifecycle.run_callbacks :enqueue, *arguments, &wrapped_block
|
31
|
+
end
|
32
|
+
end
|
33
|
+
|
34
|
+
describe 'around callbacks' do
|
35
|
+
before(:each) do
|
36
|
+
lifecycle.around(:enqueue) do |*args, &block|
|
37
|
+
behavior.before!
|
38
|
+
block.call(*args)
|
39
|
+
behavior.after!
|
40
|
+
end
|
41
|
+
end
|
42
|
+
|
43
|
+
it 'wraps a block' do
|
44
|
+
expect(behavior).to receive(:before!).ordered
|
45
|
+
expect(behavior).to receive(:inside!).ordered
|
46
|
+
expect(behavior).to receive(:after!).ordered
|
47
|
+
lifecycle.run_callbacks :enqueue, *arguments, &wrapped_block
|
48
|
+
end
|
49
|
+
|
50
|
+
it 'enqueues multiple callbacks in order' do
|
51
|
+
expect(behavior).to receive(:one).ordered
|
52
|
+
expect(behavior).to receive(:two).ordered
|
53
|
+
expect(behavior).to receive(:three).ordered
|
54
|
+
|
55
|
+
lifecycle.around(:enqueue) do |*args, &block|
|
56
|
+
behavior.one
|
57
|
+
block.call(*args)
|
58
|
+
end
|
59
|
+
lifecycle.around(:enqueue) do |*args, &block|
|
60
|
+
behavior.two
|
61
|
+
block.call(*args)
|
62
|
+
end
|
63
|
+
lifecycle.around(:enqueue) do |*args, &block|
|
64
|
+
behavior.three
|
65
|
+
block.call(*args)
|
66
|
+
end
|
67
|
+
lifecycle.run_callbacks(:enqueue, *arguments, &wrapped_block)
|
68
|
+
end
|
69
|
+
end
|
70
|
+
|
71
|
+
it 'raises if callback is enqueued with wrong number of parameters' do
|
72
|
+
lifecycle.before(:enqueue, &callback)
|
73
|
+
expect {
|
74
|
+
lifecycle.run_callbacks(:enqueue, 1, 2, 3) {} # no-op
|
75
|
+
}.to raise_error(ArgumentError, /1 parameter/)
|
76
|
+
end
|
77
|
+
end
|
@@ -0,0 +1,149 @@
|
|
1
|
+
require 'helper'
|
2
|
+
|
3
|
+
describe Delayed::MessageSending do
|
4
|
+
it 'does not include ClassMethods along with MessageSending' do
|
5
|
+
expect { ClassMethods }.to raise_error(NameError)
|
6
|
+
expect(defined?(String::ClassMethods)).to eq(nil)
|
7
|
+
end
|
8
|
+
|
9
|
+
describe 'handle_asynchronously' do
|
10
|
+
class Story
|
11
|
+
def tell!(_arg); end
|
12
|
+
handle_asynchronously :tell!
|
13
|
+
end
|
14
|
+
|
15
|
+
it 'aliases original method' do
|
16
|
+
expect(Story.new).to respond_to(:tell_without_delay!)
|
17
|
+
expect(Story.new).to respond_to(:tell_with_delay!)
|
18
|
+
end
|
19
|
+
|
20
|
+
it 'creates a PerformableMethod' do
|
21
|
+
story = Story.create
|
22
|
+
expect {
|
23
|
+
job = story.tell!(1)
|
24
|
+
expect(job.payload_object.class).to eq(Delayed::PerformableMethod)
|
25
|
+
expect(job.payload_object.method_name).to eq(:tell_without_delay!)
|
26
|
+
expect(job.payload_object.args).to eq([1])
|
27
|
+
}.to(change { Delayed::Job.count })
|
28
|
+
end
|
29
|
+
|
30
|
+
describe 'with options' do
|
31
|
+
class Fable
|
32
|
+
cattr_accessor :importance
|
33
|
+
def tell; end
|
34
|
+
handle_asynchronously :tell, priority: proc { importance }
|
35
|
+
end
|
36
|
+
|
37
|
+
it 'sets the priority based on the Fable importance' do
|
38
|
+
Fable.importance = 10
|
39
|
+
job = Fable.new.tell
|
40
|
+
expect(job.priority).to eq(10)
|
41
|
+
|
42
|
+
Fable.importance = 20
|
43
|
+
job = Fable.new.tell
|
44
|
+
expect(job.priority).to eq(20)
|
45
|
+
end
|
46
|
+
|
47
|
+
describe 'using a proc with parameters' do
|
48
|
+
class Yarn
|
49
|
+
attr_accessor :importance
|
50
|
+
|
51
|
+
def spin; end
|
52
|
+
handle_asynchronously :spin, priority: proc { |y| y.importance }
|
53
|
+
end
|
54
|
+
|
55
|
+
it 'sets the priority based on the Fable importance' do
|
56
|
+
job = Yarn.new.tap { |y| y.importance = 10 }.spin
|
57
|
+
expect(job.priority).to eq(10)
|
58
|
+
|
59
|
+
job = Yarn.new.tap { |y| y.importance = 20 }.spin
|
60
|
+
expect(job.priority).to eq(20)
|
61
|
+
end
|
62
|
+
end
|
63
|
+
end
|
64
|
+
end
|
65
|
+
|
66
|
+
context 'delay' do
|
67
|
+
class FairyTail
|
68
|
+
attr_accessor :happy_ending
|
69
|
+
|
70
|
+
def self.princesses; end
|
71
|
+
|
72
|
+
def tell
|
73
|
+
@happy_ending = true
|
74
|
+
end
|
75
|
+
end
|
76
|
+
|
77
|
+
after do
|
78
|
+
Delayed::Worker.default_queue_name = nil
|
79
|
+
end
|
80
|
+
|
81
|
+
it 'creates a new PerformableMethod job' do
|
82
|
+
expect {
|
83
|
+
job = 'hello'.delay.count('l')
|
84
|
+
expect(job.payload_object.class).to eq(Delayed::PerformableMethod)
|
85
|
+
expect(job.payload_object.method_name).to eq(:count)
|
86
|
+
expect(job.payload_object.args).to eq(['l'])
|
87
|
+
}.to change { Delayed::Job.count }.by(1)
|
88
|
+
end
|
89
|
+
|
90
|
+
it 'sets default priority' do
|
91
|
+
Delayed::Worker.default_priority = 99
|
92
|
+
job = FairyTail.delay.to_s
|
93
|
+
expect(job.priority).to eq(99)
|
94
|
+
end
|
95
|
+
|
96
|
+
it 'sets default queue name' do
|
97
|
+
Delayed::Worker.default_queue_name = 'abbazabba'
|
98
|
+
job = FairyTail.delay.to_s
|
99
|
+
expect(job.queue).to eq('abbazabba')
|
100
|
+
end
|
101
|
+
|
102
|
+
it 'sets job options' do
|
103
|
+
run_at = Time.parse('2010-05-03 12:55 AM')
|
104
|
+
job = FairyTail.delay(priority: 20, run_at: run_at).to_s
|
105
|
+
expect(job.run_at).to eq(run_at)
|
106
|
+
expect(job.priority).to eq(20)
|
107
|
+
end
|
108
|
+
|
109
|
+
it 'does not delay the job when delay_jobs is false' do
|
110
|
+
Delayed::Worker.delay_jobs = false
|
111
|
+
fairy_tail = FairyTail.new
|
112
|
+
expect {
|
113
|
+
expect {
|
114
|
+
fairy_tail.delay.tell
|
115
|
+
}.to change { fairy_tail.happy_ending }.from(nil).to(true)
|
116
|
+
}.not_to(change { Delayed::Job.count })
|
117
|
+
end
|
118
|
+
|
119
|
+
it 'does delay the job when delay_jobs is true' do
|
120
|
+
Delayed::Worker.delay_jobs = true
|
121
|
+
fairy_tail = FairyTail.new
|
122
|
+
expect {
|
123
|
+
expect {
|
124
|
+
fairy_tail.delay.tell
|
125
|
+
}.not_to change { fairy_tail.happy_ending }
|
126
|
+
}.to change { Delayed::Job.count }.by(1)
|
127
|
+
end
|
128
|
+
|
129
|
+
it 'does delay when delay_jobs is a proc returning true' do
|
130
|
+
Delayed::Worker.delay_jobs = ->(_job) { true }
|
131
|
+
fairy_tail = FairyTail.new
|
132
|
+
expect {
|
133
|
+
expect {
|
134
|
+
fairy_tail.delay.tell
|
135
|
+
}.not_to change { fairy_tail.happy_ending }
|
136
|
+
}.to change { Delayed::Job.count }.by(1)
|
137
|
+
end
|
138
|
+
|
139
|
+
it 'does not delay the job when delay_jobs is a proc returning false' do
|
140
|
+
Delayed::Worker.delay_jobs = ->(_job) { false }
|
141
|
+
fairy_tail = FairyTail.new
|
142
|
+
expect {
|
143
|
+
expect {
|
144
|
+
fairy_tail.delay.tell
|
145
|
+
}.to change { fairy_tail.happy_ending }.from(nil).to(true)
|
146
|
+
}.not_to(change { Delayed::Job.count })
|
147
|
+
end
|
148
|
+
end
|
149
|
+
end
|