clockwork 0.7.3 → 0.7.4
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 +4 -4
- data/README.md +2 -2
- data/clockwork.gemspec +1 -1
- data/lib/clockwork/manager_with_database_tasks.rb +75 -49
- data/test/manager_with_database_tasks_test.rb +129 -104
- metadata +21 -21
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: bb04c64391be1de07e805c05256430c06c1d0da6
|
4
|
+
data.tar.gz: 3804849a9e343ce52d62609390da392ccb2c6274
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: d3adf3511969f14520a4d3273dbf3555d690a8a2cb467e217825ce66f8cae9d8cae3c1431f31784ff987061c6acff1c8e081b91bebac858e96ac8013d071a67d
|
7
|
+
data.tar.gz: 06a2920e423ecf3f656b2b5f10ad5a8a32cf5bff46a55a12416b94f77bd484b3bf443a3cfdde7267e89a011cc282ef2580ae883191b167918f23cc6e9383c833
|
data/README.md
CHANGED
@@ -136,7 +136,7 @@ module Clockwork
|
|
136
136
|
end
|
137
137
|
```
|
138
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).
|
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).
|
140
140
|
|
141
141
|
Rails ActiveRecord models are a perfect candidate for the model class, but you could use something else. The only requirements are:
|
142
142
|
|
@@ -144,7 +144,7 @@ Rails ActiveRecord models are a perfect candidate for the model class, but you c
|
|
144
144
|
2. the instances returned respond to:
|
145
145
|
`frequency` returning the how frequently (in seconds) the database task should be run
|
146
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
|
147
|
+
`at` return nil or `''` if not using `:at`, or otherwise any acceptable clockwork `:at` string
|
148
148
|
|
149
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
150
|
|
data/clockwork.gemspec
CHANGED
@@ -8,14 +8,71 @@ module Clockwork
|
|
8
8
|
|
9
9
|
extend Methods
|
10
10
|
|
11
|
-
class
|
11
|
+
class DatabaseEventSyncPerformer
|
12
|
+
|
13
|
+
def initialize(manager, model, proc)
|
14
|
+
@manager = manager
|
15
|
+
@model = model
|
16
|
+
@block = proc
|
17
|
+
@events = {}
|
18
|
+
end
|
19
|
+
|
20
|
+
# Ensure clockwork events reflect database tasks
|
21
|
+
# Adds any new tasks, modifies updated ones, and delets removed ones
|
22
|
+
def sync
|
23
|
+
model_ids_that_exist = []
|
24
|
+
|
25
|
+
@model.all.each do |db_task|
|
26
|
+
model_ids_that_exist << db_task.id
|
27
|
+
|
28
|
+
if !event_exists_for_task(db_task) || db_task_has_changed(db_task)
|
29
|
+
create_event_for_database_task(db_task)
|
30
|
+
end
|
31
|
+
end
|
32
|
+
|
33
|
+
remove_deleted_database_tasks(model_ids_that_exist)
|
34
|
+
end
|
35
|
+
|
36
|
+
def events
|
37
|
+
@events.values
|
38
|
+
end
|
12
39
|
|
13
|
-
|
40
|
+
def add_event(e, task_id)
|
41
|
+
@events[task_id] = e
|
42
|
+
end
|
43
|
+
|
44
|
+
protected
|
45
|
+
|
46
|
+
def create_event_for_database_task(db_task)
|
47
|
+
options = {
|
48
|
+
:from_database => true,
|
49
|
+
:db_task_id => db_task.id,
|
50
|
+
:performer => self,
|
51
|
+
:at => db_task.at.blank? ? nil : db_task.at.split(',')
|
52
|
+
}
|
53
|
+
|
54
|
+
@manager.every db_task.frequency, db_task.name, options, &@block
|
55
|
+
end
|
56
|
+
|
57
|
+
def event_exists_for_task(db_task)
|
58
|
+
@events[db_task.id]
|
59
|
+
end
|
60
|
+
|
61
|
+
def remove_deleted_database_tasks(model_ids_that_exist)
|
62
|
+
@events.reject!{|db_task_id, _| !model_ids_that_exist.include?(db_task_id) }
|
63
|
+
end
|
64
|
+
|
65
|
+
def db_task_has_changed(task)
|
66
|
+
event = @events[task.id]
|
67
|
+
task.name != event.job || task.frequency != event.instance_variable_get(:@period)
|
68
|
+
end
|
69
|
+
end
|
70
|
+
|
71
|
+
class ManagerWithDatabaseTasks < Manager
|
14
72
|
|
15
73
|
def initialize
|
16
74
|
super
|
17
|
-
@
|
18
|
-
@next_sync_database_tasks_identifier = 0
|
75
|
+
@database_event_sync_performers = []
|
19
76
|
end
|
20
77
|
|
21
78
|
def sync_database_tasks(options={}, &block)
|
@@ -24,64 +81,33 @@ module Clockwork
|
|
24
81
|
end
|
25
82
|
raise ArgumentError.new(":every must be greater or equal to 1.minute") if options[:every] < 1.minute
|
26
83
|
|
27
|
-
|
28
|
-
|
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 } }
|
84
|
+
sync_performer = DatabaseEventSyncPerformer.new(self, options[:model], block)
|
85
|
+
@database_event_sync_performers << sync_performer
|
34
86
|
|
35
87
|
# create event that syncs clockwork events with database events
|
36
|
-
every
|
37
|
-
|
88
|
+
every options[:every], "sync_database_tasks_for_model_#{options[:model]}" do
|
89
|
+
sync_performer.sync
|
38
90
|
end
|
39
91
|
end
|
40
92
|
|
93
|
+
private
|
41
94
|
|
42
|
-
|
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
|
95
|
+
def events_from_database_as_array
|
96
|
+
@database_event_sync_performers.collect{|performer| performer.events}.flatten
|
69
97
|
end
|
70
98
|
|
71
|
-
private
|
72
|
-
|
73
99
|
def events_to_run(t)
|
74
|
-
(@events +
|
100
|
+
(@events + events_from_database_as_array).select{|event| event.run_now?(t) }
|
75
101
|
end
|
76
102
|
|
77
103
|
def register(period, job, block, options)
|
78
|
-
|
79
|
-
|
80
|
-
|
81
|
-
|
82
|
-
|
104
|
+
Event.new(self, period, job, block || handler, options).tap do |e|
|
105
|
+
if options[:from_database]
|
106
|
+
options[:performer].add_event(e, options[:db_task_id])
|
107
|
+
else
|
108
|
+
@events << e
|
109
|
+
end
|
83
110
|
end
|
84
|
-
event
|
85
111
|
end
|
86
112
|
end
|
87
113
|
end
|
@@ -56,135 +56,160 @@ class ManagerWithDatabaseTasksTest < Test::Unit::TestCase
|
|
56
56
|
end
|
57
57
|
end
|
58
58
|
|
59
|
-
|
60
|
-
|
61
|
-
|
62
|
-
|
63
|
-
|
64
|
-
|
59
|
+
context "when database reload frequency is greater than task frequency period" do
|
60
|
+
setup do
|
61
|
+
@tasks_run = []
|
62
|
+
@scheduled_task1 = stub(:frequency => 10, :name => 'ScheduledTask:1', :at => nil, :id => 1)
|
63
|
+
@scheduled_task2 = stub(:frequency => 10, :name => 'ScheduledTask:2', :at => nil, :id => 2)
|
64
|
+
@scheduled_task1_modified = stub(:frequency => 5, :name => 'ScheduledTaskModified:1', :at => nil, :id => 3)
|
65
|
+
ScheduledTask.stubs(:all).returns([@scheduled_task1])
|
65
66
|
|
66
|
-
|
67
|
+
@database_reload_frequency = 1.minute
|
67
68
|
|
68
|
-
|
69
|
-
@next_minute = next_minute(@now) # database sync task only happens on minute boundary
|
69
|
+
@now = Time.now
|
70
70
|
|
71
|
-
|
72
|
-
|
73
|
-
|
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
|
74
75
|
end
|
75
|
-
end
|
76
76
|
|
77
|
-
|
78
|
-
|
79
|
-
|
80
|
-
|
81
|
-
end
|
77
|
+
def test_fetches_and_registers_database_task
|
78
|
+
tick_at(@now, :and_every_second_for => 1.second)
|
79
|
+
assert_equal ["ScheduledTask:1"], @tasks_run
|
80
|
+
end
|
82
81
|
|
83
|
-
|
84
|
-
|
85
|
-
|
86
|
-
|
82
|
+
def test_multiple_database_tasks_can_be_registered
|
83
|
+
ScheduledTask.stubs(:all).returns([@scheduled_task1, @scheduled_task2])
|
84
|
+
tick_at(@now, :and_every_second_for => 1.second)
|
85
|
+
assert_equal ["ScheduledTask:1", "ScheduledTask:2"], @tasks_run
|
86
|
+
end
|
87
87
|
|
88
|
-
|
89
|
-
|
90
|
-
|
91
|
-
|
92
|
-
end
|
88
|
+
def test_database_task_does_not_run_again_before_frequency_specified_in_database
|
89
|
+
tick_at(@now, :and_every_second_for => @scheduled_task1.frequency - 1.second) # runs at 1
|
90
|
+
assert_equal 1, @tasks_run.length
|
91
|
+
end
|
93
92
|
|
94
|
-
|
95
|
-
|
96
|
-
|
97
|
-
|
93
|
+
def test_database_task_runs_repeatedly_with_frequency_specified_in_database
|
94
|
+
tick_at(@now, :and_every_second_for => (2 * @scheduled_task1.frequency) + 1.second) # runs at 1, 11, and 21
|
95
|
+
assert_equal 3, @tasks_run.length
|
96
|
+
end
|
98
97
|
|
99
|
-
|
100
|
-
|
101
|
-
|
102
|
-
|
98
|
+
def test_reloads_tasks_from_database
|
99
|
+
ScheduledTask.stubs(:all).returns([@scheduled_task1], [@scheduled_task2])
|
100
|
+
tick_at(@now, :and_every_second_for => @database_reload_frequency.seconds)
|
101
|
+
@manager.tick # @scheduled_task2 should run immediately on next tick (then every 10 seconds)
|
102
|
+
|
103
|
+
assert_equal [
|
104
|
+
"ScheduledTask:1",
|
105
|
+
"ScheduledTask:1",
|
106
|
+
"ScheduledTask:1",
|
107
|
+
"ScheduledTask:1",
|
108
|
+
"ScheduledTask:1",
|
109
|
+
"ScheduledTask:1",
|
110
|
+
"ScheduledTask:2"], @tasks_run
|
111
|
+
end
|
103
112
|
|
104
|
-
|
105
|
-
|
106
|
-
|
107
|
-
|
113
|
+
def test_reloaded_tasks_run_repeatedly
|
114
|
+
ScheduledTask.stubs(:all).returns([@scheduled_task1], [@scheduled_task2])
|
115
|
+
tick_at(@now, :and_every_second_for => @database_reload_frequency.seconds + 11.seconds)
|
116
|
+
assert_equal ["ScheduledTask:2", "ScheduledTask:2"], @tasks_run[-2..-1]
|
117
|
+
end
|
108
118
|
|
109
|
-
|
110
|
-
|
119
|
+
def test_reloading_task_with_modified_frequency_will_run_with_new_frequency
|
120
|
+
ScheduledTask.stubs(:all).returns([@scheduled_task1], [@scheduled_task1_modified])
|
111
121
|
|
112
|
-
|
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
|
122
|
+
tick_at(@now, :and_every_second_for => 66.seconds)
|
117
123
|
|
118
|
-
|
119
|
-
|
120
|
-
|
121
|
-
|
124
|
+
# task1 runs at: 1, 11, 21, 31, 41, 51 (6 runs)
|
125
|
+
# database tasks are reloaded at: 60
|
126
|
+
# task1_modified runs at: 61 (next tick after reload) and then 66 (2 runs)
|
127
|
+
assert_equal 8, @tasks_run.length
|
128
|
+
end
|
122
129
|
|
123
|
-
|
124
|
-
|
125
|
-
|
130
|
+
def test_stops_running_deleted_database_task
|
131
|
+
ScheduledTask.stubs(:all).returns([@scheduled_task1], [])
|
132
|
+
tick_at(@now, :and_every_second_for => @database_reload_frequency.seconds)
|
133
|
+
before = @tasks_run.dup
|
126
134
|
|
127
|
-
|
128
|
-
|
135
|
+
# tick through reload, and run for enough ticks that previous task would have run
|
136
|
+
tick_at(@now + @database_reload_frequency.seconds + 20.seconds)
|
137
|
+
after = @tasks_run
|
129
138
|
|
130
|
-
|
131
|
-
|
139
|
+
assert_equal before, after
|
140
|
+
end
|
132
141
|
|
133
|
-
|
142
|
+
def test_edited_tasks_switch_to_new_settings
|
143
|
+
tick_at @now, :and_every_second_for => @database_reload_frequency.seconds - 1.second
|
144
|
+
modified_task_1 = stub(:frequency => 30, :name => 'ScheduledTask:1_modified', :at => nil, :id => 1)
|
145
|
+
ScheduledTask.stubs(:all).returns([modified_task_1])
|
146
|
+
tick_at @now + @database_reload_frequency.seconds, :and_every_second_for => @database_reload_frequency.seconds - 1.seconds
|
147
|
+
assert_equal [
|
148
|
+
"ScheduledTask:1",
|
149
|
+
"ScheduledTask:1",
|
150
|
+
"ScheduledTask:1",
|
151
|
+
"ScheduledTask:1",
|
152
|
+
"ScheduledTask:1",
|
153
|
+
"ScheduledTask:1",
|
154
|
+
"ScheduledTask:1_modified",
|
155
|
+
"ScheduledTask:1_modified"
|
156
|
+
], @tasks_run
|
157
|
+
end
|
134
158
|
|
135
|
-
|
136
|
-
|
137
|
-
|
138
|
-
|
139
|
-
|
159
|
+
def test_daily_task_with_at_should_only_run_once
|
160
|
+
next_minute = next_minute(@now)
|
161
|
+
at = next_minute.strftime('%H:%M')
|
162
|
+
@scheduled_task_with_at = stub(:frequency => 1.day, :name => 'ScheduledTaskWithAt:1', :at => at, :id => 5)
|
163
|
+
ScheduledTask.stubs(:all).returns([@scheduled_task_with_at])
|
140
164
|
|
141
|
-
|
142
|
-
|
143
|
-
|
144
|
-
|
145
|
-
|
146
|
-
|
147
|
-
|
148
|
-
|
149
|
-
|
150
|
-
|
151
|
-
|
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
|
165
|
+
# tick from now, though specified :at time
|
166
|
+
tick_at(@now, :and_every_second_for => (2 * @database_reload_frequency.seconds) + 1.second)
|
167
|
+
|
168
|
+
assert_equal 1, @tasks_run.length
|
169
|
+
end
|
170
|
+
|
171
|
+
def test_having_multiple_sync_database_tasks_will_work
|
172
|
+
ScheduledTask.stubs(:all).returns([@scheduled_task1])
|
173
|
+
|
174
|
+
# setup 2nd database sync
|
175
|
+
@scheduled_task_type2 = stub(:frequency => 10, :name => 'ScheduledTaskType2:1', :at => nil, :id => 6)
|
173
176
|
|
174
|
-
|
175
|
-
|
177
|
+
ScheduledTaskType2.stubs(:all).returns([@scheduled_task_type2])
|
178
|
+
@manager.sync_database_tasks model: ScheduledTaskType2, every: @database_reload_frequency do |job_name|
|
179
|
+
@tasks_run << job_name
|
180
|
+
end
|
176
181
|
|
177
|
-
|
178
|
-
@scheduled_task_type2 = stub(:frequency => 10, :name => 'ScheduledTaskType2:1', :at => nil)
|
182
|
+
tick_at(@now, :and_every_second_for => 1.second)
|
179
183
|
|
180
|
-
|
181
|
-
@manager.sync_database_tasks model: ScheduledTaskType2, every: @database_reload_frequency do |job_name|
|
182
|
-
@tasks_run << job_name
|
184
|
+
assert_equal ["ScheduledTask:1", "ScheduledTaskType2:1"], @tasks_run
|
183
185
|
end
|
186
|
+
end
|
187
|
+
|
188
|
+
context "when database reload frequency is less than task frequency period" do
|
189
|
+
setup do
|
190
|
+
@tasks_run = []
|
191
|
+
@scheduled_task1 = stub(:frequency => 5.minutes, :name => 'ScheduledTask:1', :at => nil, :id => 1)
|
192
|
+
@scheduled_task2 = stub(:frequency => 10, :name => 'ScheduledTask:2', :at => nil, :id => 2)
|
193
|
+
@scheduled_task1_modified = stub(:frequency => 5, :name => 'ScheduledTaskModified:1', :at => nil)
|
194
|
+
ScheduledTask.stubs(:all).returns([@scheduled_task1])
|
195
|
+
|
196
|
+
@database_reload_frequency = 1.minute
|
184
197
|
|
185
|
-
|
198
|
+
@now = Time.now
|
199
|
+
@next_minute = next_minute(@now) # database sync task only happens on minute boundary
|
186
200
|
|
187
|
-
|
201
|
+
# setup the database sync
|
202
|
+
@manager.sync_database_tasks model: ScheduledTask, every: @database_reload_frequency do |job_name|
|
203
|
+
@tasks_run << job_name
|
204
|
+
end
|
205
|
+
end
|
206
|
+
|
207
|
+
# For example: if the manager updates every minute, but the task specifies 5 minutes,
|
208
|
+
# the task will still run every minute.
|
209
|
+
def test_it_only_runs_the_task_once_within_the_task_frequency_period
|
210
|
+
tick_at(@now, :and_every_second_for => 5.minutes)
|
211
|
+
assert_equal 1, @tasks_run.length
|
212
|
+
end
|
188
213
|
end
|
189
214
|
end
|
190
215
|
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.
|
4
|
+
version: 0.7.4
|
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-
|
12
|
+
date: 2014-04-14 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
|
@@ -152,17 +152,17 @@ require_paths:
|
|
152
152
|
- lib
|
153
153
|
required_ruby_version: !ruby/object:Gem::Requirement
|
154
154
|
requirements:
|
155
|
-
- -
|
155
|
+
- - ">="
|
156
156
|
- !ruby/object:Gem::Version
|
157
157
|
version: '0'
|
158
158
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
159
159
|
requirements:
|
160
|
-
- -
|
160
|
+
- - ">="
|
161
161
|
- !ruby/object:Gem::Version
|
162
162
|
version: '0'
|
163
163
|
requirements: []
|
164
164
|
rubyforge_project:
|
165
|
-
rubygems_version: 2.0
|
165
|
+
rubygems_version: 2.2.0
|
166
166
|
signing_key:
|
167
167
|
specification_version: 4
|
168
168
|
summary: A scheduler process to replace cron.
|