timers 4.1.2 → 4.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.
- checksums.yaml +5 -5
- data/.rspec +1 -4
- data/.travis.yml +15 -17
- data/Gemfile +7 -11
- data/README.md +60 -24
- data/Rakefile +2 -6
- data/lib/timers.rb +5 -0
- data/lib/timers/events.rb +108 -106
- data/lib/timers/group.rb +124 -119
- data/lib/timers/interval.rb +43 -0
- data/lib/timers/timer.rb +121 -116
- data/lib/timers/version.rb +6 -1
- data/lib/timers/wait.rb +47 -42
- data/spec/spec_helper.rb +30 -13
- data/spec/timers/cancel_spec.rb +33 -28
- data/spec/timers/events_spec.rb +40 -35
- data/spec/timers/every_spec.rb +27 -22
- data/spec/timers/group_spec.rb +247 -242
- data/spec/timers/performance_spec.rb +83 -54
- data/spec/timers/strict_spec.rb +37 -32
- data/spec/timers/wait_spec.rb +22 -17
- data/timers.gemspec +27 -20
- metadata +29 -18
- data/.coveralls.yml +0 -1
- data/.rubocop.yml +0 -28
- data/.ruby-version +0 -1
- data/AUTHORS.md +0 -15
- data/CHANGES.md +0 -62
- data/LICENSE +0 -23
@@ -1,4 +1,12 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
|
+
#
|
3
|
+
# This file is part of the "timers" project and released under the MIT license.
|
4
|
+
#
|
5
|
+
# Copyright, 2018, by Samuel Williams. All rights reserved.
|
6
|
+
#
|
7
|
+
|
8
|
+
require "spec_helper"
|
9
|
+
require "ruby-prof" unless RUBY_PLATFORM =~ /java|rbx/
|
2
10
|
|
3
11
|
# Event based timers:
|
4
12
|
|
@@ -39,58 +47,79 @@
|
|
39
47
|
# Serviced 1142649 events in 11.194903921 seconds, 102068.70405115146 e/s.
|
40
48
|
|
41
49
|
RSpec.describe Timers::Group do
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
-
|
52
|
-
|
53
|
-
|
54
|
-
|
55
|
-
|
56
|
-
|
57
|
-
|
58
|
-
|
59
|
-
|
60
|
-
|
61
|
-
|
62
|
-
|
63
|
-
|
64
|
-
|
65
|
-
|
66
|
-
|
67
|
-
|
68
|
-
|
69
|
-
|
70
|
-
|
71
|
-
|
72
|
-
|
73
|
-
|
74
|
-
|
75
|
-
|
76
|
-
|
77
|
-
|
78
|
-
|
79
|
-
|
80
|
-
|
81
|
-
|
82
|
-
|
83
|
-
|
84
|
-
|
85
|
-
|
86
|
-
|
87
|
-
|
88
|
-
|
89
|
-
|
90
|
-
|
91
|
-
|
92
|
-
|
93
|
-
|
94
|
-
|
95
|
-
|
50
|
+
context "with profiler" do
|
51
|
+
if defined? RubyProf
|
52
|
+
before(:each) do
|
53
|
+
# Running RubyProf makes the code slightly slower.
|
54
|
+
RubyProf.start
|
55
|
+
puts "*** Running with RubyProf reduces performance ***"
|
56
|
+
end
|
57
|
+
|
58
|
+
after(:each) do
|
59
|
+
if RubyProf.running?
|
60
|
+
# file = arg.metadata[:description].gsub(/\s+/, '-')
|
61
|
+
|
62
|
+
result = RubyProf.stop
|
63
|
+
|
64
|
+
printer = RubyProf::FlatPrinter.new(result)
|
65
|
+
printer.print($stderr, min_percent: 1.0)
|
66
|
+
end
|
67
|
+
end
|
68
|
+
end
|
69
|
+
|
70
|
+
it "runs efficiently" do
|
71
|
+
result = []
|
72
|
+
range = (1..500)
|
73
|
+
duration = 2.0
|
74
|
+
|
75
|
+
total = 0
|
76
|
+
range.each do |index|
|
77
|
+
offset = index.to_f / range.max
|
78
|
+
total += (duration / offset).floor
|
79
|
+
|
80
|
+
subject.every(index.to_f / range.max, :strict) { result << index }
|
81
|
+
end
|
82
|
+
|
83
|
+
subject.wait while result.size < total
|
84
|
+
|
85
|
+
rate = result.size.to_f / subject.current_offset
|
86
|
+
puts "Serviced #{result.size} events in #{subject.current_offset} seconds, #{rate} e/s."
|
87
|
+
|
88
|
+
expect(subject.current_offset).to be_within(20).percent_of(duration)
|
89
|
+
end
|
90
|
+
end
|
91
|
+
|
92
|
+
it "runs efficiently at high volume" do
|
93
|
+
results = []
|
94
|
+
range = (1..300)
|
95
|
+
groups = (1..20)
|
96
|
+
duration = 11
|
97
|
+
|
98
|
+
timers = []
|
99
|
+
@mutex = Mutex.new
|
100
|
+
start = Time.now
|
101
|
+
groups.each do |gi|
|
102
|
+
timers << Thread.new {
|
103
|
+
result = []
|
104
|
+
timer = Timers::Group.new
|
105
|
+
total = 0
|
106
|
+
range.each do |ri|
|
107
|
+
offset = ri.to_f / range.max
|
108
|
+
total += (duration / offset).floor
|
109
|
+
timer.every(ri.to_f / range.max, :strict) { result << ri }
|
110
|
+
end
|
111
|
+
timer.wait while result.size < total
|
112
|
+
@mutex.synchronize { results += result }
|
113
|
+
|
114
|
+
}
|
115
|
+
end
|
116
|
+
timers.each { |t| t.join }
|
117
|
+
finish = Time.now
|
118
|
+
|
119
|
+
rate = results.size.to_f / ( runtime = finish - start )
|
120
|
+
|
121
|
+
puts "Serviced #{results.size} events in #{runtime} seconds, #{rate} e/s; across #{groups.max} timers."
|
122
|
+
|
123
|
+
expect(runtime).to be_within(20).percent_of(duration)
|
124
|
+
end
|
96
125
|
end
|
data/spec/timers/strict_spec.rb
CHANGED
@@ -1,36 +1,41 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
|
+
#
|
3
|
+
# This file is part of the "timers" project and released under the MIT license.
|
4
|
+
#
|
5
|
+
# Copyright, 2018, by Samuel Williams. All rights reserved.
|
6
|
+
#
|
2
7
|
|
3
8
|
RSpec.describe Timers::Group do
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
9
|
+
it "should not diverge too much" do
|
10
|
+
fired = :not_fired_yet
|
11
|
+
count = 0
|
12
|
+
quantum = 0.01
|
13
|
+
|
14
|
+
start_offset = subject.current_offset
|
15
|
+
Timers::Timer.new(subject, quantum, :strict, start_offset) do |offset|
|
16
|
+
fired = offset
|
17
|
+
count += 1
|
18
|
+
end
|
19
|
+
|
20
|
+
iterations = 1000
|
21
|
+
subject.wait while count < iterations
|
22
|
+
|
23
|
+
# In my testing on the JVM, without the :strict recurring, I noticed 60ms of error here.
|
24
|
+
expect(fired - start_offset).to be_within(quantum).of(iterations * quantum)
|
25
|
+
end
|
26
|
+
|
27
|
+
it "should only fire once" do
|
28
|
+
fired = :not_fired_yet
|
29
|
+
count = 0
|
30
|
+
|
31
|
+
start_offset = subject.current_offset
|
32
|
+
Timers::Timer.new(subject, 0, :strict, start_offset) do |offset|
|
33
|
+
fired = offset
|
34
|
+
count += 1
|
35
|
+
end
|
36
|
+
|
37
|
+
subject.wait
|
38
|
+
|
39
|
+
expect(count).to be == 1
|
40
|
+
end
|
36
41
|
end
|
data/spec/timers/wait_spec.rb
CHANGED
@@ -1,30 +1,35 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
|
+
#
|
3
|
+
# This file is part of the "timers" project and released under the MIT license.
|
4
|
+
#
|
5
|
+
# Copyright, 2018, by Samuel Williams. All rights reserved.
|
6
|
+
#
|
2
7
|
|
3
8
|
require "spec_helper"
|
4
9
|
require "timers/wait"
|
5
10
|
|
6
11
|
RSpec.describe Timers::Wait do
|
7
|
-
|
8
|
-
|
9
|
-
|
12
|
+
it "repeats until timeout expired" do
|
13
|
+
timeout = Timers::Wait.new(5)
|
14
|
+
count = 0
|
10
15
|
|
11
|
-
|
12
|
-
|
16
|
+
timeout.while_time_remaining do |remaining|
|
17
|
+
expect(remaining).to be_within(TIMER_QUANTUM).of(timeout.duration - count)
|
13
18
|
|
14
|
-
|
15
|
-
|
16
|
-
|
19
|
+
count += 1
|
20
|
+
sleep 1
|
21
|
+
end
|
17
22
|
|
18
|
-
|
19
|
-
|
23
|
+
expect(count).to eq(5)
|
24
|
+
end
|
20
25
|
|
21
|
-
|
22
|
-
|
26
|
+
it "yields results as soon as possible" do
|
27
|
+
timeout = Timers::Wait.new(5)
|
23
28
|
|
24
|
-
|
25
|
-
|
26
|
-
|
29
|
+
result = timeout.while_time_remaining do |_remaining|
|
30
|
+
break :done
|
31
|
+
end
|
27
32
|
|
28
|
-
|
29
|
-
|
33
|
+
expect(result).to eq(:done)
|
34
|
+
end
|
30
35
|
end
|
data/timers.gemspec
CHANGED
@@ -1,26 +1,33 @@
|
|
1
|
-
# -*- encoding: utf-8 -*-
|
2
1
|
# frozen_string_literal: true
|
2
|
+
#
|
3
|
+
# This file is part of the "timers" project and released under the MIT license.
|
4
|
+
#
|
5
|
+
# Copyright, 2018, by Samuel Williams. All rights reserved.
|
6
|
+
#
|
3
7
|
|
4
|
-
|
8
|
+
require_relative 'lib/timers/version'
|
5
9
|
|
6
|
-
Gem::Specification.new do |
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
10
|
+
Gem::Specification.new do |spec|
|
11
|
+
spec.name = "timers"
|
12
|
+
spec.version = Timers::VERSION
|
13
|
+
spec.authors = ["Samuel Williams", "Tony Arcieri"]
|
14
|
+
spec.email = ["samuel@codeotaku.com", "bascule@gmail.com"]
|
15
|
+
spec.licenses = ["MIT"]
|
16
|
+
spec.homepage = "https://github.com/socketry/timers"
|
17
|
+
spec.summary = "Pure Ruby one-shot and periodic timers"
|
18
|
+
spec.description = <<-DESCRIPTION.strip.gsub(/\s+/, " ")
|
19
|
+
Schedule procs to run after a certain time, or at periodic intervals,
|
20
|
+
using any API that accepts a timeout.
|
21
|
+
DESCRIPTION
|
18
22
|
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
gem.add_runtime_dependency "hitimes"
|
23
|
+
spec.files = `git ls-files`.split($OUTPUT_RECORD_SEPARATOR)
|
24
|
+
spec.executables = spec.files.grep(%r{^bin/}).map { |f| File.basename(f) }
|
25
|
+
spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
|
26
|
+
spec.require_paths = ["lib"]
|
24
27
|
|
25
|
-
|
28
|
+
spec.required_ruby_version = '>= 2.2.1'
|
29
|
+
|
30
|
+
spec.add_development_dependency "bundler", "~> 1.3"
|
31
|
+
spec.add_development_dependency "rspec", "~> 3.6"
|
32
|
+
spec.add_development_dependency "rake"
|
26
33
|
end
|
metadata
CHANGED
@@ -1,31 +1,46 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: timers
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 4.
|
4
|
+
version: 4.2.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
|
+
- Samuel Williams
|
7
8
|
- Tony Arcieri
|
8
9
|
autorequire:
|
9
10
|
bindir: bin
|
10
11
|
cert_chain: []
|
11
|
-
date:
|
12
|
+
date: 2018-11-06 00:00:00.000000000 Z
|
12
13
|
dependencies:
|
13
14
|
- !ruby/object:Gem::Dependency
|
14
|
-
name:
|
15
|
+
name: bundler
|
15
16
|
requirement: !ruby/object:Gem::Requirement
|
16
17
|
requirements:
|
17
|
-
- - "
|
18
|
+
- - "~>"
|
18
19
|
- !ruby/object:Gem::Version
|
19
|
-
version: '
|
20
|
-
type: :
|
20
|
+
version: '1.3'
|
21
|
+
type: :development
|
21
22
|
prerelease: false
|
22
23
|
version_requirements: !ruby/object:Gem::Requirement
|
23
24
|
requirements:
|
24
|
-
- - "
|
25
|
+
- - "~>"
|
25
26
|
- !ruby/object:Gem::Version
|
26
|
-
version: '
|
27
|
+
version: '1.3'
|
27
28
|
- !ruby/object:Gem::Dependency
|
28
|
-
name:
|
29
|
+
name: rspec
|
30
|
+
requirement: !ruby/object:Gem::Requirement
|
31
|
+
requirements:
|
32
|
+
- - "~>"
|
33
|
+
- !ruby/object:Gem::Version
|
34
|
+
version: '3.6'
|
35
|
+
type: :development
|
36
|
+
prerelease: false
|
37
|
+
version_requirements: !ruby/object:Gem::Requirement
|
38
|
+
requirements:
|
39
|
+
- - "~>"
|
40
|
+
- !ruby/object:Gem::Version
|
41
|
+
version: '3.6'
|
42
|
+
- !ruby/object:Gem::Dependency
|
43
|
+
name: rake
|
29
44
|
requirement: !ruby/object:Gem::Requirement
|
30
45
|
requirements:
|
31
46
|
- - ">="
|
@@ -41,26 +56,22 @@ dependencies:
|
|
41
56
|
description: Schedule procs to run after a certain time, or at periodic intervals,
|
42
57
|
using any API that accepts a timeout.
|
43
58
|
email:
|
59
|
+
- samuel@codeotaku.com
|
44
60
|
- bascule@gmail.com
|
45
61
|
executables: []
|
46
62
|
extensions: []
|
47
63
|
extra_rdoc_files: []
|
48
64
|
files:
|
49
|
-
- ".coveralls.yml"
|
50
65
|
- ".gitignore"
|
51
66
|
- ".rspec"
|
52
|
-
- ".rubocop.yml"
|
53
|
-
- ".ruby-version"
|
54
67
|
- ".travis.yml"
|
55
|
-
- AUTHORS.md
|
56
|
-
- CHANGES.md
|
57
68
|
- Gemfile
|
58
|
-
- LICENSE
|
59
69
|
- README.md
|
60
70
|
- Rakefile
|
61
71
|
- lib/timers.rb
|
62
72
|
- lib/timers/events.rb
|
63
73
|
- lib/timers/group.rb
|
74
|
+
- lib/timers/interval.rb
|
64
75
|
- lib/timers/timer.rb
|
65
76
|
- lib/timers/version.rb
|
66
77
|
- lib/timers/wait.rb
|
@@ -73,7 +84,7 @@ files:
|
|
73
84
|
- spec/timers/strict_spec.rb
|
74
85
|
- spec/timers/wait_spec.rb
|
75
86
|
- timers.gemspec
|
76
|
-
homepage: https://github.com/
|
87
|
+
homepage: https://github.com/socketry/timers
|
77
88
|
licenses:
|
78
89
|
- MIT
|
79
90
|
metadata: {}
|
@@ -85,7 +96,7 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
85
96
|
requirements:
|
86
97
|
- - ">="
|
87
98
|
- !ruby/object:Gem::Version
|
88
|
-
version:
|
99
|
+
version: 2.2.1
|
89
100
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
90
101
|
requirements:
|
91
102
|
- - ">="
|
@@ -93,7 +104,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
93
104
|
version: '0'
|
94
105
|
requirements: []
|
95
106
|
rubyforge_project:
|
96
|
-
rubygems_version: 2.
|
107
|
+
rubygems_version: 2.7.7
|
97
108
|
signing_key:
|
98
109
|
specification_version: 4
|
99
110
|
summary: Pure Ruby one-shot and periodic timers
|
data/.coveralls.yml
DELETED
@@ -1 +0,0 @@
|
|
1
|
-
service-name: travis-pro
|
data/.rubocop.yml
DELETED
@@ -1,28 +0,0 @@
|
|
1
|
-
AllCops:
|
2
|
-
DisplayCopNames: true
|
3
|
-
|
4
|
-
#
|
5
|
-
# Style
|
6
|
-
#
|
7
|
-
|
8
|
-
LineLength:
|
9
|
-
Max: 128
|
10
|
-
|
11
|
-
Style/NumericPredicate:
|
12
|
-
Enabled: false
|
13
|
-
|
14
|
-
Style/SafeNavigation:
|
15
|
-
Enabled: false
|
16
|
-
|
17
|
-
Style/StringLiterals:
|
18
|
-
EnforcedStyle: double_quotes
|
19
|
-
|
20
|
-
#
|
21
|
-
# Metrics
|
22
|
-
#
|
23
|
-
|
24
|
-
Metrics/ClassLength:
|
25
|
-
Max: 100
|
26
|
-
|
27
|
-
Metrics/MethodLength:
|
28
|
-
Max: 25
|