timers 4.1.2 → 4.3.5

Sign up to get free protection for your applications and to get access to all the features.
@@ -1,255 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- RSpec.describe Timers::Group do
4
- describe "#wait" do
5
- it "calls the wait block with nil" do
6
- called = false
7
-
8
- subject.wait do |interval|
9
- expect(interval).to be_nil
10
- called = true
11
- end
12
-
13
- expect(called).to be true
14
- end
15
-
16
- it "calls the wait block with an interval" do
17
- called = false
18
- fired = false
19
-
20
- subject.after(0.1) { fired = true }
21
-
22
- subject.wait do |interval|
23
- expect(interval).to be_within(TIMER_QUANTUM).of(0.1)
24
- called = true
25
- sleep 0.2
26
- end
27
-
28
- expect(called).to be true
29
- expect(fired).to be true
30
- end
31
- end
32
-
33
- it "sleeps until the next timer" do
34
- interval = TIMER_QUANTUM * 2
35
- started_at = Time.now
36
-
37
- fired = false
38
- subject.after(interval) { fired = true }
39
- subject.wait
40
-
41
- expect(fired).to be true
42
- expect(Time.now - started_at).to be_within(TIMER_QUANTUM).of interval
43
- end
44
-
45
- it "fires instantly when next timer is in the past" do
46
- fired = false
47
- subject.after(TIMER_QUANTUM) { fired = true }
48
- sleep(TIMER_QUANTUM * 2)
49
- subject.wait
50
-
51
- expect(fired).to be true
52
- end
53
-
54
- it "calculates the interval until the next timer should fire" do
55
- interval = 0.1
56
-
57
- subject.after(interval)
58
- expect(subject.wait_interval).to be_within(TIMER_QUANTUM).of interval
59
-
60
- sleep(interval)
61
- expect(subject.wait_interval).to be <= 0
62
- end
63
-
64
- it "fires timers in the correct order" do
65
- result = []
66
-
67
- subject.after(TIMER_QUANTUM * 2) { result << :two }
68
- subject.after(TIMER_QUANTUM * 3) { result << :three }
69
- subject.after(TIMER_QUANTUM * 1) { result << :one }
70
-
71
- sleep TIMER_QUANTUM * 4
72
- subject.fire
73
-
74
- expect(result).to eq [:one, :two, :three]
75
- end
76
-
77
- it "raises TypeError if given an invalid time" do
78
- expect do
79
- subject.after(nil) { nil }
80
- end.to raise_exception(TypeError)
81
- end
82
-
83
- describe "recurring timers" do
84
- it "continues to fire the timers at each interval" do
85
- result = []
86
-
87
- subject.every(TIMER_QUANTUM * 2) { result << :foo }
88
-
89
- sleep TIMER_QUANTUM * 3
90
- subject.fire
91
- expect(result).to eq [:foo]
92
-
93
- sleep TIMER_QUANTUM * 5
94
- subject.fire
95
- expect(result).to eq [:foo, :foo]
96
- end
97
- end
98
-
99
- it "calculates the proper interval to wait until firing" do
100
- interval_ms = 25
101
-
102
- subject.after(interval_ms / 1000.0)
103
-
104
- expect(subject.wait_interval).to be_within(TIMER_QUANTUM).of(interval_ms / 1000.0)
105
- end
106
-
107
- describe "pause and continue timers" do
108
- before(:each) do
109
- @interval = TIMER_QUANTUM * 2
110
-
111
- @fired = false
112
- @timer = subject.after(@interval) { @fired = true }
113
- @fired2 = false
114
- @timer2 = subject.after(@interval) { @fired2 = true }
115
- end
116
-
117
- it "does not fire when paused" do
118
- @timer.pause
119
- subject.wait
120
- expect(@fired).to be false
121
- end
122
-
123
- it "fires when continued after pause" do
124
- @timer.pause
125
- subject.wait
126
- @timer.resume
127
-
128
- sleep @timer.interval
129
- subject.wait
130
-
131
- expect(@fired).to be true
132
- end
133
-
134
- it "can pause all timers at once" do
135
- subject.pause
136
- subject.wait
137
- expect(@fired).to be false
138
- expect(@fired2).to be false
139
- end
140
-
141
- it "can continue all timers at once" do
142
- subject.pause
143
- subject.wait
144
- subject.resume
145
-
146
- # We need to wait until we are sure both timers will fire, otherwise highly accurate clocks
147
- # (e.g. JVM)may only fire the first timer, but not the second, because they are actually
148
- # schedueled at different times.
149
- sleep TIMER_QUANTUM * 2
150
- subject.wait
151
-
152
- expect(@fired).to be true
153
- expect(@fired2).to be true
154
- end
155
-
156
- it "can fire the timer directly" do
157
- fired = false
158
- timer = subject.after(TIMER_QUANTUM * 1) { fired = true }
159
- timer.pause
160
- subject.wait
161
- expect(fired).not_to be true
162
- timer.resume
163
- expect(fired).not_to be true
164
- timer.fire
165
- expect(fired).to be true
166
- end
167
- end
168
-
169
- describe "delay timer" do
170
- it "adds appropriate amount of time to timer" do
171
- timer = subject.after(10)
172
- timer.delay(5)
173
- expect(timer.offset - subject.current_offset).to be_within(TIMER_QUANTUM).of(15)
174
- end
175
- end
176
-
177
- describe "delay timer collection" do
178
- it "delay on set adds appropriate amount of time to all timers" do
179
- timer = subject.after(10)
180
- timer2 = subject.after(20)
181
- subject.delay(5)
182
- expect(timer.offset - subject.current_offset).to be_within(TIMER_QUANTUM).of(15)
183
- expect(timer2.offset - subject.current_offset).to be_within(TIMER_QUANTUM).of(25)
184
- end
185
- end
186
-
187
- describe "on delaying a timer" do
188
- it "fires timers in the correct order" do
189
- result = []
190
-
191
- subject.after(TIMER_QUANTUM * 2) { result << :two }
192
- subject.after(TIMER_QUANTUM * 3) { result << :three }
193
- first = subject.after(TIMER_QUANTUM * 1) { result << :one }
194
- first.delay(TIMER_QUANTUM * 3)
195
-
196
- sleep TIMER_QUANTUM * 5
197
- subject.fire
198
-
199
- expect(result).to eq [:two, :three, :one]
200
- end
201
- end
202
-
203
- describe "#inspect" do
204
- it "before firing" do
205
- fired = false
206
- timer = subject.after(TIMER_QUANTUM * 5) { fired = true }
207
- timer.pause
208
- expect(fired).not_to be true
209
- expect(timer.inspect).to match(/\A#<Timers::Timer:[\da-f]+ fires in [-\.\de]+ seconds>\Z/)
210
- end
211
-
212
- it "after firing" do
213
- fired = false
214
- timer = subject.after(TIMER_QUANTUM) { fired = true }
215
-
216
- subject.wait
217
-
218
- expect(fired).to be true
219
- expect(timer.inspect).to match(/\A#<Timers::Timer:[\da-f]+ fired [-\.\de]+ seconds ago>\Z/)
220
- end
221
-
222
- it "recurring firing" do
223
- result = []
224
- timer = subject.every(TIMER_QUANTUM) { result << :foo }
225
-
226
- subject.wait
227
- expect(result).not_to be_empty
228
- regex = /\A#<Timers::Timer:[\da-f]+ fires in [-\.\de]+ seconds, recurs every #{format("%0.2f", TIMER_QUANTUM)}>\Z/
229
- expect(timer.inspect).to match(regex)
230
- end
231
- end
232
-
233
- describe "#fires_in" do
234
- let(:interval) { TIMER_QUANTUM * 2 }
235
-
236
- it "calculates the interval until the next fire if it's recurring" do
237
- timer = subject.every(interval) { true }
238
- expect(timer.fires_in).to be_within(TIMER_QUANTUM).of(interval)
239
- end
240
-
241
- context "when timer is not recurring" do
242
- let!(:timer) { subject.after(interval) { true } }
243
-
244
- it "calculates the interval until the next fire if it hasn't already fired" do
245
- expect(timer.fires_in).to be_within(TIMER_QUANTUM).of(interval)
246
- end
247
-
248
- it "calculates the interval since last fire if already fired" do
249
- subject.wait
250
- sleep(interval)
251
- expect(timer.fires_in).to be_within(TIMER_QUANTUM).of(0 - interval)
252
- end
253
- end
254
- end
255
- end
@@ -1,96 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- # Event based timers:
4
-
5
- # Serviced 31812 events in 2.39075272 seconds, 13306.320832794887 e/s.
6
- # Thread ID: 7336700
7
- # Fiber ID: 30106340
8
- # Total: 2.384043
9
- # Sort by: self_time
10
-
11
- # %self total self wait child calls name
12
- # 13.48 0.510 0.321 0.000 0.189 369133 Timers::Events::Handle#<=>
13
- # 8.12 0.194 0.194 0.000 0.000 427278 Timers::Events::Handle#to_f
14
- # 4.55 0.109 0.109 0.000 0.000 427278 Float#<=>
15
- # 4.40 1.857 0.105 0.000 1.752 466376 *Timers::Events#bsearch
16
- # 4.30 0.103 0.103 0.000 0.000 402945 Float#to_f
17
- # 2.65 0.063 0.063 0.000 0.000 33812 Array#insert
18
- # 2.64 1.850 0.063 0.000 1.787 33812 Timers::Events#schedule
19
- # 2.40 1.930 0.057 0.000 1.873 33812 Timers::Timer#reset
20
- # 1.89 1.894 0.045 0.000 1.849 31812 Timers::Timer#fire
21
- # 1.69 1.966 0.040 0.000 1.926 31812 Timers::Events::Handle#fire
22
- # 1.35 0.040 0.032 0.000 0.008 33812 Timers::Events::Handle#initialize
23
- # 1.29 0.044 0.031 0.000 0.013 44451 Timers::Group#current_offset
24
-
25
- # SortedSet based timers:
26
-
27
- # Serviced 32516 events in 66.753277275 seconds, 487.1072288781219 e/s.
28
- # Thread ID: 15995640
29
- # Fiber ID: 38731780
30
- # Total: 66.716394
31
- # Sort by: self_time
32
-
33
- # %self total self wait child calls name
34
- # 54.73 49.718 36.513 0.000 13.205 57084873 Timers::Timer#<=>
35
- # 23.74 65.559 15.841 0.000 49.718 32534 Array#sort!
36
- # 19.79 13.205 13.205 0.000 0.000 57084873 Float#<=>
37
-
38
- # Max out events performance (on my computer):
39
- # Serviced 1142649 events in 11.194903921 seconds, 102068.70405115146 e/s.
40
-
41
- RSpec.describe Timers::Group do
42
- it "runs efficiently" do
43
- result = []
44
- range = (1..500)
45
- duration = 2.0
46
-
47
- total = 0
48
- range.each do |index|
49
- offset = index.to_f / range.max
50
- total += (duration / offset).floor
51
-
52
- subject.every(index.to_f / range.max, :strict) { result << index }
53
- end
54
-
55
- subject.wait while result.size < total
56
-
57
- rate = result.size.to_f / subject.current_offset
58
- puts "Serviced #{result.size} events in #{subject.current_offset} seconds, #{rate} e/s."
59
-
60
- expect(subject.current_offset).to be_within(TIMER_QUANTUM).of(duration)
61
- end
62
-
63
- # it "runs efficiently at high volume" do
64
- # results = []
65
- # range = (1..300)
66
- # groups = (1..20)
67
- # duration = 101
68
- #
69
- # timers = []
70
- # @mutex = Mutex.new
71
- # start = Time.now
72
- # groups.each do |gi|
73
- # timers << Thread.new {
74
- # result = []
75
- # timer = Timers::Group.new
76
- # total = 0
77
- # range.each do |ri|
78
- # offset = ri.to_f / range.max
79
- # total += (duration / offset).floor
80
- # timer.every(ri.to_f / range.max, :strict) { result << ri }
81
- # end
82
- # timer.wait while result.size < total
83
- # @mutex.synchronize { results += result }
84
- #
85
- # }
86
- # end
87
- # timers.each { |t| t.join }
88
- # finish = Time.now
89
- #
90
- # rate = results.size.to_f / ( runtime = finish - start )
91
- #
92
- # puts "Serviced #{results.size} events in #{runtime} seconds, #{rate} e/s; across #{groups.max} timers."
93
- #
94
- # expect(runtime).to be_within(TIMER_QUANTUM).of(duration)
95
- # end
96
- end
@@ -1,36 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- RSpec.describe Timers::Group do
4
- it "should not diverge too much" do
5
- fired = :not_fired_yet
6
- count = 0
7
- quantum = 0.01
8
-
9
- start_offset = subject.current_offset
10
- Timers::Timer.new(subject, quantum, :strict, start_offset) do |offset|
11
- fired = offset
12
- count += 1
13
- end
14
-
15
- iterations = 1000
16
- subject.wait while count < iterations
17
-
18
- # In my testing on the JVM, without the :strict recurring, I noticed 60ms of error here.
19
- expect(fired - start_offset).to be_within(quantum).of(iterations * quantum)
20
- end
21
-
22
- it "should only fire once" do
23
- fired = :not_fired_yet
24
- count = 0
25
-
26
- start_offset = subject.current_offset
27
- Timers::Timer.new(subject, 0, :strict, start_offset) do |offset|
28
- fired = offset
29
- count += 1
30
- end
31
-
32
- subject.wait
33
-
34
- expect(count).to be == 1
35
- end
36
- end
@@ -1,30 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- require "spec_helper"
4
- require "timers/wait"
5
-
6
- RSpec.describe Timers::Wait do
7
- it "repeats until timeout expired" do
8
- timeout = Timers::Wait.new(5)
9
- count = 0
10
-
11
- timeout.while_time_remaining do |remaining|
12
- expect(remaining).to be_within(TIMER_QUANTUM).of(timeout.duration - count)
13
-
14
- count += 1
15
- sleep 1
16
- end
17
-
18
- expect(count).to eq(5)
19
- end
20
-
21
- it "yields results as soon as possible" do
22
- timeout = Timers::Wait.new(5)
23
-
24
- result = timeout.while_time_remaining do |_remaining|
25
- break :done
26
- end
27
-
28
- expect(result).to eq(:done)
29
- end
30
- end
data/timers.gemspec DELETED
@@ -1,26 +0,0 @@
1
- # -*- encoding: utf-8 -*-
2
- # frozen_string_literal: true
3
-
4
- require File.expand_path("../lib/timers/version", __FILE__)
5
-
6
- Gem::Specification.new do |gem|
7
- gem.name = "timers"
8
- gem.version = Timers::VERSION
9
- gem.authors = ["Tony Arcieri"]
10
- gem.email = ["bascule@gmail.com"]
11
- gem.licenses = ["MIT"]
12
- gem.homepage = "https://github.com/celluloid/timers"
13
- gem.summary = "Pure Ruby one-shot and periodic timers"
14
- gem.description = <<-DESCRIPTION.strip.gsub(/\s+/, " ")
15
- Schedule procs to run after a certain time, or at periodic intervals,
16
- using any API that accepts a timeout.
17
- DESCRIPTION
18
-
19
- gem.files = `git ls-files`.split($OUTPUT_RECORD_SEPARATOR)
20
- gem.executables = gem.files.grep(%r{^bin/}).map { |f| File.basename(f) }
21
- gem.test_files = gem.files.grep(%r{^(test|spec|features)/})
22
- gem.require_paths = ["lib"]
23
- gem.add_runtime_dependency "hitimes"
24
-
25
- gem.add_development_dependency "bundler"
26
- end