clockwork 0.5.5 → 0.6.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.
- data/README.md +0 -4
- data/Rakefile +4 -2
- data/clockwork.gemspec +2 -1
- data/lib/clockwork.rb +12 -193
- data/lib/clockwork/at.rb +49 -0
- data/lib/clockwork/event.rb +71 -0
- data/lib/clockwork/manager.rb +91 -0
- data/test/at_test.rb +67 -0
- data/test/clockwork_test.rb +37 -282
- data/test/manager_test.rb +272 -0
- metadata +13 -5
data/README.md
CHANGED
@@ -42,10 +42,6 @@ Triggering frequent.job
|
|
42
42
|
If you would not like to taint the namespace with `include Clockwork`, you can use
|
43
43
|
it as the module (thanks to [hoverlover](https://github.com/hoverlover/clockwork/)).
|
44
44
|
|
45
|
-
As reported in [issue #41](https://github.com/tomykaira/clockwork/issues/41#issuecomment-22073609),
|
46
|
-
this technique is necessary when you use Clockwork with Sinatra,
|
47
|
-
because both Sinatra and Clockwork add `register()` method into global namespace.
|
48
|
-
|
49
45
|
```ruby
|
50
46
|
require 'clockwork'
|
51
47
|
|
data/Rakefile
CHANGED
data/clockwork.gemspec
CHANGED
@@ -1,8 +1,9 @@
|
|
1
1
|
Gem::Specification.new do |s|
|
2
2
|
s.name = "clockwork"
|
3
|
-
s.version = "0.
|
3
|
+
s.version = "0.6.0"
|
4
4
|
|
5
5
|
s.authors = ["Adam Wiggins", "tomykaira"]
|
6
|
+
s.license = 'MIT'
|
6
7
|
s.description = "A scheduler process to replace cron, using a more flexible Ruby syntax running as a single long-running process. Inspired by rufus-scheduler and resque-scheduler."
|
7
8
|
s.email = ["adam@heroku.com", "tomykaira@gmail.com"]
|
8
9
|
s.extra_rdoc_files = [
|
data/lib/clockwork.rb
CHANGED
@@ -1,215 +1,34 @@
|
|
1
1
|
require 'logger'
|
2
2
|
require 'active_support/time'
|
3
3
|
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
class At
|
9
|
-
class FailedToParse < StandardError; end;
|
10
|
-
NOT_SPECIFIED = nil
|
11
|
-
WDAYS = %w[sunday monday tuesday wednesday thursday friday saturday].map do |w|
|
12
|
-
[w, w.capitalize, w[0...3], w[0...3].capitalize]
|
13
|
-
end
|
14
|
-
|
15
|
-
def self.parse(at)
|
16
|
-
return unless at
|
17
|
-
case at
|
18
|
-
when /^([[:alpha:]]+)\s(.*)$/
|
19
|
-
ret = parse($2)
|
20
|
-
wday = WDAYS.find_index { |x| x.include?($1) }
|
21
|
-
raise FailedToParse, at if wday.nil?
|
22
|
-
ret.wday = wday
|
23
|
-
ret
|
24
|
-
when /^(\d{1,2}):(\d\d)$/
|
25
|
-
new($2.to_i, $1.to_i)
|
26
|
-
when /^\*{1,2}:(\d\d)$/
|
27
|
-
new($1.to_i)
|
28
|
-
else
|
29
|
-
raise FailedToParse, at
|
30
|
-
end
|
31
|
-
rescue ArgumentError
|
32
|
-
raise FailedToParse, at
|
33
|
-
end
|
34
|
-
|
35
|
-
attr_writer :min, :hour, :wday
|
36
|
-
|
37
|
-
def initialize(min, hour=NOT_SPECIFIED, wday=NOT_SPECIFIED)
|
38
|
-
if min.nil? || min < 0 || min > 59 ||
|
39
|
-
(hour != NOT_SPECIFIED && (hour < 0 || hour > 23)) ||
|
40
|
-
(wday != NOT_SPECIFIED && (wday < 0 || wday > 6))
|
41
|
-
raise ArgumentError
|
42
|
-
end
|
43
|
-
@min = min
|
44
|
-
@hour = hour
|
45
|
-
@wday = wday
|
46
|
-
end
|
47
|
-
|
48
|
-
def ready?(t)
|
49
|
-
t.min == @min and
|
50
|
-
(@hour == NOT_SPECIFIED or t.hour == @hour) and
|
51
|
-
(@wday == NOT_SPECIFIED or t.wday == @wday)
|
52
|
-
end
|
53
|
-
end
|
54
|
-
|
55
|
-
class Event
|
56
|
-
attr_accessor :job, :last
|
57
|
-
|
58
|
-
def initialize(period, job, block, options={})
|
59
|
-
@period = period
|
60
|
-
@job = job
|
61
|
-
@at = At.parse(options[:at])
|
62
|
-
@last = nil
|
63
|
-
@block = block
|
64
|
-
if options[:if]
|
65
|
-
if options[:if].respond_to?(:call)
|
66
|
-
@if = options[:if]
|
67
|
-
else
|
68
|
-
raise ArgumentError.new(':if expects a callable object, but #{options[:if]} does not respond to call')
|
69
|
-
end
|
70
|
-
end
|
71
|
-
|
72
|
-
@thread = !!(options.has_key?(:thread) ? options[:thread] : Clockwork.config[:thread])
|
73
|
-
|
74
|
-
@timezone = options[:tz] || Clockwork.config[:tz]
|
75
|
-
end
|
76
|
-
|
77
|
-
def to_s
|
78
|
-
@job
|
79
|
-
end
|
80
|
-
|
81
|
-
def convert_timezone(t)
|
82
|
-
@timezone ? t.in_time_zone(@timezone) : t
|
83
|
-
end
|
84
|
-
|
85
|
-
def time?(t)
|
86
|
-
t = convert_timezone(t)
|
87
|
-
elapsed_ready = (@last.nil? or (t - @last).to_i >= @period)
|
88
|
-
elapsed_ready and (@at.nil? or @at.ready?(t)) and (@if.nil? or @if.call(t))
|
89
|
-
end
|
90
|
-
|
91
|
-
def thread?
|
92
|
-
@thread
|
93
|
-
end
|
94
|
-
|
95
|
-
def run(t)
|
96
|
-
t = convert_timezone(t)
|
97
|
-
@last = t
|
98
|
-
|
99
|
-
if thread?
|
100
|
-
if Clockwork.thread_available?
|
101
|
-
Thread.new { execute }
|
102
|
-
else
|
103
|
-
log_error "Threads exhausted; skipping #{self}"
|
104
|
-
end
|
105
|
-
else
|
106
|
-
execute
|
107
|
-
end
|
108
|
-
end
|
109
|
-
|
110
|
-
def execute
|
111
|
-
@block.call(@job)
|
112
|
-
rescue => e
|
113
|
-
log_error e
|
114
|
-
end
|
115
|
-
|
116
|
-
def log_error(e)
|
117
|
-
Clockwork.config[:logger].error(e)
|
118
|
-
end
|
119
|
-
|
120
|
-
def exception_message(e)
|
121
|
-
msg = [ "Exception #{e.class} -> #{e.message}" ]
|
122
|
-
|
123
|
-
base = File.expand_path(Dir.pwd) + '/'
|
124
|
-
e.backtrace.each do |t|
|
125
|
-
msg << " #{File.expand_path(t).gsub(/#{base}/, '')}"
|
126
|
-
end
|
127
|
-
|
128
|
-
msg.join("\n")
|
129
|
-
end
|
130
|
-
end
|
131
|
-
|
132
|
-
def thread_available?
|
133
|
-
Thread.list.count < config[:max_threads]
|
134
|
-
end
|
135
|
-
|
136
|
-
def configure
|
137
|
-
yield(config)
|
138
|
-
end
|
139
|
-
|
140
|
-
def config
|
141
|
-
@@configuration
|
142
|
-
end
|
4
|
+
require 'clockwork/at'
|
5
|
+
require 'clockwork/event'
|
6
|
+
require 'clockwork/manager'
|
143
7
|
|
8
|
+
module Clockwork
|
144
9
|
extend self
|
145
10
|
|
146
|
-
|
147
|
-
{ :sleep_timeout => 1, :logger => Logger.new(STDOUT), :thread => false, :max_threads => 10 }
|
148
|
-
end
|
11
|
+
@@manager = Manager.new
|
149
12
|
|
150
|
-
|
151
|
-
|
152
|
-
def handler(&block)
|
153
|
-
@@handler = block
|
13
|
+
def configure(&block)
|
14
|
+
@@manager.configure(&block)
|
154
15
|
end
|
155
16
|
|
156
|
-
|
157
|
-
|
158
|
-
def get_handler
|
159
|
-
raise NoHandlerDefined unless (defined?(@@handler) and @@handler)
|
160
|
-
@@handler
|
17
|
+
def handler(&block)
|
18
|
+
@@manager.handler(&block)
|
161
19
|
end
|
162
20
|
|
163
21
|
def every(period, job, options={}, &block)
|
164
|
-
|
165
|
-
each_options = options.clone
|
166
|
-
options[:at].each do |at|
|
167
|
-
each_options[:at] = at
|
168
|
-
register(period, job, block, each_options)
|
169
|
-
end
|
170
|
-
else
|
171
|
-
register(period, job, block, options)
|
172
|
-
end
|
22
|
+
@@manager.every(period, job, options, &block)
|
173
23
|
end
|
174
24
|
|
175
25
|
def run
|
176
|
-
|
177
|
-
loop do
|
178
|
-
tick
|
179
|
-
sleep(config[:sleep_timeout])
|
180
|
-
end
|
181
|
-
end
|
182
|
-
|
183
|
-
def log(msg)
|
184
|
-
config[:logger].info(msg)
|
185
|
-
end
|
186
|
-
|
187
|
-
def tick(t=Time.now)
|
188
|
-
to_run = @@events.select do |event|
|
189
|
-
event.time?(t)
|
190
|
-
end
|
191
|
-
|
192
|
-
to_run.each do |event|
|
193
|
-
log "Triggering '#{event}'"
|
194
|
-
event.run(t)
|
195
|
-
end
|
196
|
-
|
197
|
-
to_run
|
26
|
+
@@manager.run
|
198
27
|
end
|
199
28
|
|
200
29
|
def clear!
|
201
|
-
@@
|
202
|
-
@@handler = nil
|
203
|
-
@@configuration = Clockwork.default_configuration
|
30
|
+
@@manager = Manager.new
|
204
31
|
end
|
205
|
-
|
206
|
-
private
|
207
|
-
def register(period, job, block, options)
|
208
|
-
event = Event.new(period, job, block || get_handler, options)
|
209
|
-
@@events << event
|
210
|
-
event
|
211
|
-
end
|
212
|
-
|
213
32
|
end
|
214
33
|
|
215
34
|
unless 1.respond_to?(:seconds)
|
data/lib/clockwork/at.rb
ADDED
@@ -0,0 +1,49 @@
|
|
1
|
+
module Clockwork
|
2
|
+
class At
|
3
|
+
class FailedToParse < StandardError; end
|
4
|
+
|
5
|
+
NOT_SPECIFIED = nil
|
6
|
+
WDAYS = %w[sunday monday tuesday wednesday thursday friday saturday].map do |w|
|
7
|
+
[w, w.capitalize, w[0...3], w[0...3].capitalize]
|
8
|
+
end
|
9
|
+
|
10
|
+
def self.parse(at)
|
11
|
+
return unless at
|
12
|
+
case at
|
13
|
+
when /^([[:alpha:]]+)\s(.*)$/
|
14
|
+
ret = parse($2)
|
15
|
+
wday = WDAYS.find_index { |x| x.include?($1) }
|
16
|
+
raise FailedToParse, at if wday.nil?
|
17
|
+
ret.wday = wday
|
18
|
+
ret
|
19
|
+
when /^(\d{1,2}):(\d\d)$/
|
20
|
+
new($2.to_i, $1.to_i)
|
21
|
+
when /^\*{1,2}:(\d\d)$/
|
22
|
+
new($1.to_i)
|
23
|
+
else
|
24
|
+
raise FailedToParse, at
|
25
|
+
end
|
26
|
+
rescue ArgumentError
|
27
|
+
raise FailedToParse, at
|
28
|
+
end
|
29
|
+
|
30
|
+
attr_writer :min, :hour, :wday
|
31
|
+
|
32
|
+
def initialize(min, hour=NOT_SPECIFIED, wday=NOT_SPECIFIED)
|
33
|
+
if min.nil? || min < 0 || min > 59 ||
|
34
|
+
(hour != NOT_SPECIFIED && (hour < 0 || hour > 23)) ||
|
35
|
+
(wday != NOT_SPECIFIED && (wday < 0 || wday > 6))
|
36
|
+
raise ArgumentError
|
37
|
+
end
|
38
|
+
@min = min
|
39
|
+
@hour = hour
|
40
|
+
@wday = wday
|
41
|
+
end
|
42
|
+
|
43
|
+
def ready?(t)
|
44
|
+
t.min == @min and
|
45
|
+
(@hour == NOT_SPECIFIED or t.hour == @hour) and
|
46
|
+
(@wday == NOT_SPECIFIED or t.wday == @wday)
|
47
|
+
end
|
48
|
+
end
|
49
|
+
end
|
@@ -0,0 +1,71 @@
|
|
1
|
+
module Clockwork
|
2
|
+
class Event
|
3
|
+
attr_accessor :job, :last
|
4
|
+
|
5
|
+
def initialize(manager, period, job, block, options={})
|
6
|
+
@manager = manager
|
7
|
+
@period = period
|
8
|
+
@job = job
|
9
|
+
@at = At.parse(options[:at])
|
10
|
+
@last = nil
|
11
|
+
@block = block
|
12
|
+
@if = options[:if]
|
13
|
+
@thread = options[:thread]
|
14
|
+
@timezone = options[:tz]
|
15
|
+
end
|
16
|
+
|
17
|
+
def to_s
|
18
|
+
@job
|
19
|
+
end
|
20
|
+
|
21
|
+
def convert_timezone(t)
|
22
|
+
@timezone ? t.in_time_zone(@timezone) : t
|
23
|
+
end
|
24
|
+
|
25
|
+
def time?(t)
|
26
|
+
t = convert_timezone(t)
|
27
|
+
elapsed_ready = (@last.nil? or (t - @last).to_i >= @period)
|
28
|
+
elapsed_ready and (@at.nil? or @at.ready?(t)) and (@if.nil? or @if.call(t))
|
29
|
+
end
|
30
|
+
|
31
|
+
def thread?
|
32
|
+
@thread
|
33
|
+
end
|
34
|
+
|
35
|
+
def run(t)
|
36
|
+
t = convert_timezone(t)
|
37
|
+
@last = t
|
38
|
+
|
39
|
+
if thread?
|
40
|
+
if @manager.thread_available?
|
41
|
+
Thread.new { execute }
|
42
|
+
else
|
43
|
+
log_error "Threads exhausted; skipping #{self}"
|
44
|
+
end
|
45
|
+
else
|
46
|
+
execute
|
47
|
+
end
|
48
|
+
end
|
49
|
+
|
50
|
+
def execute
|
51
|
+
@block.call(@job)
|
52
|
+
rescue => e
|
53
|
+
log_error e
|
54
|
+
end
|
55
|
+
|
56
|
+
def log_error(e)
|
57
|
+
@manager.config[:logger].error(e)
|
58
|
+
end
|
59
|
+
|
60
|
+
def exception_message(e)
|
61
|
+
msg = [ "Exception #{e.class} -> #{e.message}" ]
|
62
|
+
|
63
|
+
base = File.expand_path(Dir.pwd) + '/'
|
64
|
+
e.backtrace.each do |t|
|
65
|
+
msg << " #{File.expand_path(t).gsub(/#{base}/, '')}"
|
66
|
+
end
|
67
|
+
|
68
|
+
msg.join("\n")
|
69
|
+
end
|
70
|
+
end
|
71
|
+
end
|
@@ -0,0 +1,91 @@
|
|
1
|
+
module Clockwork
|
2
|
+
class Manager
|
3
|
+
class NoHandlerDefined < RuntimeError; end
|
4
|
+
|
5
|
+
attr_reader :config
|
6
|
+
|
7
|
+
def initialize
|
8
|
+
@events = []
|
9
|
+
@config = default_configuration
|
10
|
+
@handler = nil
|
11
|
+
end
|
12
|
+
|
13
|
+
def thread_available?
|
14
|
+
Thread.list.count < config[:max_threads]
|
15
|
+
end
|
16
|
+
|
17
|
+
def configure
|
18
|
+
yield(config)
|
19
|
+
end
|
20
|
+
|
21
|
+
def default_configuration
|
22
|
+
{ :sleep_timeout => 1, :logger => Logger.new(STDOUT), :thread => false, :max_threads => 10 }
|
23
|
+
end
|
24
|
+
|
25
|
+
def handler(&block)
|
26
|
+
@handler = block
|
27
|
+
end
|
28
|
+
|
29
|
+
def get_handler
|
30
|
+
raise NoHandlerDefined unless (defined?(@handler) and @handler)
|
31
|
+
@handler
|
32
|
+
end
|
33
|
+
|
34
|
+
def every(period, job, options={}, &block)
|
35
|
+
if options[:at].respond_to?(:each)
|
36
|
+
each_options = options.clone
|
37
|
+
options[:at].each do |at|
|
38
|
+
each_options[:at] = at
|
39
|
+
register(period, job, block, each_options)
|
40
|
+
end
|
41
|
+
else
|
42
|
+
register(period, job, block, options)
|
43
|
+
end
|
44
|
+
end
|
45
|
+
|
46
|
+
def run
|
47
|
+
log "Starting clock for #{@events.size} events: [ " + @events.map { |e| e.to_s }.join(' ') + " ]"
|
48
|
+
loop do
|
49
|
+
tick
|
50
|
+
sleep(config[:sleep_timeout])
|
51
|
+
end
|
52
|
+
end
|
53
|
+
|
54
|
+
def tick(t=Time.now)
|
55
|
+
to_run = @events.select do |event|
|
56
|
+
event.time?(t)
|
57
|
+
end
|
58
|
+
|
59
|
+
to_run.each do |event|
|
60
|
+
log "Triggering '#{event}'"
|
61
|
+
event.run(t)
|
62
|
+
end
|
63
|
+
|
64
|
+
to_run
|
65
|
+
end
|
66
|
+
|
67
|
+
private
|
68
|
+
def log(msg)
|
69
|
+
config[:logger].info(msg)
|
70
|
+
end
|
71
|
+
|
72
|
+
def register(period, job, block, options)
|
73
|
+
event = Event.new(self, period, job, block || get_handler, parse_event_option(options))
|
74
|
+
@events << event
|
75
|
+
event
|
76
|
+
end
|
77
|
+
|
78
|
+
def parse_event_option(options)
|
79
|
+
if options[:if]
|
80
|
+
if !options[:if].respond_to?(:call)
|
81
|
+
raise ArgumentError.new(':if expects a callable object, but #{options[:if]} does not respond to call')
|
82
|
+
end
|
83
|
+
end
|
84
|
+
|
85
|
+
options[:thread] = !!(options.has_key?(:thread) ? options[:thread] : config[:thread])
|
86
|
+
options[:tz] ||= config[:tz]
|
87
|
+
|
88
|
+
options
|
89
|
+
end
|
90
|
+
end
|
91
|
+
end
|
data/test/at_test.rb
ADDED
@@ -0,0 +1,67 @@
|
|
1
|
+
require File.expand_path('../../lib/clockwork', __FILE__)
|
2
|
+
require 'rubygems'
|
3
|
+
require 'contest'
|
4
|
+
require 'mocha/setup'
|
5
|
+
require 'time'
|
6
|
+
require 'active_support/time'
|
7
|
+
|
8
|
+
class AtTest < Test::Unit::TestCase
|
9
|
+
def time_in_day(hour, minute)
|
10
|
+
Time.new(2013, 1, 1, hour, minute, 0)
|
11
|
+
end
|
12
|
+
|
13
|
+
test '16:20' do
|
14
|
+
at = Clockwork::At.parse('16:20')
|
15
|
+
assert !at.ready?(time_in_day(16, 19))
|
16
|
+
assert at.ready?(time_in_day(16, 20))
|
17
|
+
assert !at.ready?(time_in_day(16, 21))
|
18
|
+
end
|
19
|
+
|
20
|
+
test '8:20' do
|
21
|
+
at = Clockwork::At.parse('8:20')
|
22
|
+
assert !at.ready?(time_in_day(8, 19))
|
23
|
+
assert at.ready?(time_in_day(8, 20))
|
24
|
+
assert !at.ready?(time_in_day(8, 21))
|
25
|
+
end
|
26
|
+
|
27
|
+
test '**:20' do
|
28
|
+
at = Clockwork::At.parse('**:20')
|
29
|
+
|
30
|
+
assert !at.ready?(time_in_day(15, 19))
|
31
|
+
assert at.ready?(time_in_day(15, 20))
|
32
|
+
assert !at.ready?(time_in_day(15, 21))
|
33
|
+
|
34
|
+
assert !at.ready?(time_in_day(16, 19))
|
35
|
+
assert at.ready?(time_in_day(16, 20))
|
36
|
+
assert !at.ready?(time_in_day(16, 21))
|
37
|
+
end
|
38
|
+
|
39
|
+
test '**:20' do
|
40
|
+
at = Clockwork::At.parse('*:20')
|
41
|
+
|
42
|
+
assert !at.ready?(time_in_day(15, 19))
|
43
|
+
assert at.ready?(time_in_day(15, 20))
|
44
|
+
assert !at.ready?(time_in_day(15, 21))
|
45
|
+
|
46
|
+
assert !at.ready?(time_in_day(16, 19))
|
47
|
+
assert at.ready?(time_in_day(16, 20))
|
48
|
+
assert !at.ready?(time_in_day(16, 21))
|
49
|
+
end
|
50
|
+
|
51
|
+
test 'Saturday 12:00' do
|
52
|
+
at = Clockwork::At.parse('Saturday 12:00')
|
53
|
+
|
54
|
+
assert !at.ready?(Time.new(2010, 1, 1, 12, 00))
|
55
|
+
assert at.ready?(Time.new(2010, 1, 2, 12, 00)) # Saturday
|
56
|
+
assert !at.ready?(Time.new(2010, 1, 3, 12, 00))
|
57
|
+
assert at.ready?(Time.new(2010, 1, 9, 12, 00))
|
58
|
+
end
|
59
|
+
|
60
|
+
test 'Saturday 12:00' do
|
61
|
+
at = Clockwork::At.parse('sat 12:00')
|
62
|
+
|
63
|
+
assert !at.ready?(Time.new(2010, 1, 1, 12, 00))
|
64
|
+
assert at.ready?(Time.new(2010, 1, 2, 12, 00))
|
65
|
+
assert !at.ready?(Time.new(2010, 1, 3, 12, 00))
|
66
|
+
end
|
67
|
+
end
|
data/test/clockwork_test.rb
CHANGED
@@ -1,307 +1,62 @@
|
|
1
1
|
require File.expand_path('../../lib/clockwork', __FILE__)
|
2
|
-
require 'rubygems'
|
3
2
|
require 'contest'
|
4
|
-
require '
|
5
|
-
require 'time'
|
6
|
-
require 'active_support/time'
|
7
|
-
|
8
|
-
module Clockwork
|
9
|
-
def log(msg)
|
10
|
-
end
|
11
|
-
end
|
3
|
+
require 'timeout'
|
12
4
|
|
13
5
|
class ClockworkTest < Test::Unit::TestCase
|
14
|
-
|
6
|
+
teardown do
|
15
7
|
Clockwork.clear!
|
16
|
-
Clockwork.handler { }
|
17
8
|
end
|
18
9
|
|
19
|
-
def
|
20
|
-
|
21
|
-
|
10
|
+
def set_string_io_logger
|
11
|
+
string_io = StringIO.new
|
12
|
+
Clockwork.configure do |config|
|
13
|
+
config[:logger] = Logger.new(string_io)
|
22
14
|
end
|
23
|
-
|
15
|
+
string_io
|
24
16
|
end
|
25
17
|
|
26
|
-
def
|
27
|
-
|
28
|
-
|
18
|
+
def run_in_thread
|
19
|
+
Thread.new do
|
20
|
+
Clockwork.run
|
29
21
|
end
|
30
|
-
assert_equal 0, Clockwork.tick(t).size
|
31
22
|
end
|
32
23
|
|
33
|
-
test
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
assert_will_run(t+60)
|
39
|
-
end
|
40
|
-
|
41
|
-
test "every three minutes" do
|
42
|
-
Clockwork.every(3.minutes, 'myjob')
|
43
|
-
|
44
|
-
assert_will_run(t=Time.now)
|
45
|
-
assert_wont_run(t+2*60)
|
46
|
-
assert_will_run(t+3*60)
|
47
|
-
end
|
48
|
-
|
49
|
-
test "once an hour" do
|
50
|
-
Clockwork.every(1.hour, 'myjob')
|
51
|
-
|
52
|
-
assert_will_run(t=Time.now)
|
53
|
-
assert_wont_run(t+30*60)
|
54
|
-
assert_will_run(t+60*60)
|
55
|
-
end
|
56
|
-
|
57
|
-
test "once a week" do
|
58
|
-
Clockwork.every(1.week, 'myjob')
|
59
|
-
|
60
|
-
assert_will_run(t=Time.now)
|
61
|
-
assert_wont_run(t+60*60*24*6)
|
62
|
-
assert_will_run(t+60*60*24*7)
|
63
|
-
end
|
64
|
-
|
65
|
-
test "once a day at 16:20" do
|
66
|
-
Clockwork.every(1.day, 'myjob', :at => '16:20')
|
67
|
-
|
68
|
-
assert_wont_run 'jan 1 2010 16:19:59'
|
69
|
-
assert_will_run 'jan 1 2010 16:20:00'
|
70
|
-
assert_wont_run 'jan 1 2010 16:20:01'
|
71
|
-
assert_wont_run 'jan 2 2010 16:19:59'
|
72
|
-
assert_will_run 'jan 2 2010 16:20:00'
|
73
|
-
end
|
74
|
-
|
75
|
-
test ":at also accepts 8:20" do
|
76
|
-
Clockwork.every(1.hour, 'myjob', :at => '8:20')
|
77
|
-
|
78
|
-
assert_wont_run 'jan 1 2010 08:19:59'
|
79
|
-
assert_will_run 'jan 1 2010 08:20:00'
|
80
|
-
assert_wont_run 'jan 1 2010 08:20:01'
|
81
|
-
end
|
82
|
-
|
83
|
-
test "twice a day at 16:20 and 18:10" do
|
84
|
-
Clockwork.every(1.day, 'myjob', :at => ['16:20', '18:10'])
|
85
|
-
|
86
|
-
assert_wont_run 'jan 1 2010 16:19:59'
|
87
|
-
assert_will_run 'jan 1 2010 16:20:00'
|
88
|
-
assert_wont_run 'jan 1 2010 16:20:01'
|
89
|
-
|
90
|
-
assert_wont_run 'jan 1 2010 18:09:59'
|
91
|
-
assert_will_run 'jan 1 2010 18:10:00'
|
92
|
-
assert_wont_run 'jan 1 2010 18:10:01'
|
93
|
-
end
|
94
|
-
|
95
|
-
test "once an hour at **:20" do
|
96
|
-
Clockwork.every(1.hour, 'myjob', :at => '**:20')
|
97
|
-
|
98
|
-
assert_wont_run 'jan 1 2010 15:19:59'
|
99
|
-
assert_will_run 'jan 1 2010 15:20:00'
|
100
|
-
assert_wont_run 'jan 1 2010 15:20:01'
|
101
|
-
assert_wont_run 'jan 2 2010 16:19:59'
|
102
|
-
assert_will_run 'jan 2 2010 16:20:00'
|
103
|
-
end
|
104
|
-
|
105
|
-
test ":at also accepts *:20" do
|
106
|
-
Clockwork.every(1.hour, 'myjob', :at => '*:20')
|
107
|
-
|
108
|
-
assert_wont_run 'jan 1 2010 15:19:59'
|
109
|
-
assert_will_run 'jan 1 2010 15:20:00'
|
110
|
-
assert_wont_run 'jan 1 2010 15:20:01'
|
111
|
-
end
|
112
|
-
|
113
|
-
test "on every Saturday" do
|
114
|
-
Clockwork.every(1.week, 'myjob', :at => 'Saturday 12:00')
|
115
|
-
|
116
|
-
assert_wont_run 'jan 1 2010 12:00:00'
|
117
|
-
assert_will_run 'jan 2 2010 12:00:00' # Saturday
|
118
|
-
assert_wont_run 'jan 3 2010 12:00:00'
|
119
|
-
assert_wont_run 'jan 8 2010 12:00:00'
|
120
|
-
assert_will_run 'jan 9 2010 12:00:00'
|
121
|
-
end
|
122
|
-
|
123
|
-
test ":at accepts abbreviated weekday" do
|
124
|
-
Clockwork.every(1.week, 'myjob', :at => 'sat 12:00')
|
125
|
-
|
126
|
-
assert_wont_run 'jan 1 2010 12:00:00'
|
127
|
-
assert_will_run 'jan 2 2010 12:00:00' # Saturday
|
128
|
-
assert_wont_run 'jan 3 2010 12:00:00'
|
129
|
-
end
|
130
|
-
|
131
|
-
test "aborts when no handler defined" do
|
132
|
-
Clockwork.clear!
|
133
|
-
assert_raise(Clockwork::NoHandlerDefined) do
|
134
|
-
Clockwork.every(1.minute, 'myjob')
|
135
|
-
end
|
136
|
-
end
|
137
|
-
|
138
|
-
test "aborts when fails to parse" do
|
139
|
-
assert_raise(Clockwork::At::FailedToParse) do
|
140
|
-
Clockwork.every(1.day, "myjob", :at => "a:bc")
|
24
|
+
test 'should run events with configured logger' do
|
25
|
+
run = false
|
26
|
+
string_io = set_string_io_logger
|
27
|
+
Clockwork.handler do |job|
|
28
|
+
run = job == 'myjob'
|
141
29
|
end
|
142
|
-
end
|
143
|
-
|
144
|
-
test "general handler" do
|
145
|
-
$set_me = 0
|
146
|
-
Clockwork.handler { $set_me = 1 }
|
147
30
|
Clockwork.every(1.minute, 'myjob')
|
148
|
-
Clockwork.tick(Time.now)
|
149
|
-
assert_equal 1, $set_me
|
150
|
-
end
|
151
|
-
|
152
|
-
test "event-specific handler" do
|
153
|
-
$set_me = 0
|
154
|
-
Clockwork.every(1.minute, 'myjob') { $set_me = 2 }
|
155
|
-
Clockwork.tick(Time.now)
|
156
|
-
|
157
|
-
assert_equal 2, $set_me
|
158
|
-
end
|
159
31
|
|
160
|
-
|
161
|
-
Clockwork.handler { raise 'boom' }
|
162
|
-
event = Clockwork.every(1.minute, 'myjob')
|
163
|
-
event.expects(:log_error)
|
32
|
+
runner = run_in_thread
|
164
33
|
|
165
|
-
|
166
|
-
|
34
|
+
timeout(5) do
|
35
|
+
sleep 1 until run
|
167
36
|
end
|
37
|
+
runner.kill
|
38
|
+
assert run
|
39
|
+
assert string_io.string.include?('Triggering')
|
168
40
|
end
|
169
41
|
|
170
|
-
test
|
171
|
-
Clockwork.
|
172
|
-
|
173
|
-
event.stubs(:log_error)
|
174
|
-
Clockwork.tick(t = Time.now)
|
175
|
-
assert_equal t, event.last
|
176
|
-
end
|
177
|
-
|
178
|
-
test "should be configurable" do
|
179
|
-
Clockwork.configure do |config|
|
180
|
-
config[:sleep_timeout] = 200
|
181
|
-
config[:logger] = "A Logger"
|
182
|
-
config[:max_threads] = 10
|
183
|
-
config[:thread] = true
|
184
|
-
end
|
185
|
-
|
186
|
-
assert_equal 200, Clockwork.config[:sleep_timeout]
|
187
|
-
assert_equal "A Logger", Clockwork.config[:logger]
|
188
|
-
assert_equal 10, Clockwork.config[:max_threads]
|
189
|
-
assert_equal true, Clockwork.config[:thread]
|
190
|
-
end
|
191
|
-
|
192
|
-
test "configuration should have reasonable defaults" do
|
193
|
-
assert_equal 1, Clockwork.config[:sleep_timeout]
|
194
|
-
assert Clockwork.config[:logger].is_a?(Logger)
|
195
|
-
assert_equal 10, Clockwork.config[:max_threads]
|
196
|
-
assert_equal false, Clockwork.config[:thread]
|
197
|
-
end
|
198
|
-
|
199
|
-
test "should be able to specify a different timezone than local" do
|
200
|
-
Clockwork.every(1.day, 'myjob', :at => '10:00', :tz => 'UTC')
|
201
|
-
|
202
|
-
assert_wont_run 'jan 1 2010 10:00:00 EST'
|
203
|
-
assert_will_run 'jan 1 2010 10:00:00 UTC'
|
204
|
-
end
|
205
|
-
|
206
|
-
test "should be able to specify a different timezone than local for multiple times" do
|
207
|
-
Clockwork.every(1.day, 'myjob', :at => ['10:00', '8:00'], :tz => 'UTC')
|
208
|
-
|
209
|
-
assert_wont_run 'jan 1 2010 08:00:00 EST'
|
210
|
-
assert_will_run 'jan 1 2010 08:00:00 UTC'
|
211
|
-
assert_wont_run 'jan 1 2010 10:00:00 EST'
|
212
|
-
assert_will_run 'jan 1 2010 10:00:00 UTC'
|
213
|
-
end
|
214
|
-
|
215
|
-
test "should be able to configure a default timezone to use for all events" do
|
216
|
-
Clockwork.configure { |config| config[:tz] = 'UTC' }
|
217
|
-
Clockwork.every(1.day, 'myjob', :at => '10:00')
|
218
|
-
|
219
|
-
assert_wont_run 'jan 1 2010 10:00:00 EST'
|
220
|
-
assert_will_run 'jan 1 2010 10:00:00 UTC'
|
221
|
-
end
|
222
|
-
|
223
|
-
test "should be able to override a default timezone in an event" do
|
224
|
-
Clockwork.configure { |config| config[:tz] = 'UTC' }
|
225
|
-
Clockwork.every(1.day, 'myjob', :at => '10:00', :tz => 'EST')
|
226
|
-
|
227
|
-
assert_will_run 'jan 1 2010 10:00:00 EST'
|
228
|
-
assert_wont_run 'jan 1 2010 10:00:00 UTC'
|
229
|
-
end
|
230
|
-
|
231
|
-
test ":if true then always run" do
|
232
|
-
Clockwork.every(1.second, 'myjob', :if => lambda { |_| true })
|
233
|
-
|
234
|
-
assert_will_run 'jan 1 2010 16:20:00'
|
235
|
-
end
|
236
|
-
|
237
|
-
test ":if false then never run" do
|
238
|
-
Clockwork.every(1.second, 'myjob', :if => lambda { |_| false })
|
239
|
-
|
240
|
-
assert_wont_run 'jan 1 2010 16:20:00'
|
241
|
-
end
|
242
|
-
|
243
|
-
test ":if the first day of month" do
|
244
|
-
Clockwork.every(1.second, 'myjob', :if => lambda { |t| t.day == 1 })
|
245
|
-
|
246
|
-
assert_will_run 'jan 1 2010 16:20:00'
|
247
|
-
assert_wont_run 'jan 2 2010 16:20:00'
|
248
|
-
assert_will_run 'feb 1 2010 16:20:00'
|
249
|
-
end
|
250
|
-
|
251
|
-
test ":if it is compared to a time with zone" do
|
252
|
-
tz = 'America/Chicago'
|
253
|
-
time = Time.utc(2012,5,25,10,00)
|
254
|
-
Clockwork.every(1.second, 'myjob', tz: tz, :if => lambda { |t|(
|
255
|
-
((time - 1.hour)..(time + 1.hour)).cover? t
|
256
|
-
)})
|
257
|
-
assert_will_run time
|
258
|
-
end
|
259
|
-
|
260
|
-
test ":if is not callable then raise ArgumentError" do
|
261
|
-
assert_raise(ArgumentError) do
|
262
|
-
Clockwork.every(1.second, 'myjob', :if => true)
|
263
|
-
end
|
264
|
-
end
|
265
|
-
|
266
|
-
test "should warn about missing jobs upon exhausting threads" do
|
267
|
-
Clockwork.configure do |config|
|
268
|
-
config[:max_threads] = 0
|
269
|
-
end
|
270
|
-
|
271
|
-
event = Clockwork.every(1.minute, 'myjob', :thread => true)
|
272
|
-
event.expects(:log_error).with("Threads exhausted; skipping #{event}")
|
42
|
+
test 'should not run anything after reset' do
|
43
|
+
Clockwork.every(1.minute, 'myjob') { }
|
44
|
+
Clockwork.clear!
|
273
45
|
|
274
|
-
|
46
|
+
string_io = set_string_io_logger
|
47
|
+
runner = run_in_thread
|
48
|
+
sleep 1
|
49
|
+
runner.kill
|
50
|
+
assert string_io.string.include?('0 events')
|
275
51
|
end
|
276
52
|
|
277
|
-
|
278
|
-
|
279
|
-
|
280
|
-
|
281
|
-
|
282
|
-
|
283
|
-
|
284
|
-
|
285
|
-
assert event.thread?
|
286
|
-
end
|
287
|
-
|
288
|
-
test "should use thread if global thread option is set" do
|
289
|
-
Clockwork.configure do |config|
|
290
|
-
config[:thread] = true
|
291
|
-
end
|
292
|
-
|
293
|
-
event = Clockwork.every(1.minute, 'myjob')
|
294
|
-
assert event.thread?
|
295
|
-
end
|
296
|
-
|
297
|
-
test "should not use thread if job option overrides global option" do
|
298
|
-
Clockwork.configure do |config|
|
299
|
-
config[:thread] = true
|
300
|
-
end
|
301
|
-
|
302
|
-
event = Clockwork.every(1.minute, 'myjob', :thread => false)
|
303
|
-
assert !event.thread?
|
304
|
-
end
|
53
|
+
test 'should pass all arguments to every' do
|
54
|
+
Clockwork.every(1.second, 'myjob', if: lambda { false }) { }
|
55
|
+
string_io = set_string_io_logger
|
56
|
+
runner = run_in_thread
|
57
|
+
sleep 1
|
58
|
+
runner.kill
|
59
|
+
assert string_io.string.include?('1 events')
|
60
|
+
assert !string_io.string.include?('Triggering')
|
305
61
|
end
|
306
|
-
|
307
62
|
end
|
@@ -0,0 +1,272 @@
|
|
1
|
+
require File.expand_path('../../lib/clockwork', __FILE__)
|
2
|
+
require 'rubygems'
|
3
|
+
require 'contest'
|
4
|
+
require 'mocha/setup'
|
5
|
+
require 'time'
|
6
|
+
require 'active_support/time'
|
7
|
+
|
8
|
+
class ManagerTest < Test::Unit::TestCase
|
9
|
+
setup do
|
10
|
+
@manager = Clockwork::Manager.new
|
11
|
+
class << @manager
|
12
|
+
def log(msg); end
|
13
|
+
end
|
14
|
+
@manager.handler { }
|
15
|
+
end
|
16
|
+
|
17
|
+
def assert_will_run(t)
|
18
|
+
if t.is_a? String
|
19
|
+
t = Time.parse(t)
|
20
|
+
end
|
21
|
+
assert_equal 1, @manager.tick(t).size
|
22
|
+
end
|
23
|
+
|
24
|
+
def assert_wont_run(t)
|
25
|
+
if t.is_a? String
|
26
|
+
t = Time.parse(t)
|
27
|
+
end
|
28
|
+
assert_equal 0, @manager.tick(t).size
|
29
|
+
end
|
30
|
+
|
31
|
+
test "once a minute" do
|
32
|
+
@manager.every(1.minute, 'myjob')
|
33
|
+
|
34
|
+
assert_will_run(t=Time.now)
|
35
|
+
assert_wont_run(t+30)
|
36
|
+
assert_will_run(t+60)
|
37
|
+
end
|
38
|
+
|
39
|
+
test "every three minutes" do
|
40
|
+
@manager.every(3.minutes, 'myjob')
|
41
|
+
|
42
|
+
assert_will_run(t=Time.now)
|
43
|
+
assert_wont_run(t+2*60)
|
44
|
+
assert_will_run(t+3*60)
|
45
|
+
end
|
46
|
+
|
47
|
+
test "once an hour" do
|
48
|
+
@manager.every(1.hour, 'myjob')
|
49
|
+
|
50
|
+
assert_will_run(t=Time.now)
|
51
|
+
assert_wont_run(t+30*60)
|
52
|
+
assert_will_run(t+60*60)
|
53
|
+
end
|
54
|
+
|
55
|
+
test "once a week" do
|
56
|
+
@manager.every(1.week, 'myjob')
|
57
|
+
|
58
|
+
assert_will_run(t=Time.now)
|
59
|
+
assert_wont_run(t+60*60*24*6)
|
60
|
+
assert_will_run(t+60*60*24*7)
|
61
|
+
end
|
62
|
+
|
63
|
+
test "aborts when no handler defined" do
|
64
|
+
manager = Clockwork::Manager.new
|
65
|
+
assert_raise(Clockwork::Manager::NoHandlerDefined) do
|
66
|
+
manager.every(1.minute, 'myjob')
|
67
|
+
end
|
68
|
+
end
|
69
|
+
|
70
|
+
test "aborts when fails to parse" do
|
71
|
+
assert_raise(Clockwork::At::FailedToParse) do
|
72
|
+
@manager.every(1.day, "myjob", :at => "a:bc")
|
73
|
+
end
|
74
|
+
end
|
75
|
+
|
76
|
+
test "general handler" do
|
77
|
+
$set_me = 0
|
78
|
+
@manager.handler { $set_me = 1 }
|
79
|
+
@manager.every(1.minute, 'myjob')
|
80
|
+
@manager.tick(Time.now)
|
81
|
+
assert_equal 1, $set_me
|
82
|
+
end
|
83
|
+
|
84
|
+
test "event-specific handler" do
|
85
|
+
$set_me = 0
|
86
|
+
@manager.every(1.minute, 'myjob') { $set_me = 2 }
|
87
|
+
@manager.tick(Time.now)
|
88
|
+
|
89
|
+
assert_equal 2, $set_me
|
90
|
+
end
|
91
|
+
|
92
|
+
test "exceptions are trapped and logged" do
|
93
|
+
@manager.handler { raise 'boom' }
|
94
|
+
@manager.every(1.minute, 'myjob')
|
95
|
+
|
96
|
+
logger = Logger.new(StringIO.new)
|
97
|
+
@manager.configure { |c| c[:logger] = logger }
|
98
|
+
logger.expects(:error)
|
99
|
+
|
100
|
+
assert_nothing_raised do
|
101
|
+
@manager.tick(Time.now)
|
102
|
+
end
|
103
|
+
end
|
104
|
+
|
105
|
+
test "exceptions still set the last timestamp to avoid spastic error loops" do
|
106
|
+
@manager.handler { raise 'boom' }
|
107
|
+
event = @manager.every(1.minute, 'myjob')
|
108
|
+
event.stubs(:log_error)
|
109
|
+
@manager.tick(t = Time.now)
|
110
|
+
assert_equal t, event.last
|
111
|
+
end
|
112
|
+
|
113
|
+
test "should be configurable" do
|
114
|
+
@manager.configure do |config|
|
115
|
+
config[:sleep_timeout] = 200
|
116
|
+
config[:logger] = "A Logger"
|
117
|
+
config[:max_threads] = 10
|
118
|
+
config[:thread] = true
|
119
|
+
end
|
120
|
+
|
121
|
+
assert_equal 200, @manager.config[:sleep_timeout]
|
122
|
+
assert_equal "A Logger", @manager.config[:logger]
|
123
|
+
assert_equal 10, @manager.config[:max_threads]
|
124
|
+
assert_equal true, @manager.config[:thread]
|
125
|
+
end
|
126
|
+
|
127
|
+
test "configuration should have reasonable defaults" do
|
128
|
+
assert_equal 1, @manager.config[:sleep_timeout]
|
129
|
+
assert @manager.config[:logger].is_a?(Logger)
|
130
|
+
assert_equal 10, @manager.config[:max_threads]
|
131
|
+
assert_equal false, @manager.config[:thread]
|
132
|
+
end
|
133
|
+
|
134
|
+
describe ':at option' do
|
135
|
+
test "once a day at 16:20" do
|
136
|
+
@manager.every(1.day, 'myjob', :at => '16:20')
|
137
|
+
|
138
|
+
assert_wont_run 'jan 1 2010 16:19:59'
|
139
|
+
assert_will_run 'jan 1 2010 16:20:00'
|
140
|
+
assert_wont_run 'jan 1 2010 16:20:01'
|
141
|
+
assert_wont_run 'jan 2 2010 16:19:59'
|
142
|
+
assert_will_run 'jan 2 2010 16:20:00'
|
143
|
+
end
|
144
|
+
|
145
|
+
test "twice a day at 16:20 and 18:10" do
|
146
|
+
@manager.every(1.day, 'myjob', :at => ['16:20', '18:10'])
|
147
|
+
|
148
|
+
assert_wont_run 'jan 1 2010 16:19:59'
|
149
|
+
assert_will_run 'jan 1 2010 16:20:00'
|
150
|
+
assert_wont_run 'jan 1 2010 16:20:01'
|
151
|
+
|
152
|
+
assert_wont_run 'jan 1 2010 18:09:59'
|
153
|
+
assert_will_run 'jan 1 2010 18:10:00'
|
154
|
+
assert_wont_run 'jan 1 2010 18:10:01'
|
155
|
+
end
|
156
|
+
end
|
157
|
+
|
158
|
+
describe ':tz option' do
|
159
|
+
test "should be able to specify a different timezone than local" do
|
160
|
+
@manager.every(1.day, 'myjob', :at => '10:00', :tz => 'UTC')
|
161
|
+
|
162
|
+
assert_wont_run 'jan 1 2010 10:00:00 EST'
|
163
|
+
assert_will_run 'jan 1 2010 10:00:00 UTC'
|
164
|
+
end
|
165
|
+
|
166
|
+
test "should be able to specify a different timezone than local for multiple times" do
|
167
|
+
@manager.every(1.day, 'myjob', :at => ['10:00', '8:00'], :tz => 'UTC')
|
168
|
+
|
169
|
+
assert_wont_run 'jan 1 2010 08:00:00 EST'
|
170
|
+
assert_will_run 'jan 1 2010 08:00:00 UTC'
|
171
|
+
assert_wont_run 'jan 1 2010 10:00:00 EST'
|
172
|
+
assert_will_run 'jan 1 2010 10:00:00 UTC'
|
173
|
+
end
|
174
|
+
|
175
|
+
test "should be able to configure a default timezone to use for all events" do
|
176
|
+
@manager.configure { |config| config[:tz] = 'UTC' }
|
177
|
+
@manager.every(1.day, 'myjob', :at => '10:00')
|
178
|
+
|
179
|
+
assert_wont_run 'jan 1 2010 10:00:00 EST'
|
180
|
+
assert_will_run 'jan 1 2010 10:00:00 UTC'
|
181
|
+
end
|
182
|
+
|
183
|
+
test "should be able to override a default timezone in an event" do
|
184
|
+
@manager.configure { |config| config[:tz] = 'UTC' }
|
185
|
+
@manager.every(1.day, 'myjob', :at => '10:00', :tz => 'EST')
|
186
|
+
|
187
|
+
assert_will_run 'jan 1 2010 10:00:00 EST'
|
188
|
+
assert_wont_run 'jan 1 2010 10:00:00 UTC'
|
189
|
+
end
|
190
|
+
end
|
191
|
+
|
192
|
+
describe ':if option' do
|
193
|
+
test ":if true then always run" do
|
194
|
+
@manager.every(1.second, 'myjob', :if => lambda { |_| true })
|
195
|
+
|
196
|
+
assert_will_run 'jan 1 2010 16:20:00'
|
197
|
+
end
|
198
|
+
|
199
|
+
test ":if false then never run" do
|
200
|
+
@manager.every(1.second, 'myjob', :if => lambda { |_| false })
|
201
|
+
|
202
|
+
assert_wont_run 'jan 1 2010 16:20:00'
|
203
|
+
end
|
204
|
+
|
205
|
+
test ":if the first day of month" do
|
206
|
+
@manager.every(1.second, 'myjob', :if => lambda { |t| t.day == 1 })
|
207
|
+
|
208
|
+
assert_will_run 'jan 1 2010 16:20:00'
|
209
|
+
assert_wont_run 'jan 2 2010 16:20:00'
|
210
|
+
assert_will_run 'feb 1 2010 16:20:00'
|
211
|
+
end
|
212
|
+
|
213
|
+
test ":if it is compared to a time with zone" do
|
214
|
+
tz = 'America/Chicago'
|
215
|
+
time = Time.utc(2012,5,25,10,00)
|
216
|
+
@manager.every(1.second, 'myjob', tz: tz, :if => lambda { |t|
|
217
|
+
((time - 1.hour)..(time + 1.hour)).cover? t
|
218
|
+
})
|
219
|
+
assert_will_run time
|
220
|
+
end
|
221
|
+
|
222
|
+
test ":if is not callable then raise ArgumentError" do
|
223
|
+
assert_raise(ArgumentError) do
|
224
|
+
@manager.every(1.second, 'myjob', :if => true)
|
225
|
+
end
|
226
|
+
end
|
227
|
+
end
|
228
|
+
|
229
|
+
test "should warn about missing jobs upon exhausting threads" do
|
230
|
+
logger = Logger.new(StringIO.new)
|
231
|
+
@manager.configure do |config|
|
232
|
+
config[:max_threads] = 0
|
233
|
+
config[:logger] = logger
|
234
|
+
end
|
235
|
+
|
236
|
+
@manager.every(1.minute, 'myjob', :thread => true)
|
237
|
+
logger.expects(:error).with("Threads exhausted; skipping myjob")
|
238
|
+
|
239
|
+
@manager.tick(Time.now)
|
240
|
+
end
|
241
|
+
|
242
|
+
describe "thread option" do
|
243
|
+
test "should not use thread by default" do
|
244
|
+
event = @manager.every(1.minute, 'myjob')
|
245
|
+
assert !event.thread?
|
246
|
+
end
|
247
|
+
|
248
|
+
test "should use thread if thread option is specified with truly value" do
|
249
|
+
event = @manager.every(1.minute, 'myjob', :thread => true)
|
250
|
+
assert event.thread?
|
251
|
+
end
|
252
|
+
|
253
|
+
test "should use thread if global thread option is set" do
|
254
|
+
@manager.configure do |config|
|
255
|
+
config[:thread] = true
|
256
|
+
end
|
257
|
+
|
258
|
+
event = @manager.every(1.minute, 'myjob')
|
259
|
+
assert event.thread?
|
260
|
+
end
|
261
|
+
|
262
|
+
test "should not use thread if job option overrides global option" do
|
263
|
+
@manager.configure do |config|
|
264
|
+
config[:thread] = true
|
265
|
+
end
|
266
|
+
|
267
|
+
event = @manager.every(1.minute, 'myjob', :thread => false)
|
268
|
+
assert !event.thread?
|
269
|
+
end
|
270
|
+
end
|
271
|
+
|
272
|
+
end
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: clockwork
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.6.0
|
5
5
|
prerelease:
|
6
6
|
platform: ruby
|
7
7
|
authors:
|
@@ -10,7 +10,7 @@ authors:
|
|
10
10
|
autorequire:
|
11
11
|
bindir: bin
|
12
12
|
cert_chain: []
|
13
|
-
date: 2013-08-
|
13
|
+
date: 2013-08-06 00:00:00.000000000 Z
|
14
14
|
dependencies:
|
15
15
|
- !ruby/object:Gem::Dependency
|
16
16
|
name: tzinfo
|
@@ -148,9 +148,15 @@ files:
|
|
148
148
|
- gemfiles/activesupport3.gemfile
|
149
149
|
- gemfiles/activesupport4.gemfile
|
150
150
|
- lib/clockwork.rb
|
151
|
+
- lib/clockwork/at.rb
|
152
|
+
- lib/clockwork/event.rb
|
153
|
+
- lib/clockwork/manager.rb
|
154
|
+
- test/at_test.rb
|
151
155
|
- test/clockwork_test.rb
|
156
|
+
- test/manager_test.rb
|
152
157
|
homepage: http://github.com/tomykaira/clockwork
|
153
|
-
licenses:
|
158
|
+
licenses:
|
159
|
+
- MIT
|
154
160
|
post_install_message:
|
155
161
|
rdoc_options: []
|
156
162
|
require_paths:
|
@@ -163,7 +169,7 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
163
169
|
version: '0'
|
164
170
|
segments:
|
165
171
|
- 0
|
166
|
-
hash:
|
172
|
+
hash: 1040886093
|
167
173
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
168
174
|
none: false
|
169
175
|
requirements:
|
@@ -172,7 +178,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
172
178
|
version: '0'
|
173
179
|
segments:
|
174
180
|
- 0
|
175
|
-
hash:
|
181
|
+
hash: 1040886093
|
176
182
|
requirements: []
|
177
183
|
rubyforge_project:
|
178
184
|
rubygems_version: 1.8.23
|
@@ -180,4 +186,6 @@ signing_key:
|
|
180
186
|
specification_version: 3
|
181
187
|
summary: A scheduler process to replace cron.
|
182
188
|
test_files:
|
189
|
+
- test/at_test.rb
|
183
190
|
- test/clockwork_test.rb
|
191
|
+
- test/manager_test.rb
|