clockwork 2.0.2 → 2.0.4

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
- SHA1:
3
- metadata.gz: 28995c167b599267520fc42d5c489da9cf3ea3a7
4
- data.tar.gz: c185ef12635ae8fcaaf300edb133adf86e3d9ac6
2
+ SHA256:
3
+ metadata.gz: 7ad11e2b8e79db572d4240dd9ce2065067b22514919d4debc3758065b438ebca
4
+ data.tar.gz: 5dec51edf5bbd101a002e8c6ede3f11918441d75281b2baff3091bc0995721c4
5
5
  SHA512:
6
- metadata.gz: 6311c6f7d6dd160c2b5beb6cad59c87c571d7ec50e54bb50e3c8cbb656ae2fb756168a404d143ed699772c334ab2323681202509cbb9d740f954ce23bca61725
7
- data.tar.gz: c4c3b8f20fdc6da06dc73ea4f0de9ab798dfb2e8e7716777952c51bbf9a3c88fb6df5841e979ac180dbb1d4f326f3bdc78ecd7bf5e13a487fce250f3a79809ec
6
+ metadata.gz: f06770eaf4eb2b473ee165a00ddf7b6326f957ccfbf1eb71ee65a3e4a840ea8a42fe052a52a7032f7b786677bad54e94bc58a7f3961a44bb404c16685dcddc48
7
+ data.tar.gz: 5a60bddb9ae7b7312e8df9a4b01a022d9072a3a4f2fdb7f5790f03a61cf8b31a0d6fc4a76c3b80abeee63eeb269447922b2c065982497f2d6f7becd33082f78e
data/.travis.yml CHANGED
@@ -1,14 +1,18 @@
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
- - 1.9.3
6
- - 2.0.0
7
- - 2.1
8
- - 2.2
9
- - ruby-2.3.1
10
- - jruby-19mode
11
- - # rbx-2.2.7
11
+ - 2.3.8
12
+ - 2.4.5
13
+ - 2.5.3
14
+ - jruby-9.1.17.0
15
+ - jruby-9.2.6.0
12
16
  gemfile:
13
- - gemfiles/activesupport3.gemfile
14
17
  - gemfiles/activesupport4.gemfile
18
+ - gemfiles/activesupport5.gemfile
data/CHANGELOG.md ADDED
@@ -0,0 +1,9 @@
1
+ ## 2.0.4 ##
2
+
3
+ * Reverts the breaking changes in PR #18 that went out in patch 2.0.3
4
+
5
+ *Javier Julio*
6
+
7
+ ## 2.0.3 (February 15, 2018) ##
8
+
9
+ * [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.org/Rykian/clockwork.png?branch=master)](https://travis-ci.org/Rykian/clockwork) [![Dependency Status](https://gemnasium.com/Rykian/clockwork.png)](https://gemnasium.com/Rykian/clockwork)
1
+ Clockwork - a clock process to replace cron [![Build Status](https://api.travis-ci.org/Rykian/clockwork.png?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 to use [clockwork-init.sh](https://gist.github.com/1312172) to create
62
- a new project for heroku.
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,31 @@ 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`, `name`, `if?` 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).
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?` 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.
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
- 1. the class responds to `all` returning an array of instances from the database
154
-
155
- 2. the instances returned respond to:
156
+ 1. the class responds to `all` returning an array of instances from the database
156
157
 
157
- - `id` returning a unique identifier (this is needed to track changes to event settings)
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
158
161
 
159
- - `frequency` returning the how frequently (in seconds) the database event should be run
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)
160
163
 
161
- - `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)
164
+ - `at` *(optional)* return any acceptable clockwork `:at` string
162
165
 
163
- - (optionally) `at` return any acceptable clockwork `:at` string
166
+ - `name` *(optional)* returning the name for the event (used to identify it in the Clockwork output)
164
167
 
165
- - (optionally) `name` returning the name for the event (used to identify it in the Clockwork output)
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`)
166
169
 
167
- - (optionally) `if?` 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`)
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
168
171
 
169
- - (optionally) `tz` returning the timezone to use (default is the local timezone)
172
+ - `tz` *(optional)* returning the timezone to use (default is the local timezone)
170
173
 
171
174
  #### Example Setup
172
175
 
@@ -245,6 +248,28 @@ class ClockworkDatabaseEvent < ActiveRecord::Base
245
248
  end
246
249
  ```
247
250
 
251
+ #### Example use of `ignored_attributes`
252
+
253
+ 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.
254
+
255
+ 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.
256
+
257
+ 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:
258
+
259
+ ```ruby
260
+ # app/models/clockwork_database_event.rb
261
+ class ClockworkDatabaseEvent < ActiveRecord::Base
262
+
263
+ ...
264
+
265
+ def ignored_attributes
266
+ [ :last_scheduled_at ]
267
+ end
268
+
269
+ ...
270
+ end
271
+ ```
272
+
248
273
 
249
274
  Event Parameters
250
275
  ----------
@@ -305,7 +330,8 @@ If this is a problem, please use the `:thread` option to prevent the long runnin
305
330
  ```ruby
306
331
  every(1.day, 'reminders.send', :at => '00:00', :tz => 'UTC')
307
332
  # Runs the job each day at midnight, UTC.
308
- # The value for :tz can be anything supported by [TZInfo](http://tzinfo.rubyforge.org/)
333
+ # The value for :tz can be anything supported by [TZInfo](https://github.com/tzinfo/tzinfo)
334
+ # Using the 'tzinfo' gem, run TZInfo::Timezone.all_identifiers to get a list of acceptable identifiers.
309
335
  ```
310
336
 
311
337
  ### :if
@@ -341,6 +367,19 @@ Clockwork.every(1.day, 'run.me.in.new.thread', :thread => true)
341
367
 
342
368
  If a job is long-running or IO-intensive, this option helps keep the clock precise.
343
369
 
370
+ ### :skip_first_run
371
+
372
+ Normally, a clockwork process that is defined to run in a specified period will run at startup.
373
+ This is sometimes undesired behaviour, if the action being run relies on other processes booting which may be slower than clock.
374
+ To avoid this problem, `:skip_first_run` can be used.
375
+
376
+ ```ruby
377
+ Clockwork.every(5.minutes, 'myjob', :skip_first_run => true)
378
+ ```
379
+
380
+ The above job will not run at initial boot, and instead run every 5 minutes after boot.
381
+
382
+
344
383
  Configuration
345
384
  -----------------------
346
385
 
@@ -357,7 +396,6 @@ Clockwork wakes up once a second and performs its duties. To change the number o
357
396
  sleeps, set the `sleep_timeout` configuration option as shown below in the example.
358
397
 
359
398
  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
399
 
362
400
  ### :tz
363
401
 
@@ -524,10 +562,17 @@ clockworkd -c YOUR_CLOCK.rb start
524
562
 
525
563
  For more details, you can run `clockworkd -h`.
526
564
 
565
+ Integration Testing
566
+ -------------------
567
+
568
+ You could take a look at:
569
+ * [clockwork-mocks](https://github.com/dpoetzsch/clockwork-mocks) that helps with running scheduled tasks during integration testing.
570
+ * [clockwork-test](https://github.com/kevin-j-m/clockwork-test) which ensures that tasks are triggered at the right time
571
+
527
572
  Issues and Pull requests
528
573
  ------------------------
529
574
 
530
- If you find a bug, please create an issue - [Issues · tomykaira/clockwork](https://github.com/tomykaira/clockwork/issues).
575
+ If you find a bug, please create an issue - [Issues · Rykian/clockwork](https://github.com/Rykian/clockwork/issues).
531
576
 
532
577
  For a bug fix or a feature request, please send a pull-request.
533
578
  Do not forget to add tests to show how your feature works, or what bug is fixed.
@@ -543,8 +588,8 @@ Use cases
543
588
 
544
589
  Feel free to add your idea or experience and send a pull-request.
545
590
 
546
- - [Sending errors to Airbrake](https://github.com/tomykaira/clockwork/issues/58)
547
- - [Read events from a database](https://github.com/tomykaira/clockwork/issues/25)
591
+ - Sending errors to Airbrake
592
+ - Read events from a database
548
593
 
549
594
  Meta
550
595
  ----
@@ -559,4 +604,4 @@ Patches contributed by Mark McGranaghan and Lukáš Konarovský
559
604
 
560
605
  Released under the MIT License: http://www.opensource.org/licenses/mit-license.php
561
606
 
562
- http://github.com/tomykaira/clockwork
607
+ https://github.com/Rykian/clockwork
data/bin/clockwork CHANGED
@@ -4,7 +4,7 @@ STDERR.sync = STDOUT.sync = true
4
4
 
5
5
  require 'clockwork'
6
6
 
7
- usage = 'clockwork <clock.rb>'
7
+ usage = 'Usage: clockwork <clock.rb>'
8
8
  file = ARGV.shift or abort usage
9
9
 
10
10
  file = "./#{file}" unless file.match(/^[\/.]/)
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].match(/^[\/.]/)
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 = "2.0.2"
3
+ s.version = "2.0.4"
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"
@@ -6,6 +6,6 @@ platforms :rbx do
6
6
  gem 'rubinius-developer_tools'
7
7
  end
8
8
 
9
- gem 'activesupport', '~> 4.0.0'
10
- gem 'minitest', '~> 4.2'
9
+ gem 'activesupport', '~> 4.2'
10
+ gem 'minitest', '~> 5.0'
11
11
  gemspec :path=>"../"
@@ -6,5 +6,6 @@ platforms :rbx do
6
6
  gem 'rubinius-developer_tools'
7
7
  end
8
8
 
9
- gem 'activesupport', '~> 3.2.14'
9
+ gem 'activesupport', '~> 5.0'
10
+ gem 'minitest', '~> 5.0'
10
11
  gemspec :path=>"../"
@@ -14,7 +14,14 @@ module Clockwork
14
14
  def has_changed?(model)
15
15
  return true if event.nil?
16
16
 
17
- event.model_attributes != model.attributes
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,19 @@ 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)
120
122
 
121
123
  # store the state of the model at time of registering so we can
122
124
  # easily compare and determine if state has changed later
123
- options[:model_attributes] = model.attributes
125
+ options[:model_attributes] = model.attributes.select do |k, v|
126
+ not options[:ignored_attributes].include?(k.to_sym)
127
+ end
124
128
 
125
129
  options
126
130
  end
@@ -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
- elapsed_ready(t) and (@at.nil? or @at.ready?(t)) and (@if.nil? or @if.call(t))
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?
@@ -57,10 +61,18 @@ module Clockwork
57
61
  @manager.handle_error e
58
62
  end
59
63
 
60
- def elapsed_ready(t)
64
+ def elapsed_ready?(t)
61
65
  @last.nil? || (t - @last.to_i).to_i >= @period
62
66
  end
63
67
 
68
+ def run_at?(t)
69
+ @at.nil? || @at.ready?(t)
70
+ end
71
+
72
+ def run_if?(t)
73
+ @if.nil? || @if.call(t)
74
+ end
75
+
64
76
  def validate_if_option(if_option)
65
77
  if if_option && !if_option.respond_to?(:call)
66
78
  raise ArgumentError.new(':if expects a callable object, but #{if_option} does not respond to call')
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
@@ -1,4 +1,5 @@
1
1
  require 'clockwork'
2
+ require 'active_support/time'
2
3
 
3
4
  module Clockwork
4
5
  LOGFILE = File.expand_path('../../tmp/signal_test.log', __FILE__)
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: 2.0.2
4
+ version: 2.0.4
5
5
  platform: ruby
6
6
  authors:
7
7
  - Adam Wiggins
@@ -9,7 +9,7 @@ authors:
9
9
  autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
- date: 2017-03-18 00:00:00.000000000 Z
12
+ date: 2019-07-25 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,8 @@ 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
151
138
  - lib/clockwork.rb
152
139
  - lib/clockwork/at.rb
153
140
  - lib/clockwork/database_events.rb
@@ -188,7 +175,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
188
175
  version: '0'
189
176
  requirements: []
190
177
  rubyforge_project:
191
- rubygems_version: 2.5.1
178
+ rubygems_version: 2.7.6
192
179
  signing_key:
193
180
  specification_version: 4
194
181
  summary: A scheduler process to replace cron.