periodic-scheduler 0.1.0 → 0.2.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.
- 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.
|