periodic-scheduler 0.4.0 → 0.5.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/VERSION +1 -1
- data/lib/periodic-scheduler.rb +93 -112
- data/periodic-scheduler.gemspec +2 -3
- data/spec/periodic-scheduler_spec.rb +67 -70
- metadata +15 -16
- data/lib/quantized_time_space.rb +0 -20
data/VERSION
CHANGED
@@ -1 +1 @@
|
|
1
|
-
0.
|
1
|
+
0.5.0
|
data/lib/periodic-scheduler.rb
CHANGED
@@ -1,68 +1,78 @@
|
|
1
|
-
require 'quantized_time_space'
|
2
|
-
require 'set'
|
3
|
-
|
4
1
|
class PeriodicScheduler
|
5
2
|
class MissedScheduleError < RuntimeError; end
|
6
3
|
class EmptyScheduleError < RuntimeError; end
|
7
4
|
|
5
|
+
class RealTimeToQuantizedSpaceProjection
|
6
|
+
def initialize(quantum_size, quantization_rule)
|
7
|
+
@quantum_size = quantum_size
|
8
|
+
@quantization_rule = quantization_rule
|
9
|
+
end
|
10
|
+
|
11
|
+
def project(value)
|
12
|
+
@quantization_rule.call(value / @quantum_size)
|
13
|
+
end
|
14
|
+
|
15
|
+
def revers_project(value)
|
16
|
+
value * @quantum_size
|
17
|
+
end
|
18
|
+
|
19
|
+
def projection_error(value)
|
20
|
+
value - revers_project(project(value))
|
21
|
+
end
|
22
|
+
end
|
23
|
+
|
8
24
|
class Event
|
25
|
+
attr_reader :quantum_period
|
9
26
|
attr_reader :period
|
10
|
-
attr_reader :
|
11
|
-
attr_reader :group
|
27
|
+
attr_reader :keep
|
12
28
|
attr_reader :callback
|
13
29
|
|
14
|
-
def initialize(
|
30
|
+
def initialize(quantized_space, period, keep, &callback)
|
31
|
+
@quantized_space = quantized_space
|
15
32
|
@period = period
|
16
|
-
@
|
17
|
-
@group = group
|
33
|
+
@keep = keep
|
18
34
|
@callback = callback
|
35
|
+
quantatize(period)
|
19
36
|
end
|
20
37
|
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
38
|
+
def reschedule
|
39
|
+
quantatize(@period + @quantum_error)
|
40
|
+
@reschedule_hook.call(self) if @reschedule_hook
|
41
|
+
end
|
25
42
|
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
attr_reader :quantum_error
|
43
|
+
def reschedule_hook(&callback)
|
44
|
+
@reschedule_hook = callback
|
45
|
+
end
|
30
46
|
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
@quantum_error = quantum_error
|
35
|
-
end
|
36
|
-
end
|
47
|
+
def keep?
|
48
|
+
@keep
|
49
|
+
end
|
37
50
|
|
38
|
-
|
39
|
-
|
40
|
-
|
51
|
+
def stop
|
52
|
+
return if @stopped
|
53
|
+
@stopped = true
|
54
|
+
@stop_hook.call(self) if @reschedule_hook
|
55
|
+
end
|
41
56
|
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
@quantized_space.projection_error(event.period)
|
50
|
-
)
|
51
|
-
end
|
57
|
+
def stopped?
|
58
|
+
@stopped
|
59
|
+
end
|
60
|
+
|
61
|
+
def stop_hook(&callback)
|
62
|
+
@stop_hook = callback
|
63
|
+
end
|
52
64
|
|
53
|
-
def
|
54
|
-
|
55
|
-
QuantizedEvent.new(
|
56
|
-
quantized_event.period,
|
57
|
-
quantized_event.reschedule,
|
58
|
-
quantized_event.group,
|
59
|
-
quantized_event.callback,
|
60
|
-
@quantized_space.project(accumulated_period),
|
61
|
-
@quantized_space.projection_error(accumulated_period)
|
62
|
-
)
|
65
|
+
def call
|
66
|
+
@callback.call
|
63
67
|
end
|
64
|
-
end
|
65
68
|
|
69
|
+
private
|
70
|
+
|
71
|
+
def quantatize(period)
|
72
|
+
@quantum_period = @quantized_space.project(period)
|
73
|
+
@quantum_error = @quantized_space.projection_error(period)
|
74
|
+
end
|
75
|
+
end
|
66
76
|
|
67
77
|
def initialize(quantum = 5.0, options = {})
|
68
78
|
time_source = (options[:time_source] or lambda {Time.now.to_f})
|
@@ -70,25 +80,21 @@ class PeriodicScheduler
|
|
70
80
|
|
71
81
|
@quantized_space = RealTimeToQuantizedSpaceProjection.new(
|
72
82
|
quantum,
|
73
|
-
lambda {|v| v.
|
83
|
+
lambda {|v| v.ceil} # behave like sleep - never execute too early
|
74
84
|
)
|
75
|
-
@quantized_event_builder = QuantizedEventBuilder.new(@quantized_space)
|
76
85
|
@time_source = time_source
|
77
86
|
@wait_function = wait_function
|
78
87
|
|
79
88
|
@events = {}
|
80
|
-
@event_groups_to_unschedule = Set.new
|
81
89
|
end
|
82
90
|
|
83
|
-
|
84
|
-
|
85
|
-
|
86
|
-
add_event(event, period)
|
87
|
-
end
|
91
|
+
def after(period, &callback)
|
92
|
+
schedule_event Event.new(@quantized_space, period, false, &callback)
|
93
|
+
end
|
88
94
|
|
89
|
-
|
90
|
-
|
91
|
-
|
95
|
+
def every(period, &callback)
|
96
|
+
schedule_event Event.new(@quantized_space, period, true, &callback)
|
97
|
+
end
|
92
98
|
|
93
99
|
def run!(&block)
|
94
100
|
begin
|
@@ -100,12 +106,8 @@ class PeriodicScheduler
|
|
100
106
|
end
|
101
107
|
|
102
108
|
def run
|
103
|
-
|
104
|
-
|
105
|
-
earliest_quant = @events.keys.sort[0]
|
106
|
-
raise EmptyScheduleError, "no events scheduled" unless earliest_quant
|
107
|
-
|
108
|
-
errors = []
|
109
|
+
earliest_quant = @events.keys.sort.first
|
110
|
+
raise EmptyScheduleError, "no events scheduled" unless earliest_quant
|
109
111
|
|
110
112
|
wait_time = @quantized_space.revers_project(earliest_quant) - real_now
|
111
113
|
if wait_time < 0
|
@@ -113,10 +115,9 @@ class PeriodicScheduler
|
|
113
115
|
begin
|
114
116
|
# we raise it so it has proper content (backtrace)
|
115
117
|
raise MissedScheduleError.new("missed schedule by #{-wait_time} seconds")
|
116
|
-
rescue StandardError =>
|
117
|
-
|
118
|
+
rescue StandardError => error
|
119
|
+
yield error if block_given?
|
118
120
|
end
|
119
|
-
|
120
121
|
wait_time = 0
|
121
122
|
end
|
122
123
|
wait(wait_time)
|
@@ -124,75 +125,55 @@ class PeriodicScheduler
|
|
124
125
|
objects = []
|
125
126
|
|
126
127
|
qnow = quantized_now
|
127
|
-
quants = @events.keys.select{|k| k <= qnow}.sort
|
128
128
|
|
129
|
-
|
130
|
-
|
131
|
-
if quants.empty?
|
132
|
-
return objects
|
133
|
-
end
|
129
|
+
# move quants to be run away to separate array
|
130
|
+
quants = @events.keys.select{|k| k <= qnow}.sort.map{|q| @events.delete(q)}
|
134
131
|
|
135
132
|
# Call callback for every quant and reschedule if needed
|
136
|
-
quants.each do |
|
137
|
-
|
138
|
-
@events.delete(q)
|
133
|
+
quants.each do |events|
|
134
|
+
# get all events for quantum that are not stopped
|
139
135
|
events.each do |e|
|
140
136
|
begin
|
141
137
|
objects << e.call
|
142
|
-
rescue StandardError =>
|
143
|
-
|
138
|
+
rescue StandardError => error
|
139
|
+
# Yield errors to block
|
140
|
+
yield error if block_given?
|
144
141
|
end
|
145
|
-
|
142
|
+
e.reschedule if e.keep? and not e.stopped?
|
146
143
|
end
|
147
144
|
end
|
148
|
-
|
149
|
-
# Yield errors to block
|
150
|
-
if block_given?
|
151
|
-
errors.each do |error|
|
152
|
-
yield error
|
153
|
-
end
|
154
|
-
end
|
155
145
|
|
156
146
|
# return collected callabck return objects
|
157
147
|
objects
|
158
148
|
end
|
159
149
|
|
160
150
|
def empty?
|
161
|
-
|
162
|
-
process_unsheduled_events
|
163
|
-
|
164
|
-
@events.empty?
|
151
|
+
@events.empty?
|
165
152
|
end
|
166
153
|
|
167
154
|
private
|
168
155
|
|
169
|
-
|
170
|
-
|
171
|
-
|
172
|
-
new_events = {}
|
156
|
+
def schedule_event(event, from = quantized_now)
|
157
|
+
quant = from + event.quantum_period
|
158
|
+
(@events[quant] ||= []) << event
|
173
159
|
|
174
|
-
|
175
|
-
|
176
|
-
|
177
|
-
|
178
|
-
|
179
|
-
new_events[quant] = evs unless evs.empty?
|
180
|
-
end
|
160
|
+
event.reschedule_hook do |event|
|
161
|
+
unschedule_event(event, quant)
|
162
|
+
schedule_event(event, quant)
|
163
|
+
end
|
181
164
|
|
182
|
-
|
183
|
-
|
184
|
-
|
165
|
+
event.stop_hook do |event|
|
166
|
+
unschedule_event(event, quant)
|
167
|
+
end
|
185
168
|
|
186
|
-
|
187
|
-
|
188
|
-
@events[period] << quantized_event
|
189
|
-
end
|
169
|
+
event
|
170
|
+
end
|
190
171
|
|
191
|
-
|
192
|
-
|
193
|
-
|
194
|
-
|
195
|
-
|
172
|
+
def unschedule_event(event, quant)
|
173
|
+
return unless @events[quant]
|
174
|
+
@events[quant].delete(event)
|
175
|
+
@events.delete(quant) if @events[quant].empty?
|
176
|
+
end
|
196
177
|
|
197
178
|
def wait(time)
|
198
179
|
fail "time must be a positive number" if time < 0
|
data/periodic-scheduler.gemspec
CHANGED
@@ -5,11 +5,11 @@
|
|
5
5
|
|
6
6
|
Gem::Specification.new do |s|
|
7
7
|
s.name = "periodic-scheduler"
|
8
|
-
s.version = "0.
|
8
|
+
s.version = "0.5.0"
|
9
9
|
|
10
10
|
s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
|
11
11
|
s.authors = ["Jakub Pastuszek"]
|
12
|
-
s.date = "2012-
|
12
|
+
s.date = "2012-11-03"
|
13
13
|
s.description = "Controls execution of periodic scheduled tasks."
|
14
14
|
s.email = "jpastuszek@gmail.com"
|
15
15
|
s.extra_rdoc_files = [
|
@@ -26,7 +26,6 @@ Gem::Specification.new do |s|
|
|
26
26
|
"Rakefile",
|
27
27
|
"VERSION",
|
28
28
|
"lib/periodic-scheduler.rb",
|
29
|
-
"lib/quantized_time_space.rb",
|
30
29
|
"periodic-scheduler.gemspec",
|
31
30
|
"spec/periodic-scheduler_spec.rb",
|
32
31
|
"spec/spec_helper.rb"
|
@@ -21,15 +21,15 @@ describe PeriodicScheduler do
|
|
21
21
|
it "should execut event callbacks given time progress" do
|
22
22
|
s = PeriodicScheduler.new(5.0, @options)
|
23
23
|
|
24
|
-
s.
|
24
|
+
s.after(9.5) do
|
25
25
|
@got_event.call(1)
|
26
26
|
end
|
27
27
|
|
28
|
-
s.
|
28
|
+
s.after(14) do
|
29
29
|
@got_event.call(2)
|
30
30
|
end
|
31
31
|
|
32
|
-
s.
|
32
|
+
s.after(20) do
|
33
33
|
@got_event.call(3)
|
34
34
|
end
|
35
35
|
|
@@ -37,12 +37,16 @@ describe PeriodicScheduler do
|
|
37
37
|
s.empty?.should == false
|
38
38
|
|
39
39
|
s.run
|
40
|
-
@got_events.should == [1
|
40
|
+
@got_events.should == [1]
|
41
41
|
@time_now.should == 10.0
|
42
42
|
|
43
43
|
s.run
|
44
|
-
@got_events.should == [1, 2
|
45
|
-
@time_now.should ==
|
44
|
+
@got_events.should == [1, 2]
|
45
|
+
@time_now.should == 15.0
|
46
|
+
|
47
|
+
s.run
|
48
|
+
@got_events.should == [1, 2, 3]
|
49
|
+
@time_now.should == 20.0
|
46
50
|
|
47
51
|
s.empty?.should == true
|
48
52
|
end
|
@@ -50,7 +54,7 @@ describe PeriodicScheduler do
|
|
50
54
|
it "should reschedule resheduable tasks" do
|
51
55
|
s = PeriodicScheduler.new(5.0, @options)
|
52
56
|
|
53
|
-
s.
|
57
|
+
s.every(15) do
|
54
58
|
@got_event.call(1)
|
55
59
|
end
|
56
60
|
|
@@ -72,8 +76,7 @@ describe PeriodicScheduler do
|
|
72
76
|
it "should compensate for quntization error" do
|
73
77
|
s = PeriodicScheduler.new(5.0, @options)
|
74
78
|
|
75
|
-
|
76
|
-
s.schedule(12, true) do
|
79
|
+
s.every(12) do
|
77
80
|
@got_event.call(1)
|
78
81
|
end
|
79
82
|
|
@@ -81,19 +84,19 @@ describe PeriodicScheduler do
|
|
81
84
|
|
82
85
|
s.run
|
83
86
|
@got_events.should == [1]
|
84
|
-
@time_now.should ==
|
87
|
+
@time_now.should == 15
|
85
88
|
|
86
89
|
s.run
|
87
90
|
@got_events.should == [1, 1]
|
88
|
-
@time_now.should ==
|
91
|
+
@time_now.should == 25
|
89
92
|
|
90
93
|
s.run
|
91
94
|
@got_events.should == [1, 1, 1]
|
92
|
-
@time_now.should ==
|
95
|
+
@time_now.should == 40
|
93
96
|
|
94
97
|
s.run
|
95
98
|
@got_events.should == [1, 1, 1, 1]
|
96
|
-
@time_now.should ==
|
99
|
+
@time_now.should == 50
|
97
100
|
|
98
101
|
s.run
|
99
102
|
@got_events.should == [1, 1, 1, 1, 1]
|
@@ -101,11 +104,11 @@ describe PeriodicScheduler do
|
|
101
104
|
|
102
105
|
s.run
|
103
106
|
@got_events.should == [1, 1, 1, 1, 1, 1]
|
104
|
-
@time_now.should ==
|
107
|
+
@time_now.should == 75
|
105
108
|
end
|
106
109
|
|
107
110
|
it "should compensate for wait function jitter" do
|
108
|
-
jitter = [1, 0, 5, -
|
111
|
+
jitter = [1, 0, 5, -5, 0.5, -0.2, 0, 0, 0]
|
109
112
|
@options[:wait_function] = lambda{|t|
|
110
113
|
j = jitter.shift
|
111
114
|
#puts "time is: #{@time_now}"
|
@@ -115,44 +118,44 @@ describe PeriodicScheduler do
|
|
115
118
|
|
116
119
|
s = PeriodicScheduler.new(5.0, @options)
|
117
120
|
|
118
|
-
s.
|
121
|
+
s.every(12) do
|
119
122
|
@got_event.call(1)
|
120
123
|
end
|
121
124
|
|
122
125
|
@got_events.should == []
|
123
126
|
|
124
127
|
s.run.should_not be_empty
|
125
|
-
@time_now.should ==
|
128
|
+
@time_now.should == 16
|
126
129
|
@got_events.should == [1]
|
127
130
|
|
128
131
|
s.run.should_not be_empty
|
129
|
-
@time_now.should ==
|
132
|
+
@time_now.should == 25
|
130
133
|
@got_events.should == [1, 1]
|
131
134
|
|
132
135
|
s.run.should_not be_empty
|
133
|
-
@time_now.should ==
|
136
|
+
@time_now.should == 45
|
134
137
|
@got_events.should == [1, 1, 1]
|
135
138
|
|
136
139
|
# if timer returns too quickly the run will be empty
|
137
140
|
s.run.should be_empty
|
138
|
-
@time_now.should ==
|
141
|
+
@time_now.should == 45
|
139
142
|
@got_events.should == [1, 1, 1]
|
140
143
|
|
141
144
|
s.run.should_not be_empty
|
142
|
-
@time_now.should ==
|
145
|
+
@time_now.should == 50.5
|
143
146
|
@got_events.should == [1, 1, 1, 1]
|
144
147
|
|
145
|
-
|
148
|
+
# now the jitter is too small to not progress the quant
|
146
149
|
s.run.should_not be_empty
|
147
|
-
@time_now.should ==
|
150
|
+
@time_now.should == 59.8
|
148
151
|
@got_events.should == [1, 1, 1, 1, 1]
|
149
152
|
|
150
153
|
s.run.should_not be_empty
|
151
|
-
@time_now.should ==
|
154
|
+
@time_now.should == 75.0
|
152
155
|
@got_events.should == [1, 1, 1, 1, 1, 1]
|
153
156
|
|
154
157
|
s.run.should_not be_empty
|
155
|
-
@time_now.should ==
|
158
|
+
@time_now.should == 85.0
|
156
159
|
@got_events.should == [1, 1, 1, 1, 1, 1, 1]
|
157
160
|
end
|
158
161
|
|
@@ -173,12 +176,12 @@ describe PeriodicScheduler do
|
|
173
176
|
|
174
177
|
s = PeriodicScheduler.new(5.0, @options)
|
175
178
|
|
176
|
-
s.
|
179
|
+
s.every(ev1_val) do
|
177
180
|
ev1 << @time_now - ev1_last
|
178
181
|
ev1_last = @time_now
|
179
182
|
end
|
180
183
|
|
181
|
-
s.
|
184
|
+
s.every(ev2_val) do
|
182
185
|
ev2 << @time_now - ev2_last
|
183
186
|
ev2_last = @time_now
|
184
187
|
end
|
@@ -189,24 +192,18 @@ describe PeriodicScheduler do
|
|
189
192
|
(ev2.inject(0){|v, s| v + s} / ev2.length).should be_within(0.001).of(ev2_val)
|
190
193
|
end
|
191
194
|
|
192
|
-
it "should support
|
195
|
+
it "should support unscheduling of events" do
|
193
196
|
s = PeriodicScheduler.new(5.0, @options)
|
194
197
|
|
195
|
-
s.
|
196
|
-
end
|
197
|
-
|
198
|
-
it "should support unscheduling of all events within a group" do
|
199
|
-
s = PeriodicScheduler.new(5.0, @options)
|
200
|
-
|
201
|
-
s.schedule(15, true, "g1") do
|
198
|
+
e1 = s.every(15) do
|
202
199
|
@got_event.call(1)
|
203
200
|
end
|
204
201
|
|
205
|
-
s.
|
202
|
+
e2 = s.every(20) do
|
206
203
|
@got_event.call(2)
|
207
204
|
end
|
208
205
|
|
209
|
-
s.
|
206
|
+
e3 = s.every(25) do
|
210
207
|
@got_event.call(3)
|
211
208
|
end
|
212
209
|
|
@@ -228,68 +225,68 @@ describe PeriodicScheduler do
|
|
228
225
|
@got_events.should == [1, 2, 3, 1]
|
229
226
|
@time_now.should == 30
|
230
227
|
|
231
|
-
|
228
|
+
e1.stop
|
229
|
+
e2.stop
|
232
230
|
|
233
231
|
s.run
|
234
232
|
@got_events.should == [1, 2, 3, 1, 3]
|
235
|
-
|
233
|
+
@time_now.should == 50
|
236
234
|
|
237
235
|
s.empty?.should == false
|
238
236
|
|
239
|
-
|
240
|
-
|
237
|
+
e3.stop
|
241
238
|
s.empty?.should == true
|
242
239
|
end
|
243
240
|
|
244
|
-
it "should support unscheduling of
|
241
|
+
it "should support unscheduling of events from other event" do
|
245
242
|
s = PeriodicScheduler.new(1.0, @options)
|
246
243
|
|
247
|
-
s.
|
248
|
-
s.unschedule_group("g2")
|
249
|
-
@got_event.call(4)
|
250
|
-
end
|
251
|
-
|
252
|
-
s.schedule(1, true, "g1") do
|
244
|
+
e1 = s.every(1) do
|
253
245
|
@got_event.call(1)
|
254
246
|
end
|
255
247
|
|
256
|
-
s.
|
248
|
+
e2 = s.every(1) do
|
257
249
|
@got_event.call(2)
|
258
250
|
end
|
259
251
|
|
260
|
-
s.
|
252
|
+
e3 = s.every(1) do
|
261
253
|
@got_event.call(3)
|
262
254
|
end
|
263
255
|
|
256
|
+
e4 = s.every(2) do
|
257
|
+
e1.stop
|
258
|
+
@got_event.call(4)
|
259
|
+
end
|
260
|
+
|
264
261
|
@got_events.should == []
|
265
262
|
|
266
263
|
s.run
|
267
264
|
@got_events.should == [1, 2, 3]
|
268
265
|
@time_now.should == 1
|
269
266
|
|
270
|
-
#
|
267
|
+
# Will get executed this time
|
271
268
|
s.run
|
272
269
|
@got_events.should == [1, 2, 3, 4, 1, 2, 3]
|
273
270
|
@time_now.should == 2
|
274
271
|
|
275
|
-
#
|
272
|
+
# Should be not rescheduled
|
276
273
|
s.run
|
277
|
-
@got_events.should == [1, 2, 3, 4, 1, 2, 3,
|
274
|
+
@got_events.should == [1, 2, 3, 4, 1, 2, 3, 2, 3]
|
278
275
|
@time_now.should == 3
|
279
276
|
end
|
280
277
|
|
281
278
|
it "should execut all not reschedulable tasks if we miss them" do
|
282
279
|
s = PeriodicScheduler.new(5.0, @options)
|
283
280
|
|
284
|
-
s.
|
281
|
+
s.after(15) do
|
285
282
|
@got_event.call(1)
|
286
283
|
end
|
287
284
|
|
288
|
-
s.
|
285
|
+
s.after(30) do
|
289
286
|
@got_event.call(2)
|
290
287
|
end
|
291
288
|
|
292
|
-
s.
|
289
|
+
s.after(45) do
|
293
290
|
@got_event.call(3)
|
294
291
|
end
|
295
292
|
|
@@ -306,7 +303,7 @@ describe PeriodicScheduler do
|
|
306
303
|
#TODO: this behaviour is a bit of gary area
|
307
304
|
s = PeriodicScheduler.new(5.0, @options)
|
308
305
|
|
309
|
-
s.
|
306
|
+
s.every(15) do
|
310
307
|
@got_event.call(1)
|
311
308
|
end
|
312
309
|
|
@@ -322,11 +319,11 @@ describe PeriodicScheduler do
|
|
322
319
|
it "should report error if the schedule was missed" do
|
323
320
|
s = PeriodicScheduler.new(5.0, @options)
|
324
321
|
|
325
|
-
s.
|
322
|
+
s.after(15) do
|
326
323
|
@got_event.call(1)
|
327
324
|
end
|
328
325
|
|
329
|
-
s.
|
326
|
+
s.after(30) do
|
330
327
|
@got_event.call(2)
|
331
328
|
end
|
332
329
|
|
@@ -346,7 +343,7 @@ describe PeriodicScheduler do
|
|
346
343
|
it "should handle events call exceptions and return them" do
|
347
344
|
s = PeriodicScheduler.new(5.0, @options)
|
348
345
|
|
349
|
-
s.
|
346
|
+
s.every(12) do
|
350
347
|
fail "test"
|
351
348
|
end
|
352
349
|
|
@@ -366,7 +363,7 @@ describe PeriodicScheduler do
|
|
366
363
|
it "should raise PeriodicScheduler::EmptyScheduleError if there are no events left to process" do
|
367
364
|
s = PeriodicScheduler.new(5.0, @options)
|
368
365
|
|
369
|
-
s.
|
366
|
+
s.after(12) {}
|
370
367
|
|
371
368
|
lambda {
|
372
369
|
s.run
|
@@ -382,11 +379,11 @@ describe PeriodicScheduler do
|
|
382
379
|
|
383
380
|
test = 0
|
384
381
|
|
385
|
-
s.
|
382
|
+
s.every(11) do
|
386
383
|
test += 1
|
387
384
|
end
|
388
385
|
|
389
|
-
s.
|
386
|
+
s.after(12) do
|
390
387
|
test += 1
|
391
388
|
end
|
392
389
|
|
@@ -399,15 +396,15 @@ describe PeriodicScheduler do
|
|
399
396
|
it "should run schedule until there is no more events sheduled" do
|
400
397
|
s = PeriodicScheduler.new(5.0, @options)
|
401
398
|
|
402
|
-
s.
|
399
|
+
s.after(5) do
|
403
400
|
@got_event.call(1)
|
404
401
|
end
|
405
402
|
|
406
|
-
s.
|
403
|
+
s.after(10) do
|
407
404
|
@got_event.call(2)
|
408
405
|
end
|
409
406
|
|
410
|
-
s.
|
407
|
+
s.after(15) do
|
411
408
|
@got_event.call(3)
|
412
409
|
end
|
413
410
|
|
@@ -419,19 +416,19 @@ describe PeriodicScheduler do
|
|
419
416
|
it "should call block on event error" do
|
420
417
|
s = PeriodicScheduler.new(5.0, @options)
|
421
418
|
|
422
|
-
s.
|
419
|
+
s.after(5) do
|
423
420
|
raise "1"
|
424
421
|
end
|
425
422
|
|
426
|
-
s.
|
423
|
+
s.after(10) do
|
427
424
|
@got_event.call(1)
|
428
425
|
end
|
429
426
|
|
430
|
-
s.
|
427
|
+
s.after(15) do
|
431
428
|
raise "2"
|
432
429
|
end
|
433
430
|
|
434
|
-
s.
|
431
|
+
s.after(15) do
|
435
432
|
@got_event.call(2)
|
436
433
|
end
|
437
434
|
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: periodic-scheduler
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.5.0
|
5
5
|
prerelease:
|
6
6
|
platform: ruby
|
7
7
|
authors:
|
@@ -9,11 +9,11 @@ authors:
|
|
9
9
|
autorequire:
|
10
10
|
bindir: bin
|
11
11
|
cert_chain: []
|
12
|
-
date: 2012-
|
12
|
+
date: 2012-11-03 00:00:00.000000000 Z
|
13
13
|
dependencies:
|
14
14
|
- !ruby/object:Gem::Dependency
|
15
15
|
name: rspec
|
16
|
-
requirement: &
|
16
|
+
requirement: &70289045852440 !ruby/object:Gem::Requirement
|
17
17
|
none: false
|
18
18
|
requirements:
|
19
19
|
- - ~>
|
@@ -21,10 +21,10 @@ dependencies:
|
|
21
21
|
version: 2.8.0
|
22
22
|
type: :development
|
23
23
|
prerelease: false
|
24
|
-
version_requirements: *
|
24
|
+
version_requirements: *70289045852440
|
25
25
|
- !ruby/object:Gem::Dependency
|
26
26
|
name: rdoc
|
27
|
-
requirement: &
|
27
|
+
requirement: &70289045851420 !ruby/object:Gem::Requirement
|
28
28
|
none: false
|
29
29
|
requirements:
|
30
30
|
- - ~>
|
@@ -32,10 +32,10 @@ dependencies:
|
|
32
32
|
version: '3.12'
|
33
33
|
type: :development
|
34
34
|
prerelease: false
|
35
|
-
version_requirements: *
|
35
|
+
version_requirements: *70289045851420
|
36
36
|
- !ruby/object:Gem::Dependency
|
37
37
|
name: cucumber
|
38
|
-
requirement: &
|
38
|
+
requirement: &70289045850520 !ruby/object:Gem::Requirement
|
39
39
|
none: false
|
40
40
|
requirements:
|
41
41
|
- - ! '>='
|
@@ -43,10 +43,10 @@ dependencies:
|
|
43
43
|
version: '0'
|
44
44
|
type: :development
|
45
45
|
prerelease: false
|
46
|
-
version_requirements: *
|
46
|
+
version_requirements: *70289045850520
|
47
47
|
- !ruby/object:Gem::Dependency
|
48
48
|
name: bundler
|
49
|
-
requirement: &
|
49
|
+
requirement: &70289045849460 !ruby/object:Gem::Requirement
|
50
50
|
none: false
|
51
51
|
requirements:
|
52
52
|
- - ~>
|
@@ -54,10 +54,10 @@ dependencies:
|
|
54
54
|
version: 1.0.0
|
55
55
|
type: :development
|
56
56
|
prerelease: false
|
57
|
-
version_requirements: *
|
57
|
+
version_requirements: *70289045849460
|
58
58
|
- !ruby/object:Gem::Dependency
|
59
59
|
name: jeweler
|
60
|
-
requirement: &
|
60
|
+
requirement: &70289045848140 !ruby/object:Gem::Requirement
|
61
61
|
none: false
|
62
62
|
requirements:
|
63
63
|
- - ~>
|
@@ -65,10 +65,10 @@ dependencies:
|
|
65
65
|
version: 1.8.3
|
66
66
|
type: :development
|
67
67
|
prerelease: false
|
68
|
-
version_requirements: *
|
68
|
+
version_requirements: *70289045848140
|
69
69
|
- !ruby/object:Gem::Dependency
|
70
70
|
name: rcov
|
71
|
-
requirement: &
|
71
|
+
requirement: &70289045847660 !ruby/object:Gem::Requirement
|
72
72
|
none: false
|
73
73
|
requirements:
|
74
74
|
- - ! '>='
|
@@ -76,7 +76,7 @@ dependencies:
|
|
76
76
|
version: '0'
|
77
77
|
type: :development
|
78
78
|
prerelease: false
|
79
|
-
version_requirements: *
|
79
|
+
version_requirements: *70289045847660
|
80
80
|
description: Controls execution of periodic scheduled tasks.
|
81
81
|
email: jpastuszek@gmail.com
|
82
82
|
executables: []
|
@@ -94,7 +94,6 @@ files:
|
|
94
94
|
- Rakefile
|
95
95
|
- VERSION
|
96
96
|
- lib/periodic-scheduler.rb
|
97
|
-
- lib/quantized_time_space.rb
|
98
97
|
- periodic-scheduler.gemspec
|
99
98
|
- spec/periodic-scheduler_spec.rb
|
100
99
|
- spec/spec_helper.rb
|
@@ -113,7 +112,7 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
113
112
|
version: '0'
|
114
113
|
segments:
|
115
114
|
- 0
|
116
|
-
hash:
|
115
|
+
hash: -3007109713831198216
|
117
116
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
118
117
|
none: false
|
119
118
|
requirements:
|
data/lib/quantized_time_space.rb
DELETED
@@ -1,20 +0,0 @@
|
|
1
|
-
class RealTimeToQuantizedSpaceProjection
|
2
|
-
def initialize(quantum_size, quantization_rule)
|
3
|
-
@quantum_size = quantum_size
|
4
|
-
@quantization_rule = quantization_rule
|
5
|
-
end
|
6
|
-
|
7
|
-
def project(value)
|
8
|
-
@quantization_rule.call(value / @quantum_size)
|
9
|
-
end
|
10
|
-
|
11
|
-
def revers_project(value)
|
12
|
-
value * @quantum_size
|
13
|
-
end
|
14
|
-
|
15
|
-
def projection_error(value)
|
16
|
-
new_value = project(value)
|
17
|
-
value - revers_project(new_value)
|
18
|
-
end
|
19
|
-
end
|
20
|
-
|