periodic-scheduler 0.5.0 → 0.6.0

Sign up to get free protection for your applications and to get access to all the features.
data/VERSION CHANGED
@@ -1 +1 @@
1
- 0.5.0
1
+ 0.6.0
@@ -27,16 +27,22 @@ class PeriodicScheduler
27
27
  attr_reader :keep
28
28
  attr_reader :callback
29
29
 
30
- def initialize(quantized_space, period, keep, &callback)
30
+ def initialize(quantized_space, now, period, keep, &callback)
31
31
  @quantized_space = quantized_space
32
32
  @period = period
33
+ @run_time = now + period
33
34
  @keep = keep
34
35
  @callback = callback
35
36
  quantatize(period)
36
37
  end
37
38
 
38
- def reschedule
39
- quantatize(@period + @quantum_error)
39
+ def reschedule(qnow)
40
+ # keep rescheduling until we get it scheduled in future quant
41
+ until @quantum_period > qnow
42
+ @run_time += @period
43
+ quantatize(@run_time)
44
+ end
45
+
40
46
  @reschedule_hook.call(self) if @reschedule_hook
41
47
  end
42
48
 
@@ -70,7 +76,6 @@ class PeriodicScheduler
70
76
 
71
77
  def quantatize(period)
72
78
  @quantum_period = @quantized_space.project(period)
73
- @quantum_error = @quantized_space.projection_error(period)
74
79
  end
75
80
  end
76
81
 
@@ -89,11 +94,11 @@ class PeriodicScheduler
89
94
  end
90
95
 
91
96
  def after(period, &callback)
92
- schedule_event Event.new(@quantized_space, period, false, &callback)
97
+ schedule_event Event.new(@quantized_space, real_now, period, false, &callback)
93
98
  end
94
99
 
95
100
  def every(period, &callback)
96
- schedule_event Event.new(@quantized_space, period, true, &callback)
101
+ schedule_event Event.new(@quantized_space, real_now, period, true, &callback)
97
102
  end
98
103
 
99
104
  def run!(&block)
@@ -110,16 +115,7 @@ class PeriodicScheduler
110
115
  raise EmptyScheduleError, "no events scheduled" unless earliest_quant
111
116
 
112
117
  wait_time = @quantized_space.revers_project(earliest_quant) - real_now
113
- if wait_time < 0
114
- # we have missed our scheduled period
115
- begin
116
- # we raise it so it has proper content (backtrace)
117
- raise MissedScheduleError.new("missed schedule by #{-wait_time} seconds")
118
- rescue StandardError => error
119
- yield error if block_given?
120
- end
121
- wait_time = 0
122
- end
118
+ wait_time = 0 if wait_time < 0
123
119
  wait(wait_time)
124
120
 
125
121
  objects = []
@@ -129,6 +125,16 @@ class PeriodicScheduler
129
125
  # move quants to be run away to separate array
130
126
  quants = @events.keys.select{|k| k <= qnow}.sort.map{|q| @events.delete(q)}
131
127
 
128
+ # we have missed one or more scheduled quants
129
+ if quants.length > 1
130
+ begin
131
+ # we raise it so it has proper backtrace
132
+ raise MissedScheduleError.new("missed schedule by #{-wait_time} seconds")
133
+ rescue StandardError => error
134
+ yield error if block_given?
135
+ end
136
+ end
137
+
132
138
  # Call callback for every quant and reschedule if needed
133
139
  quants.each do |events|
134
140
  # get all events for quantum that are not stopped
@@ -139,7 +145,7 @@ class PeriodicScheduler
139
145
  # Yield errors to block
140
146
  yield error if block_given?
141
147
  end
142
- e.reschedule if e.keep? and not e.stopped?
148
+ e.reschedule(quantized_now) if e.keep? and not e.stopped?
143
149
  end
144
150
  end
145
151
 
@@ -153,13 +159,13 @@ class PeriodicScheduler
153
159
 
154
160
  private
155
161
 
156
- def schedule_event(event, from = quantized_now)
157
- quant = from + event.quantum_period
162
+ def schedule_event(event)
163
+ quant = event.quantum_period
158
164
  (@events[quant] ||= []) << event
159
165
 
160
166
  event.reschedule_hook do |event|
161
167
  unschedule_event(event, quant)
162
- schedule_event(event, quant)
168
+ schedule_event(event)
163
169
  end
164
170
 
165
171
  event.stop_hook do |event|
@@ -5,11 +5,11 @@
5
5
 
6
6
  Gem::Specification.new do |s|
7
7
  s.name = "periodic-scheduler"
8
- s.version = "0.5.0"
8
+ s.version = "0.6.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-11-03"
12
+ s.date = "2012-11-06"
13
13
  s.description = "Controls execution of periodic scheduled tasks."
14
14
  s.email = "jpastuszek@gmail.com"
15
15
  s.extra_rdoc_files = [
@@ -275,7 +275,7 @@ describe PeriodicScheduler do
275
275
  @time_now.should == 3
276
276
  end
277
277
 
278
- it "should execut all not reschedulable tasks if we miss them" do
278
+ it "should not miss any scheduled tasks" do
279
279
  s = PeriodicScheduler.new(5.0, @options)
280
280
 
281
281
  s.after(15) do
@@ -286,7 +286,7 @@ describe PeriodicScheduler do
286
286
  @got_event.call(2)
287
287
  end
288
288
 
289
- s.after(45) do
289
+ s.after(40) do
290
290
  @got_event.call(3)
291
291
  end
292
292
 
@@ -299,21 +299,34 @@ describe PeriodicScheduler do
299
299
  @got_events.should == [1, 2, 3]
300
300
  end
301
301
 
302
- it "should skpi reschedulable tasks if we miss them" do
303
- #TODO: this behaviour is a bit of gary area
304
- s = PeriodicScheduler.new(5.0, @options)
302
+ it "should call reschedulable tasks only once every run" do
303
+ s = PeriodicScheduler.new(5.0, @options)
305
304
 
306
- s.every(15) do
307
- @got_event.call(1)
308
- end
305
+ s.every(15) do
306
+ @got_event.call(1)
307
+ end
309
308
 
310
- @options[:wait_function].call(35)
309
+ s.every(30) do
310
+ @got_event.call(2)
311
+ end
311
312
 
312
- s.run.should
313
- @got_events.should == [1]
313
+ s.every(40) do
314
+ @got_event.call(3)
315
+ end
314
316
 
315
- s.run.should
316
- @got_events.should == [1, 1]
317
+ @options[:wait_function].call(35)
318
+
319
+ # 15, 30 executed, 15 -> 45
320
+ s.run.should
321
+ @got_events.should == [1, 2]
322
+
323
+ # 40
324
+ s.run.should
325
+ @got_events.should == [1, 2, 3]
326
+
327
+ # 45
328
+ s.run.should
329
+ @got_events.should == [1, 2, 3, 1]
317
330
  end
318
331
 
319
332
  it "should report error if the schedule was missed" do
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.5.0
4
+ version: 0.6.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-11-03 00:00:00.000000000 Z
12
+ date: 2012-11-06 00:00:00.000000000 Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: rspec
16
- requirement: &70289045852440 !ruby/object:Gem::Requirement
16
+ requirement: &70222808986940 !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: *70289045852440
24
+ version_requirements: *70222808986940
25
25
  - !ruby/object:Gem::Dependency
26
26
  name: rdoc
27
- requirement: &70289045851420 !ruby/object:Gem::Requirement
27
+ requirement: &70222808986460 !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: *70289045851420
35
+ version_requirements: *70222808986460
36
36
  - !ruby/object:Gem::Dependency
37
37
  name: cucumber
38
- requirement: &70289045850520 !ruby/object:Gem::Requirement
38
+ requirement: &70222808985980 !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: *70289045850520
46
+ version_requirements: *70222808985980
47
47
  - !ruby/object:Gem::Dependency
48
48
  name: bundler
49
- requirement: &70289045849460 !ruby/object:Gem::Requirement
49
+ requirement: &70222808985500 !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: *70289045849460
57
+ version_requirements: *70222808985500
58
58
  - !ruby/object:Gem::Dependency
59
59
  name: jeweler
60
- requirement: &70289045848140 !ruby/object:Gem::Requirement
60
+ requirement: &70222808985020 !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: *70289045848140
68
+ version_requirements: *70222808985020
69
69
  - !ruby/object:Gem::Dependency
70
70
  name: rcov
71
- requirement: &70289045847660 !ruby/object:Gem::Requirement
71
+ requirement: &70222808984540 !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: *70289045847660
79
+ version_requirements: *70222808984540
80
80
  description: Controls execution of periodic scheduled tasks.
81
81
  email: jpastuszek@gmail.com
82
82
  executables: []
@@ -112,7 +112,7 @@ required_ruby_version: !ruby/object:Gem::Requirement
112
112
  version: '0'
113
113
  segments:
114
114
  - 0
115
- hash: -3007109713831198216
115
+ hash: -3759462292764613282
116
116
  required_rubygems_version: !ruby/object:Gem::Requirement
117
117
  none: false
118
118
  requirements: