resque-scheduler 1.9.10 → 2.0.0.a

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.

@@ -18,7 +18,7 @@ module ResqueScheduler
18
18
  #
19
19
  # :name can be anything and is used only to describe the scheduled job
20
20
  # :cron can be any cron scheduling string :job can be any resque job class
21
- # :every can be used in lieu of :cron. see rufus-scheduler's 'every' usage for
21
+ # :every can be used in lieu of :cron. see rufus-scheduler's 'every' usage for
22
22
  # valid syntax. If :cron is present it will take precedence over :every.
23
23
  # :class must be a resque worker class
24
24
  # :args can be any yaml which will be converted to a ruby literal and passed
@@ -28,6 +28,11 @@ module ResqueScheduler
28
28
  # an array, each element in the array is passed as a separate param,
29
29
  # otherwise params is passed in as the only parameter to perform.
30
30
  def schedule=(schedule_hash)
31
+ if Resque::Scheduler.dynamic
32
+ schedule_hash.each do |name, job_spec|
33
+ set_schedule(name, job_spec)
34
+ end
35
+ end
31
36
  @schedule = schedule_hash
32
37
  end
33
38
 
@@ -35,37 +40,60 @@ module ResqueScheduler
35
40
  def schedule
36
41
  @schedule ||= {}
37
42
  end
43
+
44
+ # reloads the schedule from redis
45
+ def reload_schedule!
46
+ @schedule = get_schedules
47
+ end
48
+
49
+ # gets the schedule as it exists in redis
50
+ def get_schedules
51
+ if redis.exists(:schedules)
52
+ redis.hgetall(:schedules).tap do |h|
53
+ h.each do |name, config|
54
+ h[name] = decode(config)
55
+ end
56
+ end
57
+ else
58
+ nil
59
+ end
60
+ end
61
+
62
+ # create or update a schedule with the provided name and configuration
63
+ def set_schedule(name, config)
64
+ existing_config = get_schedule(name)
65
+ unless existing_config && existing_config == config
66
+ redis.hset(:schedules, name, encode(config))
67
+ redis.sadd(:schedules_changed, name)
68
+ end
69
+ config
70
+ end
71
+
72
+ # retrive the schedule configuration for the given name
73
+ def get_schedule(name)
74
+ decode(redis.hget(:schedules, name))
75
+ end
76
+
77
+ # remove a given schedule by name
78
+ def remove_schedule(name)
79
+ redis.hdel(:schedules, name)
80
+ redis.sadd(:schedules_changed, name)
81
+ end
38
82
 
39
83
  # This method is nearly identical to +enqueue+ only it also
40
84
  # takes a timestamp which will be used to schedule the job
41
85
  # for queueing. Until timestamp is in the past, the job will
42
86
  # sit in the schedule list.
43
87
  def enqueue_at(timestamp, klass, *args)
44
- validate_job!(klass)
45
88
  delayed_push(timestamp, job_to_hash(klass, args))
46
89
  end
47
90
 
48
- # Identical to +enqueue_at+, except you can also specify
49
- # a queue in which the job will be placed after the
50
- # timestamp has passed.
51
- def enqueue_at_with_queue(queue, timestamp, klass, *args)
52
- validate_job!(klass)
53
- delayed_push(timestamp, job_to_hash_with_queue(queue, klass, args))
54
- end
55
-
56
91
  # Identical to enqueue_at but takes number_of_seconds_from_now
57
92
  # instead of a timestamp.
58
93
  def enqueue_in(number_of_seconds_from_now, klass, *args)
59
94
  enqueue_at(Time.now + number_of_seconds_from_now, klass, *args)
60
95
  end
61
96
 
62
- # Identical to +enqueue_in+, except you can also specify
63
- # a queue in which the job will be placed after the
64
- # number of seconds has passed.
65
- def enqueue_in_with_queue(queue, number_of_seconds_from_now, klass, *args)
66
- enqueue_at_with_queue(queue, Time.now + number_of_seconds_from_now, klass, *args)
67
- end
68
-
69
97
  # Used internally to stuff the item into the schedule sorted list.
70
98
  # +timestamp+ can be either in seconds or a datetime object
71
99
  # Insertion if O(log(n)).
@@ -146,22 +174,18 @@ module ResqueScheduler
146
174
  end
147
175
 
148
176
  def count_all_scheduled_jobs
149
- total_jobs = 0
177
+ total_jobs = 0
150
178
  Array(redis.zrange(:delayed_queue_schedule, 0, -1)).each do |timestamp|
151
179
  total_jobs += redis.llen("delayed:#{timestamp}").to_i
152
- end
180
+ end
153
181
  total_jobs
154
- end
182
+ end
155
183
 
156
184
  private
157
185
  def job_to_hash(klass, args)
158
186
  {:class => klass.to_s, :args => args, :queue => queue_from_class(klass)}
159
187
  end
160
188
 
161
- def job_to_hash_with_queue(queue, klass, args)
162
- {:class => klass.to_s, :args => args, :queue => queue}
163
- end
164
-
165
189
  def clean_up_timestamp(key, timestamp)
166
190
  # If the list is empty, remove it.
167
191
  if 0 == redis.llen(key).to_i
@@ -170,16 +194,6 @@ module ResqueScheduler
170
194
  end
171
195
  end
172
196
 
173
- def validate_job!(klass)
174
- if klass.to_s.empty?
175
- raise Resque::NoClassError.new("Jobs must be given a class.")
176
- end
177
-
178
- unless queue_from_class(klass)
179
- raise Resque::NoQueueError.new("Jobs must be placed onto a queue.")
180
- end
181
- end
182
-
183
197
  end
184
198
 
185
199
  Resque.extend ResqueScheduler
@@ -1,7 +1,7 @@
1
1
 
2
2
  # Extend Resque::Server to add tabs
3
3
  module ResqueScheduler
4
-
4
+
5
5
  module Server
6
6
 
7
7
  def self.included(base)
@@ -19,6 +19,7 @@ module ResqueScheduler
19
19
  end
20
20
 
21
21
  get "/schedule" do
22
+ Resque.reload_schedule! if Resque::Scheduler.dynamic
22
23
  # Is there a better way to specify alternate template locations with sinatra?
23
24
  erb File.read(File.join(File.dirname(__FILE__), 'server/views/scheduler.erb'))
24
25
  end
@@ -26,9 +27,9 @@ module ResqueScheduler
26
27
  post "/schedule/requeue" do
27
28
  config = Resque.schedule[params['job_name']]
28
29
  Resque::Scheduler.enqueue_from_config(config)
29
- redirect u("/overview")
30
+ redirect url("/overview")
30
31
  end
31
-
32
+
32
33
  get "/delayed" do
33
34
  # Is there a better way to specify alternate template locations with sinatra?
34
35
  erb File.read(File.join(File.dirname(__FILE__), 'server/views/delayed.erb'))
@@ -38,11 +39,11 @@ module ResqueScheduler
38
39
  # Is there a better way to specify alternate template locations with sinatra?
39
40
  erb File.read(File.join(File.dirname(__FILE__), 'server/views/delayed_timestamp.erb'))
40
41
  end
41
-
42
+
42
43
  post "/delayed/queue_now" do
43
44
  timestamp = params['timestamp']
44
45
  Resque::Scheduler.enqueue_delayed_items_for_timestamp(timestamp.to_i) if timestamp.to_i > 0
45
- redirect u("/overview")
46
+ redirect url("/overview")
46
47
  end
47
48
 
48
49
  end
@@ -53,5 +54,5 @@ module ResqueScheduler
53
54
  Resque::Server.tabs << 'Delayed'
54
55
 
55
56
  end
56
-
57
- end
57
+
58
+ end
@@ -19,19 +19,19 @@
19
19
  <% resque.delayed_queue_peek(start, start+20).each do |timestamp| %>
20
20
  <tr>
21
21
  <td>
22
- <form action="<%= u "/delayed/queue_now" %>" method="post">
22
+ <form action="<%= url "/delayed/queue_now" %>" method="post">
23
23
  <input type="hidden" name="timestamp" value="<%= timestamp.to_i %>">
24
24
  <input type="submit" value="Queue now">
25
25
  </form>
26
26
  </td>
27
- <td><a href="<%= u "delayed/#{timestamp}" %>"><%= format_time(Time.at(timestamp)) %></a></td>
27
+ <td><a href="<%= url "delayed/#{timestamp}" %>"><%= format_time(Time.at(timestamp)) %></a></td>
28
28
  <td><%= delayed_timestamp_size = resque.delayed_timestamp_size(timestamp) %></td>
29
29
  <% job = resque.delayed_timestamp_peek(timestamp, 0, 1).first %>
30
30
  <td>
31
31
  <% if job && delayed_timestamp_size == 1 %>
32
32
  <%= h(job['class']) %>
33
33
  <% else %>
34
- <a href="<%= u "delayed/#{timestamp}" %>">see details</a>
34
+ <a href="<%= url "delayed/#{timestamp}" %>">see details</a>
35
35
  <% end %>
36
36
  </td>
37
37
  <td><%= h(job['args'].inspect) if job && delayed_timestamp_size == 1 %></td>
@@ -15,11 +15,11 @@
15
15
  <th>Queue</th>
16
16
  <th>Arguments</th>
17
17
  </tr>
18
- <% Resque.schedule.keys.map(&:to_s).sort.map(&:to_sym).each do |name| %>
18
+ <% Resque.schedule.keys.sort.each do |name| %>
19
19
  <% config = Resque.schedule[name] %>
20
20
  <tr>
21
21
  <td>
22
- <form action="<%= u "/schedule/requeue" %>" method="post">
22
+ <form action="<%= url "/schedule/requeue" %>" method="post">
23
23
  <input type="hidden" name="job_name" value="<%= h name %>">
24
24
  <input type="submit" value="Queue now">
25
25
  </form>
@@ -27,8 +27,8 @@
27
27
  <td><%= h name %></td>
28
28
  <td><%= h config['description'] %></td>
29
29
  <td style="white-space:nowrap"><%= (config['cron'].nil? && !config['every'].nil?) ?
30
- h("every: #{config['every']}") :
31
- h("cron: #{config['cron']}") %></td>
30
+ h('every: ' + config['every']) :
31
+ h('cron: ' + config['cron']) %></td>
32
32
  <td><%= (config['class'].nil? && !config['custom_job_class'].nil?) ?
33
33
  h(config['custom_job_class']) :
34
34
  h(config['class']) %></td>
@@ -21,4 +21,4 @@ namespace :resque do
21
21
  end
22
22
  end
23
23
 
24
- end
24
+ end
@@ -1,3 +1,3 @@
1
1
  module ResqueScheduler
2
- VERSION = '1.9.10'
2
+ Version = '2.0.0.a'
3
3
  end
@@ -1,32 +1,29 @@
1
1
  # -*- encoding: utf-8 -*-
2
- lib = File.expand_path('../lib', __FILE__)
3
- $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
4
- require 'resque_scheduler/version'
2
+ require File.expand_path("../lib/resque_scheduler/version", __FILE__)
5
3
 
6
- Gem::Specification.new do |spec|
7
- spec.name = 'resque-scheduler'
8
- spec.version = ResqueScheduler::VERSION
9
- spec.authors = ['Ben VandenBos']
10
- spec.email = ['bvandenbos@gmail.com']
11
- spec.homepage = 'http://github.com/resque/resque-scheduler'
12
- spec.summary = 'Light weight job scheduling on top of Resque'
13
- spec.description = %q{Light weight job scheduling on top of Resque.
4
+ Gem::Specification.new do |s|
5
+ s.name = "resque-scheduler"
6
+ s.version = ResqueScheduler::Version
7
+ s.platform = Gem::Platform::RUBY
8
+ s.authors = ['Ben VandenBos']
9
+ s.email = ['bvandenbos@gmail.com']
10
+ s.homepage = "http://github.com/bvandenbos/resque-scheduler"
11
+ s.summary = "Light weight job scheduling on top of Resque"
12
+ s.description = %q{Light weight job scheduling on top of Resque.
14
13
  Adds methods enqueue_at/enqueue_in to schedule jobs in the future.
15
14
  Also supports queueing jobs on a fixed, cron-like schedule.}
15
+
16
+ s.required_rubygems_version = ">= 1.3.6"
17
+ s.add_development_dependency "bundler", ">= 1.0.0"
16
18
 
17
- spec.files = `git ls-files`.split("\n")
18
- spec.executables = spec.files.grep(%r{^bin/}) { |f| File.basename(f) }
19
- spec.test_files = spec.files.grep(%r{^test/})
20
- spec.require_path = ['lib']
21
-
22
- spec.add_development_dependency 'bundler', '~> 1.3'
23
- spec.add_development_dependency 'mocha'
24
- spec.add_development_dependency 'rack-test'
25
- spec.add_development_dependency 'rake'
26
- spec.add_development_dependency 'json' if RUBY_VERSION < '1.9'
27
- spec.add_development_dependency 'rubocop' unless RUBY_VERSION < '1.9'
28
-
29
- spec.add_runtime_dependency 'redis', '>= 2.0.1'
30
- spec.add_runtime_dependency 'resque', ['>= 1.8.0', '< 1.25.0']
31
- spec.add_runtime_dependency 'rufus-scheduler', '>= 0'
19
+ s.files = `git ls-files`.split("\n")
20
+ s.executables = `git ls-files`.split("\n").map{|f| f =~ /^bin\/(.*)/ ? $1 : nil}.compact
21
+ s.require_path = 'lib'
22
+
23
+ s.add_runtime_dependency(%q<redis>, [">= 2.0.1"])
24
+ s.add_runtime_dependency(%q<resque>, [">= 1.8.0"])
25
+ s.add_runtime_dependency(%q<rufus-scheduler>, [">= 0"])
26
+ s.add_development_dependency(%q<mocha>, [">= 0"])
27
+ s.add_development_dependency(%q<rack-test>, [">= 0"])
28
+
32
29
  end
@@ -28,34 +28,7 @@ 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
-
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_inserts_into_correct_queue
38
- timestamp = Time.now - 1 # 1 second ago (in the past, should come out right away)
39
-
40
- assert_equal(0, Resque.redis.llen("delayed:#{timestamp.to_i}").to_i, "delayed queue should be empty to start")
41
-
42
- Resque.enqueue_at_with_queue("critical", timestamp, SomeIvarJob, "path")
43
-
44
- # Confirm the correct keys were added
45
- assert_equal(1, Resque.redis.llen("delayed:#{timestamp.to_i}").to_i, "delayed queue should have one entry now")
46
- assert_equal(1, Resque.redis.zcard(:delayed_queue_schedule), "The delayed_queue_schedule should have 1 entry now")
47
-
48
- read_timestamp = Resque.next_delayed_timestamp
49
-
50
- # Confirm the timestamp came out correctly
51
- assert_equal(timestamp.to_i, read_timestamp, "The timestamp we pull out of redis should match the one we put in")
52
- item = Resque.next_item_for_timestamp(read_timestamp)
53
-
54
- # Confirm the item came out correctly
55
- assert_equal('SomeIvarJob', item['class'], "Should be the same class that we queued")
56
- assert_equal(["path"], item['args'], "Should have the same arguments that we queued")
57
- assert_equal('critical', item['queue'], "Should have the queue that we asked for")
58
-
31
+
59
32
  # And now confirm the keys are gone
60
33
  assert(!Resque.redis.exists("delayed:#{timestamp.to_i}"))
61
34
  assert_equal(0, Resque.redis.zcard(:delayed_queue_schedule), "delayed queue should be empty")
@@ -168,10 +141,10 @@ class Resque::DelayedQueueTest < Test::Unit::TestCase
168
141
  Resque.expects(:queue_from_class).never # Should NOT need to load the class
169
142
  Resque::Scheduler.handle_delayed_items(t)
170
143
  end
171
-
144
+
172
145
  def test_enqueue_delayed_items_for_timestamp
173
146
  t = Time.now + 60
174
-
147
+
175
148
  Resque.enqueue_at(t, SomeIvarJob)
176
149
  Resque.enqueue_at(t, SomeIvarJob)
177
150
 
@@ -180,7 +153,7 @@ class Resque::DelayedQueueTest < Test::Unit::TestCase
180
153
  Resque.expects(:queue_from_class).never # Should NOT need to load the class
181
154
 
182
155
  Resque::Scheduler.enqueue_delayed_items_for_timestamp(t)
183
-
156
+
184
157
  # delayed queue for timestamp should be empty
185
158
  assert_equal(0, Resque.delayed_timestamp_peek(t, 0, 3).length)
186
159
  end
@@ -233,7 +206,7 @@ class Resque::DelayedQueueTest < Test::Unit::TestCase
233
206
  assert_equal(2, Resque.remove_delayed(SomeIvarJob, "bar"))
234
207
  assert_equal(1, Resque.delayed_queue_schedule_size)
235
208
  end
236
-
209
+
237
210
  def test_remove_specific_item_in_group_of_other_items_at_different_timestamps
238
211
  t = Time.now + 120
239
212
  Resque.enqueue_at(t, SomeIvarJob, "foo")
@@ -244,13 +217,4 @@ class Resque::DelayedQueueTest < Test::Unit::TestCase
244
217
  assert_equal(2, Resque.remove_delayed(SomeIvarJob, "bar"))
245
218
  assert_equal(2, Resque.count_all_scheduled_jobs)
246
219
  end
247
-
248
- def test_invalid_job_class
249
- assert_raise Resque::NoClassError do
250
- Resque.enqueue_in(10, nil)
251
- end
252
- assert_raise Resque::NoQueueError do
253
- Resque.enqueue_in(10, String) # string serves as invalid Job class
254
- end
255
- end
256
220
  end
@@ -112,4 +112,4 @@ databases 16
112
112
  # Glue small output buffers together in order to send small replies in a
113
113
  # single TCP packet. Uses a bit more CPU but most of the times it is a win
114
114
  # in terms of number of queries per second. Use 'yes' if unsure.
115
- # glueoutputbuf yes
115
+ glueoutputbuf yes
@@ -10,10 +10,9 @@ context "on GET to /schedule" do
10
10
  end
11
11
 
12
12
  context "on GET to /schedule with scheduled jobs" do
13
- setup do
13
+ setup do
14
14
  ENV['rails_env'] = 'production'
15
- Resque.schedule = {:some_ivar_job => {'cron' => "* * * * *", 'class' => 'SomeIvarJob', 'args' => "/tmp", 'rails_env' => 'production'},
16
- :some_other_job => {'queue' => 'high', 'class' => 'SomeOtherJob', 'args' => {:b => 'blah'}}}
15
+ Resque.schedule = {:some_ivar_job => {'cron' => "* * * * *", 'class' => 'SomeIvarJob', 'args' => "/tmp", 'rails_env' => 'production'}}
17
16
  Resque::Scheduler.load_schedule!
18
17
  get "/schedule"
19
18
  end
@@ -14,7 +14,7 @@ context "scheduling jobs with arguments" do
14
14
  test "calls the worker without arguments when 'args' is blank in the config" do
15
15
  Resque::Scheduler.enqueue_from_config(YAML.load(<<-YAML))
16
16
  class: SomeIvarJob
17
- args:
17
+ args:
18
18
  YAML
19
19
  SomeIvarJob.expects(:perform).once.with()
20
20
  Resque.reserve('ivar').perform
@@ -7,7 +7,12 @@ class Resque::SchedulerTest < Test::Unit::TestCase
7
7
  end
8
8
 
9
9
  def setup
10
+ Resque::Scheduler.dynamic = false
11
+ Resque.redis.del(:schedules)
12
+ Resque.redis.del(:schedules_changed)
13
+ Resque::Scheduler.mute = true
10
14
  Resque::Scheduler.clear_schedule!
15
+ Resque::Scheduler.send(:class_variable_set, :@@scheduled_jobs, {})
11
16
  end
12
17
 
13
18
  def test_enqueue_from_config_puts_stuff_in_the_resque_queue_without_class_loaded
@@ -20,16 +25,11 @@ class Resque::SchedulerTest < Test::Unit::TestCase
20
25
  Resque::Scheduler.enqueue_from_config('every' => '1m', 'class' => 'JamesJob', 'args' => '/tmp', 'queue' => 'james_queue')
21
26
  end
22
27
 
23
- def test_enqueue_from_config_doesnt_crash_on_exception_when_enqueueing
24
- Resque::Job.stubs(:create).raises(Resque::NoQueueError, 'test exception').with(:ivar, 'SomeIvarJob', '/tmp')
25
- Resque::Scheduler.enqueue_from_config('cron' => "* * * * *", 'class' => 'SomeIvarJob', 'args' => "/tmp")
26
- end
27
-
28
28
  def test_enqueue_from_config_puts_stuff_in_the_resque_queue
29
29
  Resque::Job.stubs(:create).once.returns(true).with(:ivar, 'SomeIvarJob', '/tmp')
30
30
  Resque::Scheduler.enqueue_from_config('cron' => "* * * * *", 'class' => 'SomeIvarJob', 'args' => "/tmp")
31
31
  end
32
-
32
+
33
33
  def test_enqueue_from_config_with_custom_class_job_in_the_resque_queue
34
34
  FakeJob.stubs(:scheduled).once.returns(true).with(:ivar, 'SomeIvarJob', '/tmp')
35
35
  Resque::Scheduler.enqueue_from_config('cron' => "* * * * *", 'class' => 'SomeIvarJob', 'custom_job_class' => 'Resque::SchedulerTest::FakeJob', 'args' => "/tmp")
@@ -80,11 +80,164 @@ class Resque::SchedulerTest < Test::Unit::TestCase
80
80
  Resque::Scheduler.load_schedule!
81
81
 
82
82
  assert_equal(1, Resque::Scheduler.rufus_scheduler.all_jobs.size)
83
+ assert Resque::Scheduler.scheduled_jobs.include?(:some_ivar_job)
84
+ end
85
+
86
+ def test_can_reload_schedule
87
+ Resque::Scheduler.dynamic = true
88
+ Resque.schedule = {"some_ivar_job" => {'cron' => "* * * * *", 'class' => 'SomeIvarJob', 'args' => "/tmp"}}
89
+
90
+ Resque::Scheduler.load_schedule!
91
+
92
+ assert_equal(1, Resque::Scheduler.rufus_scheduler.all_jobs.size)
93
+ assert Resque::Scheduler.scheduled_jobs.include?("some_ivar_job")
94
+
95
+ Resque.redis.del(:schedules)
96
+ Resque.redis.hset(:schedules, "some_ivar_job2", Resque.encode(
97
+ {'cron' => "* * * * *", 'class' => 'SomeIvarJob', 'args' => "/tmp/2"}
98
+ ))
99
+
100
+ Resque::Scheduler.reload_schedule!
101
+
102
+ assert_equal(1, Resque::Scheduler.rufus_scheduler.all_jobs.size)
103
+
104
+ assert_equal '/tmp/2', Resque.schedule["some_ivar_job2"]["args"]
105
+ assert Resque::Scheduler.scheduled_jobs.include?("some_ivar_job2")
106
+ end
107
+
108
+ def test_load_schedule_job
109
+ Resque::Scheduler.load_schedule_job("some_ivar_job", {'cron' => "* * * * *", 'class' => 'SomeIvarJob', 'args' => "/tmp"})
110
+
111
+ assert_equal(1, Resque::Scheduler.rufus_scheduler.all_jobs.size)
112
+ assert_equal(1, Resque::Scheduler.scheduled_jobs.size)
113
+ assert Resque::Scheduler.scheduled_jobs.keys.include?("some_ivar_job")
114
+ end
115
+
116
+ def test_load_schedule_job_with_no_cron
117
+ Resque::Scheduler.load_schedule_job("some_ivar_job", {'class' => 'SomeIvarJob', 'args' => "/tmp"})
118
+
119
+ assert_equal(0, Resque::Scheduler.rufus_scheduler.all_jobs.size)
120
+ assert_equal(0, Resque::Scheduler.scheduled_jobs.size)
121
+ assert !Resque::Scheduler.scheduled_jobs.keys.include?("some_ivar_job")
122
+ end
123
+
124
+ def test_load_schedule_job_with_blank_cron
125
+ Resque::Scheduler.load_schedule_job("some_ivar_job", {'cron' => '', 'class' => 'SomeIvarJob', 'args' => "/tmp"})
126
+
127
+ assert_equal(0, Resque::Scheduler.rufus_scheduler.all_jobs.size)
128
+ assert_equal(0, Resque::Scheduler.scheduled_jobs.size)
129
+ assert !Resque::Scheduler.scheduled_jobs.keys.include?("some_ivar_job")
130
+ end
131
+
132
+ def test_update_schedule
133
+ Resque::Scheduler.dynamic = true
134
+ Resque.schedule = {
135
+ "some_ivar_job" => {'cron' => "* * * * *", 'class' => 'SomeIvarJob', 'args' => "/tmp"},
136
+ "another_ivar_job" => {'cron' => "* * * * *", 'class' => 'SomeIvarJob', 'args' => "/tmp/5"},
137
+ "stay_put_job" => {'cron' => "* * * * *", 'class' => 'SomeJob', 'args' => "/tmp"}
138
+ }
139
+
140
+ Resque::Scheduler.load_schedule!
141
+
142
+ Resque.set_schedule("some_ivar_job",
143
+ {'cron' => "* * * * *", 'class' => 'SomeIvarJob', 'args' => "/tmp/2"}
144
+ )
145
+ Resque.set_schedule("new_ivar_job",
146
+ {'cron' => "* * * * *", 'class' => 'SomeJob', 'args' => "/tmp/3"}
147
+ )
148
+ Resque.set_schedule("stay_put_job",
149
+ {'cron' => "* * * * *", 'class' => 'SomeJob', 'args' => "/tmp"}
150
+ )
151
+ Resque.remove_schedule("another_ivar_job")
152
+
153
+ Resque::Scheduler.update_schedule
154
+
155
+ assert_equal(3, Resque::Scheduler.rufus_scheduler.all_jobs.size)
156
+ assert_equal(3, Resque::Scheduler.scheduled_jobs.size)
157
+ %w(some_ivar_job new_ivar_job stay_put_job).each do |job_name|
158
+ assert Resque::Scheduler.scheduled_jobs.keys.include?(job_name)
159
+ assert Resque.schedule.keys.include?(job_name)
160
+ end
161
+ assert !Resque::Scheduler.scheduled_jobs.keys.include?("another_ivar_job")
162
+ assert !Resque.schedule.keys.include?("another_ivar_job")
163
+ assert_equal 0, Resque.redis.scard(:schedules_changed)
164
+ end
165
+
166
+ def test_update_schedule_with_mocks
167
+ Resque::Scheduler.dynamic = true
168
+ Resque.schedule = {
169
+ "some_ivar_job" => {'cron' => "* * * * *", 'class' => 'SomeIvarJob', 'args' => "/tmp"},
170
+ "another_ivar_job" => {'cron' => "* * * * *", 'class' => 'SomeIvarJob', 'args' => "/tmp/5"},
171
+ "stay_put_job" => {'cron' => "* * * * *", 'class' => 'SomeJob', 'args' => "/tmp"}
172
+ }
173
+
174
+ Resque::Scheduler.load_schedule!
175
+
176
+ Resque::Scheduler.rufus_scheduler.expects(:unschedule).with(Resque::Scheduler.scheduled_jobs["some_ivar_job"].job_id)
177
+ Resque::Scheduler.rufus_scheduler.expects(:unschedule).with(Resque::Scheduler.scheduled_jobs["another_ivar_job"].job_id)
178
+
179
+ Resque.set_schedule("some_ivar_job",
180
+ {'cron' => "* * * * *", 'class' => 'SomeIvarJob', 'args' => "/tmp/2"}
181
+ )
182
+ Resque.set_schedule("new_ivar_job",
183
+ {'cron' => "* * * * *", 'class' => 'SomeJob', 'args' => "/tmp/3"}
184
+ )
185
+ Resque.set_schedule("stay_put_job",
186
+ {'cron' => "* * * * *", 'class' => 'SomeJob', 'args' => "/tmp"}
187
+ )
188
+ Resque.remove_schedule("another_ivar_job")
189
+
190
+ Resque::Scheduler.update_schedule
191
+
192
+ assert_equal(3, Resque::Scheduler.scheduled_jobs.size)
193
+ %w(some_ivar_job new_ivar_job stay_put_job).each do |job_name|
194
+ assert Resque::Scheduler.scheduled_jobs.keys.include?(job_name)
195
+ assert Resque.schedule.keys.include?(job_name)
196
+ end
197
+ assert !Resque::Scheduler.scheduled_jobs.keys.include?("another_ivar_job")
198
+ assert !Resque.schedule.keys.include?("another_ivar_job")
199
+ assert_equal 0, Resque.redis.scard(:schedules_changed)
200
+ end
201
+
202
+ def test_set_schedules
203
+ Resque::Scheduler.dynamic = true
204
+ Resque.schedule = {"my_ivar_job" => {
205
+ 'cron' => "* * * * *", 'class' => 'SomeIvarJob', 'args' => "/tmp/75"
206
+ }}
207
+ assert_equal({'cron' => "* * * * *", 'class' => 'SomeIvarJob', 'args' => "/tmp/75"},
208
+ Resque.decode(Resque.redis.hget(:schedules, "my_ivar_job")))
209
+ end
210
+
211
+ def test_set_schedule
212
+ Resque.set_schedule("some_ivar_job", {
213
+ 'cron' => "* * * * *", 'class' => 'SomeIvarJob', 'args' => "/tmp/22"
214
+ })
215
+ assert_equal({'cron' => "* * * * *", 'class' => 'SomeIvarJob', 'args' => "/tmp/22"},
216
+ Resque.decode(Resque.redis.hget(:schedules, "some_ivar_job")))
217
+ assert Resque.redis.sismember(:schedules_changed, "some_ivar_job")
218
+ end
219
+
220
+ def test_get_schedule
221
+ Resque.redis.hset(:schedules, "some_ivar_job2", Resque.encode(
222
+ {'cron' => "* * * * *", 'class' => 'SomeIvarJob', 'args' => "/tmp/33"}
223
+ ))
224
+ assert_equal({'cron' => "* * * * *", 'class' => 'SomeIvarJob', 'args' => "/tmp/33"},
225
+ Resque.get_schedule("some_ivar_job2"))
226
+ end
227
+
228
+ def test_remove_schedule
229
+ Resque.redis.hset(:schedules, "some_ivar_job3", Resque.encode(
230
+ {'cron' => "* * * * *", 'class' => 'SomeIvarJob', 'args' => "/tmp/44"}
231
+ ))
232
+ Resque.remove_schedule("some_ivar_job3")
233
+ assert_equal nil, Resque.redis.hget(:schedules, "some_ivar_job3")
234
+ assert Resque.redis.sismember(:schedules_changed, "some_ivar_job3")
83
235
  end
84
236
 
85
237
  def test_adheres_to_lint
86
238
  assert_nothing_raised do
87
239
  Resque::Plugin.lint(Resque::Scheduler)
240
+ Resque::Plugin.lint(ResqueScheduler)
88
241
  end
89
242
  end
90
243