clockwork 0.7.7 → 1.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 +7 -0
- data/LICENSE +21 -0
- data/README.md +55 -48
- data/Rakefile +1 -1
- data/clockwork.gemspec +1 -1
- data/clockworkd.1 +62 -0
- data/lib/clockwork/at.rb +5 -1
- data/lib/clockwork/database_events.rb +26 -0
- data/lib/clockwork/database_events/event.rb +38 -0
- data/lib/clockwork/database_events/manager.rb +20 -0
- data/lib/clockwork/database_events/registry.rb +39 -0
- data/lib/clockwork/database_events/sync_performer.rb +94 -0
- data/test/database_events/sync_performer_test.rb +283 -0
- data/test/database_events/test_helpers.rb +101 -0
- metadata +36 -52
- data/lib/clockwork/manager_with_database_tasks.rb +0 -150
- data/test/manager_with_database_tasks_test.rb +0 -292
@@ -0,0 +1,283 @@
|
|
1
|
+
require 'contest'
|
2
|
+
require 'mocha/setup'
|
3
|
+
require 'time'
|
4
|
+
require 'active_support/time'
|
5
|
+
|
6
|
+
require_relative '../../lib/clockwork'
|
7
|
+
require_relative '../../lib/clockwork/database_events'
|
8
|
+
require_relative 'test_helpers'
|
9
|
+
|
10
|
+
module DatabaseEvents
|
11
|
+
|
12
|
+
class SyncPerformerTest < Test::Unit::TestCase
|
13
|
+
|
14
|
+
setup do
|
15
|
+
@now = Time.now
|
16
|
+
DatabaseEventModelClass.delete_all
|
17
|
+
DatabaseEventModelClass2.delete_all
|
18
|
+
|
19
|
+
Clockwork.manager = @manager = Clockwork::DatabaseEvents::Manager.new
|
20
|
+
class << @manager
|
21
|
+
def log(msg); end # silence log output
|
22
|
+
end
|
23
|
+
end
|
24
|
+
|
25
|
+
describe "setup" do
|
26
|
+
setup do
|
27
|
+
@subject = Clockwork::DatabaseEvents::SyncPerformer
|
28
|
+
end
|
29
|
+
|
30
|
+
describe "arguments" do
|
31
|
+
def test_does_not_raise_error_with_valid_arguments
|
32
|
+
@subject.setup(model: DatabaseEventModelClass, every: 1.minute) {}
|
33
|
+
end
|
34
|
+
|
35
|
+
def test_raises_argument_error_if_model_is_not_set
|
36
|
+
error = assert_raises KeyError do
|
37
|
+
@subject.setup(every: 1.minute) {}
|
38
|
+
end
|
39
|
+
assert_equal error.message, ":model must be set to the model class"
|
40
|
+
end
|
41
|
+
|
42
|
+
def test_raises_argument_error_if_every_is_not_set
|
43
|
+
error = assert_raises KeyError do
|
44
|
+
@subject.setup(model: DatabaseEventModelClass) {}
|
45
|
+
end
|
46
|
+
assert_equal error.message, ":every must be set to the database sync frequency"
|
47
|
+
end
|
48
|
+
end
|
49
|
+
|
50
|
+
context "when database reload frequency is greater than model frequency period" do
|
51
|
+
setup do
|
52
|
+
@events_run = []
|
53
|
+
@sync_frequency = 1.minute
|
54
|
+
end
|
55
|
+
|
56
|
+
def test_fetches_and_registers_event_from_database
|
57
|
+
DatabaseEventModelClass.create(:frequency => 10)
|
58
|
+
setup_sync(model: DatabaseEventModelClass, :every => @sync_frequency, :events_run => @events_run)
|
59
|
+
|
60
|
+
tick_at(@now, :and_every_second_for => 1.second)
|
61
|
+
|
62
|
+
assert_equal ["DatabaseEventModelClass:1"], @events_run
|
63
|
+
end
|
64
|
+
|
65
|
+
def test_multiple_events_from_database_can_be_registered
|
66
|
+
DatabaseEventModelClass.create(:frequency => 10)
|
67
|
+
DatabaseEventModelClass.create(:frequency => 10)
|
68
|
+
setup_sync(model: DatabaseEventModelClass, :every => @sync_frequency, :events_run => @events_run)
|
69
|
+
|
70
|
+
tick_at(@now, :and_every_second_for => 1.second)
|
71
|
+
|
72
|
+
assert_equal ["DatabaseEventModelClass:1", "DatabaseEventModelClass:2"], @events_run
|
73
|
+
end
|
74
|
+
|
75
|
+
def test_event_from_database_does_not_run_again_before_frequency_specified_in_database
|
76
|
+
model = DatabaseEventModelClass.create(:frequency => 10)
|
77
|
+
setup_sync(model: DatabaseEventModelClass, :every => @sync_frequency, :events_run => @events_run)
|
78
|
+
|
79
|
+
tick_at(@now, :and_every_second_for => model.frequency - 1.second)
|
80
|
+
assert_equal 1, @events_run.length
|
81
|
+
end
|
82
|
+
|
83
|
+
def test_event_from_database_runs_repeatedly_with_frequency_specified_in_database
|
84
|
+
model = DatabaseEventModelClass.create(:frequency => 10)
|
85
|
+
setup_sync(model: DatabaseEventModelClass, :every => @sync_frequency, :events_run => @events_run)
|
86
|
+
|
87
|
+
tick_at(@now, :and_every_second_for => (2 * model.frequency) + 1.second)
|
88
|
+
|
89
|
+
assert_equal 3, @events_run.length
|
90
|
+
end
|
91
|
+
|
92
|
+
def test_reloaded_events_from_database_run_repeatedly
|
93
|
+
model = DatabaseEventModelClass.create(:frequency => 10)
|
94
|
+
setup_sync(model: DatabaseEventModelClass, :every => @sync_frequency, :events_run => @events_run)
|
95
|
+
|
96
|
+
tick_at(@now, :and_every_second_for => @sync_frequency - 1)
|
97
|
+
|
98
|
+
model.update(:name => "DatabaseEventModelClass:1:Reloaded")
|
99
|
+
|
100
|
+
tick_at(@now + @sync_frequency, :and_every_second_for => model.frequency * 2)
|
101
|
+
|
102
|
+
assert_equal ["DatabaseEventModelClass:1:Reloaded", "DatabaseEventModelClass:1:Reloaded"], @events_run[-2..-1]
|
103
|
+
end
|
104
|
+
|
105
|
+
def test_reloading_events_from_database_with_modified_frequency_will_run_with_new_frequency
|
106
|
+
model = DatabaseEventModelClass.create(:frequency => 10)
|
107
|
+
setup_sync(model: DatabaseEventModelClass, :every => @sync_frequency, :events_run => @events_run)
|
108
|
+
|
109
|
+
tick_at(@now, :and_every_second_for => @sync_frequency - 1.second)
|
110
|
+
model.update(:frequency => 5)
|
111
|
+
tick_at(@now + @sync_frequency, :and_every_second_for => 6.seconds)
|
112
|
+
|
113
|
+
# model runs at: 1, 11, 21, 31, 41, 51 (6 runs)
|
114
|
+
# database sync happens at: 60
|
115
|
+
# modified model runs at: 61 (next tick after reload) and then 66 (2 runs)
|
116
|
+
assert_equal 8, @events_run.length
|
117
|
+
end
|
118
|
+
|
119
|
+
def test_stops_running_deleted_events_from_database
|
120
|
+
model = DatabaseEventModelClass.create(:frequency => 10)
|
121
|
+
setup_sync(model: DatabaseEventModelClass, :every => @sync_frequency, :events_run => @events_run)
|
122
|
+
|
123
|
+
tick_at(@now, :and_every_second_for => (@sync_frequency - 1.second))
|
124
|
+
before = @events_run.dup
|
125
|
+
model.delete!
|
126
|
+
tick_at(@now + @sync_frequency, :and_every_second_for => @sync_frequency)
|
127
|
+
after = @events_run
|
128
|
+
|
129
|
+
assert_equal before, after
|
130
|
+
end
|
131
|
+
|
132
|
+
def test_event_from_database_with_edited_name_switches_to_new_name
|
133
|
+
model = DatabaseEventModelClass.create(:frequency => 10.seconds)
|
134
|
+
setup_sync(model: DatabaseEventModelClass, :every => @sync_frequency, :events_run => @events_run)
|
135
|
+
|
136
|
+
tick_at @now, :and_every_second_for => @sync_frequency - 1.second
|
137
|
+
@events_run.clear
|
138
|
+
model.update(:name => "DatabaseEventModelClass:1_modified")
|
139
|
+
tick_at @now + @sync_frequency, :and_every_second_for => (model.frequency * 2)
|
140
|
+
|
141
|
+
assert_equal ["DatabaseEventModelClass:1_modified", "DatabaseEventModelClass:1_modified"], @events_run
|
142
|
+
end
|
143
|
+
|
144
|
+
def test_event_from_database_with_edited_frequency_switches_to_new_frequency
|
145
|
+
model = DatabaseEventModelClass.create(:frequency => 10)
|
146
|
+
setup_sync(model: DatabaseEventModelClass, :every => @sync_frequency, :events_run => @events_run)
|
147
|
+
|
148
|
+
tick_at @now, :and_every_second_for => @sync_frequency - 1.second
|
149
|
+
@events_run.clear
|
150
|
+
model.update(:frequency => 30)
|
151
|
+
tick_at @now + @sync_frequency, :and_every_second_for => @sync_frequency - 1.seconds
|
152
|
+
|
153
|
+
assert_equal 2, @events_run.length
|
154
|
+
end
|
155
|
+
|
156
|
+
def test_event_from_database_with_edited_at_runs_at_new_at
|
157
|
+
model = DatabaseEventModelClass.create(:frequency => 1.day, :at => '10:30')
|
158
|
+
setup_sync(model: DatabaseEventModelClass, :every => @sync_frequency, :events_run => @events_run)
|
159
|
+
|
160
|
+
assert_will_run 'jan 1 2010 10:30:00'
|
161
|
+
assert_wont_run 'jan 1 2010 09:30:00'
|
162
|
+
|
163
|
+
model.update(:at => '09:30')
|
164
|
+
tick_at @now, :and_every_second_for => @sync_frequency + 1.second
|
165
|
+
|
166
|
+
assert_will_run 'jan 1 2010 09:30:00'
|
167
|
+
assert_wont_run 'jan 1 2010 10:30:00'
|
168
|
+
end
|
169
|
+
|
170
|
+
def test_daily_event_from_database_with_at_should_only_run_once
|
171
|
+
DatabaseEventModelClass.create(:frequency => 1.day, :at => next_minute(@now).strftime('%H:%M'))
|
172
|
+
setup_sync(model: DatabaseEventModelClass, :every => @sync_frequency, :events_run => @events_run)
|
173
|
+
|
174
|
+
# tick from now, though specified :at time
|
175
|
+
tick_at(@now, :and_every_second_for => (2 * @sync_frequency) + 1.second)
|
176
|
+
|
177
|
+
assert_equal 1, @events_run.length
|
178
|
+
end
|
179
|
+
|
180
|
+
def test_event_from_databse_with_comma_separated_at_leads_to_multiple_event_ats
|
181
|
+
DatabaseEventModelClass.create(:frequency => 1.day, :at => '16:20, 18:10')
|
182
|
+
setup_sync(model: DatabaseEventModelClass, :every => @sync_frequency, :events_run => @events_run)
|
183
|
+
|
184
|
+
tick_at @now, :and_every_second_for => 1.second
|
185
|
+
|
186
|
+
assert_wont_run 'jan 1 2010 16:19:59'
|
187
|
+
assert_will_run 'jan 1 2010 16:20:00'
|
188
|
+
assert_wont_run 'jan 1 2010 16:20:01'
|
189
|
+
|
190
|
+
assert_wont_run 'jan 1 2010 18:09:59'
|
191
|
+
assert_will_run 'jan 1 2010 18:10:00'
|
192
|
+
assert_wont_run 'jan 1 2010 18:10:01'
|
193
|
+
end
|
194
|
+
|
195
|
+
def test_syncing_multiple_database_models_works
|
196
|
+
DatabaseEventModelClass.create(:frequency => 10)
|
197
|
+
setup_sync(model: DatabaseEventModelClass, :every => @sync_frequency, :events_run => @events_run)
|
198
|
+
|
199
|
+
DatabaseEventModelClass2.create(:frequency => 10)
|
200
|
+
setup_sync(model: DatabaseEventModelClass2, :every => @sync_frequency, :events_run => @events_run)
|
201
|
+
|
202
|
+
tick_at(@now, :and_every_second_for => 1.second)
|
203
|
+
|
204
|
+
assert_equal ["DatabaseEventModelClass:1", "DatabaseEventModelClass2:1"], @events_run
|
205
|
+
end
|
206
|
+
end
|
207
|
+
|
208
|
+
context "when database reload frequency is less than model frequency period" do
|
209
|
+
setup do
|
210
|
+
@events_run = []
|
211
|
+
end
|
212
|
+
|
213
|
+
def test_the_event_only_runs_once_within_the_model_frequency_period
|
214
|
+
DatabaseEventModelClass.create(:frequency => 5.minutes)
|
215
|
+
setup_sync(model: DatabaseEventModelClass, :every => 1.minute, :events_run => @events_run)
|
216
|
+
|
217
|
+
tick_at(@now, :and_every_second_for => 5.minutes)
|
218
|
+
|
219
|
+
assert_equal 1, @events_run.length
|
220
|
+
end
|
221
|
+
end
|
222
|
+
|
223
|
+
context "with database event with :at as empty string" do
|
224
|
+
setup do
|
225
|
+
@events_run = []
|
226
|
+
|
227
|
+
DatabaseEventModelClass.create(:frequency => 10)
|
228
|
+
setup_sync(model: DatabaseEventModelClass, :every => 1.minute, :events_run => @events_run)
|
229
|
+
end
|
230
|
+
|
231
|
+
def test_it_does_not_raise_an_error
|
232
|
+
begin
|
233
|
+
tick_at(Time.now, :and_every_second_for => 10.seconds)
|
234
|
+
rescue => e
|
235
|
+
assert false, "Raised an error: #{e.message}"
|
236
|
+
end
|
237
|
+
end
|
238
|
+
|
239
|
+
def test_the_event_runs
|
240
|
+
begin
|
241
|
+
tick_at(Time.now, :and_every_second_for => 10.seconds)
|
242
|
+
rescue => e
|
243
|
+
end
|
244
|
+
assert_equal 1, @events_run.length
|
245
|
+
end
|
246
|
+
end
|
247
|
+
|
248
|
+
context "with task that respond to `tz`" do
|
249
|
+
setup do
|
250
|
+
@events_run = []
|
251
|
+
@utc_time_now = Time.now.utc
|
252
|
+
|
253
|
+
DatabaseEventModelClass.create(:frequency => 1.days, :at => @utc_time_now.strftime('%H:%M'), :tz => 'America/Montreal')
|
254
|
+
setup_sync(model: DatabaseEventModelClass, :every => 1.minute, :events_run => @events_run)
|
255
|
+
end
|
256
|
+
|
257
|
+
def test_it_does_not_raise_an_error
|
258
|
+
begin
|
259
|
+
tick_at(@utc_time_now, :and_every_second_for => 10.seconds)
|
260
|
+
rescue => e
|
261
|
+
assert false, "Raised an error: #{e.message}"
|
262
|
+
end
|
263
|
+
end
|
264
|
+
|
265
|
+
def test_it_do_not_runs_the_task_as_utc
|
266
|
+
begin
|
267
|
+
tick_at(@utc_time_now, :and_every_second_for => 3.hours)
|
268
|
+
rescue => e
|
269
|
+
end
|
270
|
+
assert_equal 0, @events_run.length
|
271
|
+
end
|
272
|
+
|
273
|
+
def test_it_does_runs_the_task_as_est
|
274
|
+
begin
|
275
|
+
tick_at(@utc_time_now, :and_every_second_for => 5.hours)
|
276
|
+
rescue => e
|
277
|
+
end
|
278
|
+
assert_equal 1, @events_run.length
|
279
|
+
end
|
280
|
+
end
|
281
|
+
end
|
282
|
+
end
|
283
|
+
end
|
@@ -0,0 +1,101 @@
|
|
1
|
+
def setup_sync(options={})
|
2
|
+
model_class = options.fetch(:model) { raise KeyError, ":model must be set to the model class" }
|
3
|
+
frequency = options.fetch(:every) { raise KeyError, ":every must be set to the database sync frequency" }
|
4
|
+
events_run = options.fetch(:events_run) { raise KeyError, ":events_run must be provided"}
|
5
|
+
|
6
|
+
Clockwork::DatabaseEvents::SyncPerformer.setup model: model_class, every: frequency do |model|
|
7
|
+
events_run << model.name
|
8
|
+
end
|
9
|
+
end
|
10
|
+
|
11
|
+
def assert_will_run(t)
|
12
|
+
assert_equal 1, @manager.tick(normalize_time(t)).size
|
13
|
+
end
|
14
|
+
|
15
|
+
def assert_wont_run(t)
|
16
|
+
assert_equal 0, @manager.tick(normalize_time(t)).size
|
17
|
+
end
|
18
|
+
|
19
|
+
def tick_at(now = Time.now, options = {})
|
20
|
+
seconds_to_tick_for = options[:and_every_second_for] || 0
|
21
|
+
number_of_ticks = 1 + seconds_to_tick_for
|
22
|
+
number_of_ticks.times{|i| @manager.tick(now + i) }
|
23
|
+
end
|
24
|
+
|
25
|
+
def next_minute(now = Time.now)
|
26
|
+
Time.at((now.to_i / 60 + 1) * 60)
|
27
|
+
end
|
28
|
+
|
29
|
+
def normalize_time t
|
30
|
+
t.is_a?(String) ? Time.parse(t) : t
|
31
|
+
end
|
32
|
+
|
33
|
+
|
34
|
+
class ActiveRecordFake
|
35
|
+
attr_accessor :id, :name, :at, :frequency, :tz
|
36
|
+
|
37
|
+
class << self
|
38
|
+
def create *args
|
39
|
+
new *args
|
40
|
+
end
|
41
|
+
|
42
|
+
def add instance
|
43
|
+
@events << instance
|
44
|
+
end
|
45
|
+
|
46
|
+
def remove instance
|
47
|
+
@events.delete(instance)
|
48
|
+
end
|
49
|
+
|
50
|
+
def next_id
|
51
|
+
id = @next_id
|
52
|
+
@next_id += 1
|
53
|
+
id
|
54
|
+
end
|
55
|
+
|
56
|
+
def reset_id
|
57
|
+
@next_id = 1
|
58
|
+
end
|
59
|
+
|
60
|
+
def delete_all
|
61
|
+
@events.clear
|
62
|
+
reset_id
|
63
|
+
end
|
64
|
+
|
65
|
+
def all
|
66
|
+
@events.dup
|
67
|
+
end
|
68
|
+
end
|
69
|
+
|
70
|
+
def initialize options={}
|
71
|
+
@id = options.fetch(:id) { self.class.next_id }
|
72
|
+
@name = options.fetch(:name) { nil }
|
73
|
+
@at = options.fetch(:at) { nil }
|
74
|
+
@frequency = options.fetch(:frequency) { raise KeyError, ":every must be supplied" }
|
75
|
+
@tz = options.fetch(:tz) { nil }
|
76
|
+
|
77
|
+
self.class.add self
|
78
|
+
end
|
79
|
+
|
80
|
+
def name
|
81
|
+
@name || "#{self.class}:#{id}"
|
82
|
+
end
|
83
|
+
|
84
|
+
def delete!
|
85
|
+
self.class.remove(self)
|
86
|
+
end
|
87
|
+
|
88
|
+
def update options={}
|
89
|
+
options.each{|attr, value| self.send("#{attr}=".to_sym, value) }
|
90
|
+
end
|
91
|
+
end
|
92
|
+
|
93
|
+
class DatabaseEventModelClass < ActiveRecordFake
|
94
|
+
@events = []
|
95
|
+
@next_id = 1
|
96
|
+
end
|
97
|
+
|
98
|
+
class DatabaseEventModelClass2 < ActiveRecordFake
|
99
|
+
@events = []
|
100
|
+
@next_id = 1
|
101
|
+
end
|
metadata
CHANGED
@@ -1,8 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: clockwork
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
5
|
-
prerelease:
|
4
|
+
version: 1.0.0
|
6
5
|
platform: ruby
|
7
6
|
authors:
|
8
7
|
- Adam Wiggins
|
@@ -10,134 +9,118 @@ authors:
|
|
10
9
|
autorequire:
|
11
10
|
bindir: bin
|
12
11
|
cert_chain: []
|
13
|
-
date: 2014-
|
12
|
+
date: 2014-09-03 00:00:00.000000000 Z
|
14
13
|
dependencies:
|
15
14
|
- !ruby/object:Gem::Dependency
|
16
15
|
name: tzinfo
|
17
16
|
requirement: !ruby/object:Gem::Requirement
|
18
|
-
none: false
|
19
17
|
requirements:
|
20
|
-
- -
|
18
|
+
- - ">="
|
21
19
|
- !ruby/object:Gem::Version
|
22
20
|
version: '0'
|
23
21
|
type: :runtime
|
24
22
|
prerelease: false
|
25
23
|
version_requirements: !ruby/object:Gem::Requirement
|
26
|
-
none: false
|
27
24
|
requirements:
|
28
|
-
- -
|
25
|
+
- - ">="
|
29
26
|
- !ruby/object:Gem::Version
|
30
27
|
version: '0'
|
31
28
|
- !ruby/object:Gem::Dependency
|
32
29
|
name: activesupport
|
33
30
|
requirement: !ruby/object:Gem::Requirement
|
34
|
-
none: false
|
35
31
|
requirements:
|
36
|
-
- -
|
32
|
+
- - ">="
|
37
33
|
- !ruby/object:Gem::Version
|
38
34
|
version: '0'
|
39
35
|
type: :runtime
|
40
36
|
prerelease: false
|
41
37
|
version_requirements: !ruby/object:Gem::Requirement
|
42
|
-
none: false
|
43
38
|
requirements:
|
44
|
-
- -
|
39
|
+
- - ">="
|
45
40
|
- !ruby/object:Gem::Version
|
46
41
|
version: '0'
|
47
42
|
- !ruby/object:Gem::Dependency
|
48
43
|
name: bundler
|
49
44
|
requirement: !ruby/object:Gem::Requirement
|
50
|
-
none: false
|
51
45
|
requirements:
|
52
|
-
- - ~>
|
46
|
+
- - "~>"
|
53
47
|
- !ruby/object:Gem::Version
|
54
48
|
version: '1.3'
|
55
49
|
type: :development
|
56
50
|
prerelease: false
|
57
51
|
version_requirements: !ruby/object:Gem::Requirement
|
58
|
-
none: false
|
59
52
|
requirements:
|
60
|
-
- - ~>
|
53
|
+
- - "~>"
|
61
54
|
- !ruby/object:Gem::Version
|
62
55
|
version: '1.3'
|
63
56
|
- !ruby/object:Gem::Dependency
|
64
57
|
name: rake
|
65
58
|
requirement: !ruby/object:Gem::Requirement
|
66
|
-
none: false
|
67
59
|
requirements:
|
68
|
-
- -
|
60
|
+
- - ">="
|
69
61
|
- !ruby/object:Gem::Version
|
70
62
|
version: '0'
|
71
63
|
type: :development
|
72
64
|
prerelease: false
|
73
65
|
version_requirements: !ruby/object:Gem::Requirement
|
74
|
-
none: false
|
75
66
|
requirements:
|
76
|
-
- -
|
67
|
+
- - ">="
|
77
68
|
- !ruby/object:Gem::Version
|
78
69
|
version: '0'
|
79
70
|
- !ruby/object:Gem::Dependency
|
80
71
|
name: daemons
|
81
72
|
requirement: !ruby/object:Gem::Requirement
|
82
|
-
none: false
|
83
73
|
requirements:
|
84
|
-
- -
|
74
|
+
- - ">="
|
85
75
|
- !ruby/object:Gem::Version
|
86
76
|
version: '0'
|
87
77
|
type: :development
|
88
78
|
prerelease: false
|
89
79
|
version_requirements: !ruby/object:Gem::Requirement
|
90
|
-
none: false
|
91
80
|
requirements:
|
92
|
-
- -
|
81
|
+
- - ">="
|
93
82
|
- !ruby/object:Gem::Version
|
94
83
|
version: '0'
|
95
84
|
- !ruby/object:Gem::Dependency
|
96
85
|
name: contest
|
97
86
|
requirement: !ruby/object:Gem::Requirement
|
98
|
-
none: false
|
99
87
|
requirements:
|
100
|
-
- -
|
88
|
+
- - ">="
|
101
89
|
- !ruby/object:Gem::Version
|
102
90
|
version: '0'
|
103
91
|
type: :development
|
104
92
|
prerelease: false
|
105
93
|
version_requirements: !ruby/object:Gem::Requirement
|
106
|
-
none: false
|
107
94
|
requirements:
|
108
|
-
- -
|
95
|
+
- - ">="
|
109
96
|
- !ruby/object:Gem::Version
|
110
97
|
version: '0'
|
111
98
|
- !ruby/object:Gem::Dependency
|
112
99
|
name: minitest
|
113
100
|
requirement: !ruby/object:Gem::Requirement
|
114
|
-
none: false
|
115
101
|
requirements:
|
116
|
-
- - ~>
|
102
|
+
- - "~>"
|
117
103
|
- !ruby/object:Gem::Version
|
118
104
|
version: '4.0'
|
119
105
|
type: :development
|
120
106
|
prerelease: false
|
121
107
|
version_requirements: !ruby/object:Gem::Requirement
|
122
|
-
none: false
|
123
108
|
requirements:
|
124
|
-
- - ~>
|
109
|
+
- - "~>"
|
125
110
|
- !ruby/object:Gem::Version
|
126
111
|
version: '4.0'
|
127
112
|
- !ruby/object:Gem::Dependency
|
128
113
|
name: mocha
|
129
114
|
requirement: !ruby/object:Gem::Requirement
|
130
|
-
none: false
|
131
115
|
requirements:
|
132
|
-
- -
|
116
|
+
- - ">="
|
133
117
|
- !ruby/object:Gem::Version
|
134
118
|
version: '0'
|
135
119
|
type: :development
|
136
120
|
prerelease: false
|
137
121
|
version_requirements: !ruby/object:Gem::Requirement
|
138
|
-
none: false
|
139
122
|
requirements:
|
140
|
-
- -
|
123
|
+
- - ">="
|
141
124
|
- !ruby/object:Gem::Version
|
142
125
|
version: '0'
|
143
126
|
description: A scheduler process to replace cron, using a more flexible Ruby syntax
|
@@ -152,61 +135,62 @@ extensions: []
|
|
152
135
|
extra_rdoc_files:
|
153
136
|
- README.md
|
154
137
|
files:
|
155
|
-
- .gitignore
|
156
|
-
- .travis.yml
|
138
|
+
- ".gitignore"
|
139
|
+
- ".travis.yml"
|
157
140
|
- Gemfile
|
141
|
+
- LICENSE
|
158
142
|
- README.md
|
159
143
|
- Rakefile
|
160
144
|
- bin/clockwork
|
161
145
|
- bin/clockworkd
|
162
146
|
- clockwork.gemspec
|
147
|
+
- clockworkd.1
|
163
148
|
- example.rb
|
164
149
|
- gemfiles/activesupport3.gemfile
|
165
150
|
- gemfiles/activesupport4.gemfile
|
166
151
|
- lib/clockwork.rb
|
167
152
|
- lib/clockwork/at.rb
|
153
|
+
- lib/clockwork/database_events.rb
|
154
|
+
- lib/clockwork/database_events/event.rb
|
155
|
+
- lib/clockwork/database_events/manager.rb
|
156
|
+
- lib/clockwork/database_events/registry.rb
|
157
|
+
- lib/clockwork/database_events/sync_performer.rb
|
168
158
|
- lib/clockwork/event.rb
|
169
159
|
- lib/clockwork/manager.rb
|
170
|
-
- lib/clockwork/manager_with_database_tasks.rb
|
171
160
|
- test/at_test.rb
|
172
161
|
- test/clockwork_test.rb
|
162
|
+
- test/database_events/sync_performer_test.rb
|
163
|
+
- test/database_events/test_helpers.rb
|
173
164
|
- test/event_test.rb
|
174
165
|
- test/manager_test.rb
|
175
|
-
- test/manager_with_database_tasks_test.rb
|
176
166
|
homepage: http://github.com/tomykaira/clockwork
|
177
167
|
licenses:
|
178
168
|
- MIT
|
169
|
+
metadata: {}
|
179
170
|
post_install_message:
|
180
171
|
rdoc_options: []
|
181
172
|
require_paths:
|
182
173
|
- lib
|
183
174
|
required_ruby_version: !ruby/object:Gem::Requirement
|
184
|
-
none: false
|
185
175
|
requirements:
|
186
|
-
- -
|
176
|
+
- - ">="
|
187
177
|
- !ruby/object:Gem::Version
|
188
178
|
version: '0'
|
189
|
-
segments:
|
190
|
-
- 0
|
191
|
-
hash: -1006563675732551945
|
192
179
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
193
|
-
none: false
|
194
180
|
requirements:
|
195
|
-
- -
|
181
|
+
- - ">="
|
196
182
|
- !ruby/object:Gem::Version
|
197
183
|
version: '0'
|
198
|
-
segments:
|
199
|
-
- 0
|
200
|
-
hash: -1006563675732551945
|
201
184
|
requirements: []
|
202
185
|
rubyforge_project:
|
203
|
-
rubygems_version:
|
186
|
+
rubygems_version: 2.2.0
|
204
187
|
signing_key:
|
205
|
-
specification_version:
|
188
|
+
specification_version: 4
|
206
189
|
summary: A scheduler process to replace cron.
|
207
190
|
test_files:
|
208
191
|
- test/at_test.rb
|
209
192
|
- test/clockwork_test.rb
|
193
|
+
- test/database_events/sync_performer_test.rb
|
194
|
+
- test/database_events/test_helpers.rb
|
210
195
|
- test/event_test.rb
|
211
196
|
- test/manager_test.rb
|
212
|
-
- test/manager_with_database_tasks_test.rb
|