inst-jobs 2.0.0 → 3.0.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/db/migrate/20101216224513_create_delayed_jobs.rb +9 -7
- data/db/migrate/20110531144916_cleanup_delayed_jobs_indexes.rb +8 -13
- data/db/migrate/20110610213249_optimize_delayed_jobs.rb +8 -8
- data/db/migrate/20110831210257_add_delayed_jobs_next_in_strand.rb +25 -25
- data/db/migrate/20120510004759_delayed_jobs_delete_trigger_lock_for_update.rb +4 -8
- data/db/migrate/20120531150712_drop_psql_jobs_pop_fn.rb +1 -3
- data/db/migrate/20120607164022_delayed_jobs_use_advisory_locks.rb +11 -15
- data/db/migrate/20120607181141_index_jobs_on_locked_by.rb +1 -1
- data/db/migrate/20120608191051_add_jobs_run_at_index.rb +2 -2
- data/db/migrate/20120927184213_change_delayed_jobs_handler_to_text.rb +1 -1
- data/db/migrate/20140505215510_copy_failed_jobs_original_id.rb +2 -3
- data/db/migrate/20150807133223_add_max_concurrent_to_jobs.rb +9 -13
- data/db/migrate/20151210162949_improve_max_concurrent.rb +4 -8
- data/db/migrate/20161206323555_add_back_default_string_limits_jobs.rb +3 -2
- data/db/migrate/20181217155351_speed_up_max_concurrent_triggers.rb +13 -17
- data/db/migrate/20200330230722_add_id_to_get_delayed_jobs_index.rb +8 -8
- data/db/migrate/20200824222232_speed_up_max_concurrent_delete_trigger.rb +72 -77
- data/db/migrate/20200825011002_add_strand_order_override.rb +93 -97
- data/db/migrate/20210809145804_add_n_strand_index.rb +12 -0
- data/db/migrate/20210812210128_add_singleton_column.rb +200 -0
- data/db/migrate/20210917232626_add_delete_conflicting_singletons_before_unlock_trigger.rb +27 -0
- data/db/migrate/20210928174754_fix_singleton_condition_in_before_insert.rb +56 -0
- data/db/migrate/20210929204903_update_conflicting_singleton_function_to_use_index.rb +27 -0
- data/exe/inst_jobs +3 -2
- data/lib/delayed/backend/active_record.rb +211 -168
- data/lib/delayed/backend/base.rb +110 -72
- data/lib/delayed/batch.rb +11 -9
- data/lib/delayed/cli.rb +98 -84
- data/lib/delayed/core_ext/kernel.rb +4 -2
- data/lib/delayed/daemon.rb +70 -74
- data/lib/delayed/job_tracking.rb +26 -25
- data/lib/delayed/lifecycle.rb +27 -23
- data/lib/delayed/log_tailer.rb +17 -17
- data/lib/delayed/logging.rb +13 -16
- data/lib/delayed/message_sending.rb +43 -52
- data/lib/delayed/performable_method.rb +6 -8
- data/lib/delayed/periodic.rb +72 -68
- data/lib/delayed/plugin.rb +2 -4
- data/lib/delayed/pool.rb +205 -168
- data/lib/delayed/server/helpers.rb +6 -6
- data/lib/delayed/server.rb +51 -54
- data/lib/delayed/settings.rb +94 -81
- data/lib/delayed/testing.rb +21 -22
- data/lib/delayed/version.rb +1 -1
- data/lib/delayed/work_queue/in_process.rb +21 -17
- data/lib/delayed/work_queue/parent_process/client.rb +55 -53
- data/lib/delayed/work_queue/parent_process/server.rb +245 -207
- data/lib/delayed/work_queue/parent_process.rb +52 -53
- data/lib/delayed/worker/consul_health_check.rb +32 -33
- data/lib/delayed/worker/health_check.rb +34 -26
- data/lib/delayed/worker/null_health_check.rb +3 -1
- data/lib/delayed/worker/process_helper.rb +8 -9
- data/lib/delayed/worker.rb +272 -241
- data/lib/delayed/yaml_extensions.rb +12 -10
- data/lib/delayed_job.rb +37 -37
- data/lib/inst-jobs.rb +1 -1
- data/spec/active_record_job_spec.rb +143 -139
- data/spec/delayed/cli_spec.rb +7 -7
- data/spec/delayed/daemon_spec.rb +10 -9
- data/spec/delayed/message_sending_spec.rb +16 -9
- data/spec/delayed/periodic_spec.rb +14 -21
- data/spec/delayed/server_spec.rb +38 -38
- data/spec/delayed/settings_spec.rb +26 -25
- data/spec/delayed/work_queue/in_process_spec.rb +7 -8
- data/spec/delayed/work_queue/parent_process/client_spec.rb +17 -12
- data/spec/delayed/work_queue/parent_process/server_spec.rb +117 -41
- data/spec/delayed/work_queue/parent_process_spec.rb +21 -23
- data/spec/delayed/worker/consul_health_check_spec.rb +37 -50
- data/spec/delayed/worker/health_check_spec.rb +60 -52
- data/spec/delayed/worker_spec.rb +44 -21
- data/spec/sample_jobs.rb +45 -15
- data/spec/shared/delayed_batch.rb +74 -67
- data/spec/shared/delayed_method.rb +143 -102
- data/spec/shared/performable_method.rb +39 -38
- data/spec/shared/shared_backend.rb +550 -437
- data/spec/shared/testing.rb +14 -14
- data/spec/shared/worker.rb +156 -148
- data/spec/shared_jobs_specs.rb +13 -13
- data/spec/spec_helper.rb +53 -55
- metadata +148 -82
- data/lib/delayed/backend/redis/bulk_update.lua +0 -50
- data/lib/delayed/backend/redis/destroy_job.lua +0 -2
- data/lib/delayed/backend/redis/enqueue.lua +0 -29
- data/lib/delayed/backend/redis/fail_job.lua +0 -5
- data/lib/delayed/backend/redis/find_available.lua +0 -3
- data/lib/delayed/backend/redis/functions.rb +0 -59
- data/lib/delayed/backend/redis/get_and_lock_next_available.lua +0 -17
- data/lib/delayed/backend/redis/includes/jobs_common.lua +0 -203
- data/lib/delayed/backend/redis/job.rb +0 -535
- data/lib/delayed/backend/redis/set_running.lua +0 -5
- data/lib/delayed/backend/redis/tickle_strand.lua +0 -2
- data/spec/gemfiles/42.gemfile +0 -7
- data/spec/gemfiles/50.gemfile +0 -7
- data/spec/gemfiles/51.gemfile +0 -7
- data/spec/gemfiles/52.gemfile +0 -7
- data/spec/gemfiles/60.gemfile +0 -7
- data/spec/redis_job_spec.rb +0 -148
@@ -1,131 +1,183 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
-
|
4
|
-
|
3
|
+
module UnlessInJob
|
4
|
+
class << self
|
5
|
+
attr_accessor :runs
|
6
|
+
|
7
|
+
def run
|
8
|
+
self.runs += 1
|
9
|
+
end
|
10
|
+
|
11
|
+
def run_later
|
12
|
+
delay(synchronous: Delayed::Job.in_delayed_job?).run
|
13
|
+
end
|
14
|
+
end
|
15
|
+
end
|
16
|
+
|
17
|
+
shared_examples_for "random ruby objects" do
|
18
|
+
def set_queue(name) # rubocop:disable Naming/AccessorMethodName
|
5
19
|
old_name = Delayed::Settings.queue
|
6
20
|
Delayed::Settings.queue = name
|
7
21
|
ensure
|
8
22
|
Delayed::Settings.queue = old_name
|
9
23
|
end
|
10
24
|
|
11
|
-
it "
|
25
|
+
it "respond_toes :delay method" do
|
12
26
|
Object.new.respond_to?(:delay)
|
13
27
|
end
|
14
28
|
|
15
|
-
it "
|
16
|
-
|
29
|
+
it "raises a ArgumentError if delay is called but the target method doesn't exist" do
|
30
|
+
expect { Object.new.delay.method_that_deos_not_exist }.to raise_error(NoMethodError)
|
17
31
|
end
|
18
32
|
|
19
|
-
it "
|
20
|
-
|
33
|
+
it "adds a new entry to the job table when delay is called on it" do
|
34
|
+
expect { Object.new.delay.to_s }.to change { Delayed::Job.jobs_count(:current) }.by(1)
|
21
35
|
end
|
22
36
|
|
23
|
-
it "
|
24
|
-
|
37
|
+
it "adds a new entry to the job table when delay is called on it with a queue" do
|
38
|
+
expect { Object.new.delay(queue: "testqueue").to_s }.to change {
|
39
|
+
Delayed::Job.jobs_count(:current, "testqueue")
|
40
|
+
}.by(1)
|
25
41
|
end
|
26
42
|
|
27
|
-
it "
|
28
|
-
|
43
|
+
it "adds a new entry to the job table when delay is called on the class" do
|
44
|
+
expect { Object.delay.to_s }.to change { Delayed::Job.jobs_count(:current) }.by(1)
|
29
45
|
end
|
30
46
|
|
31
|
-
it "
|
32
|
-
|
47
|
+
it "adds a new entry to the job table when delay is called on the class with a queue" do
|
48
|
+
expect { Object.delay(queue: "testqueue").to_s }.to change { Delayed::Job.jobs_count(:current, "testqueue") }.by(1)
|
33
49
|
end
|
34
50
|
|
35
51
|
context "class methods" do
|
36
52
|
context "handle_asynchronously" do
|
37
|
-
it "
|
53
|
+
it "works with default_async" do
|
38
54
|
klass = Class.new do
|
39
55
|
attr_reader :ran
|
40
|
-
|
56
|
+
|
57
|
+
def test_method
|
58
|
+
@ran = true
|
59
|
+
end
|
41
60
|
handle_asynchronously :test_method
|
42
61
|
end
|
43
62
|
obj = klass.new
|
44
|
-
|
45
|
-
obj.ran.
|
46
|
-
|
47
|
-
obj.ran.
|
63
|
+
expect { obj.test_method }.to change { Delayed::Job.jobs_count(:current) }.by(1)
|
64
|
+
expect(obj.ran).to be_falsey
|
65
|
+
expect { obj.test_method(synchronous: true) }.not_to(change { Delayed::Job.jobs_count(:current) })
|
66
|
+
expect(obj.ran).to be true
|
48
67
|
end
|
49
68
|
|
50
|
-
it
|
69
|
+
it "must work with enqueue args that are lambdas" do
|
51
70
|
klass = Class.new do
|
52
71
|
attr_reader :ran
|
53
|
-
|
54
|
-
|
72
|
+
|
73
|
+
def test_method
|
74
|
+
@ran = true
|
75
|
+
end
|
76
|
+
handle_asynchronously :test_method, singleton: ->(obj) { "foobar:#{obj.object_id}" }
|
55
77
|
end
|
56
78
|
|
57
79
|
obj = klass.new
|
58
|
-
|
80
|
+
expect { obj.test_method }.to change { Delayed::Job.jobs_count(:current) }.by(1)
|
59
81
|
end
|
60
82
|
|
61
|
-
it
|
83
|
+
it "must work with kwargs in the original method" do
|
62
84
|
klass = Class.new do
|
63
85
|
attr_reader :run
|
64
|
-
|
86
|
+
|
87
|
+
def test_method(my_kwarg: nil)
|
88
|
+
@run = my_kwarg
|
89
|
+
end
|
65
90
|
handle_asynchronously :test_method
|
66
91
|
|
67
|
-
def other_test(arg)
|
92
|
+
def other_test(arg)
|
93
|
+
@foo = arg
|
94
|
+
end
|
68
95
|
handle_asynchronously :other_test
|
69
96
|
end
|
70
97
|
|
71
98
|
obj = klass.new
|
72
|
-
obj.test_method(my_kwarg:
|
73
|
-
expect(obj.run).to eq
|
99
|
+
obj.test_method(my_kwarg: "foo", synchronous: true)
|
100
|
+
expect(obj.run).to eq "foo"
|
74
101
|
end
|
75
102
|
|
76
|
-
it "
|
103
|
+
it "sends along enqueue args and args" do
|
77
104
|
klass = Class.new do
|
78
105
|
attr_accessor :ran
|
79
|
-
|
80
|
-
|
106
|
+
|
107
|
+
def test_method(*args)
|
108
|
+
@ran = args
|
109
|
+
end
|
110
|
+
handle_asynchronously(:test_method, enqueue_arg1: :thing)
|
81
111
|
end
|
82
112
|
obj = klass.new
|
83
|
-
method = double
|
84
|
-
|
85
|
-
expect(Delayed::PerformableMethod).to receive(:new)
|
86
|
-
|
87
|
-
|
88
|
-
|
89
|
-
|
90
|
-
|
113
|
+
method = double
|
114
|
+
|
115
|
+
expect(Delayed::PerformableMethod).to receive(:new)
|
116
|
+
.with(obj,
|
117
|
+
:test_method,
|
118
|
+
args: [1, 2, 3],
|
119
|
+
kwargs: { synchronous: true },
|
120
|
+
on_failure: nil,
|
121
|
+
on_permanent_failure: nil,
|
122
|
+
sender: obj)
|
123
|
+
.and_return(method)
|
124
|
+
expect(Delayed::Job).to receive(:enqueue).with(method, enqueue_arg1: :thing)
|
125
|
+
obj.test_method(1, 2, 3)
|
126
|
+
|
127
|
+
expect(Delayed::PerformableMethod).to receive(:new)
|
128
|
+
.with(obj,
|
129
|
+
:test_method,
|
130
|
+
args: [4],
|
131
|
+
kwargs: { synchronous: true },
|
132
|
+
on_failure: nil,
|
133
|
+
on_permanent_failure: nil,
|
134
|
+
sender: obj)
|
135
|
+
.and_return(method)
|
136
|
+
expect(Delayed::Job).to receive(:enqueue).with(method, enqueue_arg1: :thing)
|
91
137
|
obj.test_method(4)
|
92
138
|
|
93
|
-
obj.ran.
|
139
|
+
expect(obj.ran).to be_nil
|
94
140
|
obj.test_method(7, synchronous: true)
|
95
|
-
obj.ran.
|
141
|
+
expect(obj.ran).to eq([7])
|
96
142
|
obj.ran = nil
|
97
|
-
obj.ran.
|
98
|
-
obj.test_method(8,9, synchronous: true)
|
99
|
-
obj.ran.
|
143
|
+
expect(obj.ran).to eq(nil)
|
144
|
+
obj.test_method(8, 9, synchronous: true)
|
145
|
+
expect(obj.ran).to eq([8, 9])
|
100
146
|
end
|
101
147
|
|
102
|
-
it "
|
148
|
+
it "handles punctuation correctly" do
|
103
149
|
klass = Class.new do
|
104
150
|
attr_reader :ran
|
105
|
-
|
151
|
+
|
152
|
+
def test_method?
|
153
|
+
@ran = true
|
154
|
+
end
|
106
155
|
handle_asynchronously :test_method?
|
107
156
|
end
|
108
157
|
obj = klass.new
|
109
|
-
|
110
|
-
obj.ran.
|
111
|
-
|
112
|
-
obj.ran.
|
158
|
+
expect { obj.test_method? }.to change { Delayed::Job.jobs_count(:current) }.by(1)
|
159
|
+
expect(obj.ran).to be_falsey
|
160
|
+
expect { obj.test_method?(synchronous: true) }.not_to(change { Delayed::Job.jobs_count(:current) })
|
161
|
+
expect(obj.ran).to be true
|
113
162
|
end
|
114
163
|
|
115
|
-
it "
|
164
|
+
it "handles assignment punctuation correctly" do
|
116
165
|
klass = Class.new do
|
117
166
|
attr_reader :ran
|
118
|
-
|
167
|
+
|
168
|
+
def test_method=(val)
|
169
|
+
@ran = val
|
170
|
+
end
|
119
171
|
handle_asynchronously :test_method=
|
120
172
|
end
|
121
173
|
obj = klass.new
|
122
|
-
|
123
|
-
obj.ran.
|
124
|
-
|
125
|
-
obj.ran.
|
174
|
+
expect { obj.test_method = 3 }.to change { Delayed::Job.jobs_count(:current) }.by(1)
|
175
|
+
expect(obj.ran).to be_nil
|
176
|
+
expect { obj.send(:test_method=, 5, synchronous: true) }.not_to(change { Delayed::Job.jobs_count(:current) })
|
177
|
+
expect(obj.ran).to eq(5)
|
126
178
|
end
|
127
179
|
|
128
|
-
it "
|
180
|
+
it "correctlies sort out method accessibility" do
|
129
181
|
klass1 = Class.new do
|
130
182
|
def test_method; end
|
131
183
|
handle_asynchronously :test_method
|
@@ -133,114 +185,103 @@ shared_examples_for 'random ruby objects' do
|
|
133
185
|
|
134
186
|
klass2 = Class.new do
|
135
187
|
protected
|
188
|
+
|
136
189
|
def test_method; end
|
137
190
|
handle_asynchronously :test_method
|
138
191
|
end
|
139
192
|
|
140
193
|
klass3 = Class.new do
|
141
194
|
private
|
195
|
+
|
142
196
|
def test_method; end
|
143
197
|
handle_asynchronously :test_method
|
144
198
|
end
|
145
199
|
|
146
|
-
klass1.public_method_defined?(:test_method).
|
147
|
-
klass2.protected_method_defined?(:test_method).
|
148
|
-
klass3.private_method_defined?(:test_method).
|
200
|
+
expect(klass1.public_method_defined?(:test_method)).to be true
|
201
|
+
expect(klass2.protected_method_defined?(:test_method)).to be true
|
202
|
+
expect(klass3.private_method_defined?(:test_method)).to be true
|
149
203
|
end
|
150
204
|
end
|
151
205
|
end
|
152
206
|
|
153
|
-
it "
|
154
|
-
story = Story.create :
|
207
|
+
it "calls send later on methods which are wrapped with handle_asynchronously" do
|
208
|
+
story = Story.create text: "Once upon..."
|
155
209
|
|
156
210
|
expect { story.whatever(1, 5) }.to change { Delayed::Job.jobs_count(:current) }.by(1)
|
157
211
|
|
158
212
|
job = Delayed::Job.list_jobs(:current, 1).first
|
159
|
-
job.payload_object.class.
|
160
|
-
job.payload_object.method.
|
161
|
-
job.payload_object.args.
|
162
|
-
job.payload_object.kwargs.
|
163
|
-
job.payload_object.perform.
|
213
|
+
expect(job.payload_object.class).to eq(Delayed::PerformableMethod)
|
214
|
+
expect(job.payload_object.method).to eq(:whatever)
|
215
|
+
expect(job.payload_object.args).to eq([1, 5])
|
216
|
+
expect(job.payload_object.kwargs).to eq({ synchronous: true })
|
217
|
+
expect(job.payload_object.perform).to eq("Once upon...")
|
164
218
|
end
|
165
219
|
|
166
220
|
context "delay" do
|
167
|
-
it "
|
221
|
+
it "uses the default queue if there is one" do
|
168
222
|
set_queue("testqueue") do
|
169
223
|
"string".delay.reverse
|
170
224
|
job = Delayed::Job.list_jobs(:current, 1).first
|
171
|
-
job.queue.
|
225
|
+
expect(job.queue).to eq("testqueue")
|
172
226
|
|
173
227
|
"string".delay(queue: nil).reverse
|
174
228
|
job2 = Delayed::Job.list_jobs(:current, 2).last
|
175
|
-
job2.queue.
|
229
|
+
expect(job2.queue).to eq("testqueue")
|
176
230
|
end
|
177
231
|
end
|
178
232
|
|
179
|
-
it "
|
233
|
+
it "requires a queue" do
|
180
234
|
expect { set_queue(nil) }.to raise_error(ArgumentError)
|
181
235
|
end
|
182
236
|
end
|
183
237
|
|
184
238
|
context "delay with run_at" do
|
185
|
-
it "
|
186
|
-
|
239
|
+
it "queues a new job" do
|
240
|
+
expect do
|
187
241
|
"string".delay(run_at: 1.hour.from_now).length
|
188
|
-
end.
|
242
|
+
end.to change { Delayed::Job.jobs_count(:future) }.by(1)
|
189
243
|
end
|
190
244
|
|
191
|
-
it "
|
245
|
+
it "schedules the job in the future" do
|
192
246
|
time = 1.hour.from_now
|
193
247
|
"string".delay(run_at: time).length
|
194
248
|
job = Delayed::Job.list_jobs(:future, 1).first
|
195
|
-
job.run_at.to_i.
|
249
|
+
expect(job.run_at.to_i).to eq(time.to_i)
|
196
250
|
end
|
197
251
|
|
198
|
-
it "
|
199
|
-
"string".delay(run_at: 1.hour.from_now).count(
|
252
|
+
it "stores payload as PerformableMethod" do
|
253
|
+
"string".delay(run_at: 1.hour.from_now).count("r")
|
200
254
|
job = Delayed::Job.list_jobs(:future, 1).first
|
201
|
-
job.payload_object.class.
|
202
|
-
job.payload_object.method.
|
203
|
-
job.payload_object.args.
|
204
|
-
job.payload_object.perform.
|
255
|
+
expect(job.payload_object.class).to eq(Delayed::PerformableMethod)
|
256
|
+
expect(job.payload_object.method).to eq(:count)
|
257
|
+
expect(job.payload_object.args).to eq(["r"])
|
258
|
+
expect(job.payload_object.perform).to eq(1)
|
205
259
|
end
|
206
260
|
|
207
|
-
it "
|
261
|
+
it "uses the default queue if there is one" do
|
208
262
|
set_queue("testqueue") do
|
209
263
|
"string".delay(run_at: 1.hour.from_now).reverse
|
210
264
|
job = Delayed::Job.list_jobs(:current, 1).first
|
211
|
-
job.queue.
|
265
|
+
expect(job.queue).to eq("testqueue")
|
212
266
|
end
|
213
267
|
end
|
214
268
|
end
|
215
269
|
|
216
270
|
describe "delay with synchronous argument" do
|
217
|
-
module UnlessInJob
|
218
|
-
@runs = 0
|
219
|
-
def self.runs; @runs; end
|
220
|
-
|
221
|
-
def self.run
|
222
|
-
@runs += 1
|
223
|
-
end
|
224
|
-
|
225
|
-
def self.run_later
|
226
|
-
self.delay(synchronous: Delayed::Job.in_delayed_job?).run
|
227
|
-
end
|
228
|
-
end
|
229
|
-
|
230
271
|
before do
|
231
|
-
UnlessInJob.
|
272
|
+
UnlessInJob.runs = 0
|
232
273
|
end
|
233
274
|
|
234
|
-
it "
|
275
|
+
it "performs immediately if in job" do
|
235
276
|
UnlessInJob.delay.run_later
|
236
277
|
job = Delayed::Job.list_jobs(:current, 1).first
|
237
278
|
job.invoke_job
|
238
|
-
UnlessInJob.runs.
|
279
|
+
expect(UnlessInJob.runs).to eq(1)
|
239
280
|
end
|
240
281
|
|
241
|
-
it "
|
282
|
+
it "queues up for later if not in job" do
|
242
283
|
UnlessInJob.run_later
|
243
|
-
UnlessInJob.runs.
|
284
|
+
expect(UnlessInJob.runs).to eq(0)
|
244
285
|
end
|
245
286
|
end
|
246
287
|
end
|
@@ -1,73 +1,74 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
-
shared_examples_for
|
4
|
-
|
5
|
-
|
6
|
-
story = Story.create :text => 'Once upon...'
|
3
|
+
shared_examples_for "Delayed::PerformableMethod" do
|
4
|
+
it "does not ignore ActiveRecord::RecordNotFound errors because they are not always permanent" do
|
5
|
+
story = Story.create text: "Once upon..."
|
7
6
|
p = Delayed::PerformableMethod.new(story, :tell)
|
8
7
|
story.destroy
|
9
|
-
|
8
|
+
expect { YAML.load(p.to_yaml) }.to raise_error(Delayed::Backend::RecordNotFound)
|
10
9
|
end
|
11
10
|
|
12
|
-
it "
|
13
|
-
story = Story.create :
|
11
|
+
it "stores the object using native YAML even if its an active record" do
|
12
|
+
story = Story.create text: "Once upon..."
|
14
13
|
p = Delayed::PerformableMethod.new(story, :tell)
|
15
|
-
p.class.
|
16
|
-
p.object.
|
17
|
-
p.method.
|
18
|
-
p.args.
|
19
|
-
p.perform.
|
14
|
+
expect(p.class).to eq(Delayed::PerformableMethod)
|
15
|
+
expect(p.object).to eq(story)
|
16
|
+
expect(p.method).to eq(:tell)
|
17
|
+
expect(p.args).to eq([])
|
18
|
+
expect(p.perform).to eq("Once upon...")
|
20
19
|
end
|
21
20
|
|
22
|
-
it "
|
23
|
-
Story.create!(:
|
21
|
+
it "allows class methods to be called on ActiveRecord models" do
|
22
|
+
Story.create!(text: "Once upon a...")
|
24
23
|
p = Delayed::PerformableMethod.new(Story, :count)
|
25
|
-
|
24
|
+
expect { expect(p.send(:perform)).to be 1 }.not_to raise_error
|
26
25
|
end
|
27
26
|
|
28
|
-
it "
|
27
|
+
it "allows class methods to be called" do
|
29
28
|
p = Delayed::PerformableMethod.new(StoryReader, :reverse, args: ["ohai"])
|
30
|
-
|
29
|
+
expect { expect(p.send(:perform)).to eq("iaho") }.not_to raise_error
|
31
30
|
end
|
32
31
|
|
33
|
-
it "
|
32
|
+
it "allows module methods to be called" do
|
34
33
|
p = Delayed::PerformableMethod.new(MyReverser, :reverse, args: ["ohai"])
|
35
|
-
|
34
|
+
expect { expect(p.send(:perform)).to eq("iaho") }.not_to raise_error
|
36
35
|
end
|
37
36
|
|
38
|
-
it "
|
39
|
-
story = Story.create :
|
37
|
+
it "stores arguments as native YAML if they are active record objects" do
|
38
|
+
story = Story.create text: "Once upon..."
|
40
39
|
reader = StoryReader.new
|
41
40
|
p = Delayed::PerformableMethod.new(reader, :read, args: [story])
|
42
|
-
p.class.
|
43
|
-
p.method.
|
44
|
-
p.args.
|
45
|
-
p.perform.
|
41
|
+
expect(p.class).to eq(Delayed::PerformableMethod)
|
42
|
+
expect(p.method).to eq(:read)
|
43
|
+
expect(p.args).to eq([story])
|
44
|
+
expect(p.perform).to eq("Epilog: Once upon...")
|
46
45
|
end
|
47
46
|
|
48
|
-
it "
|
49
|
-
story = Story.create :
|
47
|
+
it "deeplies de-AR-ize arguments in full name" do
|
48
|
+
story = Story.create text: "Once upon..."
|
50
49
|
reader = StoryReader.new
|
51
|
-
p = Delayed::PerformableMethod.new(reader, :read, args: [[
|
52
|
-
p.full_name.
|
50
|
+
p = Delayed::PerformableMethod.new(reader, :read, args: [["arg1", story, { [:key, 1] => story }]])
|
51
|
+
expect(p.full_name).to eq(
|
52
|
+
"StoryReader#read([\"arg1\", Story.find(#{story.id}), {[:key, 1] => Story.find(#{story.id})}])"
|
53
|
+
)
|
53
54
|
end
|
54
55
|
|
55
|
-
it "
|
56
|
-
story = Story.create :
|
56
|
+
it "calls the on_failure callback" do
|
57
|
+
story = Story.create text: "wat"
|
57
58
|
p = Delayed::PerformableMethod.new(story, :tell, on_failure: :text=)
|
58
|
-
p.send(:on_failure,
|
59
|
-
story.text.
|
59
|
+
p.send(:on_failure, "fail")
|
60
|
+
expect(story.text).to eq("fail")
|
60
61
|
end
|
61
62
|
|
62
|
-
it "
|
63
|
-
story = Story.create :
|
63
|
+
it "calls the on_permanent_failure callback" do
|
64
|
+
story = Story.create text: "wat"
|
64
65
|
p = Delayed::PerformableMethod.new(story, :tell, on_permanent_failure: :text=)
|
65
|
-
p.send(:on_permanent_failure,
|
66
|
-
story.text.
|
66
|
+
p.send(:on_permanent_failure, "fail_frd")
|
67
|
+
expect(story.text).to eq("fail_frd")
|
67
68
|
end
|
68
69
|
|
69
70
|
it "can still generate a name with no kwargs" do
|
70
|
-
story = Story.create :
|
71
|
+
story = Story.create text: "wat"
|
71
72
|
p = Delayed::PerformableMethod.new(story, :tell, kwargs: nil)
|
72
73
|
expect(p.full_name).to eq("Story.find(#{story.id}).tell()")
|
73
74
|
end
|