clockwork 0.7.2 → 0.7.3

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
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