clockwork 2.0.1 → 3.0.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +5 -5
- data/.travis.yml +24 -8
- data/CHANGELOG.md +20 -0
- data/README.md +68 -21
- data/bin/clockwork +1 -1
- data/bin/clockworkd +2 -1
- data/clockwork.gemspec +1 -2
- data/gemfiles/activesupport4.gemfile +2 -8
- data/gemfiles/activesupport5.gemfile +5 -0
- data/gemfiles/activesupport6.gemfile +5 -0
- data/lib/clockwork/database_events/event_collection.rb +8 -1
- data/lib/clockwork/database_events/event_store.rb +6 -1
- data/lib/clockwork/database_events/synchronizer.rb +0 -2
- data/lib/clockwork/event.rb +24 -3
- data/lib/clockwork/manager.rb +10 -3
- data/lib/clockwork.rb +1 -0
- data/test/at_test.rb +1 -1
- data/test/clockwork_test.rb +17 -1
- data/test/database_events/event_store_test.rb +1 -0
- data/test/database_events/support/active_record_fake.rb +2 -2
- data/test/database_events/synchronizer_test.rb +1 -1
- data/test/database_events/test_helpers.rb +30 -6
- data/test/event_test.rb +37 -0
- data/test/manager_test.rb +1 -1
- data/test/samples/signal_test.rb +1 -0
- data/test/signal_test.rb +1 -1
- metadata +9 -22
- data/gemfiles/activesupport3.gemfile +0 -10
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
|
-
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
2
|
+
SHA256:
|
3
|
+
metadata.gz: 81357fe2cd463fcf64f263400fd180f02a2c6e14fc281c32cd5098dbe6971487
|
4
|
+
data.tar.gz: 2eec51851477a00654c88adaa7b5e4b5abac252fa808957d1f3cfafda49572f4
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: ee46e6ec0c2da3bda8c38ab24ad29b50d01d058e0e1580c6cc2c0f1a5b000a649453ddc780b5d007b37c25f3a8380303f00344b9c171f5febb2742b11127c25c
|
7
|
+
data.tar.gz: 1d64979d6c6a494963bf27283aff3da36345441be828c0496fc25858e6c0834d87aaf8283ea3cf7d3bf396dea30e0d27c681b2ea52ab8e04681440491ddbef20
|
data/.travis.yml
CHANGED
@@ -1,14 +1,30 @@
|
|
1
1
|
language: ruby
|
2
2
|
sudo: false
|
3
3
|
cache: bundler
|
4
|
+
before_install:
|
5
|
+
- gem update --system
|
6
|
+
# This is required to support ActiveSupport 4
|
7
|
+
# https://docs.travis-ci.com/user/languages/ruby/#bundler-20
|
8
|
+
- gem uninstall -v '>= 2' -i $(rvm gemdir)@global -ax bundler || true
|
9
|
+
- gem install bundler -v '< 2'
|
4
10
|
rvm:
|
5
|
-
-
|
6
|
-
- 2.
|
7
|
-
- 2.
|
8
|
-
- 2.
|
9
|
-
-
|
10
|
-
-
|
11
|
-
-
|
11
|
+
- 2.3.8
|
12
|
+
- 2.4.9
|
13
|
+
- 2.5.7
|
14
|
+
- 2.6.5
|
15
|
+
- 2.7.0
|
16
|
+
- 3.0.2
|
17
|
+
- jruby-9.1.17.0
|
18
|
+
- jruby-9.2.11.0
|
12
19
|
gemfile:
|
13
|
-
- gemfiles/activesupport3.gemfile
|
14
20
|
- gemfiles/activesupport4.gemfile
|
21
|
+
- gemfiles/activesupport5.gemfile
|
22
|
+
- gemfiles/activesupport6.gemfile
|
23
|
+
matrix:
|
24
|
+
exclude:
|
25
|
+
- rvm: 2.3.8
|
26
|
+
gemfile: gemfiles/activesupport6.gemfile
|
27
|
+
- rvm: 2.4.9
|
28
|
+
gemfile: gemfiles/activesupport6.gemfile
|
29
|
+
- rvm: jruby-9.1.17.0
|
30
|
+
gemfile: gemfiles/activesupport6.gemfile
|
data/CHANGELOG.md
ADDED
@@ -0,0 +1,20 @@
|
|
1
|
+
## 3.0.0 ##
|
2
|
+
|
3
|
+
* BREAKING CHANGE: drop Rubinius support
|
4
|
+
* add Ruby 3.0 support (65d71f)
|
5
|
+
* fix a bug with OpenStruct (15eb030)
|
6
|
+
* allow `:skip_first_run` in database events (429bc0a)
|
7
|
+
* add rescue to prevent hung up by exception (cc1b7c9)
|
8
|
+
* fix CI errors (16b4e19 & e4480ea)
|
9
|
+
* fix a compatibility bug with Rails 7 (5907bc7)
|
10
|
+
* Add "Finished" log with duration and error summary (66419ab)
|
11
|
+
|
12
|
+
## 2.0.4 ##
|
13
|
+
|
14
|
+
* Reverts the breaking changes in PR #18 that went out in patch 2.0.3
|
15
|
+
|
16
|
+
*Javier Julio*
|
17
|
+
|
18
|
+
## 2.0.3 (February 15, 2018) ##
|
19
|
+
|
20
|
+
* [See the version release](https://github.com/Rykian/clockwork/releases) for the commits that were included.
|
data/README.md
CHANGED
@@ -1,4 +1,4 @@
|
|
1
|
-
Clockwork - a clock process to replace cron [![Build Status](https://api.travis-ci.
|
1
|
+
Clockwork - a clock process to replace cron [![Build Status](https://api.travis-ci.com/Rykian/clockwork.svg?branch=master)](https://travis-ci.org/Rykian/clockwork)
|
2
2
|
===========================================
|
3
3
|
|
4
4
|
Cron is non-ideal for running scheduled application tasks, especially in an app
|
@@ -18,6 +18,8 @@ Create clock.rb:
|
|
18
18
|
|
19
19
|
```ruby
|
20
20
|
require 'clockwork'
|
21
|
+
require 'active_support/time' # Allow numeric durations (eg: 1.minutes)
|
22
|
+
|
21
23
|
module Clockwork
|
22
24
|
handler do |job|
|
23
25
|
puts "Running #{job}"
|
@@ -58,8 +60,8 @@ Quickstart for Heroku
|
|
58
60
|
|
59
61
|
Clockwork fits well with heroku's cedar stack.
|
60
62
|
|
61
|
-
Consider
|
62
|
-
a new project for
|
63
|
+
Consider using [clockwork-init.sh](https://gist.github.com/tomykaira/1312172) to create
|
64
|
+
a new project for Heroku.
|
63
65
|
|
64
66
|
Use with queueing
|
65
67
|
-----------------
|
@@ -80,6 +82,7 @@ For example, if you're using Beanstalk/Stalker:
|
|
80
82
|
|
81
83
|
```ruby
|
82
84
|
require 'stalker'
|
85
|
+
require 'active_support/time'
|
83
86
|
|
84
87
|
module Clockwork
|
85
88
|
handler { |job| Stalker.enqueue(job) }
|
@@ -142,31 +145,33 @@ module Clockwork
|
|
142
145
|
end
|
143
146
|
```
|
144
147
|
|
145
|
-
This tells clockwork to fetch all `ClockworkDatabaseEvent` instances from the database, and create an internal clockwork event for each one. Each clockwork event will be configured based on the instance's `frequency` and, optionally, its `at`, `
|
148
|
+
This tells clockwork to fetch all `ClockworkDatabaseEvent` instances from the database, and create an internal clockwork event for each one. Each clockwork event will be configured based on the instance's `frequency` and, optionally, its `at`, `if?`, `ignored_attributes`, `name`, and, `tz` methods. The code above also says to reload the events from the database every `1.minute`; we need pick up any changes in the database frequently (choose a sensible reload frequency by changing the `every:` option).
|
146
149
|
|
147
|
-
When one of the events is ready to be run (based on it's `frequency`, and possible `at`, `if
|
150
|
+
When one of the events is ready to be run (based on it's `frequency`, and possible `at`, `if?`, `ignored attributes`, and `tz` methods), clockwork arranges for the block passed to `sync_database_events` to be run. The above example shows how you could use either DelayedJob or Sidekiq to kick off a worker job. This approach is good because the ideal is to use clockwork as a simple scheduler, and avoid making it carry out any long-running tasks.
|
148
151
|
|
149
152
|
### Your Model Classes
|
150
153
|
|
151
154
|
`ActiveRecord` models are a perfect candidate for the model class. Having said that, the only requirements are:
|
152
155
|
|
153
|
-
|
156
|
+
1. the class responds to `all` returning an array of instances from the database
|
154
157
|
|
155
|
-
|
158
|
+
2. the instances returned respond to:
|
159
|
+
- `id` returning a unique identifier (this is needed to track changes to event settings)
|
160
|
+
- `frequency` returning the how frequently (in seconds) the database event should be run
|
156
161
|
|
157
|
-
|
162
|
+
- `attributes` returning a hash of [attribute name] => [attribute value] values (or really anything that we can use store on registering the event, and then compare again to see if the state has changed later)
|
158
163
|
|
159
|
-
|
164
|
+
- `at` *(optional)* return any acceptable clockwork `:at` string
|
160
165
|
|
161
|
-
|
166
|
+
- `name` *(optional)* returning the name for the event (used to identify it in the Clockwork output)
|
162
167
|
|
163
|
-
|
168
|
+
- `if?`*(optional)* returning either true or false, depending on whether the database event should run at the given time (this method will be passed the time as a parameter, much like the standard clockwork `:if`)
|
164
169
|
|
165
|
-
|
170
|
+
- `ignored_attributes` *(optional)* returning an array of model attributes (as symbols) to ignore when determining whether the database event has been modified since our last run
|
166
171
|
|
167
|
-
|
172
|
+
- `tz` *(optional)* returning the timezone to use (default is the local timezone)
|
168
173
|
|
169
|
-
|
174
|
+
- `skip_first_run` *(optional)* self explanatory, see [dedicated section](#skip_first_run)
|
170
175
|
|
171
176
|
#### Example Setup
|
172
177
|
|
@@ -245,6 +250,28 @@ class ClockworkDatabaseEvent < ActiveRecord::Base
|
|
245
250
|
end
|
246
251
|
```
|
247
252
|
|
253
|
+
#### Example use of `ignored_attributes`
|
254
|
+
|
255
|
+
Clockwork compares all attributes of the model between runs to determine if the model has changed, and if it has, it runs the event if all other conditions are met.
|
256
|
+
|
257
|
+
However, in certain cases, you may want to store additional attributes in your model that you don't want to affect whether a database event is executed prior to its next interval.
|
258
|
+
|
259
|
+
So for example, you may update an attribute of your model named `last_scheduled_at` on each run to track the last time it was successfully scheduled. You can tell Clockwork to ignore that attribute in its comparison as follows:
|
260
|
+
|
261
|
+
```ruby
|
262
|
+
# app/models/clockwork_database_event.rb
|
263
|
+
class ClockworkDatabaseEvent < ActiveRecord::Base
|
264
|
+
|
265
|
+
...
|
266
|
+
|
267
|
+
def ignored_attributes
|
268
|
+
[ :last_scheduled_at ]
|
269
|
+
end
|
270
|
+
|
271
|
+
...
|
272
|
+
end
|
273
|
+
```
|
274
|
+
|
248
275
|
|
249
276
|
Event Parameters
|
250
277
|
----------
|
@@ -305,7 +332,8 @@ If this is a problem, please use the `:thread` option to prevent the long runnin
|
|
305
332
|
```ruby
|
306
333
|
every(1.day, 'reminders.send', :at => '00:00', :tz => 'UTC')
|
307
334
|
# Runs the job each day at midnight, UTC.
|
308
|
-
# The value for :tz can be anything supported by [TZInfo](
|
335
|
+
# The value for :tz can be anything supported by [TZInfo](https://github.com/tzinfo/tzinfo)
|
336
|
+
# Using the 'tzinfo' gem, run TZInfo::Timezone.all_identifiers to get a list of acceptable identifiers.
|
309
337
|
```
|
310
338
|
|
311
339
|
### :if
|
@@ -341,6 +369,19 @@ Clockwork.every(1.day, 'run.me.in.new.thread', :thread => true)
|
|
341
369
|
|
342
370
|
If a job is long-running or IO-intensive, this option helps keep the clock precise.
|
343
371
|
|
372
|
+
### :skip_first_run
|
373
|
+
|
374
|
+
Normally, a clockwork process that is defined to run in a specified period will run at startup.
|
375
|
+
This is sometimes undesired behaviour, if the action being run relies on other processes booting which may be slower than clock.
|
376
|
+
To avoid this problem, `:skip_first_run` can be used.
|
377
|
+
|
378
|
+
```ruby
|
379
|
+
Clockwork.every(5.minutes, 'myjob', :skip_first_run => true)
|
380
|
+
```
|
381
|
+
|
382
|
+
The above job will not run at initial boot, and instead run every 5 minutes after boot.
|
383
|
+
|
384
|
+
|
344
385
|
Configuration
|
345
386
|
-----------------------
|
346
387
|
|
@@ -357,7 +398,6 @@ Clockwork wakes up once a second and performs its duties. To change the number o
|
|
357
398
|
sleeps, set the `sleep_timeout` configuration option as shown below in the example.
|
358
399
|
|
359
400
|
From 1.1.0, Clockwork does not accept `sleep_timeout` less than 1 seconds.
|
360
|
-
This restriction is introduced to solve more severe bug [#135](https://github.com/tomykaira/clockwork/pull/135).
|
361
401
|
|
362
402
|
### :tz
|
363
403
|
|
@@ -464,7 +504,7 @@ end
|
|
464
504
|
```
|
465
505
|
|
466
506
|
In addition, Clockwork also supports `:before_tick`, `:after_tick`, `:before_run`, and `:after_run` callbacks.
|
467
|
-
All callbacks are optional. The `tick` callbacks run every tick (a tick being whatever your `:sleep_timeout`
|
507
|
+
All callbacks are optional. All `before` callbacks must return a truthy value otherwise the job will not run. The `tick` callbacks run every tick (a tick being whatever your `:sleep_timeout`
|
468
508
|
is set to, default is 1 second):
|
469
509
|
|
470
510
|
```ruby
|
@@ -524,10 +564,17 @@ clockworkd -c YOUR_CLOCK.rb start
|
|
524
564
|
|
525
565
|
For more details, you can run `clockworkd -h`.
|
526
566
|
|
567
|
+
Integration Testing
|
568
|
+
-------------------
|
569
|
+
|
570
|
+
You could take a look at:
|
571
|
+
* [clockwork-mocks](https://github.com/dpoetzsch/clockwork-mocks) that helps with running scheduled tasks during integration testing.
|
572
|
+
* [clockwork-test](https://github.com/kevin-j-m/clockwork-test) which ensures that tasks are triggered at the right time
|
573
|
+
|
527
574
|
Issues and Pull requests
|
528
575
|
------------------------
|
529
576
|
|
530
|
-
If you find a bug, please create an issue - [Issues ·
|
577
|
+
If you find a bug, please create an issue - [Issues · Rykian/clockwork](https://github.com/Rykian/clockwork/issues).
|
531
578
|
|
532
579
|
For a bug fix or a feature request, please send a pull-request.
|
533
580
|
Do not forget to add tests to show how your feature works, or what bug is fixed.
|
@@ -543,8 +590,8 @@ Use cases
|
|
543
590
|
|
544
591
|
Feel free to add your idea or experience and send a pull-request.
|
545
592
|
|
546
|
-
-
|
547
|
-
-
|
593
|
+
- Sending errors to Airbrake
|
594
|
+
- Read events from a database
|
548
595
|
|
549
596
|
Meta
|
550
597
|
----
|
@@ -559,4 +606,4 @@ Patches contributed by Mark McGranaghan and Lukáš Konarovský
|
|
559
606
|
|
560
607
|
Released under the MIT License: http://www.opensource.org/licenses/mit-license.php
|
561
608
|
|
562
|
-
|
609
|
+
https://github.com/Rykian/clockwork
|
data/bin/clockwork
CHANGED
data/bin/clockworkd
CHANGED
@@ -4,6 +4,7 @@ STDERR.sync = STDOUT.sync = true
|
|
4
4
|
|
5
5
|
require 'clockwork'
|
6
6
|
require 'optparse'
|
7
|
+
require 'pathname'
|
7
8
|
|
8
9
|
begin
|
9
10
|
require 'daemons'
|
@@ -45,7 +46,7 @@ opts = OptionParser.new do |opts|
|
|
45
46
|
end
|
46
47
|
opts.on('-c', '--clock=FILE',"Clock .rb file. Default is #{@options[:file]}.") do |clock_file|
|
47
48
|
@options[:file] = clock_file
|
48
|
-
@options[:file] = "./#{@options[:file]}" unless @options[:file].
|
49
|
+
@options[:file] = "./#{@options[:file]}" unless Pathname.new(@options[:file]).absolute?
|
49
50
|
@options[:file] = File.expand_path(@options[:file])
|
50
51
|
end
|
51
52
|
opts.on('-d', '--dir=DIR', 'Directory to change to once the process starts') do |dir|
|
data/clockwork.gemspec
CHANGED
@@ -1,6 +1,6 @@
|
|
1
1
|
Gem::Specification.new do |s|
|
2
2
|
s.name = "clockwork"
|
3
|
-
s.version = "
|
3
|
+
s.version = "3.0.0"
|
4
4
|
|
5
5
|
s.authors = ["Adam Wiggins", "tomykaira"]
|
6
6
|
s.license = 'MIT'
|
@@ -20,7 +20,6 @@ Gem::Specification.new do |s|
|
|
20
20
|
s.add_dependency(%q<tzinfo>)
|
21
21
|
s.add_dependency(%q<activesupport>)
|
22
22
|
|
23
|
-
s.add_development_dependency "bundler", "~> 1.3"
|
24
23
|
s.add_development_dependency "rake"
|
25
24
|
s.add_development_dependency "daemons"
|
26
25
|
s.add_development_dependency "minitest", "~> 5.8"
|
@@ -1,11 +1,5 @@
|
|
1
1
|
source 'https://rubygems.org'
|
2
2
|
|
3
|
-
|
4
|
-
|
5
|
-
gem 'rubysl-test-unit'
|
6
|
-
gem 'rubinius-developer_tools'
|
7
|
-
end
|
8
|
-
|
9
|
-
gem 'activesupport', '~> 4.0.0'
|
10
|
-
gem 'minitest', '~> 4.2'
|
3
|
+
gem 'activesupport', '~> 4.2'
|
4
|
+
gem 'minitest', '~> 5.0'
|
11
5
|
gemspec :path=>"../"
|
@@ -14,7 +14,14 @@ module Clockwork
|
|
14
14
|
def has_changed?(model)
|
15
15
|
return true if event.nil?
|
16
16
|
|
17
|
-
|
17
|
+
ignored_attributes = model.ignored_attributes if model.respond_to?(:ignored_attributes)
|
18
|
+
ignored_attributes ||= []
|
19
|
+
|
20
|
+
model_attributes = model.attributes.select do |k, _|
|
21
|
+
not ignored_attributes.include?(k.to_sym)
|
22
|
+
end
|
23
|
+
|
24
|
+
event.model_attributes != model_attributes
|
18
25
|
end
|
19
26
|
|
20
27
|
def unregister
|
@@ -112,15 +112,20 @@ module Clockwork
|
|
112
112
|
options = {
|
113
113
|
:from_database => true,
|
114
114
|
:synchronizer => self,
|
115
|
+
:ignored_attributes => [],
|
115
116
|
}
|
116
117
|
|
117
118
|
options[:at] = at_strings_for(model) if model.respond_to?(:at)
|
118
119
|
options[:if] = ->(time){ model.if?(time) } if model.respond_to?(:if?)
|
119
120
|
options[:tz] = model.tz if model.respond_to?(:tz)
|
121
|
+
options[:ignored_attributes] = model.ignored_attributes if model.respond_to?(:ignored_attributes)
|
122
|
+
options[:skip_first_run] = model.skip_first_run if model.respond_to?(:skip_first_run)
|
120
123
|
|
121
124
|
# store the state of the model at time of registering so we can
|
122
125
|
# easily compare and determine if state has changed later
|
123
|
-
options[:model_attributes] = model.attributes
|
126
|
+
options[:model_attributes] = model.attributes.select do |k, v|
|
127
|
+
not options[:ignored_attributes].include?(k.to_sym)
|
128
|
+
end
|
124
129
|
|
125
130
|
options
|
126
131
|
end
|
data/lib/clockwork/event.rb
CHANGED
@@ -8,11 +8,12 @@ module Clockwork
|
|
8
8
|
@period = period
|
9
9
|
@job = job
|
10
10
|
@at = At.parse(options[:at])
|
11
|
-
@last = nil
|
12
11
|
@block = block
|
13
12
|
@if = options[:if]
|
14
13
|
@thread = options.fetch(:thread, @manager.config[:thread])
|
15
14
|
@timezone = options.fetch(:tz, @manager.config[:tz])
|
15
|
+
@skip_first_run = options[:skip_first_run]
|
16
|
+
@last = @skip_first_run ? convert_timezone(Time.now) : nil
|
16
17
|
end
|
17
18
|
|
18
19
|
def convert_timezone(t)
|
@@ -21,7 +22,10 @@ module Clockwork
|
|
21
22
|
|
22
23
|
def run_now?(t)
|
23
24
|
t = convert_timezone(t)
|
24
|
-
|
25
|
+
return false unless elapsed_ready?(t)
|
26
|
+
return false unless run_at?(t)
|
27
|
+
return false unless run_if?(t)
|
28
|
+
true
|
25
29
|
end
|
26
30
|
|
27
31
|
def thread?
|
@@ -51,16 +55,33 @@ module Clockwork
|
|
51
55
|
|
52
56
|
private
|
53
57
|
def execute
|
58
|
+
start = Process.clock_gettime(Process::CLOCK_MONOTONIC)
|
59
|
+
error = nil
|
60
|
+
|
54
61
|
@block.call(@job, @last)
|
55
62
|
rescue => e
|
63
|
+
error = e
|
56
64
|
@manager.log_error e
|
57
65
|
@manager.handle_error e
|
66
|
+
ensure
|
67
|
+
finish = Process.clock_gettime(Process::CLOCK_MONOTONIC)
|
68
|
+
duration = ((finish - start) * 1000).round # milliseconds
|
69
|
+
|
70
|
+
@manager.log "Finished '#{self}' duration_ms=#{duration} error=#{error.inspect}"
|
58
71
|
end
|
59
72
|
|
60
|
-
def elapsed_ready(t)
|
73
|
+
def elapsed_ready?(t)
|
61
74
|
@last.nil? || (t - @last.to_i).to_i >= @period
|
62
75
|
end
|
63
76
|
|
77
|
+
def run_at?(t)
|
78
|
+
@at.nil? || @at.ready?(t)
|
79
|
+
end
|
80
|
+
|
81
|
+
def run_if?(t)
|
82
|
+
@if.nil? || @if.call(t)
|
83
|
+
end
|
84
|
+
|
64
85
|
def validate_if_option(if_option)
|
65
86
|
if if_option && !if_option.respond_to?(:call)
|
66
87
|
raise ArgumentError.new(':if expects a callable object, but #{if_option} does not respond to call')
|
data/lib/clockwork/manager.rb
CHANGED
@@ -37,7 +37,7 @@ module Clockwork
|
|
37
37
|
|
38
38
|
def error_handler(&block)
|
39
39
|
@error_handler = block if block_given?
|
40
|
-
@error_handler
|
40
|
+
@error_handler if instance_variable_defined?("@error_handler")
|
41
41
|
end
|
42
42
|
|
43
43
|
def on(event, options={}, &block)
|
@@ -66,7 +66,7 @@ module Clockwork
|
|
66
66
|
|
67
67
|
sig_read, sig_write = IO.pipe
|
68
68
|
|
69
|
-
%w[INT TERM HUP].each do |sig|
|
69
|
+
(%w[INT TERM HUP] & Signal.list.keys).each do |sig|
|
70
70
|
trap sig do
|
71
71
|
sig_write.puts(sig)
|
72
72
|
end
|
@@ -160,7 +160,14 @@ module Clockwork
|
|
160
160
|
|
161
161
|
private
|
162
162
|
def events_to_run(t)
|
163
|
-
@events.select
|
163
|
+
@events.select do |event|
|
164
|
+
begin
|
165
|
+
event.run_now?(t)
|
166
|
+
rescue => e
|
167
|
+
log_error(e)
|
168
|
+
false
|
169
|
+
end
|
170
|
+
end
|
164
171
|
end
|
165
172
|
|
166
173
|
def register(period, job, block, options)
|
data/lib/clockwork.rb
CHANGED
data/test/at_test.rb
CHANGED
data/test/clockwork_test.rb
CHANGED
@@ -1,6 +1,6 @@
|
|
1
1
|
require File.expand_path('../../lib/clockwork', __FILE__)
|
2
2
|
require 'minitest/autorun'
|
3
|
-
require 'mocha/
|
3
|
+
require 'mocha/minitest'
|
4
4
|
|
5
5
|
describe Clockwork do
|
6
6
|
before do
|
@@ -27,6 +27,7 @@ describe Clockwork do
|
|
27
27
|
|
28
28
|
assert run
|
29
29
|
assert @log_output.string.include?('Triggering')
|
30
|
+
assert @log_output.string.include?('Finished')
|
30
31
|
end
|
31
32
|
|
32
33
|
it 'should log event correctly' do
|
@@ -39,6 +40,21 @@ describe Clockwork do
|
|
39
40
|
Clockwork.run
|
40
41
|
assert run
|
41
42
|
assert @log_output.string.include?("Triggering 'an event'")
|
43
|
+
assert_match /Finished 'an event' duration_ms=\d+ error=nil/, @log_output.string
|
44
|
+
end
|
45
|
+
|
46
|
+
it 'should log exceptions' do
|
47
|
+
run = false
|
48
|
+
Clockwork.handler do |job|
|
49
|
+
run = job == 'an event'
|
50
|
+
raise 'boom'
|
51
|
+
end
|
52
|
+
Clockwork.every(1.minute, 'an event')
|
53
|
+
Clockwork.manager.stubs(:run_tick_loop).returns(Clockwork.manager.tick)
|
54
|
+
Clockwork.run
|
55
|
+
assert run
|
56
|
+
assert @log_output.string.include?("Triggering 'an event'")
|
57
|
+
assert_match /Finished 'an event' duration_ms=\d+ error=#<RuntimeError: boom>/, @log_output.string
|
42
58
|
end
|
43
59
|
|
44
60
|
it 'should pass event without modification to handler' do
|
@@ -36,19 +36,35 @@ end
|
|
36
36
|
|
37
37
|
class DatabaseEventModel
|
38
38
|
include ActiveRecordFake
|
39
|
-
attr_accessor :
|
39
|
+
attr_accessor :frequency, :at, :tz
|
40
40
|
|
41
41
|
def name
|
42
|
-
@name
|
42
|
+
if instance_variable_defined?("@name")
|
43
|
+
@name
|
44
|
+
else
|
45
|
+
"#{self.class}:#{id}"
|
46
|
+
end
|
47
|
+
end
|
48
|
+
|
49
|
+
def name=(name)
|
50
|
+
@name = name
|
43
51
|
end
|
44
52
|
end
|
45
53
|
|
46
54
|
class DatabaseEventModel2
|
47
55
|
include ActiveRecordFake
|
48
|
-
attr_accessor :
|
56
|
+
attr_accessor :frequency, :at, :tz
|
49
57
|
|
50
58
|
def name
|
51
|
-
@name
|
59
|
+
if instance_variable_defined?("@name")
|
60
|
+
@name
|
61
|
+
else
|
62
|
+
"#{self.class}:#{id}"
|
63
|
+
end
|
64
|
+
end
|
65
|
+
|
66
|
+
def name=(name)
|
67
|
+
@name = name
|
52
68
|
end
|
53
69
|
end
|
54
70
|
|
@@ -59,10 +75,18 @@ end
|
|
59
75
|
|
60
76
|
class DatabaseEventModelWithIf
|
61
77
|
include ActiveRecordFake
|
62
|
-
attr_accessor :
|
78
|
+
attr_accessor :frequency, :at, :tz, :if_state
|
63
79
|
|
64
80
|
def name
|
65
|
-
@name
|
81
|
+
if instance_variable_defined?("@name")
|
82
|
+
@name
|
83
|
+
else
|
84
|
+
"#{self.class}:#{id}"
|
85
|
+
end
|
86
|
+
end
|
87
|
+
|
88
|
+
def name=(name)
|
89
|
+
@name = name
|
66
90
|
end
|
67
91
|
|
68
92
|
def if?(time)
|
data/test/event_test.rb
CHANGED
@@ -34,4 +34,41 @@ describe Clockwork::Event do
|
|
34
34
|
end
|
35
35
|
end
|
36
36
|
end
|
37
|
+
|
38
|
+
describe '#run_now?' do
|
39
|
+
before do
|
40
|
+
@manager = Class.new
|
41
|
+
@manager.stubs(:config).returns({})
|
42
|
+
end
|
43
|
+
|
44
|
+
describe 'event skip_first_run option set to true' do
|
45
|
+
it 'returns false on first attempt' do
|
46
|
+
event = Clockwork::Event.new(@manager, 1, nil, nil, :skip_first_run => true)
|
47
|
+
assert_equal false, event.run_now?(Time.now)
|
48
|
+
end
|
49
|
+
|
50
|
+
it 'returns true on subsequent attempts' do
|
51
|
+
event = Clockwork::Event.new(@manager, 1, nil, nil, :skip_first_run => true)
|
52
|
+
# first run
|
53
|
+
event.run_now?(Time.now)
|
54
|
+
|
55
|
+
# second run
|
56
|
+
assert_equal true, event.run_now?(Time.now + 1)
|
57
|
+
end
|
58
|
+
end
|
59
|
+
|
60
|
+
describe 'event skip_first_run option not set' do
|
61
|
+
it 'returns true on first attempt' do
|
62
|
+
event = Clockwork::Event.new(@manager, 1, nil, nil)
|
63
|
+
assert_equal true, event.run_now?(Time.now + 1)
|
64
|
+
end
|
65
|
+
end
|
66
|
+
|
67
|
+
describe 'event skip_first_run option set to false' do
|
68
|
+
it 'returns true on first attempt' do
|
69
|
+
event = Clockwork::Event.new(@manager, 1, nil, nil, :skip_first_run => false)
|
70
|
+
assert_equal true, event.run_now?(Time.now)
|
71
|
+
end
|
72
|
+
end
|
73
|
+
end
|
37
74
|
end
|
data/test/manager_test.rb
CHANGED
data/test/samples/signal_test.rb
CHANGED
data/test/signal_test.rb
CHANGED
metadata
CHANGED
@@ -1,15 +1,15 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: clockwork
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version:
|
4
|
+
version: 3.0.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Adam Wiggins
|
8
8
|
- tomykaira
|
9
|
-
autorequire:
|
9
|
+
autorequire:
|
10
10
|
bindir: bin
|
11
11
|
cert_chain: []
|
12
|
-
date:
|
12
|
+
date: 2021-12-07 00:00:00.000000000 Z
|
13
13
|
dependencies:
|
14
14
|
- !ruby/object:Gem::Dependency
|
15
15
|
name: tzinfo
|
@@ -39,20 +39,6 @@ dependencies:
|
|
39
39
|
- - ">="
|
40
40
|
- !ruby/object:Gem::Version
|
41
41
|
version: '0'
|
42
|
-
- !ruby/object:Gem::Dependency
|
43
|
-
name: bundler
|
44
|
-
requirement: !ruby/object:Gem::Requirement
|
45
|
-
requirements:
|
46
|
-
- - "~>"
|
47
|
-
- !ruby/object:Gem::Version
|
48
|
-
version: '1.3'
|
49
|
-
type: :development
|
50
|
-
prerelease: false
|
51
|
-
version_requirements: !ruby/object:Gem::Requirement
|
52
|
-
requirements:
|
53
|
-
- - "~>"
|
54
|
-
- !ruby/object:Gem::Version
|
55
|
-
version: '1.3'
|
56
42
|
- !ruby/object:Gem::Dependency
|
57
43
|
name: rake
|
58
44
|
requirement: !ruby/object:Gem::Requirement
|
@@ -137,6 +123,7 @@ extra_rdoc_files:
|
|
137
123
|
files:
|
138
124
|
- ".gitignore"
|
139
125
|
- ".travis.yml"
|
126
|
+
- CHANGELOG.md
|
140
127
|
- Gemfile
|
141
128
|
- LICENSE
|
142
129
|
- README.md
|
@@ -146,8 +133,9 @@ files:
|
|
146
133
|
- clockwork.gemspec
|
147
134
|
- clockworkd.1
|
148
135
|
- example.rb
|
149
|
-
- gemfiles/activesupport3.gemfile
|
150
136
|
- gemfiles/activesupport4.gemfile
|
137
|
+
- gemfiles/activesupport5.gemfile
|
138
|
+
- gemfiles/activesupport6.gemfile
|
151
139
|
- lib/clockwork.rb
|
152
140
|
- lib/clockwork/at.rb
|
153
141
|
- lib/clockwork/database_events.rb
|
@@ -172,7 +160,7 @@ homepage: http://github.com/Rykian/clockwork
|
|
172
160
|
licenses:
|
173
161
|
- MIT
|
174
162
|
metadata: {}
|
175
|
-
post_install_message:
|
163
|
+
post_install_message:
|
176
164
|
rdoc_options: []
|
177
165
|
require_paths:
|
178
166
|
- lib
|
@@ -187,9 +175,8 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
187
175
|
- !ruby/object:Gem::Version
|
188
176
|
version: '0'
|
189
177
|
requirements: []
|
190
|
-
|
191
|
-
|
192
|
-
signing_key:
|
178
|
+
rubygems_version: 3.2.22
|
179
|
+
signing_key:
|
193
180
|
specification_version: 4
|
194
181
|
summary: A scheduler process to replace cron.
|
195
182
|
test_files:
|