lusnoc 0.1.0 → 0.1.2.16548
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/LICENSE +19 -0
- data/README.md +34 -13
- data/lib/lusnoc.rb +1 -0
- data/lib/lusnoc/guard.rb +67 -0
- data/lib/lusnoc/mutex.rb +8 -10
- data/lib/lusnoc/session.rb +21 -34
- data/lib/lusnoc/version.rb +1 -1
- data/lib/lusnoc/watcher.rb +9 -10
- metadata +48 -5
- data/lib/lusnoc/timeouter.rb +0 -51
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 7bbe9d1f94b450c09aaeb7fe5283bef89ee796a4b57712af40603ba8eb5a3f0c
|
4
|
+
data.tar.gz: 2ceec91d3f94a92631698ad391b5c7848e57d4033dbd1766ab37d0cd75a1f322
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 11b1834bca1940eea5d5099cff6100587bc5fbcf75ea012866629d23daa6f43a4c2cceeb76c26b58689adad5cffaad33f62d104fe3d75a33645cb4e39607b8e8
|
7
|
+
data.tar.gz: 5b356bfa4e314d7da5e4cba97e24abbe5b5ccfaa2e98c977d3c8f6d583c3f5ad3d12a616cf96f6ad120a3382d48dac2b53d197667fbcc9fbcee3886ad11362de
|
data/LICENSE
ADDED
@@ -0,0 +1,19 @@
|
|
1
|
+
Copyright (c) 2014-2019 Рнд Софт
|
2
|
+
|
3
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
4
|
+
of this software and associated documentation files (the "Software"), to deal
|
5
|
+
in the Software without restriction, including without limitation the rights
|
6
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
7
|
+
copies of the Software, and to permit persons to whom the Software is
|
8
|
+
furnished to do so, subject to the following conditions:
|
9
|
+
|
10
|
+
The above copyright notice and this permission notice shall be included in all
|
11
|
+
copies or substantial portions of the Software.
|
12
|
+
|
13
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
14
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
15
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
16
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
17
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
18
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
19
|
+
SOFTWARE.
|
data/README.md
CHANGED
@@ -1,6 +1,15 @@
|
|
1
1
|
# Lusnoc
|
2
2
|
|
3
|
-
|
3
|
+
[](https://rubygems.org/gems/lusnoc)
|
4
|
+
[](https://rubygems.org/gems/lusnoc/versions)
|
5
|
+
|
6
|
+
[](https://codeclimate.com/github/RnD-Soft/lusnoc/test_coverage)
|
7
|
+
[](https://codeclimate.com/github/RnD-Soft/lusnoc/maintainability)
|
8
|
+
[](https://lysander.x.rnds.pro/api/v1/badges/lusnoc_quality.html)
|
9
|
+
[](https://lysander.x.rnds.pro/api/v1/badges/lusnoc_outdated.html)
|
10
|
+
[](https://lysander.x.rnds.pro/api/v1/badges/lusnoc_vulnerable.html)
|
11
|
+
|
12
|
+
Lusnoc is reliable gem to deal with [Consul](https://www.consul.io). It is designed to be simple and work without dark background magic.
|
4
13
|
It is inspired by [consul-mutex](https://github.com/discourse/consul-mutex)(which has hard background magic).
|
5
14
|
|
6
15
|
## FAQ
|
@@ -13,20 +22,20 @@ Lusnoc allows you to interact with Consul to provide distributed locks(mutex) to
|
|
13
22
|
* consul-mutex starts background thread and ***the block of code that you pass to #synchronize runs on a separate thread, and can be killed without warning if the mutex determines that it no longer holds the lock.***
|
14
23
|
* diplomat provides the basic session/locks functionality but no automated control over it
|
15
24
|
|
16
|
-
#### How
|
17
|
-
*
|
18
|
-
*
|
19
|
-
*
|
20
|
-
*
|
25
|
+
#### How Lusnoc deal with sessions/mutexes?
|
26
|
+
* Lusnoc ensures session creation/destruction upon block execution
|
27
|
+
* Lusnoc uses only sessions with TTL to protect you system from stale sessions/locks
|
28
|
+
* Lusnoc enforces you to manualy renew session(through callback or explicit check) but provide background session checker
|
29
|
+
* Lusnoc tries to carefuly handle timeouts and expiration using Consul [blocking queries](https://www.consul.io/api/features/blocking.html)
|
21
30
|
|
22
31
|
# Usage
|
23
32
|
|
24
|
-
Simply instantiate a new `
|
33
|
+
Simply instantiate a new `Lusnoc::Mutex`, giving it the key you want to use
|
25
34
|
as the "lock":
|
26
35
|
|
27
36
|
```ruby
|
28
|
-
require '
|
29
|
-
mutex =
|
37
|
+
require 'lusnoc/mutex'
|
38
|
+
mutex = Lusnoc::Mutex.new('/locks/mx1', ttl: 20)
|
30
39
|
```
|
31
40
|
TTL will be used in session creation on `#synchronize`:
|
32
41
|
```ruby
|
@@ -39,13 +48,13 @@ By default, the "value" of the lock resource will be the hostname of the
|
|
39
48
|
machine that it's running on (so you know who has the lock). If, for some
|
40
49
|
reason, you'd like to set the value to something else, you can do that, too:
|
41
50
|
```ruby
|
42
|
-
|
51
|
+
Lusnoc::Mutex.new('/some/key', value: {time: Time.now}).synchronize do |mx|
|
43
52
|
#...
|
44
53
|
end
|
45
54
|
```
|
46
|
-
Session invalidation/
|
55
|
+
Session invalidation/renewal handled through mutex instance:
|
47
56
|
```ruby
|
48
|
-
|
57
|
+
Lusnoc::Mutex.new('/some/key').synchronize do |mx|
|
49
58
|
mx.time_to_expiration # seconds to session expiration in consul.
|
50
59
|
mx.ttl # session ttl.
|
51
60
|
mx.need_renew? # true when time_to_expiration less than half of ttl
|
@@ -84,7 +93,7 @@ You can use only Session:
|
|
84
93
|
Typical usage scenario:
|
85
94
|
|
86
95
|
```ruby
|
87
|
-
|
96
|
+
Lusnoc::Mutex.new('/some/key').synchronize do |mx|
|
88
97
|
# do some work
|
89
98
|
mx.renew if mx.need_renew?
|
90
99
|
# do other work
|
@@ -95,3 +104,15 @@ Typical usage scenario:
|
|
95
104
|
end
|
96
105
|
```
|
97
106
|
|
107
|
+
# Installation
|
108
|
+
|
109
|
+
It's a gem:
|
110
|
+
```bash
|
111
|
+
gem install lusnoc
|
112
|
+
```
|
113
|
+
There's also the wonders of [the Gemfile](http://bundler.io):
|
114
|
+
```ruby
|
115
|
+
gem 'lusnoc'
|
116
|
+
```
|
117
|
+
|
118
|
+
|
data/lib/lusnoc.rb
CHANGED
data/lib/lusnoc/guard.rb
ADDED
@@ -0,0 +1,67 @@
|
|
1
|
+
require 'timeouter'
|
2
|
+
require 'lusnoc/helper'
|
3
|
+
|
4
|
+
module Lusnoc
|
5
|
+
class Guard
|
6
|
+
|
7
|
+
include Helper
|
8
|
+
|
9
|
+
def initialize(base_url)
|
10
|
+
@base_url = base_url
|
11
|
+
yield(self) if block_given?
|
12
|
+
end
|
13
|
+
|
14
|
+
def condition(&block)
|
15
|
+
@condition = block
|
16
|
+
self
|
17
|
+
end
|
18
|
+
|
19
|
+
def then(&block)
|
20
|
+
@callback = block
|
21
|
+
self
|
22
|
+
end
|
23
|
+
|
24
|
+
def run
|
25
|
+
th = Thread.new do
|
26
|
+
logger.info "Guard[#{@base_url.inspect}] thread started"
|
27
|
+
watch_forever(@base_url)
|
28
|
+
fire!
|
29
|
+
rescue StandardError => e
|
30
|
+
logger.error "Guard[#{@base_url.inspect}] error: #{e.inspect}"
|
31
|
+
fire!
|
32
|
+
ensure
|
33
|
+
logger.info "Guard[#{@base_url.inspect}] finihsed"
|
34
|
+
end
|
35
|
+
|
36
|
+
yield
|
37
|
+
ensure
|
38
|
+
th.kill rescue nil
|
39
|
+
end
|
40
|
+
|
41
|
+
private
|
42
|
+
|
43
|
+
def fire!
|
44
|
+
@callback&.tap do |cb|
|
45
|
+
@callback = nil
|
46
|
+
logger.info "Guard[#{@base_url.inspect}] fired"
|
47
|
+
cb.call
|
48
|
+
end
|
49
|
+
end
|
50
|
+
|
51
|
+
def watch_forever(base_url)
|
52
|
+
last_x_consul_index = 1
|
53
|
+
|
54
|
+
Kernel.loop do
|
55
|
+
resp = Lusnoc.http_get("#{base_url}?index=#{last_x_consul_index}&wait=10s", timeout: 15)
|
56
|
+
logger.debug "Guard[#{@base_url.inspect}] response: #{resp.body}"
|
57
|
+
return unless @condition.call(resp.body)
|
58
|
+
|
59
|
+
index = [Integer(resp['x-consul-index']), 1].max
|
60
|
+
last_x_consul_index = (index < last_x_consul_index ? 1 : index)
|
61
|
+
sleep 1
|
62
|
+
end
|
63
|
+
end
|
64
|
+
|
65
|
+
end
|
66
|
+
end
|
67
|
+
|
data/lib/lusnoc/mutex.rb
CHANGED
@@ -34,9 +34,7 @@ module Lusnoc
|
|
34
34
|
end
|
35
35
|
|
36
36
|
def synchronize(timeout: 0, &block)
|
37
|
-
|
38
|
-
exception_class: TimeoutError,
|
39
|
-
exception_message: 'mutex acquisition expired')
|
37
|
+
t = Timeouter::Timer.new(timeout, eclass: TimeoutError, message: 'mutex acquisition expired')
|
40
38
|
|
41
39
|
Session.new("mutex_session/#{key}", ttl: @ttl) do |session|
|
42
40
|
@session = session
|
@@ -45,7 +43,7 @@ module Lusnoc
|
|
45
43
|
@on_mutex_lost&.call(self)
|
46
44
|
end
|
47
45
|
|
48
|
-
return acquisition_loop! key, session, value,
|
46
|
+
return acquisition_loop! key, session, value, t, &block
|
49
47
|
ensure
|
50
48
|
release(key, session.id, timeout: 2) rescue nil
|
51
49
|
logger.info("Lock #{key} released for session #{session.name}[#{session.id}]")
|
@@ -70,13 +68,13 @@ module Lusnoc
|
|
70
68
|
Lusnoc.http_put(build_url("/v1/kv/#{key}?release=#{session.id}"), timeout: 1)
|
71
69
|
end
|
72
70
|
|
73
|
-
def acquisition_loop!(key, session, value,
|
71
|
+
def acquisition_loop!(key, session, value, t)
|
74
72
|
return yield(self) if acquire(key, session, value)
|
75
73
|
|
76
74
|
logger.debug("Start #{key} acquisition loop for session #{session.name}[#{session.id}]")
|
77
|
-
|
75
|
+
t.loop! do
|
78
76
|
session.alive!(TimeoutError)
|
79
|
-
wait_for_key_released(key,
|
77
|
+
wait_for_key_released(key, t.left)
|
80
78
|
|
81
79
|
return yield(self) if acquire(key, session, value)
|
82
80
|
|
@@ -88,9 +86,9 @@ module Lusnoc
|
|
88
86
|
def wait_for_key_released(key, timeout = nil)
|
89
87
|
logger.debug "Waiting for key #{key} to be fre of any session"
|
90
88
|
Lusnoc::Watcher.new(build_url("/v1/kv/#{key}"),
|
91
|
-
timeout:
|
92
|
-
|
93
|
-
|
89
|
+
timeout: timeout,
|
90
|
+
eclass: TimeoutError,
|
91
|
+
emessage: 'mutex acquisition expired').run do |body|
|
94
92
|
result = JSON.parse(body.empty? ? '[{}]' : body)
|
95
93
|
return true if result.first['Session'].nil?
|
96
94
|
end
|
data/lib/lusnoc/session.rb
CHANGED
@@ -1,4 +1,5 @@
|
|
1
1
|
require 'lusnoc/watcher'
|
2
|
+
require 'lusnoc/guard'
|
2
3
|
|
3
4
|
module Lusnoc
|
4
5
|
class Session
|
@@ -12,9 +13,12 @@ module Lusnoc
|
|
12
13
|
@ttl = ttl
|
13
14
|
|
14
15
|
@id = create_session(name, ttl)
|
15
|
-
|
16
|
+
|
17
|
+
prepare_guard(@id).run do
|
18
|
+
yield(self)
|
19
|
+
end
|
16
20
|
ensure
|
17
|
-
destroy_session(@id)
|
21
|
+
destroy_session(@id) if @id
|
18
22
|
end
|
19
23
|
|
20
24
|
def expired?
|
@@ -34,14 +38,14 @@ module Lusnoc
|
|
34
38
|
end
|
35
39
|
|
36
40
|
def alive!(exception_class = ExpiredError)
|
37
|
-
alive? || (raise exception_class.new("Session
|
41
|
+
alive? || (raise exception_class.new("Session[#{@name}:#{@id}] expired"))
|
38
42
|
end
|
39
43
|
|
40
44
|
def renew
|
41
45
|
alive!
|
42
46
|
Lusnoc.http_put(build_url("/v1/session/renew/#{@id}"), nil, timeout: 1)
|
43
47
|
@expired_at = Time.now + ttl
|
44
|
-
logger.info "Session
|
48
|
+
logger.info "Session[#{@name}:#{@id}] renewed. Next expiration: #{@expired_at}"
|
45
49
|
end
|
46
50
|
|
47
51
|
def on_session_die(&block)
|
@@ -56,50 +60,33 @@ module Lusnoc
|
|
56
60
|
{ timeout: 1 })
|
57
61
|
session_id = JSON.parse(resp.body)['ID']
|
58
62
|
@expired_at = Time.now + ttl
|
59
|
-
logger.info "Session
|
63
|
+
logger.info "Session[#{name}:#{session_id}] created. TTL:#{ttl}s. Next expiration: #{@expired_at}"
|
60
64
|
@alive = true
|
61
|
-
@th = start_watch_thread(session_id)
|
62
65
|
session_id
|
63
66
|
end
|
64
67
|
|
65
|
-
def
|
66
|
-
|
67
|
-
|
68
|
-
|
69
|
-
|
70
|
-
logger.info "Session destroyed: #{name}[#{session_id}]"
|
71
|
-
@alive = false
|
72
|
-
@expired_at = nil
|
73
|
-
end
|
74
|
-
|
75
|
-
def start_watch_thread(session_id)
|
76
|
-
Thread.new do
|
77
|
-
logger.debug "Guard thread for Session #{name}[#{session_id}] started"
|
68
|
+
def prepare_guard(session_id)
|
69
|
+
Lusnoc::Guard.new(build_url("/v1/session/info/#{session_id}")) do |guard|
|
70
|
+
guard.condition do |body|
|
71
|
+
!JSON.parse(body).empty? rescue false
|
72
|
+
end
|
78
73
|
|
79
|
-
|
80
|
-
logger.error "Session #{name}[#{session_id}] is gone"
|
74
|
+
guard.then do
|
81
75
|
@alive = false
|
82
76
|
@expired_at = nil
|
77
|
+
logger.info "Session[#{@name}:#{session_id}] is gone"
|
83
78
|
@session_die_cb&.call(self)
|
84
|
-
else
|
85
|
-
logger.unknown 'Something is wrong with thread logic'
|
86
79
|
end
|
87
|
-
ensure
|
88
|
-
logger.debug "Guard thread for Session #{name}[#{session_id}] finihsed"
|
89
80
|
end
|
90
81
|
end
|
91
82
|
|
92
|
-
def
|
93
|
-
|
94
|
-
|
95
|
-
|
96
|
-
|
97
|
-
logger.error "Session #{name}[#{session_id}] watch exception: #{e.inspect}"
|
98
|
-
logger.error e.backtrace.join("\n")
|
99
|
-
true
|
83
|
+
def destroy_session(session_id)
|
84
|
+
@alive = false
|
85
|
+
@expired_at = nil
|
86
|
+
Lusnoc.http_put(build_url("/v1/session/destroy/#{session_id}"), nil, timeout: 1) rescue nil
|
87
|
+
logger.info "Session[#{@name}:#{session_id}] destroyed"
|
100
88
|
end
|
101
89
|
|
102
|
-
|
103
90
|
end
|
104
91
|
end
|
105
92
|
|
data/lib/lusnoc/version.rb
CHANGED
data/lib/lusnoc/watcher.rb
CHANGED
@@ -1,4 +1,5 @@
|
|
1
|
-
require '
|
1
|
+
require 'timeouter'
|
2
|
+
require 'lusnoc/exceptions'
|
2
3
|
require 'lusnoc/helper'
|
3
4
|
|
4
5
|
module Lusnoc
|
@@ -8,12 +9,12 @@ module Lusnoc
|
|
8
9
|
|
9
10
|
def initialize(base_url,
|
10
11
|
timeout: 0,
|
11
|
-
|
12
|
-
|
12
|
+
eclass: Lusnoc::TimeoutError,
|
13
|
+
emessage: 'watch timeout')
|
13
14
|
@base_url = base_url
|
14
15
|
@timeout = timeout
|
15
|
-
@
|
16
|
-
@
|
16
|
+
@eclass = eclass
|
17
|
+
@emessage = emessage
|
17
18
|
end
|
18
19
|
|
19
20
|
# run Consul blocking request in a loop with timeout support.
|
@@ -22,13 +23,11 @@ module Lusnoc
|
|
22
23
|
logger.debug "Watch #{@base_url} with #{@timeout.inspect} timeout"
|
23
24
|
last_x_consul_index = 1
|
24
25
|
|
25
|
-
Timeouter.
|
26
|
-
|
27
|
-
exception_message: @exception_message).loop! do |timeouter|
|
28
|
-
wait_condition = timeouter.left ? "&wait=#{timeouter.left.to_i}s" : ''
|
26
|
+
Timeouter.loop!(@timeout, eclass: @eclass, message: @emessage) do |t|
|
27
|
+
wait_condition = t.left ? "&wait=#{t.left.to_i}s" : ''
|
29
28
|
url = "#{@base_url}?index=#{last_x_consul_index}#{wait_condition}"
|
30
29
|
|
31
|
-
resp = Lusnoc.http_get(url, timeout:
|
30
|
+
resp = Lusnoc.http_get(url, timeout: t.left)
|
32
31
|
return true if yield(resp.body)
|
33
32
|
|
34
33
|
logger.debug "Watch #{@base_url} response: #{resp.body}"
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: lusnoc
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.1.
|
4
|
+
version: 0.1.2.16548
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Samoilenko Yuri
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2019-09-
|
11
|
+
date: 2019-09-23 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: bundler
|
@@ -59,7 +59,35 @@ dependencies:
|
|
59
59
|
- !ruby/object:Gem::Version
|
60
60
|
version: '0'
|
61
61
|
- !ruby/object:Gem::Dependency
|
62
|
-
name:
|
62
|
+
name: rspec_junit_formatter
|
63
|
+
requirement: !ruby/object:Gem::Requirement
|
64
|
+
requirements:
|
65
|
+
- - ">="
|
66
|
+
- !ruby/object:Gem::Version
|
67
|
+
version: '0'
|
68
|
+
type: :development
|
69
|
+
prerelease: false
|
70
|
+
version_requirements: !ruby/object:Gem::Requirement
|
71
|
+
requirements:
|
72
|
+
- - ">="
|
73
|
+
- !ruby/object:Gem::Version
|
74
|
+
version: '0'
|
75
|
+
- !ruby/object:Gem::Dependency
|
76
|
+
name: simplecov
|
77
|
+
requirement: !ruby/object:Gem::Requirement
|
78
|
+
requirements:
|
79
|
+
- - ">="
|
80
|
+
- !ruby/object:Gem::Version
|
81
|
+
version: '0'
|
82
|
+
type: :development
|
83
|
+
prerelease: false
|
84
|
+
version_requirements: !ruby/object:Gem::Requirement
|
85
|
+
requirements:
|
86
|
+
- - ">="
|
87
|
+
- !ruby/object:Gem::Version
|
88
|
+
version: '0'
|
89
|
+
- !ruby/object:Gem::Dependency
|
90
|
+
name: simplecov-console
|
63
91
|
requirement: !ruby/object:Gem::Requirement
|
64
92
|
requirements:
|
65
93
|
- - ">="
|
@@ -100,6 +128,20 @@ dependencies:
|
|
100
128
|
- - ">="
|
101
129
|
- !ruby/object:Gem::Version
|
102
130
|
version: '0'
|
131
|
+
- !ruby/object:Gem::Dependency
|
132
|
+
name: timeouter
|
133
|
+
requirement: !ruby/object:Gem::Requirement
|
134
|
+
requirements:
|
135
|
+
- - ">="
|
136
|
+
- !ruby/object:Gem::Version
|
137
|
+
version: '0'
|
138
|
+
type: :runtime
|
139
|
+
prerelease: false
|
140
|
+
version_requirements: !ruby/object:Gem::Requirement
|
141
|
+
requirements:
|
142
|
+
- - ">="
|
143
|
+
- !ruby/object:Gem::Version
|
144
|
+
version: '0'
|
103
145
|
description: Lusnoc is reliable gem to deal with consul
|
104
146
|
email:
|
105
147
|
- kinnalru@gmail.com
|
@@ -107,14 +149,15 @@ executables: []
|
|
107
149
|
extensions: []
|
108
150
|
extra_rdoc_files: []
|
109
151
|
files:
|
152
|
+
- LICENSE
|
110
153
|
- README.md
|
111
154
|
- lib/lusnoc.rb
|
112
155
|
- lib/lusnoc/configuration.rb
|
113
156
|
- lib/lusnoc/exceptions.rb
|
157
|
+
- lib/lusnoc/guard.rb
|
114
158
|
- lib/lusnoc/helper.rb
|
115
159
|
- lib/lusnoc/mutex.rb
|
116
160
|
- lib/lusnoc/session.rb
|
117
|
-
- lib/lusnoc/timeouter.rb
|
118
161
|
- lib/lusnoc/version.rb
|
119
162
|
- lib/lusnoc/watcher.rb
|
120
163
|
homepage: https://github.com/RnD-Soft/lusnoc
|
@@ -136,7 +179,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
136
179
|
- !ruby/object:Gem::Version
|
137
180
|
version: '0'
|
138
181
|
requirements: []
|
139
|
-
rubygems_version: 3.0.
|
182
|
+
rubygems_version: 3.0.3
|
140
183
|
signing_key:
|
141
184
|
specification_version: 4
|
142
185
|
summary: Lusnoc is reliable gem to deal with consul
|
data/lib/lusnoc/timeouter.rb
DELETED
@@ -1,51 +0,0 @@
|
|
1
|
-
require 'lusnoc/exceptions'
|
2
|
-
|
3
|
-
module Lusnoc
|
4
|
-
class Timeouter
|
5
|
-
|
6
|
-
attr_reader :exhausted_at, :started_at
|
7
|
-
|
8
|
-
def initialize(timeout = 0,
|
9
|
-
exception_class: TimeoutError,
|
10
|
-
exception_message: 'execution expired')
|
11
|
-
timeout ||= 0
|
12
|
-
timeout = [timeout, 0].max
|
13
|
-
|
14
|
-
@default_exception_class = exception_class
|
15
|
-
@default_exception_message = exception_message
|
16
|
-
|
17
|
-
@started_at = Time.now.to_f
|
18
|
-
@exhausted_at = timeout > 0 ? @started_at + timeout : nil
|
19
|
-
end
|
20
|
-
|
21
|
-
def self.timeout(timeout = 0)
|
22
|
-
self.new(timeout)
|
23
|
-
end
|
24
|
-
|
25
|
-
def elapsed
|
26
|
-
Time.now.to_f - @started_at
|
27
|
-
end
|
28
|
-
|
29
|
-
def left
|
30
|
-
@exhausted_at && [@exhausted_at - Time.now.to_f, 0].max
|
31
|
-
end
|
32
|
-
|
33
|
-
def check
|
34
|
-
!@exhausted_at || (@exhausted_at > Time.now.to_f)
|
35
|
-
end
|
36
|
-
|
37
|
-
def check!(exception_class = @default_exception_class)
|
38
|
-
check || (raise exception_class.new(@default_exception_message))
|
39
|
-
end
|
40
|
-
|
41
|
-
def loop
|
42
|
-
yield(self) while self.check
|
43
|
-
end
|
44
|
-
|
45
|
-
def loop!(exception_class = @default_exception_class)
|
46
|
-
yield(self) while self.check!(exception_class)
|
47
|
-
end
|
48
|
-
|
49
|
-
end
|
50
|
-
end
|
51
|
-
|