clockwork 0.7.2 → 0.7.3

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: b89afd90ad2ece3d2dab28742a2f463deb786754
4
- data.tar.gz: cd50508469046e76e210aeb219e66aa553a0febd
3
+ metadata.gz: fae14bd8566db2cb7c3be8c5c9625b01dc66ae00
4
+ data.tar.gz: ecbed0c0a9cf6017a0e62f62da9cfb67112624da
5
5
  SHA512:
6
- metadata.gz: 4dc13ede6fad5c5bd63a9755ec0b6816da426321d4de3ef3a20db5271b22db00eb437aaf93057026bd189f608906fd08701dad9241e4e2da971fde79f1657894
7
- data.tar.gz: a264b85a81b8f4363f38f811a0077bb9fb255497dca480324ab3f2decf17e290c0092e99a4c19d23728663668c32185353bab050add94797c34964ab61cee499
6
+ metadata.gz: c75686b464777f74d87ca6b15d3ac1d57ee83f190e22d32c6b585fecb86c5192575f90d6151588e9454f7d3f8054bd1c63f3fa4d6a3a067f1d93bbd10a14fe4a
7
+ data.tar.gz: c68c69e967a99422394197ed570c2c0ce0968e73a7495ec44a55158b99a6c6450a84fd3160d4707d95c5385ddc00b584f4fb350a6b0566b44222f8201215c504
data/README.md CHANGED
@@ -103,6 +103,120 @@ every(1.hour, 'feeds.refresh') { Feed.send_later(:refresh) }
103
103
  every(1.day, 'reminders.send', :at => '01:30') { Reminder.send_later(:send_reminders) }
104
104
  ```
105
105
 
106
+ Use with database tasks
107
+ -----------------------
108
+
109
+ You can dynamically add tasks from a database to be scheduled along with the regular events in clock.rb.
110
+
111
+ To do this, use the `sync_database_tasks` method call:
112
+
113
+ ```ruby
114
+ require 'clockwork'
115
+ require 'clockwork/manager_with_database_tasks'
116
+ require_relative './config/boot'
117
+ require_relative './config/environment'
118
+
119
+ module Clockwork
120
+
121
+ # required to enable database syncing support
122
+ Clockwork.manager = ManagerWithDatabaseTasks.new
123
+
124
+ sync_database_tasks model: MyScheduledTask, every: 1.minute do |instance_job_name|
125
+ # Where your model will acts as a worker:
126
+ id = instance_job_name.split(':').last
127
+ task = MyScheduledTask.find(id)
128
+ task.perform_async
129
+
130
+ # Or, e.g. if your queue system just needs job names
131
+ # Stalker.enqueue(instance_job_name)
132
+ end
133
+
134
+ [...other tasks if you have...]
135
+
136
+ end
137
+ ```
138
+
139
+ This tells clockwork to fetch all MyScheduledTask instances from the database, and create an event for each, configured based on the instances' `frequency`, `name`, and `at` methods. It also says to reload the tasks from the database every 1.minute - we need to frequently do this as they could have changed (but you can choose a sensible reload frequency by changing the `every:` option). Note that the database sync event will always run on the minute-boundary (i.e. HH:MM::00), and that events which have been synced from the database won't be run in that same clock cycle (this prevents a task from the database being run twice).
140
+
141
+ Rails ActiveRecord models are a perfect candidate for the model class, but you could use something else. The only requirements are:
142
+
143
+ 1. the class responds to `all` returning an array of instances from the database
144
+ 2. the instances returned respond to:
145
+ `frequency` returning the how frequently (in seconds) the database task should be run
146
+ `name` returning the task's job name (this is what gets passed into the block above)
147
+ `at` return nil or '' if not using :at, or any acceptable clockwork :at string
148
+
149
+ Here's an example of one way of setting up your ActiveRecord models, using Sidekiq for background tasks, and making the model class a worker:
150
+
151
+ ```ruby
152
+ # db/migrate/20140302220659_create_frequency_periods.rb
153
+ class CreateFrequencyPeriods < ActiveRecord::Migration
154
+ def change
155
+ create_table :frequency_periods do |t|
156
+ t.string :name
157
+
158
+ t.timestamps
159
+ end
160
+ end
161
+ end
162
+
163
+ # 20140302221102_create_my_scheduled_tasks.rb
164
+ class CreateMyScheduledTasks < ActiveRecord::Migration
165
+ def change
166
+ create_table :my_scheduled_tasks do |t|
167
+ t.integer :frequency_quantity
168
+ t.references :frequency_period
169
+ t.string :at
170
+
171
+ t.timestamps
172
+ end
173
+ add_index :my_scheduled_tasks, :frequency_period_id
174
+ end
175
+ end
176
+
177
+ # app/models/my_scheduled_task.rb
178
+ class MyScheduledTask < ActiveRecord::Base
179
+ include Sidekiq::Worker
180
+
181
+ belongs_to :frequency_period
182
+ attr_accessible :frequency_quantity, :frequency_period_id, :at
183
+
184
+ # Used by clockwork to schedule how frequently this task should be run
185
+ # Should be the intended number of seconds between executions
186
+ def frequency
187
+ frequency_quantity.send(frequency_period.name.pluralize)
188
+ end
189
+
190
+ # Used by clockwork to name this task internally for its logging
191
+ # Should return a reference for this task to be used in clockwork
192
+ # Include the instance ID if you want to be able to retrieve the
193
+ # model instance inside the sync_database_tasks block in clock.rb
194
+ def name
195
+ "Database_MyScheduledTask:#{id}"
196
+ end
197
+
198
+ # Method required by Sidekiq
199
+ def perform
200
+ # the task that will be performed in the background
201
+ end
202
+ end
203
+
204
+ # app/models/frequency_period.rb
205
+ class FrequencyPeriod < ActiveRecord::Base
206
+ attr_accessible :name
207
+ end
208
+
209
+ # db/seeds.rb
210
+ ...
211
+ # creating the FrequencyPeriods
212
+ [:second, :minute, :hour, :day, :week, :month].each do |period|
213
+ FrequencyPeriod.create(name: period)
214
+ end
215
+ ...
216
+ ```
217
+
218
+ You could, of course, create a separate Sidekiq or DelayedJob worker class under app/workers, and simply use the model referenced by clockwork to trigger that worker to run asynchronously.
219
+
106
220
  Event Parameters
107
221
  ----------
108
222
 
@@ -324,6 +438,16 @@ on(:after_tick) do
324
438
  end
325
439
  ```
326
440
 
441
+ Finally, you can use tasks synchronised from a database as described in detail above:
442
+
443
+ ```ruby
444
+ sync_database_tasks model: MyScheduledTask, every: 1.minute do |instance_job_name|
445
+ # what to do with each instance
446
+ end
447
+ ```
448
+
449
+ You can use multiple `sync_database_tasks` if you wish, so long as you use different model classes for each (ActiveRecord Single Table Inheritance could be a good idea if you're doing this).
450
+
327
451
  In production
328
452
  -------------
329
453
 
@@ -1,6 +1,6 @@
1
1
  Gem::Specification.new do |s|
2
2
  s.name = "clockwork"
3
- s.version = "0.7.2"
3
+ s.version = "0.7.3"
4
4
 
5
5
  s.authors = ["Adam Wiggins", "tomykaira"]
6
6
  s.license = 'MIT'
@@ -0,0 +1,87 @@
1
+ module Clockwork
2
+
3
+ module Methods
4
+ def sync_database_tasks(options={}, &block)
5
+ Clockwork.manager.sync_database_tasks(options, &block)
6
+ end
7
+ end
8
+
9
+ extend Methods
10
+
11
+ class ManagerWithDatabaseTasks < Manager
12
+
13
+ SECOND_TO_RUN_DATABASE_SYNC_AT = 0
14
+
15
+ def initialize
16
+ super
17
+ @events_from_database = []
18
+ @next_sync_database_tasks_identifier = 0
19
+ end
20
+
21
+ def sync_database_tasks(options={}, &block)
22
+ [:model, :every].each do |option|
23
+ raise ArgumentError.new("requires :#{option} option") unless options.include?(option)
24
+ end
25
+ raise ArgumentError.new(":every must be greater or equal to 1.minute") if options[:every] < 1.minute
26
+
27
+ model = options[:model]
28
+ frequency = options[:every]
29
+ sync_task_id = get_sync_task_id
30
+
31
+ # Prevent database tasks from running in same cycle as the database sync,
32
+ # as this can lead to the same task being run twice
33
+ options_to_run_database_sync_in_own_cycle = { :if => lambda { |t| t.sec == SECOND_TO_RUN_DATABASE_SYNC_AT } }
34
+
35
+ # create event that syncs clockwork events with database events
36
+ every frequency, "sync_database_tasks_for_model_#{model}", options_to_run_database_sync_in_own_cycle do
37
+ reload_events_from_database sync_task_id, model, &block
38
+ end
39
+ end
40
+
41
+
42
+ protected
43
+
44
+ # sync_task_id's are used to group the database events from a particular sync_database_tasks call
45
+ # This method hands out the ids, incrementing the id to keep them unique.
46
+ def get_sync_task_id
47
+ current_sync_task_id = @next_sync_database_tasks_identifier
48
+ @next_sync_database_tasks_identifier += 1
49
+ current_sync_task_id
50
+ end
51
+
52
+ def reload_events_from_database(sync_task_id, model, &block)
53
+ @events_from_database[sync_task_id] = []
54
+
55
+ model.all.each do |db_task|
56
+ options = { from_database: true, :sync_task_id => sync_task_id }
57
+ options[:at] = db_task.at.split(',') unless db_task.at.blank?
58
+
59
+ # If database tasks can be scheduled in same clock cycle that database syncs occur
60
+ # then previous copy of database sync task will be stored and set to run (in #tick events variable)
61
+ # *before* we then delete all database tasks. This causes the task to be run at HH:00 (previous copy)
62
+ # and at HH:01 (newly fetched copy).
63
+ option_to_prevent_database_tasks_running_in_same_cycle_as_sync = { :if => lambda{|t| t.sec != SECOND_TO_RUN_DATABASE_SYNC_AT } }
64
+ every db_task.frequency,
65
+ db_task.name,
66
+ options.merge(option_to_prevent_database_tasks_running_in_same_cycle_as_sync),
67
+ &block
68
+ end
69
+ end
70
+
71
+ private
72
+
73
+ def events_to_run(t)
74
+ (@events + @events_from_database.flatten).select{|event| event.run_now?(t) }
75
+ end
76
+
77
+ def register(period, job, block, options)
78
+ event = Event.new(self, period, job, block || handler, options)
79
+ if options[:from_database]
80
+ @events_from_database[options[:sync_task_id]] << event
81
+ else
82
+ @events << event
83
+ end
84
+ event
85
+ end
86
+ end
87
+ end
@@ -0,0 +1,190 @@
1
+ require File.expand_path('../../lib/clockwork', __FILE__)
2
+ require 'clockwork/manager_with_database_tasks'
3
+ require 'rubygems'
4
+ require 'contest'
5
+ require 'mocha/setup'
6
+ require 'time'
7
+ require 'active_support/time'
8
+
9
+ class ManagerWithDatabaseTasksTest < Test::Unit::TestCase
10
+
11
+ class ScheduledTask; end
12
+ class ScheduledTaskType2; end
13
+
14
+ setup do
15
+ @manager = Clockwork::ManagerWithDatabaseTasks.new
16
+ class << @manager
17
+ def log(msg); end
18
+ end
19
+ @manager.handler { }
20
+ end
21
+
22
+ def tick_at(now = Time.now, options = {})
23
+ seconds_to_tick_for = options[:and_every_second_for] || 0
24
+ number_of_ticks = seconds_to_tick_for + 1 # add one for right now
25
+ number_of_ticks.times{|i| @manager.tick(now + i) }
26
+ end
27
+
28
+ def next_minute(now = Time.now)
29
+ Time.new(now.year, now.month, now.day, now.hour, now.min + 1, 0)
30
+ end
31
+
32
+ describe "sync_database_tasks" do
33
+
34
+ describe "arguments" do
35
+
36
+ def test_does_not_raise_error_with_valid_arguments
37
+ @manager.sync_database_tasks(model: ScheduledTask, every: 1.minute) {}
38
+ end
39
+
40
+ def test_raises_argument_error_if_param_called_model_is_not_set
41
+ assert_raises ArgumentError do
42
+ @manager.sync_database_tasks(model: ScheduledTask) {}
43
+ end
44
+ end
45
+
46
+ def test_raises_argument_error_if_param_called_every_is_not_set
47
+ assert_raises ArgumentError do
48
+ @manager.sync_database_tasks(every: 1.minute) {}
49
+ end
50
+ end
51
+
52
+ def test_raises_argument_error_if_param_called_every_is_less_than_1_minute
53
+ assert_raises ArgumentError do
54
+ @manager.sync_database_tasks(model: ScheduledTask, every: 59.seconds) {}
55
+ end
56
+ end
57
+ end
58
+
59
+ setup do
60
+ @tasks_run = []
61
+ @scheduled_task1 = stub(:frequency => 10, :name => 'ScheduledTask:1', :at => nil)
62
+ @scheduled_task2 = stub(:frequency => 10, :name => 'ScheduledTask:2', :at => nil)
63
+ @scheduled_task1_modified = stub(:frequency => 5, :name => 'ScheduledTaskModified:1', :at => nil)
64
+ ScheduledTask.stubs(:all).returns([@scheduled_task1])
65
+
66
+ @database_reload_frequency = 1.minute
67
+
68
+ @now = Time.now
69
+ @next_minute = next_minute(@now) # database sync task only happens on minute boundary
70
+
71
+ # setup the database sync
72
+ @manager.sync_database_tasks model: ScheduledTask, every: @database_reload_frequency do |job_name|
73
+ @tasks_run << job_name
74
+ end
75
+ end
76
+
77
+ def test_does_not_fetch_database_tasks_until_next_minute
78
+ seconds_upto_and_including_next_minute = (@next_minute - @now).seconds.to_i + 1
79
+ tick_at(@now, :and_every_second_for => seconds_upto_and_including_next_minute)
80
+ assert_equal [], @tasks_run
81
+ end
82
+
83
+ def test_fetches_and_registers_database_task
84
+ tick_at(@next_minute, :and_every_second_for => 1.second)
85
+ assert_equal ["ScheduledTask:1"], @tasks_run
86
+ end
87
+
88
+ def test_multiple_database_tasks_can_be_registered
89
+ ScheduledTask.stubs(:all).returns([@scheduled_task1, @scheduled_task2])
90
+ tick_at(@next_minute, :and_every_second_for => 1.second)
91
+ assert_equal ["ScheduledTask:1", "ScheduledTask:2"], @tasks_run
92
+ end
93
+
94
+ def test_database_task_does_not_run_again_before_frequency_specified_in_database
95
+ tick_at(@next_minute, :and_every_second_for => 9.seconds) # runs at 1
96
+ assert_equal 1, @tasks_run.length
97
+ end
98
+
99
+ def test_database_task_runs_repeatedly_with_frequency_specified_in_database
100
+ tick_at(@next_minute, :and_every_second_for => 21.seconds) # runs at 1, 11, and 21
101
+ assert_equal 3, @tasks_run.length
102
+ end
103
+
104
+ def test_reloads_tasks_from_database
105
+ ScheduledTask.stubs(:all).returns([@scheduled_task1], [@scheduled_task2])
106
+ tick_at(@next_minute, :and_every_second_for => @database_reload_frequency.seconds)
107
+ @manager.tick # @scheduled_task2 should run immediately on next tick (then every 10 seconds)
108
+
109
+ assert_equal "ScheduledTask:2", @tasks_run.last
110
+ end
111
+
112
+ def test_reloaded_tasks_run_repeatedly
113
+ ScheduledTask.stubs(:all).returns([@scheduled_task1], [@scheduled_task2])
114
+ tick_at(@next_minute, :and_every_second_for => @database_reload_frequency.seconds + 11.seconds)
115
+ assert_equal ["ScheduledTask:2", "ScheduledTask:2"], @tasks_run[-2..-1]
116
+ end
117
+
118
+ def test_stops_running_deleted_database_task
119
+ ScheduledTask.stubs(:all).returns([@scheduled_task1], [])
120
+ tick_at(@next_minute, :and_every_second_for => @database_reload_frequency.seconds)
121
+ before = @tasks_run.dup
122
+
123
+ # tick through reload, and run for enough ticks that previous task would have run
124
+ tick_at(@next_minute + @database_reload_frequency.seconds + 20.seconds)
125
+ after = @tasks_run
126
+
127
+ assert_equal before, after
128
+ end
129
+
130
+ def test_reloading_task_with_modified_frequency_will_run_with_new_frequency
131
+ ScheduledTask.stubs(:all).returns([@scheduled_task1], [@scheduled_task1_modified])
132
+
133
+ tick_at(@next_minute, :and_every_second_for => 66.seconds)
134
+
135
+ # task1 runs at: 1, 11, 21, 31, 41, 51 (6 runs)
136
+ # database tasks are reloaded at: 60
137
+ # task1_modified runs at: 61 (next tick after reload) and then 66 (2 runs)
138
+ assert_equal 8, @tasks_run.length
139
+ end
140
+
141
+ # Catch a bug caused by allowing database tasks to be run in the same clock cycle that the database
142
+ # sync occurs. When this happens, a previously scheduled database task will be scheduled to run,
143
+ # we then fetch the same task afresh (wiping out the @events_from_database object), but the
144
+ # previously scheduled task still runs because #task `events` variable already stored it *before*
145
+ # we wiped out the @events_from_database objects.
146
+ #
147
+ # We have a situation like this:
148
+ #
149
+ # 12:31:00 #tick loops through events to run
150
+ # sync_database_tasks_for_model_ task is run
151
+ # fetches database task 1 with :at => 12:32, and schedules it to run (object task 1')
152
+ #
153
+ # ...
154
+ #
155
+ # 12:32:00 #tick loops through events that should be run, of which task 1' is included
156
+ # sync_database_tasks_for_model_ task is run
157
+ # fetches database task 1 with :at => 12:32, and schedules it to run (object task 1'')
158
+ # task 1' is run
159
+ #
160
+ # 12:32:01 #tick loops through events that should be run, of which task 1'' is included
161
+ # task 1'' is run
162
+ def test_daily_task_with_at_should_not_run_twice_when_already_scheduled
163
+ minute_after_next = next_minute(@next_minute)
164
+ at = minute_after_next.strftime('%H:%M')
165
+ @scheduled_task_with_at = stub(:frequency => 1.day, :name => 'ScheduledTaskWithAt:1', :at => at)
166
+ ScheduledTask.stubs(:all).returns([@scheduled_task_with_at])
167
+
168
+ # tick from now, though specified :at time
169
+ tick_at(@now, :and_every_second_for => (2 * @database_reload_frequency.seconds) + 1.second)
170
+
171
+ assert_equal 1, @tasks_run.length
172
+ end
173
+
174
+ def test_having_multiple_sync_database_tasks_will_work
175
+ ScheduledTask.stubs(:all).returns([@scheduled_task1])
176
+
177
+ # setup 2nd database sync
178
+ @scheduled_task_type2 = stub(:frequency => 10, :name => 'ScheduledTaskType2:1', :at => nil)
179
+
180
+ ScheduledTaskType2.stubs(:all).returns([@scheduled_task_type2])
181
+ @manager.sync_database_tasks model: ScheduledTaskType2, every: @database_reload_frequency do |job_name|
182
+ @tasks_run << job_name
183
+ end
184
+
185
+ tick_at(@next_minute, :and_every_second_for => 1.second)
186
+
187
+ assert_equal ["ScheduledTask:1", "ScheduledTaskType2:1"], @tasks_run
188
+ end
189
+ end
190
+ 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: 0.7.2
4
+ version: 0.7.3
5
5
  platform: ruby
6
6
  authors:
7
7
  - Adam Wiggins
@@ -9,104 +9,104 @@ authors:
9
9
  autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
- date: 2014-02-14 00:00:00.000000000 Z
12
+ date: 2014-03-20 00:00:00.000000000 Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: tzinfo
16
16
  requirement: !ruby/object:Gem::Requirement
17
17
  requirements:
18
- - - ">="
18
+ - - '>='
19
19
  - !ruby/object:Gem::Version
20
20
  version: '0'
21
21
  type: :runtime
22
22
  prerelease: false
23
23
  version_requirements: !ruby/object:Gem::Requirement
24
24
  requirements:
25
- - - ">="
25
+ - - '>='
26
26
  - !ruby/object:Gem::Version
27
27
  version: '0'
28
28
  - !ruby/object:Gem::Dependency
29
29
  name: activesupport
30
30
  requirement: !ruby/object:Gem::Requirement
31
31
  requirements:
32
- - - ">="
32
+ - - '>='
33
33
  - !ruby/object:Gem::Version
34
34
  version: '0'
35
35
  type: :runtime
36
36
  prerelease: false
37
37
  version_requirements: !ruby/object:Gem::Requirement
38
38
  requirements:
39
- - - ">="
39
+ - - '>='
40
40
  - !ruby/object:Gem::Version
41
41
  version: '0'
42
42
  - !ruby/object:Gem::Dependency
43
43
  name: bundler
44
44
  requirement: !ruby/object:Gem::Requirement
45
45
  requirements:
46
- - - "~>"
46
+ - - ~>
47
47
  - !ruby/object:Gem::Version
48
48
  version: '1.3'
49
49
  type: :development
50
50
  prerelease: false
51
51
  version_requirements: !ruby/object:Gem::Requirement
52
52
  requirements:
53
- - - "~>"
53
+ - - ~>
54
54
  - !ruby/object:Gem::Version
55
55
  version: '1.3'
56
56
  - !ruby/object:Gem::Dependency
57
57
  name: rake
58
58
  requirement: !ruby/object:Gem::Requirement
59
59
  requirements:
60
- - - ">="
60
+ - - '>='
61
61
  - !ruby/object:Gem::Version
62
62
  version: '0'
63
63
  type: :development
64
64
  prerelease: false
65
65
  version_requirements: !ruby/object:Gem::Requirement
66
66
  requirements:
67
- - - ">="
67
+ - - '>='
68
68
  - !ruby/object:Gem::Version
69
69
  version: '0'
70
70
  - !ruby/object:Gem::Dependency
71
71
  name: daemons
72
72
  requirement: !ruby/object:Gem::Requirement
73
73
  requirements:
74
- - - ">="
74
+ - - '>='
75
75
  - !ruby/object:Gem::Version
76
76
  version: '0'
77
77
  type: :development
78
78
  prerelease: false
79
79
  version_requirements: !ruby/object:Gem::Requirement
80
80
  requirements:
81
- - - ">="
81
+ - - '>='
82
82
  - !ruby/object:Gem::Version
83
83
  version: '0'
84
84
  - !ruby/object:Gem::Dependency
85
85
  name: contest
86
86
  requirement: !ruby/object:Gem::Requirement
87
87
  requirements:
88
- - - ">="
88
+ - - '>='
89
89
  - !ruby/object:Gem::Version
90
90
  version: '0'
91
91
  type: :development
92
92
  prerelease: false
93
93
  version_requirements: !ruby/object:Gem::Requirement
94
94
  requirements:
95
- - - ">="
95
+ - - '>='
96
96
  - !ruby/object:Gem::Version
97
97
  version: '0'
98
98
  - !ruby/object:Gem::Dependency
99
99
  name: mocha
100
100
  requirement: !ruby/object:Gem::Requirement
101
101
  requirements:
102
- - - ">="
102
+ - - '>='
103
103
  - !ruby/object:Gem::Version
104
104
  version: '0'
105
105
  type: :development
106
106
  prerelease: false
107
107
  version_requirements: !ruby/object:Gem::Requirement
108
108
  requirements:
109
- - - ">="
109
+ - - '>='
110
110
  - !ruby/object:Gem::Version
111
111
  version: '0'
112
112
  description: A scheduler process to replace cron, using a more flexible Ruby syntax
@@ -121,8 +121,8 @@ extensions: []
121
121
  extra_rdoc_files:
122
122
  - README.md
123
123
  files:
124
- - ".gitignore"
125
- - ".travis.yml"
124
+ - .gitignore
125
+ - .travis.yml
126
126
  - Gemfile
127
127
  - README.md
128
128
  - Rakefile
@@ -136,10 +136,12 @@ files:
136
136
  - lib/clockwork/at.rb
137
137
  - lib/clockwork/event.rb
138
138
  - lib/clockwork/manager.rb
139
+ - lib/clockwork/manager_with_database_tasks.rb
139
140
  - test/at_test.rb
140
141
  - test/clockwork_test.rb
141
142
  - test/event_test.rb
142
143
  - test/manager_test.rb
144
+ - test/manager_with_database_tasks_test.rb
143
145
  homepage: http://github.com/tomykaira/clockwork
144
146
  licenses:
145
147
  - MIT
@@ -150,17 +152,17 @@ require_paths:
150
152
  - lib
151
153
  required_ruby_version: !ruby/object:Gem::Requirement
152
154
  requirements:
153
- - - ">="
155
+ - - '>='
154
156
  - !ruby/object:Gem::Version
155
157
  version: '0'
156
158
  required_rubygems_version: !ruby/object:Gem::Requirement
157
159
  requirements:
158
- - - ">="
160
+ - - '>='
159
161
  - !ruby/object:Gem::Version
160
162
  version: '0'
161
163
  requirements: []
162
164
  rubyforge_project:
163
- rubygems_version: 2.2.0
165
+ rubygems_version: 2.0.3
164
166
  signing_key:
165
167
  specification_version: 4
166
168
  summary: A scheduler process to replace cron.
@@ -169,3 +171,4 @@ test_files:
169
171
  - test/clockwork_test.rb
170
172
  - test/event_test.rb
171
173
  - test/manager_test.rb
174
+ - test/manager_with_database_tasks_test.rb