resque-scheduler 2.3.1 → 2.4.0

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.

Files changed (49) hide show
  1. data/.gitignore +3 -0
  2. data/.rubocop.yml +11 -11
  3. data/.simplecov +1 -0
  4. data/.travis.yml +5 -2
  5. data/AUTHORS.md +3 -0
  6. data/HISTORY.md +26 -2
  7. data/LICENSE +1 -1
  8. data/README.md +120 -31
  9. data/ROADMAP.md +10 -0
  10. data/Rakefile +7 -19
  11. data/bin/resque-scheduler +5 -0
  12. data/examples/Rakefile +2 -0
  13. data/examples/config/initializers/resque-web.rb +37 -0
  14. data/examples/dynamic-scheduling/README.md +28 -0
  15. data/examples/dynamic-scheduling/app/jobs/fix_schedules_job.rb +54 -0
  16. data/examples/dynamic-scheduling/app/jobs/send_email_job.rb +9 -0
  17. data/examples/dynamic-scheduling/app/models/user.rb +16 -0
  18. data/examples/dynamic-scheduling/config/resque.yml +4 -0
  19. data/examples/dynamic-scheduling/config/static_schedule.yml +7 -0
  20. data/examples/dynamic-scheduling/lib/tasks/resque.rake +48 -0
  21. data/examples/run-resque-web +3 -0
  22. data/lib/resque-scheduler.rb +2 -0
  23. data/lib/resque/scheduler.rb +130 -41
  24. data/lib/resque/scheduler/lock/resilient.rb +1 -1
  25. data/lib/resque/scheduler_locking.rb +3 -1
  26. data/lib/resque_scheduler.rb +73 -31
  27. data/lib/resque_scheduler/cli.rb +160 -0
  28. data/lib/resque_scheduler/logger_builder.rb +27 -8
  29. data/lib/resque_scheduler/plugin.rb +10 -7
  30. data/lib/resque_scheduler/server.rb +52 -11
  31. data/lib/resque_scheduler/server/views/delayed.erb +2 -0
  32. data/lib/resque_scheduler/server/views/delayed_schedules.erb +20 -0
  33. data/lib/resque_scheduler/server/views/scheduler.erb +4 -12
  34. data/lib/resque_scheduler/tasks.rb +15 -27
  35. data/lib/resque_scheduler/version.rb +1 -1
  36. data/resque-scheduler.gemspec +2 -0
  37. data/test/cli_test.rb +286 -0
  38. data/test/delayed_queue_test.rb +70 -1
  39. data/test/resque-web_test.rb +36 -1
  40. data/test/scheduler_args_test.rb +51 -17
  41. data/test/scheduler_hooks_test.rb +1 -1
  42. data/test/scheduler_locking_test.rb +63 -1
  43. data/test/scheduler_setup_test.rb +54 -18
  44. data/test/scheduler_task_test.rb +35 -0
  45. data/test/scheduler_test.rb +130 -42
  46. data/test/support/redis_instance.rb +8 -3
  47. data/test/test_helper.rb +47 -20
  48. metadata +77 -6
  49. checksums.yaml +0 -15
@@ -1,4 +1,4 @@
1
- require File.dirname(__FILE__) + '/test_helper'
1
+ require_relative 'test_helper'
2
2
 
3
3
  # Pull in the server test_helper from resque
4
4
  require 'resque/server/test_helper.rb'
@@ -45,6 +45,41 @@ context "on GET to /delayed" do
45
45
  should_respond_with_success
46
46
  end
47
47
 
48
+ context "on GET to /delayed/jobs/:klass" do
49
+ setup do
50
+ @t = Time.now + 3600
51
+ Resque.enqueue_at(@t, SomeIvarJob, 'foo', 'bar')
52
+ get URI("/delayed/jobs/SomeIvarJob?args=" + URI.encode(%w{foo bar}.to_json)).to_s
53
+ end
54
+
55
+ should_respond_with_success
56
+
57
+ test 'see the scheduled job' do
58
+ assert last_response.body.include?(@t.to_s)
59
+ end
60
+
61
+ context 'with a namespaced class' do
62
+ setup do
63
+ @t = Time.now + 3600
64
+ module Foo
65
+ class Bar
66
+ def self.queue
67
+ 'bar'
68
+ end
69
+ end
70
+ end
71
+ Resque.enqueue_at(@t, Foo::Bar, 'foo', 'bar')
72
+ get URI("/delayed/jobs/Foo::Bar?args=" + URI.encode(%w{foo bar}.to_json)).to_s
73
+ end
74
+
75
+ should_respond_with_success
76
+
77
+ test 'see the scheduled job' do
78
+ assert last_response.body.include?(@t.to_s)
79
+ end
80
+ end
81
+ end
82
+
48
83
  def resque_schedule
49
84
  {
50
85
  'job_without_params' => {
@@ -1,4 +1,4 @@
1
- require File.dirname(__FILE__) + '/test_helper'
1
+ require_relative 'test_helper'
2
2
 
3
3
  context "scheduling jobs with arguments" do
4
4
 
@@ -28,40 +28,74 @@ context "scheduling jobs with arguments" do
28
28
  Resque::Scheduler.enqueue_from_config('cron' => "* * * * *", 'class' => 'SomeIvarJob', 'custom_job_class' => 'FakeCustomJobClass', 'args' => "/tmp")
29
29
  end
30
30
 
31
- test "enqueue_from_config puts stuff in resquewhen rails_env matches" do
32
- # The job should be loaded : its rails_env config matches the RAILS_ENV variable:
33
- ENV['RAILS_ENV'] = 'production'
31
+ test 'enqueue_from_config puts stuff in resque when env matches' do
32
+ Resque::Scheduler.env = 'production'
34
33
  assert_equal(0, Resque::Scheduler.rufus_scheduler.all_jobs.size)
35
34
 
36
- Resque.schedule = {:some_ivar_job => {'cron' => "* * * * *", 'class' => 'SomeIvarJob', 'args' => "/tmp", 'rails_env' => 'production'}}
35
+ Resque.schedule = {
36
+ 'some_ivar_job' => {
37
+ 'cron' => '* * * * *',
38
+ 'class' => 'SomeIvarJob',
39
+ 'args' => '/tmp',
40
+ 'rails_env' => 'production'
41
+ }
42
+ }
43
+
37
44
  Resque::Scheduler.load_schedule!
38
45
  assert_equal(1, Resque::Scheduler.rufus_scheduler.all_jobs.size)
39
46
 
40
- # we allow multiple rails_env definition, it should work also:
41
- Resque.schedule = {:some_ivar_job => {'cron' => "* * * * *", 'class' => 'SomeIvarJob', 'args' => "/tmp", 'rails_env' => 'staging, production'}}
47
+ Resque.schedule = {
48
+ 'some_ivar_job' => {
49
+ 'cron' => '* * * * *',
50
+ 'class' => 'SomeIvarJob',
51
+ 'args' => '/tmp',
52
+ 'env' => 'staging, production'
53
+ }
54
+ }
55
+
42
56
  Resque::Scheduler.load_schedule!
43
57
  assert_equal(2, Resque::Scheduler.rufus_scheduler.all_jobs.size)
44
58
  end
45
59
 
46
- test "enqueue_from_config doesnt put stuff in resque when rails_env doesnt match" do
47
- # RAILS_ENV is not set:
60
+ test 'enqueue_from_config does not enqueue when env does not match' do
61
+ Resque::Scheduler.env = nil
48
62
  assert_equal(0, Resque::Scheduler.rufus_scheduler.all_jobs.size)
49
- Resque.schedule = {:some_ivar_job => {'cron' => "* * * * *", 'class' => 'SomeIvarJob', 'args' => "/tmp", 'rails_env' => 'staging'}}
63
+ Resque.schedule = {
64
+ 'some_ivar_job' => {
65
+ 'cron' => '* * * * *',
66
+ 'class' => 'SomeIvarJob',
67
+ 'args' => '/tmp',
68
+ 'rails_env' => 'staging'
69
+ }
70
+ }
71
+
50
72
  Resque::Scheduler.load_schedule!
51
73
  assert_equal(0, Resque::Scheduler.rufus_scheduler.all_jobs.size)
52
74
 
53
- # SET RAILS_ENV to a common value:
54
- ENV['RAILS_ENV'] = 'production'
55
- Resque.schedule = {:some_ivar_job => {'cron' => "* * * * *", 'class' => 'SomeIvarJob', 'args' => "/tmp", 'rails_env' => 'staging'}}
75
+ Resque::Scheduler.env = 'production'
76
+ Resque.schedule = {
77
+ 'some_ivar_job' => {
78
+ 'cron' => '* * * * *',
79
+ 'class' => 'SomeIvarJob',
80
+ 'args' => '/tmp',
81
+ 'env' => 'staging'
82
+ }
83
+ }
56
84
  Resque::Scheduler.load_schedule!
57
85
  assert_equal(0, Resque::Scheduler.rufus_scheduler.all_jobs.size)
58
86
  end
59
87
 
60
- test "enqueue_from_config when rails env arg is not set" do
61
- # The job should be loaded, since a missing rails_env means ALL envs.
62
- ENV['RAILS_ENV'] = 'production'
88
+ test 'enqueue_from_config when env env arg is not set' do
89
+ Resque::Scheduler.env = 'production'
63
90
  assert_equal(0, Resque::Scheduler.rufus_scheduler.all_jobs.size)
64
- Resque.schedule = {:some_ivar_job => {'cron' => "* * * * *", 'class' => 'SomeIvarJob', 'args' => "/tmp"}}
91
+
92
+ Resque.schedule = {
93
+ 'some_ivar_job' => {
94
+ 'cron' => '* * * * *',
95
+ 'class' => 'SomeIvarJob',
96
+ 'args' => '/tmp'
97
+ }
98
+ }
65
99
  Resque::Scheduler.load_schedule!
66
100
  assert_equal(1, Resque::Scheduler.rufus_scheduler.all_jobs.size)
67
101
  end
@@ -1,4 +1,4 @@
1
- require File.dirname(__FILE__) + '/test_helper'
1
+ require_relative 'test_helper'
2
2
 
3
3
  context "scheduling jobs with hooks" do
4
4
  setup do
@@ -1,4 +1,4 @@
1
- require File.dirname(__FILE__) + '/test_helper'
1
+ require_relative 'test_helper'
2
2
 
3
3
  module LockTestHelper
4
4
  def lock_is_not_held(lock)
@@ -6,6 +6,68 @@ module LockTestHelper
6
6
  end
7
7
  end
8
8
 
9
+ context '#master_lock_key' do
10
+ setup do
11
+ @subject = Class.new { extend Resque::SchedulerLocking }
12
+ end
13
+
14
+ teardown do
15
+ Resque.redis.del(@subject.master_lock.key)
16
+ end
17
+
18
+ test 'it should have resque prefix' do
19
+ assert_equal @subject.master_lock.key, 'resque:resque_scheduler_master_lock'
20
+ end
21
+
22
+ context 'with a prefix set via ENV' do
23
+ setup do
24
+ ENV['RESQUE_SCHEDULER_MASTER_LOCK_PREFIX'] = 'my.prefix'
25
+ @subject = Class.new { extend Resque::SchedulerLocking }
26
+ end
27
+
28
+ teardown do
29
+ Resque.redis.del(@subject.master_lock.key)
30
+ end
31
+
32
+ test 'it should have ENV prefix' do
33
+ assert_equal @subject.master_lock.key, 'resque:my.prefix:resque_scheduler_master_lock'
34
+ end
35
+ end
36
+
37
+ context 'with a namespace set for resque' do
38
+ setup do
39
+ Resque.redis.namespace = 'my.namespace'
40
+ @subject = Class.new { extend Resque::SchedulerLocking }
41
+ end
42
+
43
+ teardown do
44
+ Resque.redis.namespace = 'resque'
45
+ Resque.redis.del(@subject.master_lock.key)
46
+ end
47
+
48
+ test 'it should have resque prefix' do
49
+ assert_equal @subject.master_lock.key, 'my.namespace:resque_scheduler_master_lock'
50
+ end
51
+
52
+ context 'with a prefix set via ENV' do
53
+ setup do
54
+ Resque.redis.namespace = 'my.namespace'
55
+ ENV['RESQUE_SCHEDULER_MASTER_LOCK_PREFIX'] = 'my.prefix'
56
+ @subject = Class.new { extend Resque::SchedulerLocking }
57
+ end
58
+
59
+ teardown do
60
+ Resque.redis.namespace = 'resque'
61
+ Resque.redis.del(@subject.master_lock.key)
62
+ end
63
+
64
+ test 'it should have ENV prefix' do
65
+ assert_equal @subject.master_lock.key, 'my.namespace:my.prefix:resque_scheduler_master_lock'
66
+ end
67
+ end
68
+ end
69
+ end
70
+
9
71
  context 'Resque::SchedulerLocking' do
10
72
  setup do
11
73
  @subject = Class.new { extend Resque::SchedulerLocking }
@@ -1,59 +1,95 @@
1
- require File.dirname(__FILE__) + '/test_helper'
1
+ require_relative 'test_helper'
2
2
 
3
3
  context "Resque::Scheduler" do
4
-
5
4
  setup do
5
+ ENV['VERBOSE'] = nil
6
+ nullify_logger
6
7
  Resque::Scheduler.dynamic = false
7
8
  Resque.redis.flushall
8
9
  Resque::Scheduler.clear_schedule!
9
10
  end
10
11
 
12
+ teardown { restore_devnull_logfile }
13
+
11
14
  test 'set custom logger' do
12
15
  custom_logger = Logger.new('/dev/null')
13
16
  Resque::Scheduler.logger = custom_logger
14
17
  assert_equal(custom_logger, Resque::Scheduler.logger)
15
18
  end
16
19
 
17
- context 'logger default settings' do
18
- setup do
19
- nullify_logger
20
+ test 'configure block' do
21
+ Resque::Scheduler.mute = false
22
+ Resque::Scheduler.configure do |c|
23
+ c.mute = true
20
24
  end
25
+ assert_equal(Resque::Scheduler.mute, true)
26
+ end
27
+
28
+ context 'when getting the env' do
29
+ def wipe
30
+ Resque::Scheduler.env = nil
31
+ Rails.env = nil
32
+ ENV['RAILS_ENV'] = nil
33
+ end
34
+
35
+ setup { wipe }
36
+ teardown { wipe }
37
+
38
+ test 'uses the value if set' do
39
+ Resque::Scheduler.env = 'foo'
40
+ assert_equal('foo', Resque::Scheduler.env)
41
+ end
42
+
43
+ test 'uses Rails.env if present' do
44
+ Rails.env = 'bar'
45
+ assert_equal('bar', Resque::Scheduler.env)
46
+ end
47
+
48
+ test 'uses $RAILS_ENV if present' do
49
+ ENV['RAILS_ENV'] = 'baz'
50
+ assert_equal('baz', Resque::Scheduler.env)
51
+ end
52
+ end
53
+
54
+ context 'logger default settings' do
55
+ setup { nullify_logger }
56
+ teardown { restore_devnull_logfile }
21
57
 
22
58
  test 'uses STDOUT' do
23
- assert_equal(Resque::Scheduler.logger.instance_variable_get(:@logdev).dev, STDOUT)
59
+ assert_equal(
60
+ Resque::Scheduler.logger.instance_variable_get(:@logdev).dev, $stdout
61
+ )
24
62
  end
63
+
25
64
  test 'not verbose' do
26
65
  assert Resque::Scheduler.logger.level > Logger::DEBUG
27
66
  end
67
+
28
68
  test 'not muted' do
29
69
  assert Resque::Scheduler.logger.level < Logger::FATAL
30
70
  end
31
-
32
- teardown do
33
- nullify_logger
34
- end
35
71
  end
36
72
 
37
73
  context 'logger custom settings' do
38
- setup do
39
- nullify_logger
40
- end
74
+ setup { nullify_logger }
75
+ teardown { restore_devnull_logfile }
41
76
 
42
77
  test 'uses logfile' do
43
78
  Resque::Scheduler.logfile = '/dev/null'
44
- assert_equal(Resque::Scheduler.logger.instance_variable_get(:@logdev).filename, '/dev/null')
79
+ assert_equal(
80
+ Resque::Scheduler.logger.instance_variable_get(:@logdev).filename,
81
+ '/dev/null'
82
+ )
45
83
  end
84
+
46
85
  test 'set verbosity' do
47
86
  Resque::Scheduler.verbose = true
48
87
  assert Resque::Scheduler.logger.level == Logger::DEBUG
49
88
  end
89
+
50
90
  test 'mute logger' do
51
91
  Resque::Scheduler.mute = true
52
92
  assert Resque::Scheduler.logger.level == Logger::FATAL
53
93
  end
54
-
55
- teardown do
56
- nullify_logger
57
- end
58
94
  end
59
95
  end
@@ -0,0 +1,35 @@
1
+ require_relative 'test_helper'
2
+
3
+ context "Resque::Scheduler" do
4
+ setup do
5
+ Resque::Scheduler.dynamic = false
6
+ Resque.redis.flushall
7
+ Resque::Scheduler.mute = true
8
+ Resque::Scheduler.clear_schedule!
9
+ Resque::Scheduler.send(:class_variable_set, :@@scheduled_jobs, {})
10
+ Resque::Scheduler.send(:instance_variable_set, :@shutdown, false)
11
+ end
12
+
13
+ test "shutdown raises Interrupt when sleeping" do
14
+ Thread.current.expects(:raise).with(Interrupt)
15
+ Resque::Scheduler.send(:instance_variable_set, :@th, Thread.current)
16
+ Resque::Scheduler.send(:instance_variable_set, :@sleeping, true)
17
+ Resque::Scheduler.shutdown
18
+ end
19
+
20
+ test "sending TERM to scheduler breaks out of poll_sleep" do
21
+ Resque::Scheduler.expects(:release_master_lock!)
22
+ fork do
23
+ sleep(0.5)
24
+ system("kill -TERM #{Process.ppid}")
25
+ exit!
26
+ end
27
+
28
+ assert_raises SystemExit do
29
+ Resque::Scheduler.run
30
+ end
31
+
32
+ Resque::Scheduler.unstub(:release_master_lock!)
33
+ Resque::Scheduler.release_master_lock!
34
+ end
35
+ end
@@ -1,41 +1,56 @@
1
- require File.dirname(__FILE__) + '/test_helper'
2
-
3
- context "Resque::Scheduler" do
1
+ require_relative 'test_helper'
4
2
 
3
+ context 'Resque::Scheduler' do
5
4
  setup do
6
- Resque::Scheduler.dynamic = false
5
+ Resque::Scheduler.configure do |c|
6
+ c.dynamic = false
7
+ c.mute = true
8
+ c.env = nil
9
+ c.app_name = nil
10
+ end
7
11
  Resque.redis.flushall
8
- Resque::Scheduler.mute = true
9
12
  Resque::Scheduler.clear_schedule!
10
13
  Resque::Scheduler.send(:class_variable_set, :@@scheduled_jobs, {})
11
14
  end
12
15
 
13
- test "enqueue constantizes" do
14
- # The job should be loaded, since a missing rails_env means ALL envs.
15
- ENV['RAILS_ENV'] = 'production'
16
- config = {'cron' => "* * * * *", 'class' => 'SomeRealClass', 'args' => "/tmp"}
17
- Resque::Job.expects(:create).with(SomeRealClass.queue, SomeRealClass, '/tmp')
16
+ test 'enqueue constantizes' do
17
+ Resque::Scheduler.env = 'production'
18
+ config = {
19
+ 'cron' => '* * * * *',
20
+ 'class' => 'SomeRealClass',
21
+ 'args' => '/tmp'
22
+ }
23
+ Resque::Job.expects(:create).with(
24
+ SomeRealClass.queue, SomeRealClass, '/tmp'
25
+ )
18
26
  Resque::Scheduler.enqueue_from_config(config)
19
27
  end
20
28
 
21
- test "enqueue runs hooks" do
22
- # The job should be loaded, since a missing rails_env means ALL envs.
23
- ENV['RAILS_ENV'] = 'production'
24
- config = {'cron' => "* * * * *", 'class' => 'SomeRealClass', 'args' => "/tmp"}
29
+ test 'enqueue runs hooks' do
30
+ Resque::Scheduler.env = 'production'
31
+ config = {
32
+ 'cron' => '* * * * *',
33
+ 'class' => 'SomeRealClass',
34
+ 'args' => '/tmp'
35
+ }
25
36
 
26
- Resque::Job.expects(:create).with(SomeRealClass.queue, SomeRealClass, '/tmp')
27
- SomeRealClass.expects(:before_delayed_enqueue_example).with("/tmp")
28
- SomeRealClass.expects(:before_enqueue_example).with("/tmp")
29
- SomeRealClass.expects(:after_enqueue_example).with("/tmp")
37
+ Resque::Job.expects(:create).with(
38
+ SomeRealClass.queue, SomeRealClass, '/tmp'
39
+ )
40
+ SomeRealClass.expects(:before_delayed_enqueue_example).with('/tmp')
41
+ SomeRealClass.expects(:before_enqueue_example).with('/tmp')
42
+ SomeRealClass.expects(:after_enqueue_example).with('/tmp')
30
43
 
31
44
  Resque::Scheduler.enqueue_from_config(config)
32
45
  end
33
46
 
34
- test "enqueue_from_config respects queue params" do
35
- config = {'cron' => "* * * * *", 'class' => 'SomeIvarJob', 'queue' => 'high'}
36
-
47
+ test 'enqueue_from_config respects queue params' do
48
+ config = {
49
+ 'cron' => '* * * * *',
50
+ 'class' => 'SomeIvarJob',
51
+ 'queue' => 'high'
52
+ }
37
53
  Resque.expects(:enqueue_to).with('high', SomeIvarJob)
38
-
39
54
  Resque::Scheduler.enqueue_from_config(config)
40
55
  end
41
56
 
@@ -71,46 +86,77 @@ context "Resque::Scheduler" do
71
86
  assert Resque::Scheduler.scheduled_jobs.include?("some_ivar_job2")
72
87
  end
73
88
 
74
- test "load_schedule_job loads a schedule" do
75
- Resque::Scheduler.load_schedule_job("some_ivar_job", {'cron' => "* * * * *", 'class' => 'SomeIvarJob', 'args' => "/tmp"})
89
+ test 'load_schedule_job loads a schedule' do
90
+ Resque::Scheduler.load_schedule_job(
91
+ 'some_ivar_job', {
92
+ 'cron' => '* * * * *',
93
+ 'class' => 'SomeIvarJob',
94
+ 'args' => '/tmp'
95
+ }
96
+ )
76
97
 
77
98
  assert_equal(1, Resque::Scheduler.rufus_scheduler.all_jobs.size)
78
99
  assert_equal(1, Resque::Scheduler.scheduled_jobs.size)
79
- assert Resque::Scheduler.scheduled_jobs.keys.include?("some_ivar_job")
100
+ assert Resque::Scheduler.scheduled_jobs.keys.include?('some_ivar_job')
80
101
  end
81
102
 
82
- test "load_schedule_job with every with options" do
83
- Resque::Scheduler.load_schedule_job("some_ivar_job", {'every' => ['30s', {'first_in' => '60s'}], 'class' => 'SomeIvarJob', 'args' => "/tmp"})
103
+ test 'load_schedule_job with every with options' do
104
+ Resque::Scheduler.load_schedule_job(
105
+ 'some_ivar_job', {
106
+ 'every' => ['30s', { 'first_in' => '60s' }],
107
+ 'class' => 'SomeIvarJob',
108
+ 'args' => '/tmp'
109
+ }
110
+ )
84
111
 
85
112
  assert_equal(1, Resque::Scheduler.rufus_scheduler.all_jobs.size)
86
113
  assert_equal(1, Resque::Scheduler.scheduled_jobs.size)
87
- assert Resque::Scheduler.scheduled_jobs.keys.include?("some_ivar_job")
88
- assert Resque::Scheduler.scheduled_jobs["some_ivar_job"].params.keys.include?(:first_in)
114
+ assert Resque::Scheduler.scheduled_jobs.keys.include?('some_ivar_job')
115
+ job = Resque::Scheduler.scheduled_jobs['some_ivar_job']
116
+ assert job.params.keys.include?(:first_in)
89
117
  end
90
118
 
91
- test "load_schedule_job with cron with options" do
92
- Resque::Scheduler.load_schedule_job("some_ivar_job", {'cron' => ['* * * * *', {'allow_overlapping' => 'true'}], 'class' => 'SomeIvarJob', 'args' => "/tmp"})
119
+ test 'load_schedule_job with cron with options' do
120
+ Resque::Scheduler.load_schedule_job(
121
+ 'some_ivar_job', {
122
+ 'cron' => ['* * * * *', { 'allow_overlapping' => 'true' }],
123
+ 'class' => 'SomeIvarJob',
124
+ 'args' => '/tmp'
125
+ }
126
+ )
93
127
 
94
128
  assert_equal(1, Resque::Scheduler.rufus_scheduler.all_jobs.size)
95
129
  assert_equal(1, Resque::Scheduler.scheduled_jobs.size)
96
- assert Resque::Scheduler.scheduled_jobs.keys.include?("some_ivar_job")
97
- assert Resque::Scheduler.scheduled_jobs["some_ivar_job"].params.keys.include?(:allow_overlapping)
130
+ assert Resque::Scheduler.scheduled_jobs.keys.include?('some_ivar_job')
131
+ job = Resque::Scheduler.scheduled_jobs['some_ivar_job']
132
+ assert job.params.keys.include?(:allow_overlapping)
98
133
  end
99
134
 
100
- test "load_schedule_job without cron" do
101
- Resque::Scheduler.load_schedule_job("some_ivar_job", {'class' => 'SomeIvarJob', 'args' => "/tmp"})
135
+ test 'load_schedule_job without cron' do
136
+ Resque::Scheduler.load_schedule_job(
137
+ 'some_ivar_job', {
138
+ 'class' => 'SomeIvarJob',
139
+ 'args' => '/tmp'
140
+ }
141
+ )
102
142
 
103
143
  assert_equal(0, Resque::Scheduler.rufus_scheduler.all_jobs.size)
104
144
  assert_equal(0, Resque::Scheduler.scheduled_jobs.size)
105
- assert !Resque::Scheduler.scheduled_jobs.keys.include?("some_ivar_job")
145
+ assert !Resque::Scheduler.scheduled_jobs.keys.include?('some_ivar_job')
106
146
  end
107
147
 
108
- test "load_schedule_job with an empty cron" do
109
- Resque::Scheduler.load_schedule_job("some_ivar_job", {'cron' => '', 'class' => 'SomeIvarJob', 'args' => "/tmp"})
148
+ test 'load_schedule_job with an empty cron' do
149
+ Resque::Scheduler.load_schedule_job(
150
+ 'some_ivar_job', {
151
+ 'cron' => '',
152
+ 'class' => 'SomeIvarJob',
153
+ 'args' => '/tmp'
154
+ }
155
+ )
110
156
 
111
157
  assert_equal(0, Resque::Scheduler.rufus_scheduler.all_jobs.size)
112
158
  assert_equal(0, Resque::Scheduler.scheduled_jobs.size)
113
- assert !Resque::Scheduler.scheduled_jobs.keys.include?("some_ivar_job")
159
+ assert !Resque::Scheduler.scheduled_jobs.keys.include?('some_ivar_job')
114
160
  end
115
161
 
116
162
  test "update_schedule" do
@@ -239,12 +285,32 @@ context "Resque::Scheduler" do
239
285
  end
240
286
 
241
287
  test "remove_schedule removes a schedule" do
242
- Resque.redis.hset(:schedules, "some_ivar_job3", Resque.encode(
243
- 'cron' => "* * * * *", 'class' => 'SomeIvarJob', 'args' => "/tmp/44"
244
- ))
288
+ Resque.set_schedule("some_ivar_job3",
289
+ {'cron' => "* * * * *", 'class' => 'SomeIvarJob', 'args' => "/tmp/44", 'persist' => true}
290
+ )
291
+ Resque::Scheduler.load_schedule!
245
292
  Resque.remove_schedule("some_ivar_job3")
246
293
  assert_equal nil, Resque.redis.hget(:schedules, "some_ivar_job3")
247
294
  assert Resque.redis.sismember(:schedules_changed, "some_ivar_job3")
295
+ assert_equal [], Resque.redis.smembers(:persisted_schedules)
296
+ end
297
+
298
+ test "persisted schedules" do
299
+ Resque.set_schedule("some_ivar_job",
300
+ {'cron' => "* * * * *", 'class' => 'SomeIvarJob', 'args' => "/tmp/2", 'persist' => true}
301
+ )
302
+ Resque.set_schedule("new_ivar_job",
303
+ {'cron' => "* * * * *", 'class' => 'SomeJob', 'args' => "/tmp/3"}
304
+ )
305
+
306
+ Resque.schedule=({
307
+ 'a_schedule' => {'cron' => "* * * * *", 'class' => 'SomeOtherJob', 'args' => '/tmp'}
308
+ })
309
+ Resque::Scheduler.load_schedule!
310
+
311
+ assert_equal({'cron' => "* * * * *", 'class' => 'SomeIvarJob', 'args' => "/tmp/2"},
312
+ Resque.schedule['some_ivar_job'])
313
+ assert_equal(nil, Resque.schedule['some_job'])
248
314
  end
249
315
 
250
316
  test "adheres to lint" do
@@ -253,4 +319,26 @@ context "Resque::Scheduler" do
253
319
  Resque::Plugin.lint(ResqueScheduler)
254
320
  end
255
321
  end
322
+
323
+ test 'procline contains app_name when present' do
324
+ Resque::Scheduler.app_name = 'foo'
325
+ assert Resque::Scheduler.send(:build_procline, 'bar') =~ /\[foo\]:/
326
+ end
327
+
328
+ test 'procline omits app_name when absent' do
329
+ Resque::Scheduler.app_name = nil
330
+ assert Resque::Scheduler.send(:build_procline, 'bar') =~
331
+ /#{Resque::Scheduler.send(:internal_name)}: bar/
332
+ end
333
+
334
+ test 'procline contains env when present' do
335
+ Resque::Scheduler.env = 'derp'
336
+ assert Resque::Scheduler.send(:build_procline, 'cage') =~ /\[derp\]: cage/
337
+ end
338
+
339
+ test 'procline omits env when absent' do
340
+ Resque::Scheduler.env = nil
341
+ assert Resque::Scheduler.send(:build_procline, 'cage') =~
342
+ /#{Resque::Scheduler.send(:internal_name)}: cage/
343
+ end
256
344
  end