periodic-scheduler 0.1.0 → 0.2.0
Sign up to get free protection for your applications and to get access to all the features.
- data/Gemfile +4 -2
- data/Gemfile.lock +28 -12
- data/Rakefile +1 -1
- data/VERSION +1 -1
- data/lib/periodic-scheduler.rb +27 -6
- data/periodic-scheduler.gemspec +67 -0
- data/spec/periodic-scheduler_spec.rb +131 -84
- metadata +58 -30
data/Gemfile
CHANGED
@@ -6,8 +6,10 @@ source "http://rubygems.org"
|
|
6
6
|
# Add dependencies to develop your gem here.
|
7
7
|
# Include everything needed to run rake, tests, features, etc.
|
8
8
|
group :development do
|
9
|
-
gem "rspec", "
|
9
|
+
gem "rspec", "~> 2.8.0"
|
10
|
+
gem "rdoc", "~> 3.12"
|
11
|
+
gem "cucumber", ">= 0"
|
10
12
|
gem "bundler", "~> 1.0.0"
|
11
|
-
gem "jeweler", "~> 1.
|
13
|
+
gem "jeweler", "~> 1.8.3"
|
12
14
|
gem "rcov", ">= 0"
|
13
15
|
end
|
data/Gemfile.lock
CHANGED
@@ -1,28 +1,44 @@
|
|
1
1
|
GEM
|
2
2
|
remote: http://rubygems.org/
|
3
3
|
specs:
|
4
|
-
|
4
|
+
builder (3.0.0)
|
5
|
+
cucumber (1.1.4)
|
6
|
+
builder (>= 2.1.2)
|
7
|
+
diff-lcs (>= 1.1.2)
|
8
|
+
gherkin (~> 2.7.1)
|
9
|
+
json (>= 1.4.6)
|
10
|
+
term-ansicolor (>= 1.0.6)
|
11
|
+
diff-lcs (1.1.3)
|
12
|
+
gherkin (2.7.6)
|
13
|
+
json (>= 1.4.6)
|
5
14
|
git (1.2.5)
|
6
|
-
jeweler (1.
|
15
|
+
jeweler (1.8.3)
|
7
16
|
bundler (~> 1.0)
|
8
17
|
git (>= 1.2.5)
|
9
18
|
rake
|
10
|
-
|
19
|
+
rdoc
|
20
|
+
json (1.6.5)
|
21
|
+
rake (0.9.2.2)
|
11
22
|
rcov (0.9.9)
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
rspec-
|
16
|
-
|
17
|
-
|
23
|
+
rdoc (3.12)
|
24
|
+
json (~> 1.4)
|
25
|
+
rspec (2.8.0)
|
26
|
+
rspec-core (~> 2.8.0)
|
27
|
+
rspec-expectations (~> 2.8.0)
|
28
|
+
rspec-mocks (~> 2.8.0)
|
29
|
+
rspec-core (2.8.0)
|
30
|
+
rspec-expectations (2.8.0)
|
18
31
|
diff-lcs (~> 1.1.2)
|
19
|
-
rspec-mocks (2.
|
32
|
+
rspec-mocks (2.8.0)
|
33
|
+
term-ansicolor (1.0.7)
|
20
34
|
|
21
35
|
PLATFORMS
|
22
36
|
ruby
|
23
37
|
|
24
38
|
DEPENDENCIES
|
25
39
|
bundler (~> 1.0.0)
|
26
|
-
|
40
|
+
cucumber
|
41
|
+
jeweler (~> 1.8.3)
|
27
42
|
rcov
|
28
|
-
|
43
|
+
rdoc (~> 3.12)
|
44
|
+
rspec (~> 2.8.0)
|
data/Rakefile
CHANGED
data/VERSION
CHANGED
@@ -1 +1 @@
|
|
1
|
-
0.
|
1
|
+
0.2.0
|
data/lib/periodic-scheduler.rb
CHANGED
@@ -3,6 +3,7 @@ require 'set'
|
|
3
3
|
|
4
4
|
class PeriodicScheduler
|
5
5
|
class MissedScheduleError < RuntimeError; end
|
6
|
+
class EmptyScheduleError < RuntimeError; end
|
6
7
|
|
7
8
|
class Event
|
8
9
|
attr_reader :period
|
@@ -63,7 +64,10 @@ class PeriodicScheduler
|
|
63
64
|
end
|
64
65
|
|
65
66
|
|
66
|
-
def initialize(quantum = 5.0,
|
67
|
+
def initialize(quantum = 5.0, options = {})
|
68
|
+
time_source = (options[:time_source] or lambda {Time.now.to_f})
|
69
|
+
wait_function = (options[:wait_function] or lambda{|t| sleep t})
|
70
|
+
|
67
71
|
@quantized_space = RealTimeToQuantizedSpaceProjection.new(
|
68
72
|
quantum,
|
69
73
|
lambda {|v| v.floor}
|
@@ -86,12 +90,22 @@ class PeriodicScheduler
|
|
86
90
|
@event_groups_to_unschedule << group
|
87
91
|
end
|
88
92
|
|
89
|
-
def
|
93
|
+
def run!
|
94
|
+
begin
|
95
|
+
loop do
|
96
|
+
run.each do |error|
|
97
|
+
yield error if block_given?
|
98
|
+
end
|
99
|
+
end
|
100
|
+
rescue EmptyScheduleError
|
101
|
+
end
|
102
|
+
end
|
103
|
+
|
104
|
+
def run
|
90
105
|
process_unsheduled_events
|
91
106
|
|
92
107
|
earliest_quant = @events.keys.sort[0]
|
93
|
-
|
94
|
-
return nil unless earliest_quant
|
108
|
+
raise EmptyScheduleError, "no events scheduled" unless earliest_quant
|
95
109
|
|
96
110
|
errors = []
|
97
111
|
|
@@ -111,9 +125,9 @@ class PeriodicScheduler
|
|
111
125
|
|
112
126
|
qnow = quantized_now
|
113
127
|
quants = @events.keys.select{|k| k <= qnow}.sort
|
114
|
-
# It may happen that wait returned qucker
|
128
|
+
# It may happen that wait returned qucker than it should
|
115
129
|
if quants.empty?
|
116
|
-
return
|
130
|
+
return run
|
117
131
|
end
|
118
132
|
|
119
133
|
quants.each do |q|
|
@@ -132,6 +146,13 @@ class PeriodicScheduler
|
|
132
146
|
errors
|
133
147
|
end
|
134
148
|
|
149
|
+
def empty?
|
150
|
+
# do the cleanup - this may be causing problems!
|
151
|
+
process_unsheduled_events
|
152
|
+
|
153
|
+
@events.empty?
|
154
|
+
end
|
155
|
+
|
135
156
|
private
|
136
157
|
|
137
158
|
def process_unsheduled_events
|
@@ -0,0 +1,67 @@
|
|
1
|
+
# Generated by jeweler
|
2
|
+
# DO NOT EDIT THIS FILE DIRECTLY
|
3
|
+
# Instead, edit Jeweler::Tasks in Rakefile, and run 'rake gemspec'
|
4
|
+
# -*- encoding: utf-8 -*-
|
5
|
+
|
6
|
+
Gem::Specification.new do |s|
|
7
|
+
s.name = "periodic-scheduler"
|
8
|
+
s.version = "0.2.0"
|
9
|
+
|
10
|
+
s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
|
11
|
+
s.authors = ["Jakub Pastuszek"]
|
12
|
+
s.date = "2012-02-03"
|
13
|
+
s.description = "Controls execution of periodic scheduled tasks."
|
14
|
+
s.email = "jpastuszek@gmail.com"
|
15
|
+
s.extra_rdoc_files = [
|
16
|
+
"LICENSE.txt",
|
17
|
+
"README.rdoc"
|
18
|
+
]
|
19
|
+
s.files = [
|
20
|
+
".document",
|
21
|
+
".rspec",
|
22
|
+
"Gemfile",
|
23
|
+
"Gemfile.lock",
|
24
|
+
"LICENSE.txt",
|
25
|
+
"README.rdoc",
|
26
|
+
"Rakefile",
|
27
|
+
"VERSION",
|
28
|
+
"lib/periodic-scheduler.rb",
|
29
|
+
"lib/quantized_time_space.rb",
|
30
|
+
"periodic-scheduler.gemspec",
|
31
|
+
"spec/periodic-scheduler_spec.rb",
|
32
|
+
"spec/spec_helper.rb"
|
33
|
+
]
|
34
|
+
s.homepage = "http://github.com/jpastuszek/periodic-scheduler"
|
35
|
+
s.licenses = ["MIT"]
|
36
|
+
s.require_paths = ["lib"]
|
37
|
+
s.rubygems_version = "1.8.10"
|
38
|
+
s.summary = "Scheduler for periodic tasks."
|
39
|
+
|
40
|
+
if s.respond_to? :specification_version then
|
41
|
+
s.specification_version = 3
|
42
|
+
|
43
|
+
if Gem::Version.new(Gem::VERSION) >= Gem::Version.new('1.2.0') then
|
44
|
+
s.add_development_dependency(%q<rspec>, ["~> 2.8.0"])
|
45
|
+
s.add_development_dependency(%q<rdoc>, ["~> 3.12"])
|
46
|
+
s.add_development_dependency(%q<cucumber>, [">= 0"])
|
47
|
+
s.add_development_dependency(%q<bundler>, ["~> 1.0.0"])
|
48
|
+
s.add_development_dependency(%q<jeweler>, ["~> 1.8.3"])
|
49
|
+
s.add_development_dependency(%q<rcov>, [">= 0"])
|
50
|
+
else
|
51
|
+
s.add_dependency(%q<rspec>, ["~> 2.8.0"])
|
52
|
+
s.add_dependency(%q<rdoc>, ["~> 3.12"])
|
53
|
+
s.add_dependency(%q<cucumber>, [">= 0"])
|
54
|
+
s.add_dependency(%q<bundler>, ["~> 1.0.0"])
|
55
|
+
s.add_dependency(%q<jeweler>, ["~> 1.8.3"])
|
56
|
+
s.add_dependency(%q<rcov>, [">= 0"])
|
57
|
+
end
|
58
|
+
else
|
59
|
+
s.add_dependency(%q<rspec>, ["~> 2.8.0"])
|
60
|
+
s.add_dependency(%q<rdoc>, ["~> 3.12"])
|
61
|
+
s.add_dependency(%q<cucumber>, [">= 0"])
|
62
|
+
s.add_dependency(%q<bundler>, ["~> 1.0.0"])
|
63
|
+
s.add_dependency(%q<jeweler>, ["~> 1.8.3"])
|
64
|
+
s.add_dependency(%q<rcov>, [">= 0"])
|
65
|
+
end
|
66
|
+
end
|
67
|
+
|
@@ -3,10 +3,12 @@ require 'periodic-scheduler'
|
|
3
3
|
describe PeriodicScheduler do
|
4
4
|
before :each do
|
5
5
|
@time_now = 0
|
6
|
-
@
|
7
|
-
|
8
|
-
|
9
|
-
|
6
|
+
@options = {
|
7
|
+
:time_source => lambda{@time_now},
|
8
|
+
:wait_function => lambda{|t|
|
9
|
+
@time_now += t
|
10
|
+
#puts "sleeping for #{t}"
|
11
|
+
}
|
10
12
|
}
|
11
13
|
|
12
14
|
@got_events = []
|
@@ -17,7 +19,7 @@ describe PeriodicScheduler do
|
|
17
19
|
end
|
18
20
|
|
19
21
|
it "should execut event callbacks given time progress" do
|
20
|
-
s = PeriodicScheduler.new(5.0, @
|
22
|
+
s = PeriodicScheduler.new(5.0, @options)
|
21
23
|
|
22
24
|
s.schedule(11.5) do
|
23
25
|
@got_event.call(1)
|
@@ -32,25 +34,21 @@ describe PeriodicScheduler do
|
|
32
34
|
end
|
33
35
|
|
34
36
|
@got_events.should == []
|
37
|
+
s.empty?.should == false
|
35
38
|
|
36
|
-
s.
|
39
|
+
s.run
|
37
40
|
@got_events.should == [1, 2]
|
38
41
|
@time_now.should == 10.0
|
39
42
|
|
40
|
-
s.
|
43
|
+
s.run
|
41
44
|
@got_events.should == [1, 2, 3]
|
42
45
|
@time_now.should == 20.0
|
43
46
|
|
44
|
-
|
45
|
-
s.wait_events
|
46
|
-
@got_events.should == [1, 2, 3]
|
47
|
-
|
48
|
-
s.wait_events
|
49
|
-
@got_events.should == [1, 2, 3]
|
47
|
+
s.empty?.should == true
|
50
48
|
end
|
51
49
|
|
52
50
|
it "should reschedule resheduable tasks" do
|
53
|
-
s = PeriodicScheduler.new(5.0, @
|
51
|
+
s = PeriodicScheduler.new(5.0, @options)
|
54
52
|
|
55
53
|
s.schedule(15, true) do
|
56
54
|
@got_event.call(1)
|
@@ -58,21 +56,21 @@ describe PeriodicScheduler do
|
|
58
56
|
|
59
57
|
@got_events.should == []
|
60
58
|
|
61
|
-
s.
|
59
|
+
s.run
|
62
60
|
@got_events.should == [1]
|
63
61
|
@time_now.should == 15.0
|
64
62
|
|
65
|
-
s.
|
63
|
+
s.run
|
66
64
|
@got_events.should == [1, 1]
|
67
65
|
@time_now.should == 30
|
68
66
|
|
69
|
-
s.
|
67
|
+
s.run
|
70
68
|
@got_events.should == [1, 1, 1]
|
71
69
|
@time_now.should == 45
|
72
70
|
end
|
73
71
|
|
74
72
|
it "should compensate for quntization error" do
|
75
|
-
s = PeriodicScheduler.new(5.0, @
|
73
|
+
s = PeriodicScheduler.new(5.0, @options)
|
76
74
|
|
77
75
|
# Note that now we are using floor to quantize event
|
78
76
|
s.schedule(12, true) do
|
@@ -81,41 +79,41 @@ describe PeriodicScheduler do
|
|
81
79
|
|
82
80
|
@got_events.should == []
|
83
81
|
|
84
|
-
s.
|
82
|
+
s.run
|
85
83
|
@got_events.should == [1]
|
86
84
|
@time_now.should == 10
|
87
85
|
|
88
|
-
s.
|
86
|
+
s.run
|
89
87
|
@got_events.should == [1, 1]
|
90
88
|
@time_now.should == 20
|
91
89
|
|
92
|
-
s.
|
90
|
+
s.run
|
93
91
|
@got_events.should == [1, 1, 1]
|
94
92
|
@time_now.should == 35
|
95
93
|
|
96
|
-
s.
|
94
|
+
s.run
|
97
95
|
@got_events.should == [1, 1, 1, 1]
|
98
96
|
@time_now.should == 45
|
99
97
|
|
100
|
-
s.
|
98
|
+
s.run
|
101
99
|
@got_events.should == [1, 1, 1, 1, 1]
|
102
100
|
@time_now.should == 60
|
103
101
|
|
104
|
-
s.
|
102
|
+
s.run
|
105
103
|
@got_events.should == [1, 1, 1, 1, 1, 1]
|
106
104
|
@time_now.should == 70
|
107
105
|
end
|
108
106
|
|
109
107
|
it "should compensate for wait function jitter" do
|
110
108
|
jitter = [1, 0, 5, -1, 0.5, -0.2, 0, 0, 0]
|
111
|
-
@
|
109
|
+
@options[:wait_function] = lambda{|t|
|
112
110
|
j = jitter.shift
|
113
111
|
#puts "time is: #{@time_now}"
|
114
112
|
@time_now += t + j
|
115
113
|
#puts "sleeping fou #{t} + jitter #{j}: #{t + j}"
|
116
114
|
}
|
117
115
|
|
118
|
-
s = PeriodicScheduler.new(5.0, @
|
116
|
+
s = PeriodicScheduler.new(5.0, @options)
|
119
117
|
|
120
118
|
s.schedule(12, true) do
|
121
119
|
@got_event.call(1)
|
@@ -123,38 +121,38 @@ describe PeriodicScheduler do
|
|
123
121
|
|
124
122
|
@got_events.should == []
|
125
123
|
|
126
|
-
s.
|
124
|
+
s.run
|
127
125
|
@got_events.should == [1]
|
128
126
|
@time_now.should == 11
|
129
127
|
|
130
|
-
s.
|
128
|
+
s.run
|
131
129
|
@got_events.should == [1, 1]
|
132
130
|
@time_now.should == 20
|
133
131
|
|
134
|
-
s.
|
132
|
+
s.run
|
135
133
|
@got_events.should == [1, 1, 1]
|
136
134
|
@time_now.should == 40
|
137
135
|
|
138
|
-
s.
|
136
|
+
s.run
|
139
137
|
@got_events.should == [1, 1, 1, 1]
|
140
138
|
@time_now.should == 45.5
|
141
139
|
|
142
|
-
s.
|
140
|
+
s.run
|
143
141
|
@got_events.should == [1, 1, 1, 1, 1]
|
144
142
|
@time_now.should == 60
|
145
143
|
|
146
|
-
s.
|
144
|
+
s.run
|
147
145
|
@got_events.should == [1, 1, 1, 1, 1, 1]
|
148
146
|
@time_now.should == 70.0
|
149
147
|
|
150
|
-
s.
|
148
|
+
s.run
|
151
149
|
@got_events.should == [1, 1, 1, 1, 1, 1, 1]
|
152
150
|
@time_now.should == 80.0
|
153
151
|
end
|
154
152
|
|
155
153
|
it "should keep average scheduling precision over longer time" do
|
156
154
|
srand(100) # make rand deterministic
|
157
|
-
@
|
155
|
+
@options[:wait_function] = lambda{|t|
|
158
156
|
j = (rand - 0.5) * 10
|
159
157
|
@time_now += t + j
|
160
158
|
}
|
@@ -167,7 +165,7 @@ describe PeriodicScheduler do
|
|
167
165
|
ev2 = []
|
168
166
|
ev2_last = 0
|
169
167
|
|
170
|
-
s = PeriodicScheduler.new(5.0, @
|
168
|
+
s = PeriodicScheduler.new(5.0, @options)
|
171
169
|
|
172
170
|
s.schedule(ev1_val, true) do
|
173
171
|
ev1 << @time_now - ev1_last
|
@@ -179,20 +177,20 @@ describe PeriodicScheduler do
|
|
179
177
|
ev2_last = @time_now
|
180
178
|
end
|
181
179
|
|
182
|
-
10000.times{ s.
|
180
|
+
10000.times{ s.run }
|
183
181
|
|
184
182
|
(ev1.inject(0){|v, s| v + s} / ev1.length).should be_within(0.001).of(ev1_val)
|
185
183
|
(ev2.inject(0){|v, s| v + s} / ev2.length).should be_within(0.001).of(ev2_val)
|
186
184
|
end
|
187
185
|
|
188
186
|
it "should support grouping of events" do
|
189
|
-
s = PeriodicScheduler.new(5.0, @
|
187
|
+
s = PeriodicScheduler.new(5.0, @options)
|
190
188
|
|
191
189
|
s.schedule(12, true, "test group") {}
|
192
190
|
end
|
193
191
|
|
194
192
|
it "should support unscheduling of all events within a group" do
|
195
|
-
s = PeriodicScheduler.new(5.0, @
|
193
|
+
s = PeriodicScheduler.new(5.0, @options)
|
196
194
|
|
197
195
|
s.schedule(15, true, "g1") do
|
198
196
|
@got_event.call(1)
|
@@ -208,37 +206,37 @@ describe PeriodicScheduler do
|
|
208
206
|
|
209
207
|
@got_events.should == []
|
210
208
|
|
211
|
-
s.
|
209
|
+
s.run
|
212
210
|
@got_events.should == [1]
|
213
211
|
@time_now.should == 15
|
214
212
|
|
215
|
-
s.
|
213
|
+
s.run
|
216
214
|
@got_events.should == [1, 2]
|
217
215
|
@time_now.should == 20
|
218
216
|
|
219
|
-
s.
|
217
|
+
s.run
|
220
218
|
@got_events.should == [1, 2, 3]
|
221
219
|
@time_now.should == 25
|
222
220
|
|
223
|
-
s.
|
221
|
+
s.run
|
224
222
|
@got_events.should == [1, 2, 3, 1]
|
225
223
|
@time_now.should == 30
|
226
224
|
|
227
225
|
s.unschedule_group("g1")
|
228
226
|
|
229
|
-
s.
|
227
|
+
s.run
|
230
228
|
@got_events.should == [1, 2, 3, 1, 3]
|
231
229
|
@time_now.should == 50
|
232
230
|
|
231
|
+
s.empty?.should == false
|
232
|
+
|
233
233
|
s.unschedule_group("g2")
|
234
234
|
|
235
|
-
s.
|
236
|
-
@got_events.should == [1, 2, 3, 1, 3]
|
237
|
-
@time_now.should == 50
|
235
|
+
s.empty?.should == true
|
238
236
|
end
|
239
237
|
|
240
238
|
it "should support unscheduling of all events within a group from other event" do
|
241
|
-
s = PeriodicScheduler.new(1.0, @
|
239
|
+
s = PeriodicScheduler.new(1.0, @options)
|
242
240
|
|
243
241
|
s.schedule(2, true, "g4") do
|
244
242
|
s.unschedule_group("g2")
|
@@ -259,23 +257,23 @@ describe PeriodicScheduler do
|
|
259
257
|
|
260
258
|
@got_events.should == []
|
261
259
|
|
262
|
-
s.
|
260
|
+
s.run
|
263
261
|
@got_events.should == [1, 2, 3]
|
264
262
|
@time_now.should == 1
|
265
263
|
|
266
264
|
# They will get executed this time
|
267
|
-
s.
|
265
|
+
s.run
|
268
266
|
@got_events.should == [1, 2, 3, 4, 1, 2, 3]
|
269
267
|
@time_now.should == 2
|
270
268
|
|
271
269
|
# They should be not rescheduled and gone
|
272
|
-
s.
|
270
|
+
s.run
|
273
271
|
@got_events.should == [1, 2, 3, 4, 1, 2, 3, 1]
|
274
272
|
@time_now.should == 3
|
275
273
|
end
|
276
274
|
|
277
275
|
it "should execut all not reschedulable tasks if we miss them" do
|
278
|
-
s = PeriodicScheduler.new(5.0, @
|
276
|
+
s = PeriodicScheduler.new(5.0, @options)
|
279
277
|
|
280
278
|
s.schedule(15) do
|
281
279
|
@got_event.call(1)
|
@@ -289,34 +287,34 @@ describe PeriodicScheduler do
|
|
289
287
|
@got_event.call(3)
|
290
288
|
end
|
291
289
|
|
292
|
-
@
|
290
|
+
@options[:wait_function].call(35)
|
293
291
|
|
294
|
-
s.
|
292
|
+
s.run.should
|
295
293
|
@got_events.should == [1, 2]
|
296
294
|
|
297
|
-
s.
|
295
|
+
s.run.should
|
298
296
|
@got_events.should == [1, 2, 3]
|
299
297
|
end
|
300
298
|
|
301
299
|
it "should skpi reschedulable tasks if we miss them" do
|
302
300
|
#TODO: this behaviour is a bit of gary area
|
303
|
-
s = PeriodicScheduler.new(5.0, @
|
301
|
+
s = PeriodicScheduler.new(5.0, @options)
|
304
302
|
|
305
303
|
s.schedule(15, true) do
|
306
304
|
@got_event.call(1)
|
307
305
|
end
|
308
306
|
|
309
|
-
@
|
307
|
+
@options[:wait_function].call(35)
|
310
308
|
|
311
|
-
s.
|
309
|
+
s.run.should
|
312
310
|
@got_events.should == [1]
|
313
311
|
|
314
|
-
s.
|
312
|
+
s.run.should
|
315
313
|
@got_events.should == [1, 1]
|
316
314
|
end
|
317
315
|
|
318
316
|
it "should report error if the schedule was missed" do
|
319
|
-
s = PeriodicScheduler.new(5.0, @
|
317
|
+
s = PeriodicScheduler.new(5.0, @options)
|
320
318
|
|
321
319
|
s.schedule(15) do
|
322
320
|
@got_event.call(1)
|
@@ -326,48 +324,97 @@ describe PeriodicScheduler do
|
|
326
324
|
@got_event.call(2)
|
327
325
|
end
|
328
326
|
|
329
|
-
@
|
327
|
+
@options[:wait_function].call(35)
|
330
328
|
|
331
|
-
errors = s.
|
329
|
+
errors = s.run
|
332
330
|
errors.should_not be_empty
|
333
331
|
errors[0].class.should == PeriodicScheduler::MissedScheduleError
|
334
332
|
@got_events.should == [1, 2]
|
335
333
|
end
|
336
334
|
|
337
|
-
|
335
|
+
describe "run" do
|
336
|
+
it "should handle events call exceptions and return them" do
|
337
|
+
s = PeriodicScheduler.new(5.0, @options)
|
338
338
|
|
339
|
-
|
340
|
-
|
341
|
-
|
342
|
-
@time = lambda{@time_now}
|
343
|
-
@wait = lambda{|t| @time_now += t}
|
344
|
-
end
|
339
|
+
s.schedule(12, true) do
|
340
|
+
fail "test"
|
341
|
+
end
|
345
342
|
|
346
|
-
|
347
|
-
s = PeriodicScheduler.new(5.0, @time, @wait)
|
343
|
+
errors = nil
|
348
344
|
|
349
|
-
|
350
|
-
|
345
|
+
lambda {
|
346
|
+
errors = s.run
|
347
|
+
}.should_not raise_exception
|
348
|
+
|
349
|
+
errors.should have(1).error
|
350
|
+
errors[0].should be_kind_of RuntimeError
|
351
|
+
errors[0].to_s.should == "test"
|
351
352
|
end
|
352
353
|
|
353
|
-
|
354
|
+
it "should raise PeriodicScheduler::EmptyScheduleError if there are no events left to process" do
|
355
|
+
s = PeriodicScheduler.new(5.0, @options)
|
356
|
+
|
357
|
+
s.schedule(12) {}
|
354
358
|
|
355
|
-
|
356
|
-
|
357
|
-
|
359
|
+
lambda {
|
360
|
+
s.run
|
361
|
+
}.should_not raise_error
|
358
362
|
|
359
|
-
|
360
|
-
|
361
|
-
|
363
|
+
lambda {
|
364
|
+
s.run
|
365
|
+
}.should raise_error PeriodicScheduler::EmptyScheduleError
|
366
|
+
end
|
362
367
|
end
|
363
368
|
|
364
|
-
|
365
|
-
|
369
|
+
describe "#run!" do
|
370
|
+
it "should run schedule until there is no more events sheduled" do
|
371
|
+
s = PeriodicScheduler.new(5.0, @options)
|
372
|
+
|
373
|
+
s.schedule(5) do
|
374
|
+
@got_event.call(1)
|
375
|
+
end
|
376
|
+
|
377
|
+
s.schedule(10) do
|
378
|
+
@got_event.call(2)
|
379
|
+
end
|
380
|
+
|
381
|
+
s.schedule(15) do
|
382
|
+
@got_event.call(3)
|
383
|
+
end
|
384
|
+
|
385
|
+
s.run!
|
386
|
+
|
387
|
+
@got_events.should == [1, 2, 3]
|
388
|
+
end
|
366
389
|
|
367
|
-
|
390
|
+
it "should call block on event error" do
|
391
|
+
s = PeriodicScheduler.new(5.0, @options)
|
368
392
|
|
369
|
-
|
370
|
-
|
393
|
+
s.schedule(5) do
|
394
|
+
raise "1"
|
395
|
+
end
|
396
|
+
|
397
|
+
s.schedule(10) do
|
398
|
+
@got_event.call(1)
|
399
|
+
end
|
400
|
+
|
401
|
+
s.schedule(15) do
|
402
|
+
raise "2"
|
403
|
+
end
|
404
|
+
|
405
|
+
s.schedule(15) do
|
406
|
+
@got_event.call(2)
|
407
|
+
end
|
408
|
+
|
409
|
+
@got_fails = []
|
410
|
+
s.run! do |error|
|
411
|
+
error.should be_kind_of RuntimeError
|
412
|
+
@got_fails << error.message
|
413
|
+
end
|
414
|
+
|
415
|
+
@got_fails.map{|m| m.to_i}.should == [1, 2]
|
416
|
+
@got_events.should == [1, 2]
|
417
|
+
end
|
371
418
|
end
|
372
419
|
end
|
373
420
|
|
metadata
CHANGED
@@ -1,13 +1,13 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: periodic-scheduler
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
hash:
|
5
|
-
prerelease:
|
4
|
+
hash: 23
|
5
|
+
prerelease:
|
6
6
|
segments:
|
7
7
|
- 0
|
8
|
-
-
|
8
|
+
- 2
|
9
9
|
- 0
|
10
|
-
version: 0.
|
10
|
+
version: 0.2.0
|
11
11
|
platform: ruby
|
12
12
|
authors:
|
13
13
|
- Jakub Pastuszek
|
@@ -15,28 +15,56 @@ autorequire:
|
|
15
15
|
bindir: bin
|
16
16
|
cert_chain: []
|
17
17
|
|
18
|
-
date:
|
19
|
-
default_executable:
|
18
|
+
date: 2012-02-03 00:00:00 Z
|
20
19
|
dependencies:
|
21
20
|
- !ruby/object:Gem::Dependency
|
22
|
-
|
23
|
-
|
21
|
+
type: :development
|
22
|
+
requirement: &id001 !ruby/object:Gem::Requirement
|
24
23
|
none: false
|
25
24
|
requirements:
|
26
|
-
- -
|
25
|
+
- - ~>
|
27
26
|
- !ruby/object:Gem::Version
|
28
|
-
hash:
|
27
|
+
hash: 47
|
29
28
|
segments:
|
30
29
|
- 2
|
31
|
-
-
|
30
|
+
- 8
|
32
31
|
- 0
|
33
|
-
version: 2.
|
32
|
+
version: 2.8.0
|
33
|
+
prerelease: false
|
34
34
|
name: rspec
|
35
|
-
|
35
|
+
version_requirements: *id001
|
36
|
+
- !ruby/object:Gem::Dependency
|
36
37
|
type: :development
|
38
|
+
requirement: &id002 !ruby/object:Gem::Requirement
|
39
|
+
none: false
|
40
|
+
requirements:
|
41
|
+
- - ~>
|
42
|
+
- !ruby/object:Gem::Version
|
43
|
+
hash: 31
|
44
|
+
segments:
|
45
|
+
- 3
|
46
|
+
- 12
|
47
|
+
version: "3.12"
|
48
|
+
prerelease: false
|
49
|
+
name: rdoc
|
50
|
+
version_requirements: *id002
|
37
51
|
- !ruby/object:Gem::Dependency
|
52
|
+
type: :development
|
53
|
+
requirement: &id003 !ruby/object:Gem::Requirement
|
54
|
+
none: false
|
55
|
+
requirements:
|
56
|
+
- - ">="
|
57
|
+
- !ruby/object:Gem::Version
|
58
|
+
hash: 3
|
59
|
+
segments:
|
60
|
+
- 0
|
61
|
+
version: "0"
|
38
62
|
prerelease: false
|
39
|
-
|
63
|
+
name: cucumber
|
64
|
+
version_requirements: *id003
|
65
|
+
- !ruby/object:Gem::Dependency
|
66
|
+
type: :development
|
67
|
+
requirement: &id004 !ruby/object:Gem::Requirement
|
40
68
|
none: false
|
41
69
|
requirements:
|
42
70
|
- - ~>
|
@@ -47,28 +75,28 @@ dependencies:
|
|
47
75
|
- 0
|
48
76
|
- 0
|
49
77
|
version: 1.0.0
|
78
|
+
prerelease: false
|
50
79
|
name: bundler
|
51
|
-
|
52
|
-
type: :development
|
80
|
+
version_requirements: *id004
|
53
81
|
- !ruby/object:Gem::Dependency
|
54
|
-
|
55
|
-
|
82
|
+
type: :development
|
83
|
+
requirement: &id005 !ruby/object:Gem::Requirement
|
56
84
|
none: false
|
57
85
|
requirements:
|
58
86
|
- - ~>
|
59
87
|
- !ruby/object:Gem::Version
|
60
|
-
hash:
|
88
|
+
hash: 49
|
61
89
|
segments:
|
62
90
|
- 1
|
63
|
-
-
|
64
|
-
-
|
65
|
-
version: 1.
|
91
|
+
- 8
|
92
|
+
- 3
|
93
|
+
version: 1.8.3
|
94
|
+
prerelease: false
|
66
95
|
name: jeweler
|
67
|
-
|
68
|
-
type: :development
|
96
|
+
version_requirements: *id005
|
69
97
|
- !ruby/object:Gem::Dependency
|
70
|
-
|
71
|
-
|
98
|
+
type: :development
|
99
|
+
requirement: &id006 !ruby/object:Gem::Requirement
|
72
100
|
none: false
|
73
101
|
requirements:
|
74
102
|
- - ">="
|
@@ -77,9 +105,9 @@ dependencies:
|
|
77
105
|
segments:
|
78
106
|
- 0
|
79
107
|
version: "0"
|
108
|
+
prerelease: false
|
80
109
|
name: rcov
|
81
|
-
|
82
|
-
type: :development
|
110
|
+
version_requirements: *id006
|
83
111
|
description: Controls execution of periodic scheduled tasks.
|
84
112
|
email: jpastuszek@gmail.com
|
85
113
|
executables: []
|
@@ -100,9 +128,9 @@ files:
|
|
100
128
|
- VERSION
|
101
129
|
- lib/periodic-scheduler.rb
|
102
130
|
- lib/quantized_time_space.rb
|
131
|
+
- periodic-scheduler.gemspec
|
103
132
|
- spec/periodic-scheduler_spec.rb
|
104
133
|
- spec/spec_helper.rb
|
105
|
-
has_rdoc: true
|
106
134
|
homepage: http://github.com/jpastuszek/periodic-scheduler
|
107
135
|
licenses:
|
108
136
|
- MIT
|
@@ -132,7 +160,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
132
160
|
requirements: []
|
133
161
|
|
134
162
|
rubyforge_project:
|
135
|
-
rubygems_version: 1.
|
163
|
+
rubygems_version: 1.8.10
|
136
164
|
signing_key:
|
137
165
|
specification_version: 3
|
138
166
|
summary: Scheduler for periodic tasks.
|