clockwork 0.3.4 → 0.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.
data/Gemfile CHANGED
@@ -1,5 +1,7 @@
1
1
  source :rubygems
2
2
 
3
+ gem 'tzinfo'
4
+
3
5
  group :development, :test do
4
6
  gem 'jeweler'
5
7
  gem 'contest'
@@ -11,6 +11,7 @@ GEM
11
11
  mocha (0.10.0)
12
12
  metaclass (~> 0.0.1)
13
13
  rake (0.9.2)
14
+ tzinfo (0.3.32)
14
15
 
15
16
  PLATFORMS
16
17
  ruby
@@ -19,3 +20,4 @@ DEPENDENCIES
19
20
  contest
20
21
  jeweler
21
22
  mocha
23
+ tzinfo
data/README.md CHANGED
@@ -119,6 +119,41 @@ You can set more than one timing:
119
119
  every(1.hour, 'reminders.send', :at => ['12:00', '18:00'])
120
120
  # send reminders at noon and evening
121
121
 
122
+ You can also specify a timezone (default is the local timezone):
123
+
124
+ every(1.day, 'reminders.send', :at => '00:00', :tz => 'UTC')
125
+ # Runs the job each day at midnight, UTC.
126
+ # The value for :tz can be anything supported by [TZInfo](http://tzinfo.rubyforge.org/)
127
+
128
+
129
+ Configuration
130
+ -----------------------
131
+
132
+ Clockwork exposes a couple of configuration options you may change:
133
+
134
+ ### :logger
135
+
136
+ By default Clockwork logs to STDOUT. In case you prefer to make it to use our
137
+ own logger implementation you have to specify the `logger` configuration option. See example below.
138
+
139
+ ### :sleep_timeout
140
+
141
+ Clockwork wakes up once a second (by default) and performs its duties. If that
142
+ is the rare case you need to tweak the number of seconds it sleeps then you have
143
+ the `sleep_timeout` configuration option to set like shown below.
144
+
145
+ ### :tz
146
+
147
+ This is the default timezone to use for all events. When not specified this defaults to the local
148
+ timezone. Specifying :tz in the the parameters for an event overrides anything set here.
149
+
150
+ ### Configuration example
151
+
152
+ Clockwork.configure do |config|
153
+ config[:sleep_timeout] = 5
154
+ config[:logger] = Logger.new(log_file_path)
155
+ config[:tz] = 'EST'
156
+ end
122
157
 
123
158
  Anatomy of a clock file
124
159
  -----------------------
data/VERSION CHANGED
@@ -1 +1 @@
1
- 0.3.4
1
+ 0.4.0
@@ -1,3 +1,6 @@
1
+ require 'logger'
2
+ require 'tzinfo'
3
+
1
4
  module Clockwork
2
5
 
3
6
  @@events = []
@@ -58,18 +61,34 @@ module Clockwork
58
61
  @at = At.parse(options[:at])
59
62
  @last = nil
60
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
+ tz = options[:tz] || Clockwork.config[:tz]
73
+ @timezone = TZInfo::Timezone.get(tz) if tz
61
74
  end
62
75
 
63
76
  def to_s
64
77
  @job
65
78
  end
66
79
 
80
+ def convert_timezone(t)
81
+ @timezone ? @timezone.utc_to_local(t.dup.utc) : t
82
+ end
83
+
67
84
  def time?(t)
68
- ellapsed_ready = (@last.nil? or (t - @last).to_i >= @period)
69
- ellapsed_ready and (@at.nil? or @at.ready?(t))
85
+ t = convert_timezone(t)
86
+ elapsed_ready = (@last.nil? or (t - @last).to_i >= @period)
87
+ elapsed_ready and (@at.nil? or @at.ready?(t)) and (@if.nil? or @if.call(t))
70
88
  end
71
89
 
72
90
  def run(t)
91
+ t = convert_timezone(t)
73
92
  @last = t
74
93
  @block.call(@job)
75
94
  rescue => e
@@ -77,7 +96,7 @@ module Clockwork
77
96
  end
78
97
 
79
98
  def log_error(e)
80
- STDERR.puts exception_message(e)
99
+ Clockwork.config[:logger].error(e)
81
100
  end
82
101
 
83
102
  def exception_message(e)
@@ -92,8 +111,22 @@ module Clockwork
92
111
  end
93
112
  end
94
113
 
114
+ def configure
115
+ yield(config)
116
+ end
117
+
118
+ def config
119
+ @@configuration
120
+ end
121
+
95
122
  extend self
96
123
 
124
+ def default_configuration
125
+ { :sleep_timeout => 1, :logger => Logger.new(STDOUT) }
126
+ end
127
+
128
+ @@configuration = default_configuration
129
+
97
130
  def handler(&block)
98
131
  @@handler = block
99
132
  end
@@ -121,12 +154,12 @@ module Clockwork
121
154
  log "Starting clock for #{@@events.size} events: [ " + @@events.map { |e| e.to_s }.join(' ') + " ]"
122
155
  loop do
123
156
  tick
124
- sleep 1
157
+ sleep(config[:sleep_timeout])
125
158
  end
126
159
  end
127
160
 
128
161
  def log(msg)
129
- puts msg
162
+ config[:logger].info(msg)
130
163
  end
131
164
 
132
165
  def tick(t=Time.now)
@@ -135,7 +168,7 @@ module Clockwork
135
168
  end
136
169
 
137
170
  to_run.each do |event|
138
- log "Triggering #{event}"
171
+ log "Triggering '#{event}'"
139
172
  event.run(t)
140
173
  end
141
174
 
@@ -145,6 +178,7 @@ module Clockwork
145
178
  def clear!
146
179
  @@events = []
147
180
  @@handler = nil
181
+ @@configuration = Clockwork.default_configuration
148
182
  end
149
183
 
150
184
  private
@@ -169,4 +169,78 @@ class ClockworkTest < Test::Unit::TestCase
169
169
  Clockwork.tick(t = Time.now)
170
170
  assert_equal t, event.last
171
171
  end
172
+
173
+ test "should be configurable" do
174
+ Clockwork.configure do |config|
175
+ config[:sleep_timeout] = 200
176
+ config[:logger] = "A Logger"
177
+ end
178
+
179
+ assert_equal 200, Clockwork.config[:sleep_timeout]
180
+ assert_equal "A Logger", Clockwork.config[:logger]
181
+ end
182
+
183
+ test "configuration should have reasonable defaults" do
184
+ assert_equal 1, Clockwork.config[:sleep_timeout]
185
+ assert Clockwork.config[:logger].is_a?(Logger)
186
+ end
187
+
188
+ test "should be able to specify a different timezone than local" do
189
+ Clockwork.every(1.day, 'myjob', :at => '10:00', :tz => 'UTC')
190
+
191
+ assert_wont_run 'jan 1 2010 10:00:00 EST'
192
+ assert_will_run 'jan 1 2010 10:00:00 UTC'
193
+ end
194
+
195
+ test "should be able to specify a different timezone than local for multiple times" do
196
+ Clockwork.every(1.day, 'myjob', :at => ['10:00', '8:00'], :tz => 'UTC')
197
+
198
+ assert_wont_run 'jan 1 2010 08:00:00 EST'
199
+ assert_will_run 'jan 1 2010 08:00:00 UTC'
200
+ assert_wont_run 'jan 1 2010 10:00:00 EST'
201
+ assert_will_run 'jan 1 2010 10:00:00 UTC'
202
+ end
203
+
204
+ test "should be able to configure a default timezone to use for all events" do
205
+ Clockwork.configure { |config| config[:tz] = 'UTC' }
206
+ Clockwork.every(1.day, 'myjob', :at => '10:00')
207
+
208
+ assert_wont_run 'jan 1 2010 10:00:00 EST'
209
+ assert_will_run 'jan 1 2010 10:00:00 UTC'
210
+ end
211
+
212
+ test "should be able to override a default timezone in an event" do
213
+ Clockwork.configure { |config| config[:tz] = 'UTC' }
214
+ Clockwork.every(1.day, 'myjob', :at => '10:00', :tz => 'EST')
215
+
216
+ assert_will_run 'jan 1 2010 10:00:00 EST'
217
+ assert_wont_run 'jan 1 2010 10:00:00 UTC'
218
+ end
219
+
220
+ test ":if true then always run" do
221
+ Clockwork.every(1.second, 'myjob', :if => lambda { |_| true })
222
+
223
+ assert_will_run 'jan 1 2010 16:20:00'
224
+ end
225
+
226
+ test ":if false then never run" do
227
+ Clockwork.every(1.second, 'myjob', :if => lambda { |_| false })
228
+
229
+ assert_wont_run 'jan 1 2010 16:20:00'
230
+ end
231
+
232
+ test ":if the first day of month" do
233
+ Clockwork.every(1.second, 'myjob', :if => lambda { |t| t.day == 1 })
234
+
235
+ assert_will_run 'jan 1 2010 16:20:00'
236
+ assert_wont_run 'jan 2 2010 16:20:00'
237
+ assert_will_run 'feb 1 2010 16:20:00'
238
+ end
239
+
240
+ test ":if is not callable then raise ArgumentError" do
241
+ assert_raise(ArgumentError) do
242
+ Clockwork.every(1.second, 'myjob', :if => true)
243
+ end
244
+ end
245
+
172
246
  end
metadata CHANGED
@@ -2,7 +2,7 @@
2
2
  name: clockwork
3
3
  version: !ruby/object:Gem::Version
4
4
  prerelease:
5
- version: 0.3.4
5
+ version: 0.4.0
6
6
  platform: ruby
7
7
  authors:
8
8
  - Adam Wiggins
@@ -10,21 +10,21 @@ autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
12
 
13
- date: 2011-12-14 00:00:00 Z
13
+ date: 2012-03-31 00:00:00 Z
14
14
  dependencies:
15
15
  - !ruby/object:Gem::Dependency
16
- name: jeweler
16
+ name: tzinfo
17
17
  requirement: &id001 !ruby/object:Gem::Requirement
18
18
  none: false
19
19
  requirements:
20
20
  - - ">="
21
21
  - !ruby/object:Gem::Version
22
22
  version: "0"
23
- type: :development
23
+ type: :runtime
24
24
  prerelease: false
25
25
  version_requirements: *id001
26
26
  - !ruby/object:Gem::Dependency
27
- name: contest
27
+ name: jeweler
28
28
  requirement: &id002 !ruby/object:Gem::Requirement
29
29
  none: false
30
30
  requirements:
@@ -35,7 +35,7 @@ dependencies:
35
35
  prerelease: false
36
36
  version_requirements: *id002
37
37
  - !ruby/object:Gem::Dependency
38
- name: mocha
38
+ name: contest
39
39
  requirement: &id003 !ruby/object:Gem::Requirement
40
40
  none: false
41
41
  requirements:
@@ -45,6 +45,17 @@ dependencies:
45
45
  type: :development
46
46
  prerelease: false
47
47
  version_requirements: *id003
48
+ - !ruby/object:Gem::Dependency
49
+ name: mocha
50
+ requirement: &id004 !ruby/object:Gem::Requirement
51
+ none: false
52
+ requirements:
53
+ - - ">="
54
+ - !ruby/object:Gem::Version
55
+ version: "0"
56
+ type: :development
57
+ prerelease: false
58
+ version_requirements: *id004
48
59
  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.
49
60
  email: adam@heroku.com
50
61
  executables:
@@ -75,6 +86,9 @@ required_ruby_version: !ruby/object:Gem::Requirement
75
86
  requirements:
76
87
  - - ">="
77
88
  - !ruby/object:Gem::Version
89
+ hash: -383118451
90
+ segments:
91
+ - 0
78
92
  version: "0"
79
93
  required_rubygems_version: !ruby/object:Gem::Requirement
80
94
  none: false
@@ -85,7 +99,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
85
99
  requirements: []
86
100
 
87
101
  rubyforge_project: clockwork
88
- rubygems_version: 1.8.6
102
+ rubygems_version: 1.8.17
89
103
  signing_key:
90
104
  specification_version: 3
91
105
  summary: A scheduler process to replace cron.