resque-scheduler 2.0.0.d → 2.0.0.e
Sign up to get free protection for your applications and to get access to all the features.
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")
|