canvas-jobs 0.9.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (61) hide show
  1. checksums.yaml +7 -0
  2. data/db/migrate/20101216224513_create_delayed_jobs.rb +40 -0
  3. data/db/migrate/20110208031356_add_delayed_jobs_tag.rb +14 -0
  4. data/db/migrate/20110426161613_add_delayed_jobs_max_attempts.rb +13 -0
  5. data/db/migrate/20110516225834_add_delayed_jobs_strand.rb +14 -0
  6. data/db/migrate/20110531144916_cleanup_delayed_jobs_indexes.rb +26 -0
  7. data/db/migrate/20110610213249_optimize_delayed_jobs.rb +40 -0
  8. data/db/migrate/20110831210257_add_delayed_jobs_next_in_strand.rb +52 -0
  9. data/db/migrate/20120510004759_delayed_jobs_delete_trigger_lock_for_update.rb +31 -0
  10. data/db/migrate/20120531150712_drop_psql_jobs_pop_fn.rb +15 -0
  11. data/db/migrate/20120607164022_delayed_jobs_use_advisory_locks.rb +80 -0
  12. data/db/migrate/20120607181141_index_jobs_on_locked_by.rb +15 -0
  13. data/db/migrate/20120608191051_add_jobs_run_at_index.rb +15 -0
  14. data/db/migrate/20120927184213_change_delayed_jobs_handler_to_text.rb +13 -0
  15. data/db/migrate/20140505215131_add_failed_jobs_original_job_id.rb +13 -0
  16. data/db/migrate/20140505215510_copy_failed_jobs_original_id.rb +13 -0
  17. data/db/migrate/20140505223637_drop_failed_jobs_original_id.rb +13 -0
  18. data/db/migrate/20140512213941_add_source_to_jobs.rb +15 -0
  19. data/lib/canvas-jobs.rb +1 -0
  20. data/lib/delayed/backend/active_record.rb +297 -0
  21. data/lib/delayed/backend/base.rb +317 -0
  22. data/lib/delayed/backend/redis/bulk_update.lua +40 -0
  23. data/lib/delayed/backend/redis/destroy_job.lua +2 -0
  24. data/lib/delayed/backend/redis/enqueue.lua +29 -0
  25. data/lib/delayed/backend/redis/fail_job.lua +5 -0
  26. data/lib/delayed/backend/redis/find_available.lua +3 -0
  27. data/lib/delayed/backend/redis/functions.rb +57 -0
  28. data/lib/delayed/backend/redis/get_and_lock_next_available.lua +17 -0
  29. data/lib/delayed/backend/redis/includes/jobs_common.lua +203 -0
  30. data/lib/delayed/backend/redis/job.rb +481 -0
  31. data/lib/delayed/backend/redis/set_running.lua +5 -0
  32. data/lib/delayed/backend/redis/tickle_strand.lua +2 -0
  33. data/lib/delayed/batch.rb +56 -0
  34. data/lib/delayed/engine.rb +4 -0
  35. data/lib/delayed/job_tracking.rb +31 -0
  36. data/lib/delayed/lifecycle.rb +83 -0
  37. data/lib/delayed/message_sending.rb +130 -0
  38. data/lib/delayed/performable_method.rb +42 -0
  39. data/lib/delayed/periodic.rb +81 -0
  40. data/lib/delayed/pool.rb +335 -0
  41. data/lib/delayed/settings.rb +32 -0
  42. data/lib/delayed/version.rb +3 -0
  43. data/lib/delayed/worker.rb +213 -0
  44. data/lib/delayed/yaml_extensions.rb +63 -0
  45. data/lib/delayed_job.rb +40 -0
  46. data/spec/active_record_job_spec.rb +61 -0
  47. data/spec/gemfiles/32.gemfile +6 -0
  48. data/spec/gemfiles/40.gemfile +6 -0
  49. data/spec/gemfiles/41.gemfile +6 -0
  50. data/spec/gemfiles/42.gemfile +6 -0
  51. data/spec/migrate/20140924140513_add_story_table.rb +7 -0
  52. data/spec/redis_job_spec.rb +77 -0
  53. data/spec/sample_jobs.rb +26 -0
  54. data/spec/shared/delayed_batch.rb +85 -0
  55. data/spec/shared/delayed_method.rb +419 -0
  56. data/spec/shared/performable_method.rb +52 -0
  57. data/spec/shared/shared_backend.rb +836 -0
  58. data/spec/shared/worker.rb +291 -0
  59. data/spec/shared_jobs_specs.rb +13 -0
  60. data/spec/spec_helper.rb +91 -0
  61. metadata +329 -0
@@ -0,0 +1,291 @@
1
+ shared_examples_for 'Delayed::Worker' do
2
+ def job_create(opts = {})
3
+ Delayed::Job.create({:payload_object => SimpleJob.new, :queue => Delayed::Settings.queue}.merge(opts))
4
+ end
5
+ def worker_create(opts = {})
6
+ Delayed::Worker.new(opts.merge(:max_priority => nil, :min_priority => nil, :quiet => true))
7
+ end
8
+
9
+ before(:each) do
10
+ @worker = worker_create
11
+ SimpleJob.runs = 0
12
+ Delayed::Worker.on_max_failures = nil
13
+ Delayed::Settings.sleep_delay = ->{ 0.01 }
14
+ end
15
+
16
+ describe "running a job" do
17
+ it "should not fail when running a job with a % in the name" do
18
+ @job = "Some % Name here".send_later_enqueue_args(:starts_with?, { no_delay: true }, "Some % Name")
19
+ @worker.perform(@job)
20
+ end
21
+ end
22
+
23
+ describe "running a batch" do
24
+ context "serially" do
25
+ before do
26
+ @runs = 0
27
+ Delayed::Worker.lifecycle.after(:perform) { @runs += 1 }
28
+ end
29
+
30
+ after do
31
+ Delayed::Worker.lifecycle.reset!
32
+ end
33
+
34
+ it "should run each job in order" do
35
+ bar = "bar"
36
+ expect(bar).to receive(:scan).with("b").ordered
37
+ expect(bar).to receive(:scan).with("a").ordered
38
+ expect(bar).to receive(:scan).with("r").ordered
39
+ batch = Delayed::Batch::PerformableBatch.new(:serial, [
40
+ { :payload_object => Delayed::PerformableMethod.new(bar, :scan, ["b"]) },
41
+ { :payload_object => Delayed::PerformableMethod.new(bar, :scan, ["a"]) },
42
+ { :payload_object => Delayed::PerformableMethod.new(bar, :scan, ["r"]) },
43
+ ])
44
+
45
+ batch_job = Delayed::Job.create :payload_object => batch
46
+ @worker.perform(batch_job).should == 3
47
+ expect(@runs).to eql 4 # batch, plus all jobs
48
+ end
49
+
50
+ it "should succeed regardless of the success/failure of its component jobs" do
51
+ change_setting(Delayed::Settings, :max_attempts, 2) do
52
+ batch = Delayed::Batch::PerformableBatch.new(:serial, [
53
+ { :payload_object => Delayed::PerformableMethod.new("foo", :reverse, []) },
54
+ { :payload_object => Delayed::PerformableMethod.new(1, :/, [0]) },
55
+ { :payload_object => Delayed::PerformableMethod.new("bar", :scan, ["r"]) },
56
+ ])
57
+ batch_job = Delayed::Job.create :payload_object => batch
58
+
59
+ @worker.perform(batch_job).should == 3
60
+ expect(@runs).to eql 3 # batch, plus two successful jobs
61
+
62
+ to_retry = Delayed::Job.list_jobs(:future, 100)
63
+ to_retry.size.should eql 1
64
+ to_retry[0].payload_object.method.should eql :/
65
+ to_retry[0].last_error.should =~ /divided by 0/
66
+ to_retry[0].attempts.should == 1
67
+ end
68
+ end
69
+
70
+ it "should retry a failed individual job" do
71
+ batch = Delayed::Batch::PerformableBatch.new(:serial, [
72
+ { :payload_object => Delayed::PerformableMethod.new(1, :/, [0]) },
73
+ ])
74
+ batch_job = Delayed::Job.create :payload_object => batch
75
+
76
+ expect_any_instance_of(Delayed::Job).to receive(:reschedule).once
77
+ @worker.perform(batch_job).should == 1
78
+ expect(@runs).to eql 1 # just the batch
79
+ end
80
+ end
81
+ end
82
+
83
+ context "worker prioritization" do
84
+ before(:each) do
85
+ @worker = Delayed::Worker.new(:max_priority => 5, :min_priority => 2, :quiet => true)
86
+ end
87
+
88
+ it "should only run jobs that are >= min_priority" do
89
+ SimpleJob.runs.should == 0
90
+
91
+ job_create(:priority => 1)
92
+ job_create(:priority => 3)
93
+ @worker.run
94
+
95
+ SimpleJob.runs.should == 1
96
+ end
97
+
98
+ it "should only run jobs that are <= max_priority" do
99
+ SimpleJob.runs.should == 0
100
+
101
+ job_create(:priority => 10)
102
+ job_create(:priority => 4)
103
+
104
+ @worker.run
105
+
106
+ SimpleJob.runs.should == 1
107
+ end
108
+ end
109
+
110
+ context "while running with locked jobs" do
111
+ before(:each) do
112
+ @worker.name = 'worker1'
113
+ end
114
+
115
+ it "should not run jobs locked by another worker" do
116
+ job_create(:locked_by => 'other_worker', :locked_at => (Delayed::Job.db_time_now - 1.minutes))
117
+ lambda { @worker.run }.should_not change { SimpleJob.runs }
118
+ end
119
+
120
+ it "should run open jobs" do
121
+ job_create
122
+ lambda { @worker.run }.should change { SimpleJob.runs }.from(0).to(1)
123
+ end
124
+ end
125
+
126
+ describe "failed jobs" do
127
+ before do
128
+ # reset defaults
129
+ Delayed::Settings.max_attempts = 25
130
+ @job = Delayed::Job.enqueue ErrorJob.new
131
+ end
132
+
133
+ it "should record last_error when destroy_failed_jobs = false, max_attempts = 1" do
134
+ Delayed::Worker.on_max_failures = proc { false }
135
+ @job.max_attempts = 1
136
+ @job.save!
137
+ (job = Delayed::Job.get_and_lock_next_available('w1')).should == @job
138
+ @worker.perform(job)
139
+ old_id = @job.id
140
+ @job = Delayed::Job.list_jobs(:failed, 1).first
141
+ @job.original_job_id.should == old_id
142
+ @job.last_error.should =~ /did not work/
143
+ @job.last_error.should =~ /shared\/worker.rb/
144
+ @job.attempts.should == 1
145
+ @job.failed_at.should_not be_nil
146
+ @job.run_at.should > Delayed::Job.db_time_now - 10.minutes
147
+ @job.run_at.should < Delayed::Job.db_time_now + 10.minutes
148
+ # job stays locked after failing, for record keeping of time/worker
149
+ @job.should be_locked
150
+
151
+ Delayed::Job.find_available(100, @job.queue).should == []
152
+ end
153
+
154
+ it "should re-schedule jobs after failing" do
155
+ @worker.perform(@job)
156
+ @job = Delayed::Job.find(@job.id)
157
+ @job.last_error.should =~ /did not work/
158
+ @job.last_error.should =~ /sample_jobs.rb:8:in `perform'/
159
+ @job.attempts.should == 1
160
+ @job.run_at.should > Delayed::Job.db_time_now - 10.minutes
161
+ @job.run_at.should < Delayed::Job.db_time_now + 10.minutes
162
+ end
163
+
164
+ it "should notify jobs on failure" do
165
+ ErrorJob.failure_runs = 0
166
+ @worker.perform(@job)
167
+ ErrorJob.failure_runs.should == 1
168
+ end
169
+
170
+ it "should notify jobs on permanent failure" do
171
+ (Delayed::Settings.max_attempts - 1).times { @job.reschedule }
172
+ ErrorJob.permanent_failure_runs = 0
173
+ @worker.perform(@job)
174
+ ErrorJob.permanent_failure_runs.should == 1
175
+ end
176
+ end
177
+
178
+ context "reschedule" do
179
+ before do
180
+ @job = Delayed::Job.create :payload_object => SimpleJob.new
181
+ end
182
+
183
+ context "and we want to destroy jobs" do
184
+ it "should be destroyed if it failed more than Settings.max_attempts times" do
185
+ expect(@job).to receive(:destroy)
186
+ Delayed::Settings.max_attempts.times { @job.reschedule }
187
+ end
188
+
189
+ it "should not be destroyed if failed fewer than Settings.max_attempts times" do
190
+ expect(@job).to receive(:destroy).never
191
+ (Delayed::Settings.max_attempts - 1).times { @job.reschedule }
192
+ end
193
+
194
+ it "should be destroyed if failed more than Job#max_attempts times" do
195
+ Delayed::Settings.max_attempts = 25
196
+ expect(@job).to receive(:destroy)
197
+ @job.max_attempts = 2
198
+ @job.save!
199
+ 2.times { @job.reschedule }
200
+ end
201
+ end
202
+
203
+ context "and we don't want to destroy jobs" do
204
+ before do
205
+ Delayed::Worker.on_max_failures = proc { false }
206
+ end
207
+
208
+ after do
209
+ Delayed::Worker.on_max_failures = nil
210
+ end
211
+
212
+ it "should be failed if it failed more than Settings.max_attempts times" do
213
+ @job.failed_at.should == nil
214
+ Delayed::Settings.max_attempts.times { @job.reschedule }
215
+ Delayed::Job.list_jobs(:failed, 100).size.should == 1
216
+ end
217
+
218
+ it "should not be failed if it failed fewer than Settings.max_attempts times" do
219
+ (Delayed::Settings.max_attempts - 1).times { @job.reschedule }
220
+ @job = Delayed::Job.find(@job.id)
221
+ @job.failed_at.should == nil
222
+ end
223
+
224
+ end
225
+
226
+ context "and we give an on_max_failures callback" do
227
+ it "should be failed max_attempts times and cb is false" do
228
+ Delayed::Worker.on_max_failures = proc do |job, ex|
229
+ job.should == @job
230
+ false
231
+ end
232
+ expect(@job).to receive(:fail!)
233
+ Delayed::Settings.max_attempts.times { @job.reschedule }
234
+ end
235
+
236
+ it "should be destroyed if it failed max_attempts times and cb is true" do
237
+ Delayed::Worker.on_max_failures = proc do |job, ex|
238
+ job.should == @job
239
+ true
240
+ end
241
+ expect(@job).to receive(:destroy)
242
+ Delayed::Settings.max_attempts.times { @job.reschedule }
243
+ end
244
+ end
245
+ end
246
+
247
+
248
+ context "Queue workers" do
249
+ before :each do
250
+ Delayed::Settings.queue = "Queue workers test"
251
+ job_create(:queue => 'queue1')
252
+ job_create(:queue => 'queue2')
253
+ end
254
+
255
+ it "should only work off jobs assigned to themselves" do
256
+ worker = worker_create(:queue=>'queue1')
257
+ SimpleJob.runs.should == 0
258
+ worker.run
259
+ SimpleJob.runs.should == 1
260
+
261
+ SimpleJob.runs = 0
262
+
263
+ worker = worker_create(:queue=>'queue2')
264
+ SimpleJob.runs.should == 0
265
+ worker.run
266
+ SimpleJob.runs.should == 1
267
+ end
268
+
269
+ it "should not work off jobs not assigned to themselves" do
270
+ worker = worker_create(:queue=>'queue3')
271
+
272
+ SimpleJob.runs.should == 0
273
+ worker.run
274
+ SimpleJob.runs.should == 0
275
+ end
276
+
277
+ it "should get the default queue if none is set" do
278
+ queue_name = "default_queue"
279
+ Delayed::Settings.queue = queue_name
280
+ worker = worker_create(:queue=>nil)
281
+ worker.queue.should == queue_name
282
+ end
283
+
284
+ it "should override default queue name if specified in initialize" do
285
+ queue_name = "my_queue"
286
+ Delayed::Settings.queue = "default_queue"
287
+ worker = worker_create(:queue=>queue_name)
288
+ worker.queue.should == queue_name
289
+ end
290
+ end
291
+ end
@@ -0,0 +1,13 @@
1
+ require File.expand_path('../shared/shared_backend', __FILE__)
2
+ require File.expand_path('../shared/delayed_batch', __FILE__)
3
+ require File.expand_path('../shared/delayed_method', __FILE__)
4
+ require File.expand_path('../shared/performable_method', __FILE__)
5
+ require File.expand_path('../shared/worker', __FILE__)
6
+
7
+ shared_examples_for 'a delayed_jobs implementation' do
8
+ include_examples 'a backend'
9
+ include_examples 'Delayed::Batch'
10
+ include_examples 'random ruby objects'
11
+ include_examples 'Delayed::PerformableMethod'
12
+ include_examples 'Delayed::Worker'
13
+ end
@@ -0,0 +1,91 @@
1
+ require 'delayed_job'
2
+
3
+ require 'database_cleaner'
4
+ require 'test_after_commit'
5
+ require 'timecop'
6
+ require 'pry'
7
+
8
+ RSpec.configure do |config|
9
+
10
+ config.expect_with(:rspec) do |c|
11
+ c.syntax = [:should, :expect]
12
+ end
13
+
14
+ config.before(:suite) do
15
+ DatabaseCleaner.strategy = :transaction
16
+ DatabaseCleaner.clean_with(:truncation)
17
+ end
18
+
19
+ config.around(:each) do |example|
20
+ if Delayed::Backend::Redis::Job.redis
21
+ Delayed::Backend::Redis::Job.redis.flushdb
22
+ end
23
+ DatabaseCleaner.cleaning do
24
+ example.run
25
+ end
26
+ end
27
+
28
+ end
29
+
30
+ ENV['TEST_ENV_NUMBER'] ||= '1'
31
+ ENV['TEST_DB_HOST'] ||= 'localhost'
32
+ ENV['TEST_DB_DATABASE'] ||= "canvas-jobs-test-#{ENV['TEST_ENV_NUMBER']}"
33
+ ENV['TEST_REDIS_CONNECTION'] ||= 'redis://localhost:6379/'
34
+
35
+ Delayed::Backend::Redis::Job.redis = Redis.new(url: ENV['TEST_REDIS_CONNECTION'])
36
+
37
+ ActiveRecord::Base.establish_connection({
38
+ adapter: :postgresql,
39
+ host: ENV['TEST_DB_HOST'],
40
+ encoding: 'utf8',
41
+ username: ENV['TEST_DB_USERNAME'],
42
+ database: ENV['TEST_DB_DATABASE'],
43
+ })
44
+ # TODO reset db and migrate again, to test migrations
45
+
46
+ ActiveRecord::Migrator.migrate("db/migrate")
47
+ ActiveRecord::Migrator.migrate("spec/migrate")
48
+
49
+ Time.zone = 'UTC'
50
+ Rails.logger = Logger.new(nil)
51
+
52
+ # Purely useful for test cases...
53
+ class Story < ActiveRecord::Base
54
+ def tell; text; end
55
+ def whatever(n, _); tell*n; end
56
+ def whatever_else(n, _); tell*n; end
57
+
58
+ handle_asynchronously :whatever
59
+ handle_asynchronously_with_queue :whatever_else, "testqueue"
60
+ end
61
+
62
+ class StoryReader
63
+ def read(story)
64
+ "Epilog: #{story.tell}"
65
+ end
66
+
67
+ def self.reverse(str)
68
+ str.reverse
69
+ end
70
+ end
71
+
72
+ module MyReverser
73
+ def self.reverse(str)
74
+ str.reverse
75
+ end
76
+ end
77
+
78
+ def change_setting(klass, setting_name, value)
79
+ old_val = klass.class_variable_get(:"@@#{setting_name}")
80
+ klass.send("#{setting_name}=", value)
81
+ yield
82
+ ensure
83
+ klass.send("#{setting_name}=", old_val)
84
+ end
85
+
86
+ def run_job(job)
87
+ Delayed::Worker.new.perform(job)
88
+ end
89
+
90
+ require File.expand_path('../sample_jobs', __FILE__)
91
+ require File.expand_path('../shared_jobs_specs', __FILE__)
metadata ADDED
@@ -0,0 +1,329 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: canvas-jobs
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.9.0
5
+ platform: ruby
6
+ authors:
7
+ - Tobias Luetke
8
+ - Brian Palmer
9
+ autorequire:
10
+ bindir: bin
11
+ cert_chain: []
12
+ date: 2014-09-30 00:00:00.000000000 Z
13
+ dependencies:
14
+ - !ruby/object:Gem::Dependency
15
+ name: after_transaction_commit
16
+ requirement: !ruby/object:Gem::Requirement
17
+ requirements:
18
+ - - '='
19
+ - !ruby/object:Gem::Version
20
+ version: 1.0.1
21
+ type: :runtime
22
+ prerelease: false
23
+ version_requirements: !ruby/object:Gem::Requirement
24
+ requirements:
25
+ - - '='
26
+ - !ruby/object:Gem::Version
27
+ version: 1.0.1
28
+ - !ruby/object:Gem::Dependency
29
+ name: rails
30
+ requirement: !ruby/object:Gem::Requirement
31
+ requirements:
32
+ - - ">="
33
+ - !ruby/object:Gem::Version
34
+ version: '3.2'
35
+ type: :runtime
36
+ prerelease: false
37
+ version_requirements: !ruby/object:Gem::Requirement
38
+ requirements:
39
+ - - ">="
40
+ - !ruby/object:Gem::Version
41
+ version: '3.2'
42
+ - !ruby/object:Gem::Dependency
43
+ name: rufus-scheduler
44
+ requirement: !ruby/object:Gem::Requirement
45
+ requirements:
46
+ - - '='
47
+ - !ruby/object:Gem::Version
48
+ version: 2.0.6
49
+ type: :runtime
50
+ prerelease: false
51
+ version_requirements: !ruby/object:Gem::Requirement
52
+ requirements:
53
+ - - '='
54
+ - !ruby/object:Gem::Version
55
+ version: 2.0.6
56
+ - !ruby/object:Gem::Dependency
57
+ name: redis
58
+ requirement: !ruby/object:Gem::Requirement
59
+ requirements:
60
+ - - ">"
61
+ - !ruby/object:Gem::Version
62
+ version: '3.0'
63
+ type: :runtime
64
+ prerelease: false
65
+ version_requirements: !ruby/object:Gem::Requirement
66
+ requirements:
67
+ - - ">"
68
+ - !ruby/object:Gem::Version
69
+ version: '3.0'
70
+ - !ruby/object:Gem::Dependency
71
+ name: redis-scripting
72
+ requirement: !ruby/object:Gem::Requirement
73
+ requirements:
74
+ - - '='
75
+ - !ruby/object:Gem::Version
76
+ version: 1.0.1
77
+ type: :runtime
78
+ prerelease: false
79
+ version_requirements: !ruby/object:Gem::Requirement
80
+ requirements:
81
+ - - '='
82
+ - !ruby/object:Gem::Version
83
+ version: 1.0.1
84
+ - !ruby/object:Gem::Dependency
85
+ name: syck
86
+ requirement: !ruby/object:Gem::Requirement
87
+ requirements:
88
+ - - ">="
89
+ - !ruby/object:Gem::Version
90
+ version: '0'
91
+ type: :runtime
92
+ prerelease: false
93
+ version_requirements: !ruby/object:Gem::Requirement
94
+ requirements:
95
+ - - ">="
96
+ - !ruby/object:Gem::Version
97
+ version: '0'
98
+ - !ruby/object:Gem::Dependency
99
+ name: bump
100
+ requirement: !ruby/object:Gem::Requirement
101
+ requirements:
102
+ - - ">="
103
+ - !ruby/object:Gem::Version
104
+ version: '0'
105
+ type: :development
106
+ prerelease: false
107
+ version_requirements: !ruby/object:Gem::Requirement
108
+ requirements:
109
+ - - ">="
110
+ - !ruby/object:Gem::Version
111
+ version: '0'
112
+ - !ruby/object:Gem::Dependency
113
+ name: database_cleaner
114
+ requirement: !ruby/object:Gem::Requirement
115
+ requirements:
116
+ - - ">="
117
+ - !ruby/object:Gem::Version
118
+ version: '0'
119
+ type: :development
120
+ prerelease: false
121
+ version_requirements: !ruby/object:Gem::Requirement
122
+ requirements:
123
+ - - ">="
124
+ - !ruby/object:Gem::Version
125
+ version: '0'
126
+ - !ruby/object:Gem::Dependency
127
+ name: pg
128
+ requirement: !ruby/object:Gem::Requirement
129
+ requirements:
130
+ - - ">="
131
+ - !ruby/object:Gem::Version
132
+ version: '0'
133
+ type: :development
134
+ prerelease: false
135
+ version_requirements: !ruby/object:Gem::Requirement
136
+ requirements:
137
+ - - ">="
138
+ - !ruby/object:Gem::Version
139
+ version: '0'
140
+ - !ruby/object:Gem::Dependency
141
+ name: pry
142
+ requirement: !ruby/object:Gem::Requirement
143
+ requirements:
144
+ - - ">="
145
+ - !ruby/object:Gem::Version
146
+ version: '0'
147
+ type: :development
148
+ prerelease: false
149
+ version_requirements: !ruby/object:Gem::Requirement
150
+ requirements:
151
+ - - ">="
152
+ - !ruby/object:Gem::Version
153
+ version: '0'
154
+ - !ruby/object:Gem::Dependency
155
+ name: rake
156
+ requirement: !ruby/object:Gem::Requirement
157
+ requirements:
158
+ - - ">="
159
+ - !ruby/object:Gem::Version
160
+ version: '0'
161
+ type: :development
162
+ prerelease: false
163
+ version_requirements: !ruby/object:Gem::Requirement
164
+ requirements:
165
+ - - ">="
166
+ - !ruby/object:Gem::Version
167
+ version: '0'
168
+ - !ruby/object:Gem::Dependency
169
+ name: rspec
170
+ requirement: !ruby/object:Gem::Requirement
171
+ requirements:
172
+ - - ">="
173
+ - !ruby/object:Gem::Version
174
+ version: '0'
175
+ type: :development
176
+ prerelease: false
177
+ version_requirements: !ruby/object:Gem::Requirement
178
+ requirements:
179
+ - - ">="
180
+ - !ruby/object:Gem::Version
181
+ version: '0'
182
+ - !ruby/object:Gem::Dependency
183
+ name: test_after_commit
184
+ requirement: !ruby/object:Gem::Requirement
185
+ requirements:
186
+ - - ">="
187
+ - !ruby/object:Gem::Version
188
+ version: '0'
189
+ type: :development
190
+ prerelease: false
191
+ version_requirements: !ruby/object:Gem::Requirement
192
+ requirements:
193
+ - - ">="
194
+ - !ruby/object:Gem::Version
195
+ version: '0'
196
+ - !ruby/object:Gem::Dependency
197
+ name: timecop
198
+ requirement: !ruby/object:Gem::Requirement
199
+ requirements:
200
+ - - ">="
201
+ - !ruby/object:Gem::Version
202
+ version: '0'
203
+ type: :development
204
+ prerelease: false
205
+ version_requirements: !ruby/object:Gem::Requirement
206
+ requirements:
207
+ - - ">="
208
+ - !ruby/object:Gem::Version
209
+ version: '0'
210
+ - !ruby/object:Gem::Dependency
211
+ name: wwtd
212
+ requirement: !ruby/object:Gem::Requirement
213
+ requirements:
214
+ - - ">="
215
+ - !ruby/object:Gem::Version
216
+ version: '0'
217
+ type: :development
218
+ prerelease: false
219
+ version_requirements: !ruby/object:Gem::Requirement
220
+ requirements:
221
+ - - ">="
222
+ - !ruby/object:Gem::Version
223
+ version: '0'
224
+ description:
225
+ email:
226
+ - brianp@instructure.com
227
+ executables: []
228
+ extensions: []
229
+ extra_rdoc_files: []
230
+ files:
231
+ - db/migrate/20101216224513_create_delayed_jobs.rb
232
+ - db/migrate/20110208031356_add_delayed_jobs_tag.rb
233
+ - db/migrate/20110426161613_add_delayed_jobs_max_attempts.rb
234
+ - db/migrate/20110516225834_add_delayed_jobs_strand.rb
235
+ - db/migrate/20110531144916_cleanup_delayed_jobs_indexes.rb
236
+ - db/migrate/20110610213249_optimize_delayed_jobs.rb
237
+ - db/migrate/20110831210257_add_delayed_jobs_next_in_strand.rb
238
+ - db/migrate/20120510004759_delayed_jobs_delete_trigger_lock_for_update.rb
239
+ - db/migrate/20120531150712_drop_psql_jobs_pop_fn.rb
240
+ - db/migrate/20120607164022_delayed_jobs_use_advisory_locks.rb
241
+ - db/migrate/20120607181141_index_jobs_on_locked_by.rb
242
+ - db/migrate/20120608191051_add_jobs_run_at_index.rb
243
+ - db/migrate/20120927184213_change_delayed_jobs_handler_to_text.rb
244
+ - db/migrate/20140505215131_add_failed_jobs_original_job_id.rb
245
+ - db/migrate/20140505215510_copy_failed_jobs_original_id.rb
246
+ - db/migrate/20140505223637_drop_failed_jobs_original_id.rb
247
+ - db/migrate/20140512213941_add_source_to_jobs.rb
248
+ - lib/canvas-jobs.rb
249
+ - lib/delayed/backend/active_record.rb
250
+ - lib/delayed/backend/base.rb
251
+ - lib/delayed/backend/redis/bulk_update.lua
252
+ - lib/delayed/backend/redis/destroy_job.lua
253
+ - lib/delayed/backend/redis/enqueue.lua
254
+ - lib/delayed/backend/redis/fail_job.lua
255
+ - lib/delayed/backend/redis/find_available.lua
256
+ - lib/delayed/backend/redis/functions.rb
257
+ - lib/delayed/backend/redis/get_and_lock_next_available.lua
258
+ - lib/delayed/backend/redis/includes/jobs_common.lua
259
+ - lib/delayed/backend/redis/job.rb
260
+ - lib/delayed/backend/redis/set_running.lua
261
+ - lib/delayed/backend/redis/tickle_strand.lua
262
+ - lib/delayed/batch.rb
263
+ - lib/delayed/engine.rb
264
+ - lib/delayed/job_tracking.rb
265
+ - lib/delayed/lifecycle.rb
266
+ - lib/delayed/message_sending.rb
267
+ - lib/delayed/performable_method.rb
268
+ - lib/delayed/periodic.rb
269
+ - lib/delayed/pool.rb
270
+ - lib/delayed/settings.rb
271
+ - lib/delayed/version.rb
272
+ - lib/delayed/worker.rb
273
+ - lib/delayed/yaml_extensions.rb
274
+ - lib/delayed_job.rb
275
+ - spec/active_record_job_spec.rb
276
+ - spec/gemfiles/32.gemfile
277
+ - spec/gemfiles/40.gemfile
278
+ - spec/gemfiles/41.gemfile
279
+ - spec/gemfiles/42.gemfile
280
+ - spec/migrate/20140924140513_add_story_table.rb
281
+ - spec/redis_job_spec.rb
282
+ - spec/sample_jobs.rb
283
+ - spec/shared/delayed_batch.rb
284
+ - spec/shared/delayed_method.rb
285
+ - spec/shared/performable_method.rb
286
+ - spec/shared/shared_backend.rb
287
+ - spec/shared/worker.rb
288
+ - spec/shared_jobs_specs.rb
289
+ - spec/spec_helper.rb
290
+ homepage: http://www.instructure.com
291
+ licenses: []
292
+ metadata: {}
293
+ post_install_message:
294
+ rdoc_options: []
295
+ require_paths:
296
+ - lib
297
+ required_ruby_version: !ruby/object:Gem::Requirement
298
+ requirements:
299
+ - - ">="
300
+ - !ruby/object:Gem::Version
301
+ version: '0'
302
+ required_rubygems_version: !ruby/object:Gem::Requirement
303
+ requirements:
304
+ - - ">="
305
+ - !ruby/object:Gem::Version
306
+ version: '0'
307
+ requirements: []
308
+ rubyforge_project:
309
+ rubygems_version: 2.4.1
310
+ signing_key:
311
+ specification_version: 4
312
+ summary: Instructure-maintained fork of delayed_job
313
+ test_files:
314
+ - spec/active_record_job_spec.rb
315
+ - spec/gemfiles/32.gemfile
316
+ - spec/gemfiles/40.gemfile
317
+ - spec/gemfiles/41.gemfile
318
+ - spec/gemfiles/42.gemfile
319
+ - spec/migrate/20140924140513_add_story_table.rb
320
+ - spec/redis_job_spec.rb
321
+ - spec/sample_jobs.rb
322
+ - spec/shared/delayed_batch.rb
323
+ - spec/shared/delayed_method.rb
324
+ - spec/shared/performable_method.rb
325
+ - spec/shared/shared_backend.rb
326
+ - spec/shared/worker.rb
327
+ - spec/shared_jobs_specs.rb
328
+ - spec/spec_helper.rb
329
+ has_rdoc: