clockwork 1.3.1 → 2.0.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.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 66489a780e645c6b88fe4fe8548faaa80615d85c
4
- data.tar.gz: ad94d2f1a2f376d7f5931d177267b91ec6b69841
3
+ metadata.gz: 6614568ab73c78b0be1866b355ba1cd288cce5a6
4
+ data.tar.gz: a083d36f8fc30fb7b55f86278b1fd1e3577d4915
5
5
  SHA512:
6
- metadata.gz: 9b1409ea965916002991e9fd1a38d2453350994d027aa9b114a7f4feee4edb1a902ac07076c691d84e462fc9b697fe13989858f524184311d44d3717c7887aba
7
- data.tar.gz: 085f2739c059e90b8ea5875c0fb9b2eb161a7e09114cdd5db9a116a171fb5615db066278e65bfd641b78b1bac4cd77255438e8c27d94679d26bda66d4e2aa518
6
+ metadata.gz: dffa0ee3bcd26a2febaafebac063f71a46857001654b3748b292601f4134a9f64c0186b626bb72bc4c4d39eaec1a41e3c162d6ca5b64d53de248176854cd7915
7
+ data.tar.gz: 169d1db6499306e74dd86c89767e92818ffcc3d55873ac9dd04ddec9fe8b2d5648cb685e1dfbac4d3ad7bff4e467fcd2046e9c4cb0c680aef079906b354fd76a
data/README.md CHANGED
@@ -142,9 +142,9 @@ module Clockwork
142
142
  end
143
143
  ```
144
144
 
145
- This tells clockwork to fetch all `ClockworkDatabaseEvent` instances from the database, creating an internal clockwork event for each one, configured based on the instance's `frequency`, `at` and optionally `name` and `tz` methods. It 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).
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).
146
146
 
147
- When one of the events is ready to be run (based on it's `frequency`, `at` and possible `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 simply 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.
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.
148
148
 
149
149
  ### Your Model Classes
150
150
 
@@ -158,10 +158,14 @@ When one of the events is ready to be run (based on it's `frequency`, `at` and p
158
158
 
159
159
  - `frequency` returning the how frequently (in seconds) the database event should be run
160
160
 
161
- - `at` return nil or `''` if not using `:at`, or otherwise any acceptable clockwork `:at` string
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)
162
+
163
+ - (optionally) `at` return any acceptable clockwork `:at` string
162
164
 
163
165
  - (optionally) `name` returning the name for the event (used to identify it in the Clcockwork output)
164
166
 
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`)
168
+
165
169
  - (optionally) `tz` returning the timezone to use (default is the local timezone)
166
170
 
167
171
  #### Example Setup
@@ -220,6 +224,28 @@ end
220
224
  ...
221
225
  ```
222
226
 
227
+ #### Example use of `if?`
228
+
229
+ Database events support the ability to run events if certain conditions are met. This can be used to only run events on a given day, week, or month, or really any criteria you could conceive. Best of all, these criteria e.g. which day to
230
+ run it on can be attributes on your Model, and therefore change dynamically as you change the Model in the database.
231
+
232
+ So for example, if you had a Model that had a `day` and `month` integer attribute, you could specify that the Database event should only run on a particular day of a particular month as follows:
233
+
234
+ ```ruby
235
+ # app/models/clockwork_database_event.rb
236
+ class ClockworkDatabaseEvent < ActiveRecord::Base
237
+
238
+ ...
239
+
240
+ def if?(time)
241
+ time.day == day && time.month == month
242
+ end
243
+
244
+ ...
245
+ end
246
+ ```
247
+
248
+
223
249
  Event Parameters
224
250
  ----------
225
251
 
@@ -1,6 +1,6 @@
1
1
  Gem::Specification.new do |s|
2
2
  s.name = "clockwork"
3
- s.version = "1.3.1"
3
+ s.version = "2.0.0"
4
4
 
5
5
  s.authors = ["Adam Wiggins", "tomykaira"]
6
6
  s.license = 'MIT'
@@ -4,12 +4,13 @@ module Clockwork
4
4
 
5
5
  class Event < Clockwork::Event
6
6
 
7
- attr_accessor :event_store, :at
7
+ attr_accessor :event_store, :model_attributes
8
8
 
9
- def initialize(manager, period, job, block, event_store, options={})
9
+ def initialize(manager, period, job, block, event_store, model_attributes, options={})
10
10
  super(manager, period, job, block, options)
11
11
  @event_store = event_store
12
12
  @event_store.register(self, job)
13
+ @model_attributes = model_attributes
13
14
  end
14
15
 
15
16
  def name
@@ -14,9 +14,7 @@ module Clockwork
14
14
  def has_changed?(model)
15
15
  return true if event.nil?
16
16
 
17
- (has_name? && name != model.name) ||
18
- frequency != model.frequency ||
19
- ats != model_ats(model)
17
+ event.model_attributes != model.attributes
20
18
  end
21
19
 
22
20
  def unregister
@@ -27,33 +25,12 @@ module Clockwork
27
25
 
28
26
  attr_reader :events, :manager
29
27
 
28
+ # All events in the same collection (for a model instance) are equivalent
29
+ # so we can use any of them. Only their @at variable will be different,
30
+ # but we don't care about that here.
30
31
  def event
31
32
  events.first
32
33
  end
33
-
34
- def has_name?
35
- event.job_has_name?
36
- end
37
-
38
- def name
39
- event.name
40
- end
41
-
42
- def frequency
43
- event.frequency
44
- end
45
-
46
- def ats
47
- events.collect(&:at).compact
48
- end
49
-
50
- def model_ats(model)
51
- at_strings_for(model).collect{|at| At.parse(at) }
52
- end
53
-
54
- def at_strings_for(model)
55
- model.at.to_s.split(',').map(&:strip)
56
- end
57
34
  end
58
35
  end
59
36
  end
@@ -112,11 +112,16 @@ module Clockwork
112
112
  options = {
113
113
  :from_database => true,
114
114
  :synchronizer => self,
115
- :at => at_strings_for(model)
116
115
  }
117
116
 
117
+ options[:at] = at_strings_for(model) if model.respond_to?(:at)
118
+ options[:if] = ->(time){ model.if?(time) } if model.respond_to?(:if?)
118
119
  options[:tz] = model.tz if model.respond_to?(:tz)
119
120
 
121
+ # store the state of the model at time of registering so we can
122
+ # easily compare and determine if state has changed later
123
+ options[:model_attributes] = model.attributes
124
+
120
125
  options
121
126
  end
122
127
 
@@ -10,7 +10,11 @@ module Clockwork
10
10
 
11
11
  def register(period, job, block, options)
12
12
  @events << if options[:from_database]
13
- Clockwork::DatabaseEvents::Event.new(self, period, job, (block || handler), options.fetch(:synchronizer), options)
13
+ synchronizer = options.fetch(:synchronizer)
14
+ model_attributes = options.fetch(:model_attributes)
15
+
16
+ Clockwork::DatabaseEvents::Event.
17
+ new(self, period, job, (block || handler), synchronizer, model_attributes, options)
14
18
  else
15
19
  Clockwork::Event.new(self, period, job, block || handler, options)
16
20
  end
@@ -23,6 +23,10 @@ module ActiveRecordFake
23
23
  set_attribute_values_from_options options
24
24
  end
25
25
 
26
+ def attributes
27
+ Hash[instance_variables.map { |name| [name, instance_variable_get(name)] } ]
28
+ end
29
+
26
30
  module ClassMethods
27
31
  def create *args
28
32
  new *args
@@ -10,8 +10,6 @@ require_relative 'test_helpers'
10
10
  describe Clockwork::DatabaseEvents::Synchronizer do
11
11
  before do
12
12
  @now = Time.now
13
- DatabaseEventModel.delete_all
14
- DatabaseEventModel2.delete_all
15
13
 
16
14
  Clockwork.manager = @manager = Clockwork::DatabaseEvents::Manager.new
17
15
  class << @manager
@@ -21,6 +19,9 @@ describe Clockwork::DatabaseEvents::Synchronizer do
21
19
 
22
20
  after do
23
21
  Clockwork.clear!
22
+ DatabaseEventModel.delete_all
23
+ DatabaseEventModel2.delete_all
24
+ DatabaseEventModelWithIf.delete_all
24
25
  end
25
26
 
26
27
  describe "setup" do
@@ -254,6 +255,37 @@ describe Clockwork::DatabaseEvents::Synchronizer do
254
255
  end
255
256
  end
256
257
 
258
+ describe "with model that responds to `if?`" do
259
+
260
+ before do
261
+ @events_run = []
262
+ end
263
+
264
+ describe "when model.if? is true" do
265
+ it 'runs' do
266
+ DatabaseEventModelWithIf.create(:if_state => true, :frequency => 10)
267
+ setup_sync(model: DatabaseEventModelWithIf, :every => 1.minute, :events_run => @events_run)
268
+
269
+ tick_at(@now, :and_every_second_for => 9.seconds)
270
+
271
+ assert_equal 1, @events_run.length
272
+ end
273
+ end
274
+
275
+ describe "when model.if? is false" do
276
+ it 'does not run' do
277
+ DatabaseEventModelWithIf.create(:if_state => false, :frequency => 10, :name => 'model with if?')
278
+ setup_sync(model: DatabaseEventModelWithIf, :every => 1.minute, :events_run => @events_run)
279
+
280
+ tick_at(@now, :and_every_second_for => 1.minute)
281
+
282
+ # require 'byebug'
283
+ # byebug if events_run.length > 0
284
+ assert_equal 0, @events_run.length
285
+ end
286
+ end
287
+ end
288
+
257
289
  describe "with task that responds to `tz`" do
258
290
  before do
259
291
  @events_run = []
@@ -55,4 +55,17 @@ end
55
55
  class DatabaseEventModelWithoutName
56
56
  include ActiveRecordFake
57
57
  attr_accessor :frequency, :at
58
+ end
59
+
60
+ class DatabaseEventModelWithIf
61
+ include ActiveRecordFake
62
+ attr_accessor :name, :frequency, :at, :tz, :if_state
63
+
64
+ def name
65
+ @name || "#{self.class}:#{id}"
66
+ end
67
+
68
+ def if?(time)
69
+ @if_state
70
+ end
58
71
  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: 1.3.1
4
+ version: 2.0.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Adam Wiggins