nogara-resque-scheduler 2.0.1

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,115 @@
1
+ # Redis configuration file example
2
+
3
+ # By default Redis does not run as a daemon. Use 'yes' if you need it.
4
+ # Note that Redis will write a pid file in /var/run/redis.pid when daemonized.
5
+ daemonize yes
6
+
7
+ # When run as a daemon, Redis write a pid file in /var/run/redis.pid by default.
8
+ # You can specify a custom pid file location here.
9
+ pidfile ./test/redis-test.pid
10
+
11
+ # Accept connections on the specified port, default is 6379
12
+ port 9736
13
+
14
+ # If you want you can bind a single interface, if the bind option is not
15
+ # specified all the interfaces will listen for connections.
16
+ #
17
+ # bind 127.0.0.1
18
+
19
+ # Close the connection after a client is idle for N seconds (0 to disable)
20
+ timeout 300
21
+
22
+ # Save the DB on disk:
23
+ #
24
+ # save <seconds> <changes>
25
+ #
26
+ # Will save the DB if both the given number of seconds and the given
27
+ # number of write operations against the DB occurred.
28
+ #
29
+ # In the example below the behaviour will be to save:
30
+ # after 900 sec (15 min) if at least 1 key changed
31
+ # after 300 sec (5 min) if at least 10 keys changed
32
+ # after 60 sec if at least 10000 keys changed
33
+ save 900 1
34
+ save 300 10
35
+ save 60 10000
36
+
37
+ # The filename where to dump the DB
38
+ dbfilename dump.rdb
39
+
40
+ # For default save/load DB in/from the working directory
41
+ # Note that you must specify a directory not a file name.
42
+ dir ./test/
43
+
44
+ # Set server verbosity to 'debug'
45
+ # it can be one of:
46
+ # debug (a lot of information, useful for development/testing)
47
+ # notice (moderately verbose, what you want in production probably)
48
+ # warning (only very important / critical messages are logged)
49
+ loglevel debug
50
+
51
+ # Specify the log file name. Also 'stdout' can be used to force
52
+ # the demon to log on the standard output. Note that if you use standard
53
+ # output for logging but daemonize, logs will be sent to /dev/null
54
+ logfile stdout
55
+
56
+ # Set the number of databases. The default database is DB 0, you can select
57
+ # a different one on a per-connection basis using SELECT <dbid> where
58
+ # dbid is a number between 0 and 'databases'-1
59
+ databases 16
60
+
61
+ ################################# REPLICATION #################################
62
+
63
+ # Master-Slave replication. Use slaveof to make a Redis instance a copy of
64
+ # another Redis server. Note that the configuration is local to the slave
65
+ # so for example it is possible to configure the slave to save the DB with a
66
+ # different interval, or to listen to another port, and so on.
67
+
68
+ # slaveof <masterip> <masterport>
69
+
70
+ ################################## SECURITY ###################################
71
+
72
+ # Require clients to issue AUTH <PASSWORD> before processing any other
73
+ # commands. This might be useful in environments in which you do not trust
74
+ # others with access to the host running redis-server.
75
+ #
76
+ # This should stay commented out for backward compatibility and because most
77
+ # people do not need auth (e.g. they run their own servers).
78
+
79
+ # requirepass foobared
80
+
81
+ ################################### LIMITS ####################################
82
+
83
+ # Set the max number of connected clients at the same time. By default there
84
+ # is no limit, and it's up to the number of file descriptors the Redis process
85
+ # is able to open. The special value '0' means no limts.
86
+ # Once the limit is reached Redis will close all the new connections sending
87
+ # an error 'max number of clients reached'.
88
+
89
+ # maxclients 128
90
+
91
+ # Don't use more memory than the specified amount of bytes.
92
+ # When the memory limit is reached Redis will try to remove keys with an
93
+ # EXPIRE set. It will try to start freeing keys that are going to expire
94
+ # in little time and preserve keys with a longer time to live.
95
+ # Redis will also try to remove objects from free lists if possible.
96
+ #
97
+ # If all this fails, Redis will start to reply with errors to commands
98
+ # that will use more memory, like SET, LPUSH, and so on, and will continue
99
+ # to reply to most read-only commands like GET.
100
+ #
101
+ # WARNING: maxmemory can be a good idea mainly if you want to use Redis as a
102
+ # 'state' server or cache, not as a real DB. When Redis is used as a real
103
+ # database the memory usage will grow over the weeks, it will be obvious if
104
+ # it is going to use too much memory in the long run, and you'll have the time
105
+ # to upgrade. With maxmemory after the limit is reached you'll start to get
106
+ # errors for write operations, and this may even lead to DB inconsistency.
107
+
108
+ # maxmemory <bytes>
109
+
110
+ ############################### ADVANCED CONFIG ###############################
111
+
112
+ # Glue small output buffers together in order to send small replies in a
113
+ # single TCP packet. Uses a bit more CPU but most of the times it is a win
114
+ # in terms of number of queries per second. Use 'yes' if unsure.
115
+ glueoutputbuf yes
@@ -0,0 +1,32 @@
1
+ require File.dirname(__FILE__) + '/test_helper'
2
+
3
+ # Pull in the server test_helper from resque
4
+ require 'resque/server/test_helper.rb'
5
+
6
+ context "on GET to /schedule" do
7
+ setup { get "/schedule" }
8
+
9
+ should_respond_with_success
10
+ end
11
+
12
+ context "on GET to /schedule with scheduled jobs" do
13
+ setup do
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'}}}
17
+ Resque::Scheduler.load_schedule!
18
+ get "/schedule"
19
+ end
20
+
21
+ should_respond_with_success
22
+
23
+ test 'see the scheduled job' do
24
+ assert last_response.body.include?('SomeIvarJob')
25
+ end
26
+ end
27
+
28
+ context "on GET to /delayed" do
29
+ setup { get "/delayed" }
30
+
31
+ should_respond_with_success
32
+ end
@@ -0,0 +1,156 @@
1
+ require File.dirname(__FILE__) + '/test_helper'
2
+
3
+ context "scheduling jobs with arguments" do
4
+
5
+ setup do
6
+ Resque::Scheduler.clear_schedule!
7
+ Resque::Scheduler.dynamic = false
8
+ Resque::Scheduler.mute = true
9
+ end
10
+
11
+ test "enqueue_from_config puts stuff in resque without class loaded" do
12
+ Resque::Job.stubs(:create).once.returns(true).with('joes_queue', 'UndefinedJob', '/tmp')
13
+ Resque::Scheduler.enqueue_from_config('cron' => "* * * * *", 'class' => 'UndefinedJob', 'args' => "/tmp", 'queue' => 'joes_queue')
14
+ end
15
+
16
+ test "enqueue_from_config with_every_syntax" do
17
+ Resque::Job.stubs(:create).once.returns(true).with('james_queue', 'JamesJob', '/tmp')
18
+ Resque::Scheduler.enqueue_from_config('every' => '1m', 'class' => 'JamesJob', 'args' => '/tmp', 'queue' => 'james_queue')
19
+ end
20
+
21
+ test "enqueue_from_config puts jobs in the resque queue" do
22
+ Resque::Job.stubs(:create).once.returns(true).with(:ivar, SomeIvarJob, '/tmp')
23
+ Resque::Scheduler.enqueue_from_config('cron' => "* * * * *", 'class' => 'SomeIvarJob', 'args' => "/tmp")
24
+ end
25
+
26
+ test "enqueue_from_config with custom_class_job in resque" do
27
+ FakeCustomJobClass.stubs(:scheduled).once.returns(true).with(:ivar, 'SomeIvarJob', '/tmp')
28
+ Resque::Scheduler.enqueue_from_config('cron' => "* * * * *", 'class' => 'SomeIvarJob', 'custom_job_class' => 'FakeCustomJobClass', 'args' => "/tmp")
29
+ end
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'
34
+ assert_equal(0, Resque::Scheduler.rufus_scheduler.all_jobs.size)
35
+
36
+ Resque.schedule = {:some_ivar_job => {'cron' => "* * * * *", 'class' => 'SomeIvarJob', 'args' => "/tmp", 'rails_env' => 'production'}}
37
+ Resque::Scheduler.load_schedule!
38
+ assert_equal(1, Resque::Scheduler.rufus_scheduler.all_jobs.size)
39
+
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'}}
42
+ Resque::Scheduler.load_schedule!
43
+ assert_equal(2, Resque::Scheduler.rufus_scheduler.all_jobs.size)
44
+ end
45
+
46
+ test "enqueue_from_config doesnt put stuff in resque when rails_env doesnt match" do
47
+ # RAILS_ENV is not set:
48
+ assert_equal(0, Resque::Scheduler.rufus_scheduler.all_jobs.size)
49
+ Resque.schedule = {:some_ivar_job => {'cron' => "* * * * *", 'class' => 'SomeIvarJob', 'args' => "/tmp", 'rails_env' => 'staging'}}
50
+ Resque::Scheduler.load_schedule!
51
+ assert_equal(0, Resque::Scheduler.rufus_scheduler.all_jobs.size)
52
+
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'}}
56
+ Resque::Scheduler.load_schedule!
57
+ assert_equal(0, Resque::Scheduler.rufus_scheduler.all_jobs.size)
58
+ end
59
+
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'
63
+ assert_equal(0, Resque::Scheduler.rufus_scheduler.all_jobs.size)
64
+ Resque.schedule = {:some_ivar_job => {'cron' => "* * * * *", 'class' => 'SomeIvarJob', 'args' => "/tmp"}}
65
+ Resque::Scheduler.load_schedule!
66
+ assert_equal(1, Resque::Scheduler.rufus_scheduler.all_jobs.size)
67
+ end
68
+
69
+ test "calls the worker without arguments when 'args' is missing from the config" do
70
+ Resque::Scheduler.enqueue_from_config(YAML.load(<<-YAML))
71
+ class: SomeIvarJob
72
+ YAML
73
+ SomeIvarJob.expects(:perform).once.with()
74
+ Resque.reserve('ivar').perform
75
+ end
76
+
77
+ test "calls the worker without arguments when 'args' is blank in the config" do
78
+ Resque::Scheduler.enqueue_from_config(YAML.load(<<-YAML))
79
+ class: SomeIvarJob
80
+ args:
81
+ YAML
82
+ SomeIvarJob.expects(:perform).once.with()
83
+ Resque.reserve('ivar').perform
84
+ end
85
+
86
+ test "calls the worker with a string when the config lists a string" do
87
+ Resque::Scheduler.enqueue_from_config(YAML.load(<<-YAML))
88
+ class: SomeIvarJob
89
+ args: string
90
+ YAML
91
+ SomeIvarJob.expects(:perform).once.with('string')
92
+ Resque.reserve('ivar').perform
93
+ end
94
+
95
+ test "calls the worker with a Fixnum when the config lists an integer" do
96
+ Resque::Scheduler.enqueue_from_config(YAML.load(<<-YAML))
97
+ class: SomeIvarJob
98
+ args: 1
99
+ YAML
100
+ SomeIvarJob.expects(:perform).once.with(1)
101
+ Resque.reserve('ivar').perform
102
+ end
103
+
104
+ test "calls the worker with multiple arguments when the config lists an array" do
105
+ Resque::Scheduler.enqueue_from_config(YAML.load(<<-YAML))
106
+ class: SomeIvarJob
107
+ args:
108
+ - 1
109
+ - 2
110
+ YAML
111
+ SomeIvarJob.expects(:perform).once.with(1, 2)
112
+ Resque.reserve('ivar').perform
113
+ end
114
+
115
+ test "calls the worker with an array when the config lists a nested array" do
116
+ Resque::Scheduler.enqueue_from_config(YAML.load(<<-YAML))
117
+ class: SomeIvarJob
118
+ args:
119
+ - - 1
120
+ - 2
121
+ YAML
122
+ SomeIvarJob.expects(:perform).once.with([1, 2])
123
+ Resque.reserve('ivar').perform
124
+ end
125
+
126
+ test "calls the worker with a hash when the config lists a hash" do
127
+ Resque::Scheduler.enqueue_from_config(YAML.load(<<-YAML))
128
+ class: SomeIvarJob
129
+ args:
130
+ key: value
131
+ YAML
132
+ SomeIvarJob.expects(:perform).once.with('key' => 'value')
133
+ Resque.reserve('ivar').perform
134
+ end
135
+
136
+ test "calls the worker with a nested hash when the config lists a nested hash" do
137
+ Resque::Scheduler.enqueue_from_config(YAML.load(<<-YAML))
138
+ class: SomeIvarJob
139
+ args:
140
+ first_key:
141
+ second_key: value
142
+ YAML
143
+ SomeIvarJob.expects(:perform).once.with('first_key' => {'second_key' => 'value'})
144
+ Resque.reserve('ivar').perform
145
+ end
146
+
147
+ test "poll_sleep_amount defaults to 5" do
148
+ assert_equal 5, Resque::Scheduler.poll_sleep_amount
149
+ end
150
+
151
+ test "poll_sleep_amount is settable" do
152
+ Resque::Scheduler.poll_sleep_amount = 1
153
+ assert_equal 1, Resque::Scheduler.poll_sleep_amount
154
+ end
155
+
156
+ end
@@ -0,0 +1,23 @@
1
+ require File.dirname(__FILE__) + '/test_helper'
2
+
3
+ context "scheduling jobs with hooks" do
4
+ setup do
5
+ Resque.redis.flushall
6
+ end
7
+
8
+ test "before_schedule hook that does not return false should be enqueued" do
9
+ enqueue_time = Time.now
10
+ SomeRealClass.expects(:before_schedule_example).with(:foo)
11
+ SomeRealClass.expects(:after_schedule_example).with(:foo)
12
+ Resque.enqueue_at(enqueue_time.to_i, SomeRealClass, :foo)
13
+ assert_equal(1, Resque.delayed_timestamp_size(enqueue_time.to_i), "job should be enqueued")
14
+ end
15
+
16
+ test "before_schedule hook that returns false should not be enqueued" do
17
+ enqueue_time = Time.now
18
+ SomeRealClass.expects(:before_schedule_example).with(:foo).returns(false)
19
+ SomeRealClass.expects(:after_schedule_example).never
20
+ Resque.enqueue_at(enqueue_time.to_i, SomeRealClass, :foo)
21
+ assert_equal(0, Resque.delayed_timestamp_size(enqueue_time.to_i), "job should not be enqueued")
22
+ end
23
+ end
@@ -0,0 +1,247 @@
1
+ require File.dirname(__FILE__) + '/test_helper'
2
+
3
+ context "Resque::Scheduler" do
4
+
5
+ setup do
6
+ Resque::Scheduler.dynamic = false
7
+ Resque.redis.del(:schedules)
8
+ Resque.redis.del(:schedules_changed)
9
+ Resque::Scheduler.mute = true
10
+ Resque::Scheduler.clear_schedule!
11
+ Resque::Scheduler.send(:class_variable_set, :@@scheduled_jobs, {})
12
+ end
13
+
14
+ test "enqueue constantizes" do
15
+ # The job should be loaded, since a missing rails_env means ALL envs.
16
+ ENV['RAILS_ENV'] = 'production'
17
+ config = {'cron' => "* * * * *", 'class' => 'SomeRealClass', 'args' => "/tmp"}
18
+ Resque::Job.expects(:create).with(SomeRealClass.queue, SomeRealClass, '/tmp')
19
+ Resque::Scheduler.enqueue_from_config(config)
20
+ end
21
+
22
+ test "enqueue runs hooks" do
23
+ # The job should be loaded, since a missing rails_env means ALL envs.
24
+ ENV['RAILS_ENV'] = 'production'
25
+ config = {'cron' => "* * * * *", 'class' => 'SomeRealClass', 'args' => "/tmp"}
26
+
27
+ Resque::Job.expects(:create).with(SomeRealClass.queue, SomeRealClass, '/tmp')
28
+ SomeRealClass.expects(:before_delayed_enqueue_example).with("/tmp")
29
+ SomeRealClass.expects(:before_enqueue_example).with("/tmp")
30
+ SomeRealClass.expects(:after_enqueue_example).with("/tmp")
31
+
32
+ Resque::Scheduler.enqueue_from_config(config)
33
+ end
34
+
35
+ test "enqueue_from_config respects queue params" do
36
+ config = {'cron' => "* * * * *", 'class' => 'SomeIvarJob', 'queue' => 'high'}
37
+
38
+ Resque.expects(:enqueue_to).with('high', SomeIvarJob)
39
+
40
+ Resque::Scheduler.enqueue_from_config(config)
41
+ end
42
+
43
+ test "config makes it into the rufus_scheduler" do
44
+ assert_equal(0, Resque::Scheduler.rufus_scheduler.all_jobs.size)
45
+
46
+ Resque.schedule = {:some_ivar_job => {'cron' => "* * * * *", 'class' => 'SomeIvarJob', 'args' => "/tmp"}}
47
+ Resque::Scheduler.load_schedule!
48
+
49
+ assert_equal(1, Resque::Scheduler.rufus_scheduler.all_jobs.size)
50
+ assert Resque::Scheduler.scheduled_jobs.include?(:some_ivar_job)
51
+ end
52
+
53
+ test "can reload schedule" do
54
+ Resque::Scheduler.dynamic = true
55
+ Resque.schedule = {"some_ivar_job" => {'cron' => "* * * * *", 'class' => 'SomeIvarJob', 'args' => "/tmp"}}
56
+
57
+ Resque::Scheduler.load_schedule!
58
+
59
+ assert_equal(1, Resque::Scheduler.rufus_scheduler.all_jobs.size)
60
+ assert Resque::Scheduler.scheduled_jobs.include?("some_ivar_job")
61
+
62
+ Resque.redis.del(:schedules)
63
+ Resque.redis.hset(:schedules, "some_ivar_job2", Resque.encode(
64
+ {'cron' => "* * * * *", 'class' => 'SomeIvarJob', 'args' => "/tmp/2"}
65
+ ))
66
+
67
+ Resque::Scheduler.reload_schedule!
68
+
69
+ assert_equal(1, Resque::Scheduler.rufus_scheduler.all_jobs.size)
70
+
71
+ assert_equal '/tmp/2', Resque.schedule["some_ivar_job2"]["args"]
72
+ assert Resque::Scheduler.scheduled_jobs.include?("some_ivar_job2")
73
+ end
74
+
75
+ test "load_schedule_job loads a schedule" do
76
+ Resque::Scheduler.load_schedule_job("some_ivar_job", {'cron' => "* * * * *", 'class' => 'SomeIvarJob', 'args' => "/tmp"})
77
+
78
+ assert_equal(1, Resque::Scheduler.rufus_scheduler.all_jobs.size)
79
+ assert_equal(1, Resque::Scheduler.scheduled_jobs.size)
80
+ assert Resque::Scheduler.scheduled_jobs.keys.include?("some_ivar_job")
81
+ end
82
+
83
+ test "load_schedule_job with every with options" do
84
+ Resque::Scheduler.load_schedule_job("some_ivar_job", {'every' => ['30s', {'first_in' => '60s'}], 'class' => 'SomeIvarJob', 'args' => "/tmp"})
85
+
86
+ assert_equal(1, Resque::Scheduler.rufus_scheduler.all_jobs.size)
87
+ assert_equal(1, Resque::Scheduler.scheduled_jobs.size)
88
+ assert Resque::Scheduler.scheduled_jobs.keys.include?("some_ivar_job")
89
+ assert Resque::Scheduler.scheduled_jobs["some_ivar_job"].params.keys.include?(:first_in)
90
+ end
91
+
92
+ test "load_schedule_job with cron with options" do
93
+ Resque::Scheduler.load_schedule_job("some_ivar_job", {'cron' => ['* * * * *', {'allow_overlapping' => 'true'}], 'class' => 'SomeIvarJob', 'args' => "/tmp"})
94
+
95
+ assert_equal(1, Resque::Scheduler.rufus_scheduler.all_jobs.size)
96
+ assert_equal(1, Resque::Scheduler.scheduled_jobs.size)
97
+ assert Resque::Scheduler.scheduled_jobs.keys.include?("some_ivar_job")
98
+ assert Resque::Scheduler.scheduled_jobs["some_ivar_job"].params.keys.include?(:allow_overlapping)
99
+ end
100
+
101
+ test "load_schedule_job without cron" do
102
+ Resque::Scheduler.load_schedule_job("some_ivar_job", {'class' => 'SomeIvarJob', 'args' => "/tmp"})
103
+
104
+ assert_equal(0, Resque::Scheduler.rufus_scheduler.all_jobs.size)
105
+ assert_equal(0, Resque::Scheduler.scheduled_jobs.size)
106
+ assert !Resque::Scheduler.scheduled_jobs.keys.include?("some_ivar_job")
107
+ end
108
+
109
+ test "load_schedule_job with an empty cron" do
110
+ Resque::Scheduler.load_schedule_job("some_ivar_job", {'cron' => '', 'class' => 'SomeIvarJob', 'args' => "/tmp"})
111
+
112
+ assert_equal(0, Resque::Scheduler.rufus_scheduler.all_jobs.size)
113
+ assert_equal(0, Resque::Scheduler.scheduled_jobs.size)
114
+ assert !Resque::Scheduler.scheduled_jobs.keys.include?("some_ivar_job")
115
+ end
116
+
117
+ test "update_schedule" do
118
+ Resque::Scheduler.dynamic = true
119
+ Resque.schedule = {
120
+ "some_ivar_job" => {'cron' => "* * * * *", 'class' => 'SomeIvarJob', 'args' => "/tmp"},
121
+ "another_ivar_job" => {'cron' => "* * * * *", 'class' => 'SomeIvarJob', 'args' => "/tmp/5"},
122
+ "stay_put_job" => {'cron' => "* * * * *", 'class' => 'SomeJob', 'args' => "/tmp"}
123
+ }
124
+
125
+ Resque::Scheduler.load_schedule!
126
+
127
+ Resque.set_schedule("some_ivar_job",
128
+ {'cron' => "* * * * *", 'class' => 'SomeIvarJob', 'args' => "/tmp/2"}
129
+ )
130
+ Resque.set_schedule("new_ivar_job",
131
+ {'cron' => "* * * * *", 'class' => 'SomeJob', 'args' => "/tmp/3"}
132
+ )
133
+ Resque.set_schedule("stay_put_job",
134
+ {'cron' => "* * * * *", 'class' => 'SomeJob', 'args' => "/tmp"}
135
+ )
136
+ Resque.remove_schedule("another_ivar_job")
137
+
138
+ Resque::Scheduler.update_schedule
139
+
140
+ assert_equal(3, Resque::Scheduler.rufus_scheduler.all_jobs.size)
141
+ assert_equal(3, Resque::Scheduler.scheduled_jobs.size)
142
+ %w(some_ivar_job new_ivar_job stay_put_job).each do |job_name|
143
+ assert Resque::Scheduler.scheduled_jobs.keys.include?(job_name)
144
+ assert Resque.schedule.keys.include?(job_name)
145
+ end
146
+ assert !Resque::Scheduler.scheduled_jobs.keys.include?("another_ivar_job")
147
+ assert !Resque.schedule.keys.include?("another_ivar_job")
148
+ assert_equal 0, Resque.redis.scard(:schedules_changed)
149
+ end
150
+
151
+ test "update_schedule with mocks" do
152
+ Resque::Scheduler.dynamic = true
153
+ Resque.schedule = {
154
+ "some_ivar_job" => {'cron' => "* * * * *", 'class' => 'SomeIvarJob', 'args' => "/tmp"},
155
+ "another_ivar_job" => {'cron' => "* * * * *", 'class' => 'SomeIvarJob', 'args' => "/tmp/5"},
156
+ "stay_put_job" => {'cron' => "* * * * *", 'class' => 'SomeJob', 'args' => "/tmp"}
157
+ }
158
+
159
+ Resque::Scheduler.load_schedule!
160
+
161
+ Resque::Scheduler.rufus_scheduler.expects(:unschedule).with(Resque::Scheduler.scheduled_jobs["some_ivar_job"].job_id)
162
+ Resque::Scheduler.rufus_scheduler.expects(:unschedule).with(Resque::Scheduler.scheduled_jobs["another_ivar_job"].job_id)
163
+
164
+ Resque.set_schedule("some_ivar_job",
165
+ {'cron' => "* * * * *", 'class' => 'SomeIvarJob', 'args' => "/tmp/2"}
166
+ )
167
+ Resque.set_schedule("new_ivar_job",
168
+ {'cron' => "* * * * *", 'class' => 'SomeJob', 'args' => "/tmp/3"}
169
+ )
170
+ Resque.set_schedule("stay_put_job",
171
+ {'cron' => "* * * * *", 'class' => 'SomeJob', 'args' => "/tmp"}
172
+ )
173
+ Resque.remove_schedule("another_ivar_job")
174
+
175
+ Resque::Scheduler.update_schedule
176
+
177
+ assert_equal(3, Resque::Scheduler.scheduled_jobs.size)
178
+ %w(some_ivar_job new_ivar_job stay_put_job).each do |job_name|
179
+ assert Resque::Scheduler.scheduled_jobs.keys.include?(job_name)
180
+ assert Resque.schedule.keys.include?(job_name)
181
+ end
182
+ assert !Resque::Scheduler.scheduled_jobs.keys.include?("another_ivar_job")
183
+ assert !Resque.schedule.keys.include?("another_ivar_job")
184
+ assert_equal 0, Resque.redis.scard(:schedules_changed)
185
+ end
186
+
187
+ test "schedule= sets the schedule" do
188
+ Resque::Scheduler.dynamic = true
189
+ Resque.schedule = {"my_ivar_job" => {
190
+ 'cron' => "* * * * *", 'class' => 'SomeIvarJob', 'args' => "/tmp/75"
191
+ }}
192
+ assert_equal({'cron' => "* * * * *", 'class' => 'SomeIvarJob', 'args' => "/tmp/75"},
193
+ Resque.decode(Resque.redis.hget(:schedules, "my_ivar_job")))
194
+ end
195
+
196
+ test "schedule= uses job name as 'class' argument if it's missing" do
197
+ Resque::Scheduler.dynamic = true
198
+ Resque.schedule = {"SomeIvarJob" => {
199
+ 'cron' => "* * * * *", 'args' => "/tmp/75"
200
+ }}
201
+ assert_equal({'cron' => "* * * * *", 'class' => 'SomeIvarJob', 'args' => "/tmp/75"},
202
+ Resque.decode(Resque.redis.hget(:schedules, "SomeIvarJob")))
203
+ assert_equal('SomeIvarJob', Resque.schedule['SomeIvarJob']['class'])
204
+ end
205
+
206
+ test "schedule= does not mutate argument" do
207
+ schedule = {"SomeIvarJob" => {
208
+ 'cron' => "* * * * *", 'args' => "/tmp/75"
209
+ }}
210
+ Resque.schedule = schedule
211
+ assert !schedule['SomeIvarJob'].key?('class')
212
+ end
213
+
214
+ test "set_schedule can set an individual schedule" do
215
+ Resque.set_schedule("some_ivar_job", {
216
+ 'cron' => "* * * * *", 'class' => 'SomeIvarJob', 'args' => "/tmp/22"
217
+ })
218
+ assert_equal({'cron' => "* * * * *", 'class' => 'SomeIvarJob', 'args' => "/tmp/22"},
219
+ Resque.decode(Resque.redis.hget(:schedules, "some_ivar_job")))
220
+ assert Resque.redis.sismember(:schedules_changed, "some_ivar_job")
221
+ end
222
+
223
+ test "get_schedule returns a schedule" do
224
+ Resque.redis.hset(:schedules, "some_ivar_job2", Resque.encode(
225
+ {'cron' => "* * * * *", 'class' => 'SomeIvarJob', 'args' => "/tmp/33"}
226
+ ))
227
+ assert_equal({'cron' => "* * * * *", 'class' => 'SomeIvarJob', 'args' => "/tmp/33"},
228
+ Resque.get_schedule("some_ivar_job2"))
229
+ end
230
+
231
+ test "remove_schedule removes a schedule" do
232
+ Resque.redis.hset(:schedules, "some_ivar_job3", Resque.encode(
233
+ {'cron' => "* * * * *", 'class' => 'SomeIvarJob', 'args' => "/tmp/44"}
234
+ ))
235
+ Resque.remove_schedule("some_ivar_job3")
236
+ assert_equal nil, Resque.redis.hget(:schedules, "some_ivar_job3")
237
+ assert Resque.redis.sismember(:schedules_changed, "some_ivar_job3")
238
+ end
239
+
240
+ test "adheres to lint" do
241
+ assert_nothing_raised do
242
+ Resque::Plugin.lint(Resque::Scheduler)
243
+ Resque::Plugin.lint(ResqueScheduler)
244
+ end
245
+ end
246
+
247
+ end