resque-scheduler 1.9.10 → 2.0.0.a

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.

@@ -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