delayer 1.0.1 → 1.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 +4 -4
- data/.circleci/config.yml +40 -0
- data/README.md +2 -0
- data/Steepfile +19 -0
- data/delayer.gemspec +1 -1
- data/lib/delayer.rb +8 -3
- data/lib/delayer/delayed_procedure.rb +56 -0
- data/lib/delayer/error.rb +2 -0
- data/lib/delayer/extend.rb +83 -23
- data/lib/delayer/procedure.rb +1 -1
- data/lib/delayer/version.rb +1 -1
- data/sig/delayer.rbs +150 -0
- data/test/test_delayer.rb +108 -0
- metadata +11 -7
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: e7fea45fe078293c50cf946662ce8aace4acf2aa40b30abf894cedf117473b30
|
4
|
+
data.tar.gz: d4f0e01ce8dfce355d90022b73431d695061d6bff5fe15280d47c95b3b60f28f
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 27c1f3aca5d5e4745d341667d5ce2cdb3a032402b9fe94269017bb59535e70f6f97d00d3d4d68ddb7932d0bcb9dc13f9f3bf57a693c52fb06adc762b4d181b12
|
7
|
+
data.tar.gz: 8d80f9c8d5c06707d68f9df0017e6598a18212322c3065ffdf497e5ee5c427e703a83ea2c975bd8a66f6be3fd956171b109ee3ca44de71d933f98baeaebd0483
|
@@ -0,0 +1,40 @@
|
|
1
|
+
version: '2.1'
|
2
|
+
|
3
|
+
executors:
|
4
|
+
ruby:
|
5
|
+
parameters:
|
6
|
+
tag:
|
7
|
+
type: string
|
8
|
+
docker:
|
9
|
+
- image: circleci/ruby:<< parameters.tag >>
|
10
|
+
|
11
|
+
jobs:
|
12
|
+
build:
|
13
|
+
parameters:
|
14
|
+
ruby-version:
|
15
|
+
type: string
|
16
|
+
executor:
|
17
|
+
name: ruby
|
18
|
+
tag: << parameters.ruby-version >>
|
19
|
+
steps:
|
20
|
+
- checkout
|
21
|
+
- run:
|
22
|
+
name: Which bundler?
|
23
|
+
command: bundle -v
|
24
|
+
- run:
|
25
|
+
command: bundle install --path vendor/bundle
|
26
|
+
- run:
|
27
|
+
name: test
|
28
|
+
command: bundle exec rake test
|
29
|
+
workflows:
|
30
|
+
build:
|
31
|
+
jobs:
|
32
|
+
- build:
|
33
|
+
name: 'ruby-2.6'
|
34
|
+
ruby-version: '2.6.7'
|
35
|
+
- build:
|
36
|
+
name: 'ruby-2.7'
|
37
|
+
ruby-version: '2.7.3'
|
38
|
+
- build:
|
39
|
+
name: 'ruby-3.0'
|
40
|
+
ruby-version: '3.0.1'
|
data/README.md
CHANGED
data/Steepfile
ADDED
@@ -0,0 +1,19 @@
|
|
1
|
+
target :lib do
|
2
|
+
signature "sig"
|
3
|
+
check "lib" # Directory name
|
4
|
+
# ignore "lib/templates/*.rb"
|
5
|
+
# library "pathname", "set" # Standard libraries
|
6
|
+
# library "strong_json" # Gems
|
7
|
+
# library "instance_storage"
|
8
|
+
library "monitor"
|
9
|
+
library "set"
|
10
|
+
end
|
11
|
+
|
12
|
+
# target :spec do
|
13
|
+
# signature "sig", "sig-private"
|
14
|
+
#
|
15
|
+
# check "spec"
|
16
|
+
#
|
17
|
+
# # library "pathname", "set" # Standard libraries
|
18
|
+
# # library "rspec"
|
19
|
+
# end
|
data/delayer.gemspec
CHANGED
@@ -12,7 +12,7 @@ Gem::Specification.new do |spec|
|
|
12
12
|
spec.summary = %q{Delay the processing}
|
13
13
|
spec.homepage = "https://github.com/toshia/delayer"
|
14
14
|
spec.license = "MIT"
|
15
|
-
spec.required_ruby_version = '>= 2.
|
15
|
+
spec.required_ruby_version = '>= 2.6.0'
|
16
16
|
|
17
17
|
spec.files = `git ls-files`.split($/)
|
18
18
|
spec.executables = spec.files.grep(%r{^bin/}) { |f| File.basename(f) }
|
data/lib/delayer.rb
CHANGED
@@ -3,6 +3,7 @@ require "delayer/version"
|
|
3
3
|
require "delayer/error"
|
4
4
|
require "delayer/extend"
|
5
5
|
require "delayer/procedure"
|
6
|
+
require "delayer/delayed_procedure"
|
6
7
|
require "monitor"
|
7
8
|
|
8
9
|
module Delayer
|
@@ -23,7 +24,7 @@ module Delayer
|
|
23
24
|
include ::Delayer
|
24
25
|
@expire = options[:expire] || 0
|
25
26
|
if options.has_key?(:priority)
|
26
|
-
@priorities = options[:priority]
|
27
|
+
@priorities = options[:priority].to_a.freeze
|
27
28
|
@default_priority = options[:default]
|
28
29
|
else
|
29
30
|
@priorities = [:normal]
|
@@ -32,8 +33,12 @@ module Delayer
|
|
32
33
|
end
|
33
34
|
end
|
34
35
|
|
35
|
-
def method_missing(*args, &proc)
|
36
|
-
|
36
|
+
def method_missing(fn, *args, **kwrest, &proc)
|
37
|
+
if kwrest.empty?
|
38
|
+
(@default ||= generate_class).__send__(fn, *args, &proc)
|
39
|
+
else
|
40
|
+
(@default ||= generate_class).__send__(fn, *args, **kwrest, &proc)
|
41
|
+
end
|
37
42
|
end
|
38
43
|
end
|
39
44
|
end
|
@@ -0,0 +1,56 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Delayer
|
4
|
+
class DelayedProcedure
|
5
|
+
include Comparable
|
6
|
+
|
7
|
+
attr_reader :state, :delayer, :reserve_at
|
8
|
+
def initialize(delayer, delay:, &proc)
|
9
|
+
@delayer = delayer
|
10
|
+
@proc = proc
|
11
|
+
case delay
|
12
|
+
when Time
|
13
|
+
@reserve_at = Process.clock_gettime(Process::CLOCK_MONOTONIC) + delay.to_f - Time.now.to_f
|
14
|
+
else
|
15
|
+
@reserve_at = Process.clock_gettime(Process::CLOCK_MONOTONIC) + delay.to_f
|
16
|
+
end
|
17
|
+
@cancel = false
|
18
|
+
@procedure = nil
|
19
|
+
@delayer.class.reserve(self)
|
20
|
+
end
|
21
|
+
|
22
|
+
def register
|
23
|
+
if !canceled?
|
24
|
+
@procedure = Procedure.new(@delayer, &@proc)
|
25
|
+
end
|
26
|
+
self
|
27
|
+
end
|
28
|
+
|
29
|
+
def <=>(other)
|
30
|
+
@reserve_at <=> other.reserve_at
|
31
|
+
end
|
32
|
+
|
33
|
+
# Cancel this job
|
34
|
+
# ==== Exception
|
35
|
+
# Delayer::TooLate :: if already called run()
|
36
|
+
# ==== Return
|
37
|
+
# self
|
38
|
+
def cancel
|
39
|
+
@procedure&.cancel
|
40
|
+
@cancel = true
|
41
|
+
self
|
42
|
+
end
|
43
|
+
|
44
|
+
# Return true if canceled this task
|
45
|
+
# ==== Return
|
46
|
+
# true if canceled this task
|
47
|
+
def canceled?
|
48
|
+
procedure = @procedure
|
49
|
+
if procedure
|
50
|
+
procedure.canceled?
|
51
|
+
else
|
52
|
+
@cancel
|
53
|
+
end
|
54
|
+
end
|
55
|
+
end
|
56
|
+
end
|
data/lib/delayer/error.rb
CHANGED
data/lib/delayer/extend.rb
CHANGED
@@ -3,10 +3,20 @@
|
|
3
3
|
module Delayer
|
4
4
|
attr_reader :priority
|
5
5
|
|
6
|
-
Bucket
|
6
|
+
class Bucket
|
7
|
+
attr_accessor :first, :last, :priority_of, :stashed
|
8
|
+
|
9
|
+
def initialize(first, last, priority_of, stashed)
|
10
|
+
@first = first
|
11
|
+
@last = last
|
12
|
+
@priority_of = priority_of
|
13
|
+
@stashed = stashed
|
14
|
+
end
|
15
|
+
|
7
16
|
def stash_size
|
8
|
-
|
9
|
-
|
17
|
+
s = stashed
|
18
|
+
if s
|
19
|
+
1 + s.stash_size
|
10
20
|
else
|
11
21
|
0
|
12
22
|
end
|
@@ -19,10 +29,14 @@ module Delayer
|
|
19
29
|
end
|
20
30
|
end
|
21
31
|
|
22
|
-
def initialize(priority = self.class.instance_eval { @default_priority }, *_args, &proc)
|
32
|
+
def initialize(priority = self.class.instance_eval { @default_priority }, *_args, delay: 0, &proc)
|
23
33
|
self.class.validate_priority priority
|
24
34
|
@priority = priority
|
25
|
-
|
35
|
+
if delay == 0
|
36
|
+
@procedure = Procedure.new(self, &proc)
|
37
|
+
else
|
38
|
+
@procedure = DelayedProcedure.new(self, delay: delay, &proc)
|
39
|
+
end
|
26
40
|
end
|
27
41
|
|
28
42
|
# Cancel this job
|
@@ -46,8 +60,22 @@ module Delayer
|
|
46
60
|
@remain_hook = nil
|
47
61
|
@exception = nil
|
48
62
|
@remain_received = false
|
49
|
-
@lock =
|
63
|
+
@lock = Monitor.new
|
50
64
|
@bucket = Bucket.new(nil, nil, {}, nil)
|
65
|
+
@last_reserve = nil
|
66
|
+
@reserves = Set.new
|
67
|
+
end
|
68
|
+
end
|
69
|
+
|
70
|
+
def pop_reserve(start_time = Process.clock_gettime(Process::CLOCK_MONOTONIC))
|
71
|
+
if @last_reserve&.reserve_at&.<=(start_time)
|
72
|
+
lock.synchronize do
|
73
|
+
while @last_reserve&.reserve_at&.<=(start_time)
|
74
|
+
@last_reserve.register
|
75
|
+
@last_reserve = @reserves.min
|
76
|
+
@reserves.delete(@last_reserve)
|
77
|
+
end
|
78
|
+
end
|
51
79
|
end
|
52
80
|
end
|
53
81
|
|
@@ -57,11 +85,13 @@ module Delayer
|
|
57
85
|
# ==== Return
|
58
86
|
# self
|
59
87
|
def run(current_expire = @expire)
|
88
|
+
start_time = Process.clock_gettime(Process::CLOCK_MONOTONIC).to_f
|
89
|
+
pop_reserve(start_time)
|
60
90
|
if current_expire == 0
|
61
|
-
|
91
|
+
run_once_without_pop_reserve until empty?
|
62
92
|
else
|
63
|
-
@end_time =
|
64
|
-
|
93
|
+
@end_time = end_time = start_time + @expire
|
94
|
+
run_once_without_pop_reserve while !empty? && (end_time >= Process.clock_gettime(Process::CLOCK_MONOTONIC))
|
65
95
|
@end_time = nil
|
66
96
|
end
|
67
97
|
if @remain_hook
|
@@ -74,22 +104,25 @@ module Delayer
|
|
74
104
|
end
|
75
105
|
|
76
106
|
def expire?
|
77
|
-
|
78
|
-
@end_time < Time.new.to_f
|
79
|
-
else
|
80
|
-
false
|
81
|
-
end
|
107
|
+
!!@end_time&.<(Time.new.to_f)
|
82
108
|
end
|
83
109
|
|
84
110
|
# Run a job and forward pointer.
|
85
111
|
# ==== Return
|
86
112
|
# self
|
87
113
|
def run_once
|
114
|
+
pop_reserve
|
115
|
+
run_once_without_pop_reserve
|
116
|
+
end
|
117
|
+
|
118
|
+
private def run_once_without_pop_reserve
|
88
119
|
if @bucket.first
|
89
120
|
@busy = true
|
90
121
|
procedure = forward
|
91
|
-
procedure = forward while @bucket.first && procedure
|
92
|
-
procedure
|
122
|
+
procedure = forward while @bucket.first && procedure&.canceled?
|
123
|
+
if procedure && !procedure.canceled?
|
124
|
+
procedure.run
|
125
|
+
end
|
93
126
|
end
|
94
127
|
ensure
|
95
128
|
@busy = false
|
@@ -146,6 +179,29 @@ module Delayer
|
|
146
179
|
self
|
147
180
|
end
|
148
181
|
|
182
|
+
# Register reserved job.
|
183
|
+
# It does not execute immediately.
|
184
|
+
# it calls register() in _procedure.reserve_at_.
|
185
|
+
# ==== Args
|
186
|
+
# [procedure] job(Delayer::DelayedProcedure)
|
187
|
+
# ==== Return
|
188
|
+
# self
|
189
|
+
def reserve(procedure)
|
190
|
+
lock.synchronize do
|
191
|
+
if @last_reserve
|
192
|
+
if @last_reserve > procedure
|
193
|
+
@reserves.add(@last_reserve)
|
194
|
+
@last_reserve = procedure
|
195
|
+
else
|
196
|
+
@reserves.add(procedure)
|
197
|
+
end
|
198
|
+
else
|
199
|
+
@last_reserve = procedure
|
200
|
+
end
|
201
|
+
end
|
202
|
+
self
|
203
|
+
end
|
204
|
+
|
149
205
|
def register_remain_hook(&proc)
|
150
206
|
@remain_hook = proc
|
151
207
|
end
|
@@ -154,8 +210,10 @@ module Delayer
|
|
154
210
|
if @bucket.priority_of[priority]
|
155
211
|
@bucket.priority_of[priority]
|
156
212
|
else
|
157
|
-
|
158
|
-
|
213
|
+
@priorities.index(priority)&.yield_self do |index|
|
214
|
+
next_index = index - 1
|
215
|
+
get_prev_point @priorities[next_index] if next_index >= 0
|
216
|
+
end
|
159
217
|
end
|
160
218
|
end
|
161
219
|
|
@@ -178,10 +236,11 @@ module Delayer
|
|
178
236
|
# [Delayer::NoLowerLevelError] stash_enter!が呼ばれていない時
|
179
237
|
# [Delayer::RemainJobsError] ジョブが残っているのにこのメソッドを呼んだ時
|
180
238
|
def stash_exit!
|
181
|
-
|
239
|
+
stashed = @bucket.stashed
|
240
|
+
raise Delayer::NoLowerLevelError, 'stash_exit! called in level 0.' unless stashed
|
182
241
|
raise Delayer::RemainJobsError, 'Current level has remain jobs. It must be empty current level jobs in call this method.' unless empty?
|
183
242
|
|
184
|
-
@bucket =
|
243
|
+
@bucket = stashed
|
185
244
|
end
|
186
245
|
|
187
246
|
# 現在のDelayer Stashレベルを返す。
|
@@ -194,10 +253,11 @@ module Delayer
|
|
194
253
|
def forward
|
195
254
|
lock.synchronize do
|
196
255
|
prev = @bucket.first
|
197
|
-
|
198
|
-
@bucket.
|
256
|
+
raise 'Current bucket not found' unless prev
|
257
|
+
nex = @bucket.first = prev.next
|
258
|
+
@bucket.last = nil unless nex
|
199
259
|
@bucket.priority_of.each do |priority, pointer|
|
200
|
-
@bucket.priority_of[priority] =
|
260
|
+
@bucket.priority_of[priority] = nex if prev == pointer
|
201
261
|
end
|
202
262
|
prev.next = nil
|
203
263
|
prev
|
data/lib/delayer/procedure.rb
CHANGED
data/lib/delayer/version.rb
CHANGED
data/sig/delayer.rbs
ADDED
@@ -0,0 +1,150 @@
|
|
1
|
+
# TypeProf 0.13.0
|
2
|
+
|
3
|
+
# Classes
|
4
|
+
module Delayer
|
5
|
+
type clock = Float | Integer | Rational
|
6
|
+
|
7
|
+
VERSION: String
|
8
|
+
extend Extend
|
9
|
+
extend Delayer
|
10
|
+
self.@expire: clock
|
11
|
+
self.@priorities: Array[Symbol]
|
12
|
+
self.@default_priority: Symbol
|
13
|
+
self.@default: singleton(Delayer)
|
14
|
+
@procedure: Procedure | DelayedProcedure
|
15
|
+
self.@busy: bool
|
16
|
+
self.@remain_hook: ^() -> void
|
17
|
+
self.@exception: Exception?
|
18
|
+
self.@remain_received: bool
|
19
|
+
self.@lock: Monitor
|
20
|
+
self.@bucket: Bucket
|
21
|
+
self.@last_reserve: nil
|
22
|
+
self.@reserves: untyped
|
23
|
+
@default_priority: Symbol
|
24
|
+
self.@end_time: clock?
|
25
|
+
|
26
|
+
class GeneratedDelayerAbstract
|
27
|
+
include ::Delayer
|
28
|
+
end
|
29
|
+
|
30
|
+
def self.generate_class: (?Hash[Symbol,Integer|Symbol|Enumerable[Symbol]] options) -> singleton(Delayer)
|
31
|
+
def self.method_missing: (Symbol, *untyped, **untyped) { (*untyped) -> untyped } -> untyped
|
32
|
+
|
33
|
+
def self.StateError: (:cancel) -> singleton(AlreadyCanceledError)
|
34
|
+
| (:done) -> singleton(AlreadyExecutedError)
|
35
|
+
| (:run) -> singleton(AlreadyRunningError)
|
36
|
+
| (Symbol) -> singleton(TooLate)
|
37
|
+
|
38
|
+
attr_reader priority: Symbol
|
39
|
+
def self.included: (singleton(Delayer) klass) -> void
|
40
|
+
def initialize: (?untyped priority, *untyped _args, ?delay: Time | clock) -> void
|
41
|
+
def cancel: -> Delayer
|
42
|
+
def stash_size: -> (Integer)
|
43
|
+
def __send__: (Symbol, *untyped, **untyped) { (untyped) -> untyped } -> untyped
|
44
|
+
|
45
|
+
class DelayedProcedure
|
46
|
+
include Comparable
|
47
|
+
@proc: (^() -> void)
|
48
|
+
@cancel: bool
|
49
|
+
@procedure: Procedure?
|
50
|
+
|
51
|
+
attr_reader state: untyped
|
52
|
+
attr_reader delayer: Delayer
|
53
|
+
attr_reader reserve_at: clock
|
54
|
+
def initialize: (Delayer delayer, delay: Time | clock) { () -> void } -> void
|
55
|
+
def register: -> self
|
56
|
+
def <=>: (DelayedProcedure other) -> Integer?
|
57
|
+
def cancel: -> self
|
58
|
+
def canceled?: -> bool
|
59
|
+
end
|
60
|
+
|
61
|
+
class Error < StandardError
|
62
|
+
end
|
63
|
+
|
64
|
+
class TooLate < Error
|
65
|
+
end
|
66
|
+
|
67
|
+
class AlreadyExecutedError < TooLate
|
68
|
+
end
|
69
|
+
|
70
|
+
class AlreadyCanceledError < TooLate
|
71
|
+
end
|
72
|
+
|
73
|
+
class AlreadyRunningError < TooLate
|
74
|
+
end
|
75
|
+
|
76
|
+
class InvalidPriorityError < Error
|
77
|
+
end
|
78
|
+
|
79
|
+
class RecursiveError < Error
|
80
|
+
end
|
81
|
+
|
82
|
+
class NoLowerLevelError < RecursiveError
|
83
|
+
end
|
84
|
+
|
85
|
+
class RemainJobsError < RecursiveError
|
86
|
+
end
|
87
|
+
|
88
|
+
class Bucket
|
89
|
+
attr_accessor first(): Procedure?
|
90
|
+
attr_accessor last(): Procedure?
|
91
|
+
attr_accessor priority_of(): Hash[Symbol, Procedure?]
|
92
|
+
attr_accessor stashed(): Bucket?
|
93
|
+
|
94
|
+
def initialize: (Procedure?,Procedure?,Hash[Symbol, Procedure],Bucket?) -> void
|
95
|
+
def stash_size: () -> Integer
|
96
|
+
end
|
97
|
+
|
98
|
+
module Extend
|
99
|
+
@last_reserve: untyped
|
100
|
+
@lock: Monitor
|
101
|
+
@end_time: clock?
|
102
|
+
@bucket: Bucket
|
103
|
+
@remain_hook: ^() -> void
|
104
|
+
@remain_received: bool
|
105
|
+
@busy: bool
|
106
|
+
@priorities: Array[Symbol]
|
107
|
+
@reserves: Set[DelayedProcedure]
|
108
|
+
|
109
|
+
attr_accessor expire: clock
|
110
|
+
attr_reader exception: Exception?
|
111
|
+
def self.extended: (singleton(Delayer) klass) -> singleton(Delayer)
|
112
|
+
def pop_reserve: (?clock start_time) -> nil
|
113
|
+
def run: (?clock? current_expire) -> void
|
114
|
+
def expire?: -> bool
|
115
|
+
def run_once: -> void
|
116
|
+
|
117
|
+
private
|
118
|
+
def run_once_without_pop_reserve: -> void
|
119
|
+
|
120
|
+
public
|
121
|
+
def busy?: -> bool
|
122
|
+
def empty?: -> bool
|
123
|
+
def size: (?Delayer::Procedure? node) -> Integer
|
124
|
+
def register: (untyped procedure) -> Extend
|
125
|
+
def reserve: (untyped procedure) -> Extend
|
126
|
+
def register_remain_hook: () { () -> void } -> void
|
127
|
+
def get_prev_point: (Symbol) -> ::Delayer::Procedure?
|
128
|
+
def validate_priority: (Symbol) -> void
|
129
|
+
def stash_enter!: -> Extend
|
130
|
+
def stash_exit!: -> Bucket?
|
131
|
+
def stash_level: -> untyped
|
132
|
+
|
133
|
+
private
|
134
|
+
def forward: -> Procedure?
|
135
|
+
def lock: -> Monitor
|
136
|
+
end
|
137
|
+
|
138
|
+
class Procedure
|
139
|
+
@proc: (^() -> void)?
|
140
|
+
|
141
|
+
attr_reader state: :cancel | :done | :run | :stop
|
142
|
+
attr_reader delayer: untyped
|
143
|
+
attr_accessor next: Delayer::Procedure?
|
144
|
+
def initialize: (Delayer delayer) { () -> void } -> void
|
145
|
+
def run: -> void
|
146
|
+
def cancel: -> Procedure
|
147
|
+
def canceled?: -> bool
|
148
|
+
def break: (untyped node) -> untyped
|
149
|
+
end
|
150
|
+
end
|
data/test/test_delayer.rb
CHANGED
@@ -353,4 +353,112 @@ class TestDelayer < Test::Unit::TestCase
|
|
353
353
|
end
|
354
354
|
end
|
355
355
|
|
356
|
+
def test_timer
|
357
|
+
delayer = Delayer.generate_class expire: 0.01
|
358
|
+
a = []
|
359
|
+
delayer.new(delay: 0.01) { a << 0 }
|
360
|
+
delayer.new { a << 1 }
|
361
|
+
|
362
|
+
delayer.run
|
363
|
+
|
364
|
+
delayer.new { a << 2 }
|
365
|
+
sleep 0.1
|
366
|
+
|
367
|
+
delayer.run
|
368
|
+
|
369
|
+
delayer.new { a << 3 }
|
370
|
+
|
371
|
+
delayer.run
|
372
|
+
|
373
|
+
assert_equal([1, 2, 0, 3], a)
|
374
|
+
end
|
375
|
+
|
376
|
+
def test_timer_give_time
|
377
|
+
delayer = Delayer.generate_class expire: 0.01
|
378
|
+
a = []
|
379
|
+
delayer.new(delay: Time.new) { a << 0 }
|
380
|
+
|
381
|
+
delayer.run
|
382
|
+
|
383
|
+
assert_equal([0], a)
|
384
|
+
end
|
385
|
+
|
386
|
+
def test_plural_timer
|
387
|
+
delayer = Delayer.generate_class expire: 0.01
|
388
|
+
a = []
|
389
|
+
delayer.new(delay: 0.01) { a << 0 }
|
390
|
+
delayer.new(delay: 0.11) { a << 1 }
|
391
|
+
delayer.new { a << 2 }
|
392
|
+
|
393
|
+
delayer.run
|
394
|
+
|
395
|
+
delayer.new { a << 3 }
|
396
|
+
sleep 0.1
|
397
|
+
|
398
|
+
delayer.run
|
399
|
+
sleep 0.1
|
400
|
+
|
401
|
+
delayer.new { a << 4 }
|
402
|
+
|
403
|
+
delayer.run
|
404
|
+
|
405
|
+
assert_equal([2, 3, 0, 4, 1], a)
|
406
|
+
end
|
407
|
+
|
408
|
+
def test_many_timer
|
409
|
+
delayer = Delayer.generate_class expire: 0.01
|
410
|
+
a = []
|
411
|
+
(0..10).to_a.shuffle.each do |i|
|
412
|
+
delayer.new(delay: i / 100.0) { a << i }
|
413
|
+
end
|
414
|
+
|
415
|
+
sleep 0.1
|
416
|
+
|
417
|
+
delayer.run
|
418
|
+
|
419
|
+
assert_equal((0..10).to_a, a)
|
420
|
+
end
|
421
|
+
|
422
|
+
def test_cancel_timer
|
423
|
+
delayer = Delayer.generate_class
|
424
|
+
a = 0
|
425
|
+
delayer.new(delay: 0.01) { a += 1 }
|
426
|
+
d = delayer.new(delay: 0.01) { a += 2 }
|
427
|
+
delayer.new(delay: 0.01) { a += 4 }
|
428
|
+
|
429
|
+
assert_equal(0, a)
|
430
|
+
d.cancel
|
431
|
+
sleep 0.1
|
432
|
+
delayer.run
|
433
|
+
assert_equal(5, a)
|
434
|
+
end
|
435
|
+
|
436
|
+
def test_cancel_timer_after_expire
|
437
|
+
delayer = Delayer.generate_class
|
438
|
+
a = 0
|
439
|
+
delayer.new(delay: 0.01) { a += 1 }
|
440
|
+
d = delayer.new(delay: 0.01) { a += 2 }
|
441
|
+
delayer.new{ d.cancel }
|
442
|
+
delayer.new(delay: 0.01) { a += 4 }
|
443
|
+
|
444
|
+
assert_equal(0, a)
|
445
|
+
sleep 0.1
|
446
|
+
delayer.run
|
447
|
+
assert_equal(5, a)
|
448
|
+
end
|
449
|
+
|
450
|
+
def test_reserve_new_timer_after_cancel
|
451
|
+
delayer = Delayer.generate_class
|
452
|
+
a = 0
|
453
|
+
delayer.new(delay: 0.01) { a += 1 }
|
454
|
+
d = delayer.new(delay: 0.02) { a += 2 }
|
455
|
+
d.cancel
|
456
|
+
delayer.new(delay: 0.03) { a += 4 }
|
457
|
+
|
458
|
+
assert_equal(0, a)
|
459
|
+
sleep 0.1
|
460
|
+
delayer.run
|
461
|
+
assert_equal(5, a)
|
462
|
+
end
|
463
|
+
|
356
464
|
end
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: delayer
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 1.0
|
4
|
+
version: 1.2.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Toshiaki Asai
|
8
|
-
autorequire:
|
8
|
+
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date:
|
11
|
+
date: 2021-04-10 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: bundler
|
@@ -65,24 +65,28 @@ executables: []
|
|
65
65
|
extensions: []
|
66
66
|
extra_rdoc_files: []
|
67
67
|
files:
|
68
|
+
- ".circleci/config.yml"
|
68
69
|
- ".gitignore"
|
69
70
|
- Gemfile
|
70
71
|
- LICENSE.txt
|
71
72
|
- README.md
|
72
73
|
- Rakefile
|
74
|
+
- Steepfile
|
73
75
|
- delayer.gemspec
|
74
76
|
- lib/delayer.rb
|
77
|
+
- lib/delayer/delayed_procedure.rb
|
75
78
|
- lib/delayer/error.rb
|
76
79
|
- lib/delayer/extend.rb
|
77
80
|
- lib/delayer/procedure.rb
|
78
81
|
- lib/delayer/version.rb
|
82
|
+
- sig/delayer.rbs
|
79
83
|
- test/test_delayer.rb
|
80
84
|
- test/test_priority.rb
|
81
85
|
homepage: https://github.com/toshia/delayer
|
82
86
|
licenses:
|
83
87
|
- MIT
|
84
88
|
metadata: {}
|
85
|
-
post_install_message:
|
89
|
+
post_install_message:
|
86
90
|
rdoc_options: []
|
87
91
|
require_paths:
|
88
92
|
- lib
|
@@ -90,15 +94,15 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
90
94
|
requirements:
|
91
95
|
- - ">="
|
92
96
|
- !ruby/object:Gem::Version
|
93
|
-
version: 2.
|
97
|
+
version: 2.6.0
|
94
98
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
95
99
|
requirements:
|
96
100
|
- - ">="
|
97
101
|
- !ruby/object:Gem::Version
|
98
102
|
version: '0'
|
99
103
|
requirements: []
|
100
|
-
rubygems_version: 3.
|
101
|
-
signing_key:
|
104
|
+
rubygems_version: 3.2.13
|
105
|
+
signing_key:
|
102
106
|
specification_version: 4
|
103
107
|
summary: Delay the processing
|
104
108
|
test_files:
|