lusnoc 0.1.0 → 0.1.2.16548
Sign up to get free protection for your applications and to get access to all the features.
- 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
|
+
[![Gem Version](https://badge.fury.io/rb/lusnoc.svg)](https://rubygems.org/gems/lusnoc)
|
4
|
+
[![Gem](https://img.shields.io/gem/dt/lusnoc.svg)](https://rubygems.org/gems/lusnoc/versions)
|
5
|
+
|
6
|
+
[![Test Coverage](https://api.codeclimate.com/v1/badges/ed48b89a9793a074cd23/test_coverage)](https://codeclimate.com/github/RnD-Soft/lusnoc/test_coverage)
|
7
|
+
[![Maintainability](https://api.codeclimate.com/v1/badges/ed48b89a9793a074cd23/maintainability)](https://codeclimate.com/github/RnD-Soft/lusnoc/maintainability)
|
8
|
+
[![Quality](https://lysander.x.rnds.pro/api/v1/badges/lusnoc_quality.svg)](https://lysander.x.rnds.pro/api/v1/badges/lusnoc_quality.html)
|
9
|
+
[![Outdated](https://lysander.x.rnds.pro/api/v1/badges/lusnoc_outdated.svg)](https://lysander.x.rnds.pro/api/v1/badges/lusnoc_outdated.html)
|
10
|
+
[![Vulnerabilities](https://lysander.x.rnds.pro/api/v1/badges/lusnoc_vulnerable.svg)](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
|
-
|