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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
- SHA1:
3
- metadata.gz: 8b02d894da4c82ef8a9799121d77b83390b0a27f
4
- data.tar.gz: 7f70396d6f476bf30e3c8f7b1e82c66da165afb5
2
+ SHA256:
3
+ metadata.gz: 81357fe2cd463fcf64f263400fd180f02a2c6e14fc281c32cd5098dbe6971487
4
+ data.tar.gz: 2eec51851477a00654c88adaa7b5e4b5abac252fa808957d1f3cfafda49572f4
5
5
  SHA512:
6
- metadata.gz: 12574d7a801709ee5bc6d0215eab7c1c7fe8cfe227f641bee7a8d01c2f805eb6b5043b6ad052f5e4f97c12734b0ad575c8095b163a4ce39075c4dcda92f06aa6
7
- data.tar.gz: 1bb1cea7c8346e9dcf98b76d582c5a54802fe1769ab1065fb8aaa1396767fb627040b7a9486daad52036bdc05eb6d3debfd15761a8fa500ba2e488a3379825df
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
- - 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.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.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.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 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,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`, `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
156
+ 1. the class responds to `all` returning an array of instances from the database
154
157
 
155
- 2. the instances returned respond to:
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
- - `id` returning a unique identifier (this is needed to track changes to event settings)
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
- - `frequency` returning the how frequently (in seconds) the database event should be run
164
+ - `at` *(optional)* return any acceptable clockwork `:at` string
160
165
 
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)
166
+ - `name` *(optional)* returning the name for the event (used to identify it in the Clockwork output)
162
167
 
163
- - (optionally) `at` return any acceptable clockwork `:at` string
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
- - (optionally) `name` returning the name for the event (used to identify it in the Clockwork output)
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
- - (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`)
172
+ - `tz` *(optional)* returning the timezone to use (default is the local timezone)
168
173
 
169
- - (optionally) `tz` returning the timezone to use (default is the local timezone)
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](http://tzinfo.rubyforge.org/)
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 · tomykaira/clockwork](https://github.com/tomykaira/clockwork/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
- - [Sending errors to Airbrake](https://github.com/tomykaira/clockwork/issues/58)
547
- - [Read events from a database](https://github.com/tomykaira/clockwork/issues/25)
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
- http://github.com/tomykaira/clockwork
609
+ 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.1"
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
- platforms :rbx do
4
- gem 'rubysl', '~> 2.0'
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=>"../"
@@ -0,0 +1,5 @@
1
+ source 'https://rubygems.org'
2
+
3
+ gem 'activesupport', '~> 5.0'
4
+ gem 'minitest', '~> 5.0'
5
+ gemspec :path=>"../"
@@ -0,0 +1,5 @@
1
+ source 'https://rubygems.org'
2
+
3
+ gem 'activesupport', '~> 6.0'
4
+ gem 'minitest', '~> 5.0'
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
- 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,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
@@ -1,5 +1,3 @@
1
- require_relative '../database_events'
2
-
3
1
  module Clockwork
4
2
 
5
3
  module DatabaseEvents
@@ -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?
@@ -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')
@@ -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{ |event| event.run_now?(t) }
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
@@ -1,4 +1,5 @@
1
1
  require 'logger'
2
+ require 'active_support'
2
3
  require 'active_support/time'
3
4
 
4
5
  require 'clockwork/at'
data/test/at_test.rb CHANGED
@@ -1,6 +1,6 @@
1
1
  require File.expand_path('../../lib/clockwork', __FILE__)
2
2
  require "minitest/autorun"
3
- require 'mocha/setup'
3
+ require 'mocha/minitest'
4
4
  require 'time'
5
5
  require 'active_support/time'
6
6
 
@@ -1,6 +1,6 @@
1
1
  require File.expand_path('../../lib/clockwork', __FILE__)
2
2
  require 'minitest/autorun'
3
- require 'mocha/setup'
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
@@ -1,6 +1,7 @@
1
1
  require "minitest/autorun"
2
2
  require 'clockwork/database_events/event_store'
3
3
  require 'clockwork/database_events/event_collection'
4
+ require 'ostruct'
4
5
 
5
6
  describe Clockwork::DatabaseEvents::EventStore do
6
7
 
@@ -28,8 +28,8 @@ module ActiveRecordFake
28
28
  end
29
29
 
30
30
  module ClassMethods
31
- def create *args
32
- new *args
31
+ def create(*args)
32
+ new(*args)
33
33
  end
34
34
 
35
35
  def delete_all
@@ -1,5 +1,5 @@
1
1
  require "minitest/autorun"
2
- require 'mocha/setup'
2
+ require 'mocha/minitest'
3
3
  require 'time'
4
4
  require 'active_support/time'
5
5
 
@@ -36,19 +36,35 @@ end
36
36
 
37
37
  class DatabaseEventModel
38
38
  include ActiveRecordFake
39
- attr_accessor :name, :frequency, :at, :tz
39
+ attr_accessor :frequency, :at, :tz
40
40
 
41
41
  def name
42
- @name || "#{self.class}:#{id}"
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 :name, :frequency, :at, :tz
56
+ attr_accessor :frequency, :at, :tz
49
57
 
50
58
  def name
51
- @name || "#{self.class}:#{id}"
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 :name, :frequency, :at, :tz, :if_state
78
+ attr_accessor :frequency, :at, :tz, :if_state
63
79
 
64
80
  def name
65
- @name || "#{self.class}:#{id}"
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
@@ -1,6 +1,6 @@
1
1
  require File.expand_path('../../lib/clockwork', __FILE__)
2
2
  require "minitest/autorun"
3
- require 'mocha/setup'
3
+ require 'mocha/minitest'
4
4
  require 'time'
5
5
  require 'active_support/time'
6
6
 
@@ -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__)
data/test/signal_test.rb CHANGED
@@ -1,5 +1,5 @@
1
1
  require 'test/unit'
2
- require 'mocha/setup'
2
+ require 'mocha/minitest'
3
3
  require 'fileutils'
4
4
 
5
5
  class SignalTest < Test::Unit::TestCase
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: 2.0.1
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: 2017-02-15 00:00:00.000000000 Z
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
- rubyforge_project:
191
- rubygems_version: 2.5.1
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:
@@ -1,10 +0,0 @@
1
- source 'https://rubygems.org'
2
-
3
- platforms :rbx do
4
- gem 'rubysl', '~> 2.0'
5
- gem 'rubysl-test-unit'
6
- gem 'rubinius-developer_tools'
7
- end
8
-
9
- gem 'activesupport', '~> 3.2.14'
10
- gemspec :path=>"../"