resque-scheduler 2.0.0.d → 2.0.0.e
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.
Potentially problematic release.
This version of resque-scheduler might be problematic. Click here for more details.
- data/.gitignore +1 -0
- data/Gemfile.lock +13 -21
- data/HISTORY.md +8 -0
- data/README.markdown +141 -165
- data/Rakefile +8 -0
- data/lib/resque/scheduler.rb +54 -20
- data/lib/resque_scheduler.rb +47 -12
- data/lib/resque_scheduler/server.rb +5 -0
- data/lib/resque_scheduler/server/views/delayed.erb +8 -2
- data/lib/resque_scheduler/tasks.rb +2 -1
- data/lib/resque_scheduler/version.rb +1 -1
- data/resque-scheduler.gemspec +3 -4
- data/test/delayed_queue_test.rb +37 -12
- data/test/scheduler_args_test.rb +10 -0
- data/test/scheduler_test.rb +51 -32
- data/test/test_helper.rb +11 -5
- metadata +71 -108
data/Rakefile
CHANGED
@@ -1,4 +1,5 @@
|
|
1
1
|
require 'bundler'
|
2
|
+
require 'rake/rdoctask'
|
2
3
|
Bundler::GemHelper.install_tasks
|
3
4
|
|
4
5
|
$LOAD_PATH.unshift 'lib'
|
@@ -11,3 +12,10 @@ task :test do
|
|
11
12
|
require File.expand_path(f)
|
12
13
|
end
|
13
14
|
end
|
15
|
+
|
16
|
+
Rake::RDocTask.new do |rd|
|
17
|
+
rd.main = "README.markdown"
|
18
|
+
rd.rdoc_files.include("README.markdown", "lib/**/*.rb")
|
19
|
+
rd.rdoc_dir = 'doc'
|
20
|
+
end
|
21
|
+
|
data/lib/resque/scheduler.rb
CHANGED
@@ -11,17 +11,25 @@ module Resque
|
|
11
11
|
|
12
12
|
# If true, logs more stuff...
|
13
13
|
attr_accessor :verbose
|
14
|
-
|
14
|
+
|
15
15
|
# If set, produces no output
|
16
16
|
attr_accessor :mute
|
17
|
-
|
17
|
+
|
18
18
|
# If set, will try to update the schulde in the loop
|
19
19
|
attr_accessor :dynamic
|
20
20
|
|
21
|
+
# Amount of time in seconds to sleep between polls of the delayed
|
22
|
+
# queue. Defaults to 5
|
23
|
+
attr_writer :poll_sleep_amount
|
24
|
+
|
21
25
|
# the Rufus::Scheduler jobs that are scheduled
|
22
26
|
def scheduled_jobs
|
23
27
|
@@scheduled_jobs
|
24
28
|
end
|
29
|
+
|
30
|
+
def poll_sleep_amount
|
31
|
+
@poll_sleep_amount ||= 5 # seconds
|
32
|
+
end
|
25
33
|
|
26
34
|
# Schedule all jobs and continually look for delayed jobs (never returns)
|
27
35
|
def run
|
@@ -30,8 +38,12 @@ module Resque
|
|
30
38
|
register_signal_handlers
|
31
39
|
|
32
40
|
# Load the schedule into rufus
|
33
|
-
|
34
|
-
|
41
|
+
# If dynamic is set, load that schedule otherwise use normal load
|
42
|
+
if dynamic
|
43
|
+
reload_schedule!
|
44
|
+
else
|
45
|
+
load_schedule!
|
46
|
+
end
|
35
47
|
|
36
48
|
# Now start the scheduling part of the loop.
|
37
49
|
loop do
|
@@ -53,33 +65,45 @@ module Resque
|
|
53
65
|
def register_signal_handlers
|
54
66
|
trap("TERM") { shutdown }
|
55
67
|
trap("INT") { shutdown }
|
56
|
-
|
68
|
+
|
57
69
|
begin
|
58
|
-
trap('QUIT') { shutdown
|
59
|
-
trap('USR1') {
|
70
|
+
trap('QUIT') { shutdown }
|
71
|
+
trap('USR1') { print_schedule }
|
60
72
|
trap('USR2') { reload_schedule! }
|
61
73
|
rescue ArgumentError
|
62
74
|
warn "Signals QUIT and USR1 and USR2 not supported."
|
63
75
|
end
|
64
76
|
end
|
65
77
|
|
78
|
+
def print_schedule
|
79
|
+
if rufus_scheduler
|
80
|
+
log! "Scheduling Info\tLast Run"
|
81
|
+
scheduler_jobs = rufus_scheduler.all_jobs
|
82
|
+
scheduler_jobs.each do |k, v|
|
83
|
+
log! "#{v.t}\t#{v.last}\t"
|
84
|
+
end
|
85
|
+
end
|
86
|
+
end
|
87
|
+
|
66
88
|
# Pulls the schedule from Resque.schedule and loads it into the
|
67
89
|
# rufus scheduler instance
|
68
90
|
def load_schedule!
|
91
|
+
procline "Loading Schedule"
|
92
|
+
|
69
93
|
# Need to load the schedule from redis for the first time if dynamic
|
70
|
-
Resque.reload_schedule! if dynamic
|
71
|
-
|
94
|
+
Resque.reload_schedule! if dynamic
|
95
|
+
|
72
96
|
log! "Schedule empty! Set Resque.schedule" if Resque.schedule.empty?
|
73
|
-
|
97
|
+
|
74
98
|
@@scheduled_jobs = {}
|
75
|
-
|
99
|
+
|
76
100
|
Resque.schedule.each do |name, config|
|
77
101
|
load_schedule_job(name, config)
|
78
102
|
end
|
79
103
|
Resque.redis.del(:schedules_changed)
|
80
104
|
procline "Schedules Loaded"
|
81
105
|
end
|
82
|
-
|
106
|
+
|
83
107
|
# Loads a job schedule into the Rufus::Scheduler and stores it in @@scheduled_jobs
|
84
108
|
def load_schedule_job(name, config)
|
85
109
|
# If rails_env is set in the config, enforce ENV['RAILS_ENV'] as
|
@@ -128,7 +152,7 @@ module Resque
|
|
128
152
|
end
|
129
153
|
end
|
130
154
|
end
|
131
|
-
|
155
|
+
|
132
156
|
# Enqueues all delayed jobs for a timestamp
|
133
157
|
def enqueue_delayed_items_for_timestamp(timestamp)
|
134
158
|
item = nil
|
@@ -152,9 +176,12 @@ module Resque
|
|
152
176
|
# Enqueues a job based on a config hash
|
153
177
|
def enqueue_from_config(job_config)
|
154
178
|
args = job_config['args'] || job_config[:args]
|
179
|
+
|
155
180
|
klass_name = job_config['class'] || job_config[:class]
|
181
|
+
klass = constantize(klass_name) rescue klass_name
|
182
|
+
|
156
183
|
params = args.is_a?(Hash) ? [args] : Array(args)
|
157
|
-
queue = job_config['queue'] || job_config[:queue] || Resque.queue_from_class(
|
184
|
+
queue = job_config['queue'] || job_config[:queue] || Resque.queue_from_class(klass)
|
158
185
|
# Support custom job classes like those that inherit from Resque::JobWithStatus (resque-status)
|
159
186
|
if (job_klass = job_config['custom_job_class']) && (job_klass != 'Resque::Job')
|
160
187
|
# The custom job class API must offer a static "scheduled" method. If the custom
|
@@ -167,7 +194,14 @@ module Resque
|
|
167
194
|
Resque::Job.create(queue, job_klass, *params)
|
168
195
|
end
|
169
196
|
else
|
170
|
-
|
197
|
+
# hack to avoid havoc for people shoving stuff into queues
|
198
|
+
# for non-existent classes (for example: running scheduler in
|
199
|
+
# one app that schedules for another
|
200
|
+
if Class === klass
|
201
|
+
Resque.enqueue(klass, *params)
|
202
|
+
else
|
203
|
+
Resque::Job.create(queue, klass, *params)
|
204
|
+
end
|
171
205
|
end
|
172
206
|
rescue
|
173
207
|
log! "Failed to enqueue #{klass_name}:\n #{$!}"
|
@@ -185,13 +219,13 @@ module Resque
|
|
185
219
|
@@scheduled_jobs = {}
|
186
220
|
rufus_scheduler
|
187
221
|
end
|
188
|
-
|
222
|
+
|
189
223
|
def reload_schedule!
|
190
224
|
procline "Reloading Schedule"
|
191
225
|
clear_schedule!
|
192
226
|
load_schedule!
|
193
227
|
end
|
194
|
-
|
228
|
+
|
195
229
|
def update_schedule
|
196
230
|
if Resque.redis.scard(:schedules_changed) > 0
|
197
231
|
procline "Updating schedule"
|
@@ -207,7 +241,7 @@ module Resque
|
|
207
241
|
procline "Schedules Loaded"
|
208
242
|
end
|
209
243
|
end
|
210
|
-
|
244
|
+
|
211
245
|
def unschedule_job(name)
|
212
246
|
if scheduled_jobs[name]
|
213
247
|
log "Removing schedule #{name}"
|
@@ -219,7 +253,7 @@ module Resque
|
|
219
253
|
# Sleeps and returns true
|
220
254
|
def poll_sleep
|
221
255
|
@sleeping = true
|
222
|
-
handle_shutdown { sleep
|
256
|
+
handle_shutdown { sleep poll_sleep_amount }
|
223
257
|
@sleeping = false
|
224
258
|
true
|
225
259
|
end
|
@@ -238,7 +272,7 @@ module Resque
|
|
238
272
|
# add "verbose" logic later
|
239
273
|
log!(msg) if verbose
|
240
274
|
end
|
241
|
-
|
275
|
+
|
242
276
|
def procline(string)
|
243
277
|
log! string
|
244
278
|
$0 = "resque-scheduler-#{ResqueScheduler::Version}: #{string}"
|
data/lib/resque_scheduler.rb
CHANGED
@@ -10,23 +10,31 @@ module ResqueScheduler
|
|
10
10
|
#
|
11
11
|
# Accepts a new schedule configuration of the form:
|
12
12
|
#
|
13
|
-
# {some_name => {"cron" => "5/* * * *",
|
14
|
-
# "class" => DoSomeWork,
|
13
|
+
# {'some_name' => {"cron" => "5/* * * *",
|
14
|
+
# "class" => "DoSomeWork",
|
15
15
|
# "args" => "work on this string",
|
16
16
|
# "description" => "this thing works it"s butter off"},
|
17
17
|
# ...}
|
18
18
|
#
|
19
|
-
#
|
19
|
+
# 'some_name' can be anything and is used only to describe and reference
|
20
|
+
# the scheduled job
|
21
|
+
#
|
20
22
|
# :cron can be any cron scheduling string :job can be any resque job class
|
21
|
-
#
|
22
|
-
#
|
23
|
+
#
|
24
|
+
# :every can be used in lieu of :cron. see rufus-scheduler's 'every' usage
|
25
|
+
# for valid syntax. If :cron is present it will take precedence over :every.
|
26
|
+
#
|
23
27
|
# :class must be a resque worker class
|
24
|
-
#
|
25
|
-
#
|
26
|
-
#
|
27
|
-
#
|
28
|
-
#
|
29
|
-
#
|
28
|
+
#
|
29
|
+
# :args can be any yaml which will be converted to a ruby literal and
|
30
|
+
# passed in a params. (optional)
|
31
|
+
#
|
32
|
+
# :rails_envs is the list of envs where the job gets loaded. Envs are
|
33
|
+
# comma separated (optional)
|
34
|
+
#
|
35
|
+
# :description is just that, a description of the job (optional). If
|
36
|
+
# params is an array, each element in the array is passed as a separate
|
37
|
+
# param, otherwise params is passed in as the only parameter to perform.
|
30
38
|
def schedule=(schedule_hash)
|
31
39
|
if Resque::Scheduler.dynamic
|
32
40
|
schedule_hash.each do |name, job_spec|
|
@@ -59,7 +67,15 @@ module ResqueScheduler
|
|
59
67
|
end
|
60
68
|
end
|
61
69
|
|
62
|
-
#
|
70
|
+
# Create or update a schedule with the provided name and configuration.
|
71
|
+
#
|
72
|
+
# Note: values for class and custom_job_class need to be strings,
|
73
|
+
# not constants.
|
74
|
+
#
|
75
|
+
# Resque.set_schedule('some_job', {:class => 'SomeJob',
|
76
|
+
# :every => '15mins',
|
77
|
+
# :queue => 'high',
|
78
|
+
# :args => '/tmp/poop'})
|
63
79
|
def set_schedule(name, config)
|
64
80
|
existing_config = get_schedule(name)
|
65
81
|
unless existing_config && existing_config == config
|
@@ -89,12 +105,26 @@ module ResqueScheduler
|
|
89
105
|
delayed_push(timestamp, job_to_hash(klass, args))
|
90
106
|
end
|
91
107
|
|
108
|
+
# Identical to +enqueue_at+, except you can also specify
|
109
|
+
# a queue in which the job will be placed after the
|
110
|
+
# timestamp has passed.
|
111
|
+
def enqueue_at_with_queue(queue, timestamp, klass, *args)
|
112
|
+
delayed_push(timestamp, job_to_hash_with_queue(queue, klass, args))
|
113
|
+
end
|
114
|
+
|
92
115
|
# Identical to enqueue_at but takes number_of_seconds_from_now
|
93
116
|
# instead of a timestamp.
|
94
117
|
def enqueue_in(number_of_seconds_from_now, klass, *args)
|
95
118
|
enqueue_at(Time.now + number_of_seconds_from_now, klass, *args)
|
96
119
|
end
|
97
120
|
|
121
|
+
# Identical to +enqueue_in+, except you can also specify
|
122
|
+
# a queue in which the job will be placed after the
|
123
|
+
# number of seconds has passed.
|
124
|
+
def enqueue_in_with_queue(queue, number_of_seconds_from_now, klass, *args)
|
125
|
+
enqueue_at_with_queue(queue, Time.now + number_of_seconds_from_now, klass, *args)
|
126
|
+
end
|
127
|
+
|
98
128
|
# Used internally to stuff the item into the schedule sorted list.
|
99
129
|
# +timestamp+ can be either in seconds or a datetime object
|
100
130
|
# Insertion if O(log(n)).
|
@@ -183,9 +213,14 @@ module ResqueScheduler
|
|
183
213
|
end
|
184
214
|
|
185
215
|
private
|
216
|
+
|
186
217
|
def job_to_hash(klass, args)
|
187
218
|
{:class => klass.to_s, :args => args, :queue => queue_from_class(klass)}
|
188
219
|
end
|
220
|
+
|
221
|
+
def job_to_hash_with_queue(queue, klass, args)
|
222
|
+
{:class => klass.to_s, :args => args, :queue => queue}
|
223
|
+
end
|
189
224
|
|
190
225
|
def clean_up_timestamp(key, timestamp)
|
191
226
|
# If the list is empty, remove it.
|
@@ -45,6 +45,11 @@ module ResqueScheduler
|
|
45
45
|
Resque::Scheduler.enqueue_delayed_items_for_timestamp(timestamp.to_i) if timestamp.to_i > 0
|
46
46
|
redirect u("/overview")
|
47
47
|
end
|
48
|
+
|
49
|
+
post "/delayed/clear" do
|
50
|
+
Resque.reset_delayed_queue
|
51
|
+
redirect u('delayed')
|
52
|
+
end
|
48
53
|
|
49
54
|
end
|
50
55
|
|
@@ -1,11 +1,17 @@
|
|
1
1
|
<h1>Delayed Jobs</h1>
|
2
|
+
<%- size = resque.delayed_queue_schedule_size %>
|
3
|
+
<% if size > 0 %>
|
4
|
+
<form method="POST" action="<%=u 'delayed/clear'%>" class='clear-delayed'>
|
5
|
+
<input type='submit' name='' value='Clear Delayed Jobs' />
|
6
|
+
</form>
|
7
|
+
<% end %>
|
2
8
|
|
3
9
|
<p class='intro'>
|
4
10
|
This list below contains the timestamps for scheduled delayed jobs.
|
5
11
|
</p>
|
6
12
|
|
7
13
|
<p class='sub'>
|
8
|
-
Showing <%= start = params[:start].to_i %> to <%= start + 20 %> of <b><%=size
|
14
|
+
Showing <%= start = params[:start].to_i %> to <%= start + 20 %> of <b><%= size %></b> timestamps
|
9
15
|
</p>
|
10
16
|
|
11
17
|
<table>
|
@@ -16,7 +22,7 @@
|
|
16
22
|
<th>Class</th>
|
17
23
|
<th>Args</th>
|
18
24
|
</tr>
|
19
|
-
<% resque.delayed_queue_peek(start,
|
25
|
+
<% resque.delayed_queue_peek(start, 20).each do |timestamp| %>
|
20
26
|
<tr>
|
21
27
|
<td>
|
22
28
|
<form action="<%= u "/delayed/queue_now" %>" method="post">
|
@@ -11,6 +11,7 @@ namespace :resque do
|
|
11
11
|
|
12
12
|
File.open(ENV['PIDFILE'], 'w') { |f| f << Process.pid.to_s } if ENV['PIDFILE']
|
13
13
|
|
14
|
+
Resque::Scheduler.dynamic = true if ENV['DYNAMIC_SCHEDULE']
|
14
15
|
Resque::Scheduler.verbose = true if ENV['VERBOSE']
|
15
16
|
Resque::Scheduler.run
|
16
17
|
end
|
@@ -23,4 +24,4 @@ namespace :resque do
|
|
23
24
|
end
|
24
25
|
end
|
25
26
|
|
26
|
-
end
|
27
|
+
end
|
data/resque-scheduler.gemspec
CHANGED
@@ -12,18 +12,17 @@ Gem::Specification.new do |s|
|
|
12
12
|
s.description = %q{Light weight job scheduling on top of Resque.
|
13
13
|
Adds methods enqueue_at/enqueue_in to schedule jobs in the future.
|
14
14
|
Also supports queueing jobs on a fixed, cron-like schedule.}
|
15
|
-
|
15
|
+
|
16
16
|
s.required_rubygems_version = ">= 1.3.6"
|
17
17
|
s.add_development_dependency "bundler", ">= 1.0.0"
|
18
18
|
|
19
19
|
s.files = `git ls-files`.split("\n")
|
20
20
|
s.executables = `git ls-files`.split("\n").map{|f| f =~ /^bin\/(.*)/ ? $1 : nil}.compact
|
21
21
|
s.require_path = 'lib'
|
22
|
-
|
22
|
+
|
23
23
|
s.add_runtime_dependency(%q<redis>, [">= 2.0.1"])
|
24
|
-
s.add_runtime_dependency(%q<resque>, [">= 1.
|
24
|
+
s.add_runtime_dependency(%q<resque>, [">= 1.15.0"])
|
25
25
|
s.add_runtime_dependency(%q<rufus-scheduler>, [">= 0"])
|
26
26
|
s.add_development_dependency(%q<mocha>, [">= 0"])
|
27
27
|
s.add_development_dependency(%q<rack-test>, [">= 0"])
|
28
|
-
|
29
28
|
end
|
data/test/delayed_queue_test.rb
CHANGED
@@ -28,7 +28,35 @@ class Resque::DelayedQueueTest < Test::Unit::TestCase
|
|
28
28
|
# Confirm the item came out correctly
|
29
29
|
assert_equal('SomeIvarJob', item['class'], "Should be the same class that we queued")
|
30
30
|
assert_equal(["path"], item['args'], "Should have the same arguments that we queued")
|
31
|
-
|
31
|
+
|
32
|
+
# And now confirm the keys are gone
|
33
|
+
assert(!Resque.redis.exists("delayed:#{timestamp.to_i}"))
|
34
|
+
assert_equal(0, Resque.redis.zcard(:delayed_queue_schedule), "delayed queue should be empty")
|
35
|
+
end
|
36
|
+
|
37
|
+
def test_enqueue_at_with_queue_adds_correct_list_and_zset_and_queue
|
38
|
+
|
39
|
+
timestamp = Time.now - 1 # 1 second ago (in the past, should come out right away)
|
40
|
+
|
41
|
+
assert_equal(0, Resque.redis.llen("delayed:#{timestamp.to_i}").to_i, "delayed queue should be empty to start")
|
42
|
+
|
43
|
+
Resque.enqueue_at_with_queue('critical', timestamp, SomeIvarJob, "path")
|
44
|
+
|
45
|
+
# Confirm the correct keys were added
|
46
|
+
assert_equal(1, Resque.redis.llen("delayed:#{timestamp.to_i}").to_i, "delayed queue should have one entry now")
|
47
|
+
assert_equal(1, Resque.redis.zcard(:delayed_queue_schedule), "The delayed_queue_schedule should have 1 entry now")
|
48
|
+
|
49
|
+
read_timestamp = Resque.next_delayed_timestamp
|
50
|
+
|
51
|
+
# Confirm the timestamp came out correctly
|
52
|
+
assert_equal(timestamp.to_i, read_timestamp, "The timestamp we pull out of redis should match the one we put in")
|
53
|
+
item = Resque.next_item_for_timestamp(read_timestamp)
|
54
|
+
|
55
|
+
# Confirm the item came out correctly
|
56
|
+
assert_equal('SomeIvarJob', item['class'], "Should be the same class that we queued")
|
57
|
+
assert_equal(["path"], item['args'], "Should have the same arguments that we queued")
|
58
|
+
assert_equal('critical', item['queue'], "Should have the queue that we asked for")
|
59
|
+
|
32
60
|
# And now confirm the keys are gone
|
33
61
|
assert(!Resque.redis.exists("delayed:#{timestamp.to_i}"))
|
34
62
|
assert_equal(0, Resque.redis.zcard(:delayed_queue_schedule), "delayed queue should be empty")
|
@@ -126,8 +154,7 @@ class Resque::DelayedQueueTest < Test::Unit::TestCase
|
|
126
154
|
Resque.enqueue_at(t, SomeIvarJob)
|
127
155
|
|
128
156
|
# 2 SomeIvarJob jobs should be created in the "ivar" queue
|
129
|
-
Resque::Job.expects(:create).twice.with(
|
130
|
-
Resque.expects(:queue_from_class).never # Should NOT need to load the class
|
157
|
+
Resque::Job.expects(:create).twice.with(:ivar, SomeIvarJob, nil)
|
131
158
|
Resque::Scheduler.handle_delayed_items
|
132
159
|
end
|
133
160
|
|
@@ -137,23 +164,21 @@ class Resque::DelayedQueueTest < Test::Unit::TestCase
|
|
137
164
|
Resque.enqueue_at(t, SomeIvarJob)
|
138
165
|
|
139
166
|
# 2 SomeIvarJob jobs should be created in the "ivar" queue
|
140
|
-
Resque::Job.expects(:create).twice.with(
|
141
|
-
Resque.expects(:queue_from_class).never # Should NOT need to load the class
|
167
|
+
Resque::Job.expects(:create).twice.with(:ivar, SomeIvarJob, nil)
|
142
168
|
Resque::Scheduler.handle_delayed_items(t)
|
143
169
|
end
|
144
|
-
|
170
|
+
|
145
171
|
def test_enqueue_delayed_items_for_timestamp
|
146
172
|
t = Time.now + 60
|
147
|
-
|
173
|
+
|
148
174
|
Resque.enqueue_at(t, SomeIvarJob)
|
149
175
|
Resque.enqueue_at(t, SomeIvarJob)
|
150
176
|
|
151
177
|
# 2 SomeIvarJob jobs should be created in the "ivar" queue
|
152
|
-
Resque::Job.expects(:create).twice.with(
|
153
|
-
Resque.expects(:queue_from_class).never # Should NOT need to load the class
|
178
|
+
Resque::Job.expects(:create).twice.with(:ivar, SomeIvarJob, nil)
|
154
179
|
|
155
180
|
Resque::Scheduler.enqueue_delayed_items_for_timestamp(t)
|
156
|
-
|
181
|
+
|
157
182
|
# delayed queue for timestamp should be empty
|
158
183
|
assert_equal(0, Resque.delayed_timestamp_peek(t, 0, 3).length)
|
159
184
|
end
|
@@ -165,7 +190,7 @@ class Resque::DelayedQueueTest < Test::Unit::TestCase
|
|
165
190
|
# Since we didn't specify :queue when calling delayed_push, it will be forced
|
166
191
|
# to load the class to figure out the queue. This is the upgrade case from 1.0.4
|
167
192
|
# to 1.0.5.
|
168
|
-
Resque::Job.expects(:create).once.with(:ivar,
|
193
|
+
Resque::Job.expects(:create).once.with(:ivar, SomeIvarJob, nil)
|
169
194
|
|
170
195
|
Resque::Scheduler.handle_delayed_items
|
171
196
|
end
|
@@ -206,7 +231,7 @@ class Resque::DelayedQueueTest < Test::Unit::TestCase
|
|
206
231
|
assert_equal(2, Resque.remove_delayed(SomeIvarJob, "bar"))
|
207
232
|
assert_equal(1, Resque.delayed_queue_schedule_size)
|
208
233
|
end
|
209
|
-
|
234
|
+
|
210
235
|
def test_remove_specific_item_in_group_of_other_items_at_different_timestamps
|
211
236
|
t = Time.now + 120
|
212
237
|
Resque.enqueue_at(t, SomeIvarJob, "foo")
|