lusnoc 0.1.2.16548 → 0.9.0.44532

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 7bbe9d1f94b450c09aaeb7fe5283bef89ee796a4b57712af40603ba8eb5a3f0c
4
- data.tar.gz: 2ceec91d3f94a92631698ad391b5c7848e57d4033dbd1766ab37d0cd75a1f322
3
+ metadata.gz: 05d4b47c5281bbcf7adc5cff1e398bd4ce37e2e8953b6a09e143404777c016dc
4
+ data.tar.gz: 6a7afa4d21df7cd7b19cd56290ef35d58befa6013fa2f713973da2059e74297d
5
5
  SHA512:
6
- metadata.gz: 11b1834bca1940eea5d5099cff6100587bc5fbcf75ea012866629d23daa6f43a4c2cceeb76c26b58689adad5cffaad33f62d104fe3d75a33645cb4e39607b8e8
7
- data.tar.gz: 5b356bfa4e314d7da5e4cba97e24abbe5b5ccfaa2e98c977d3c8f6d583c3f5ad3d12a616cf96f6ad120a3382d48dac2b53d197667fbcc9fbcee3886ad11362de
6
+ metadata.gz: 34da3a07c4705381614e65b9baf6b5d6f7200abb9912ad68baa1debb043fd9b4cbb32f3c3eed37cd50cee2b1a1b7243fb8794b0be8eb1f0cb7279ab0ce889a5f
7
+ data.tar.gz: b3ae1f8dae1f35c346378e3c53075807346c157cbe50c7f8cb200e47cb00f7c845db92f8a43a2e83c6423188a620a6dafc9978781d82cd4cc531127173b56553
data/README.md CHANGED
@@ -2,15 +2,15 @@
2
2
 
3
3
  [![Gem Version](https://badge.fury.io/rb/lusnoc.svg)](https://rubygems.org/gems/lusnoc)
4
4
  [![Gem](https://img.shields.io/gem/dt/lusnoc.svg)](https://rubygems.org/gems/lusnoc/versions)
5
+ [![YARD](https://badgen.net/badge/YARD/doc/blue)](http://www.rubydoc.info/gems/lusnoc)
5
6
 
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)
7
+ [![Coverage](https://lysander.rnds.pro/api/v1/badges/lusnoc_coverage.svg)](https://lysander.rnds.pro/api/v1/badges/lusnoc_coverage.html)
8
+ [![Quality](https://lysander.rnds.pro/api/v1/badges/lusnoc_quality.svg)](https://lysander.rnds.pro/api/v1/badges/lusnoc_quality.html)
9
+ [![Outdated](https://lysander.rnds.pro/api/v1/badges/lusnoc_outdated.svg)](https://lysander.rnds.pro/api/v1/badges/lusnoc_outdated.html)
10
+ [![Vulnerabilities](https://lysander.rnds.pro/api/v1/badges/lusnoc_vulnerable.svg)](https://lysander.rnds.pro/api/v1/badges/lusnoc_vulnerable.html)
11
11
 
12
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.
13
- It is inspired by [consul-mutex](https://github.com/discourse/consul-mutex)(which has hard background magic).
13
+ It is inspired by [consul-mutex](https://github.com/kinnalru/consul-mutex)(which has hard background magic).
14
14
 
15
15
  ## FAQ
16
16
 
@@ -18,7 +18,7 @@ It is inspired by [consul-mutex](https://github.com/discourse/consul-mutex)(whic
18
18
 
19
19
  Lusnoc allows you to interact with Consul to provide distributed locks(mutex) to your application.
20
20
 
21
- #### What's the difference between lusnoc and [consul-mutex](https://github.com/discourse/consul-mutex) or [diplomat](https://github.com/WeAreFarmGeek/diplomat)
21
+ #### What's the difference between lusnoc and [consul-mutex](https://github.com/kinnalru/consul-mutex) or [diplomat](https://github.com/WeAreFarmGeek/diplomat)
22
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.***
23
23
  * diplomat provides the basic session/locks functionality but no automated control over it
24
24
 
@@ -43,7 +43,7 @@ TTL will be used in session creation on `#synchronize`:
43
43
  puts "We are exclusively owns resource"
44
44
  end
45
45
  ```
46
- If mutex cannot be acquired within given timeout Lusnoc::TimeoutError is raised.
46
+ If mutex cannot be acquired within given timeout `Lusnoc::TimeoutError` is raised.
47
47
  By default, the "value" of the lock resource will be the hostname of the
48
48
  machine that it's running on (so you know who has the lock). If, for some
49
49
  reason, you'd like to set the value to something else, you can do that, too:
@@ -6,33 +6,26 @@ module Lusnoc
6
6
 
7
7
  include Helper
8
8
 
9
+ attr_reader :callbacks
10
+
9
11
  def initialize(base_url)
10
12
  @base_url = base_url
13
+ @callbacks = {}
11
14
  yield(self) if block_given?
12
15
  end
13
16
 
14
17
  def condition(&block)
15
- @condition = block
18
+ @callbacks[:condition] = block
16
19
  self
17
20
  end
18
21
 
19
22
  def then(&block)
20
- @callback = block
23
+ @callbacks[:then] = block
21
24
  self
22
25
  end
23
26
 
24
27
  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
-
28
+ th = start_thread
36
29
  yield
37
30
  ensure
38
31
  th.kill rescue nil
@@ -40,28 +33,48 @@ module Lusnoc
40
33
 
41
34
  private
42
35
 
43
- def fire!
44
- @callback&.tap do |cb|
45
- @callback = nil
36
+ def start_thread
37
+ Thread.new do
38
+ logger.info "Guard[#{@base_url.inspect}] thread started"
39
+ watch_forever(@base_url)
40
+ fire!
41
+ rescue StandardError => e
42
+ logger.error "Guard[#{@base_url.inspect}] error: #{e.inspect}"
43
+ logger.error e.backtrace
44
+ fire!(e)
45
+ ensure
46
+ logger.info "Guard[#{@base_url.inspect}] finihsed"
47
+ end
48
+ end
49
+
50
+ def fire!(*args)
51
+ @callbacks[:then]&.tap do |cb|
52
+ @callbacks[:then] = nil
46
53
  logger.info "Guard[#{@base_url.inspect}] fired"
47
- cb.call
54
+ cb.call(*args)
48
55
  end
49
56
  end
50
57
 
51
58
  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
59
+ Lusnoc::Watcher.new(base_url).run(max_consul_wait: 10) do |body|
60
+ return true unless @callbacks[:condition].call(body)
62
61
  end
63
62
  end
64
63
 
64
+ # def watch_forever(base_url)
65
+ # last_x_consul_index = 1
66
+
67
+ # Kernel.loop do
68
+ # resp = Lusnoc.http_get("#{base_url}?index=#{last_x_consul_index}&wait=10s", timeout: 15)
69
+ # logger.debug "Guard[#{@base_url.inspect}] response: #{resp.body}"
70
+ # return unless @callbacks[:condition].call(resp.body)
71
+
72
+ # index = [Integer(resp['x-consul-index']), 1].max
73
+ # last_x_consul_index = (index < last_x_consul_index ? 1 : index)
74
+ # sleep 0.4
75
+ # end
76
+ # end
77
+
65
78
  end
66
79
  end
67
80
 
@@ -46,7 +46,7 @@ module Lusnoc
46
46
  return acquisition_loop! key, session, value, t, &block
47
47
  ensure
48
48
  release(key, session.id, timeout: 2) rescue nil
49
- logger.info("Lock #{key} released for session #{session.name}[#{session.id}]")
49
+ logger.info("Mutex[#{key}] released for Session[#{session.name}:#{session.id}]")
50
50
  @owner = nil
51
51
  @session = nil
52
52
  end
@@ -59,7 +59,7 @@ module Lusnoc
59
59
  return false if resp.body.chomp != 'true'
60
60
 
61
61
  @owner = Thread.current
62
- logger.info("Lock #{key} acquired for session #{session.name}[#{session.id}]")
62
+ logger.info("Mutex[#{key}] acquired for Session[#{session.name}:#{session.id}]")
63
63
  renew
64
64
  true
65
65
  end
@@ -69,22 +69,44 @@ module Lusnoc
69
69
  end
70
70
 
71
71
  def acquisition_loop!(key, session, value, t)
72
- return yield(self) if acquire(key, session, value)
72
+ if acquire(key, session, value)
73
+ prepare_guard(session, key).run do
74
+ return yield(self)
75
+ end
76
+ end
73
77
 
74
- logger.debug("Start #{key} acquisition loop for session #{session.name}[#{session.id}]")
78
+ logger.debug("Mutex[#{key}] run acquisition loop for Session[#{session.name}:#{session.id}]")
75
79
  t.loop! do
76
80
  session.alive!(TimeoutError)
77
81
  wait_for_key_released(key, t.left)
78
82
 
79
- return yield(self) if acquire(key, session, value)
83
+ if acquire(key, session, value)
84
+ prepare_guard(session, key).run do
85
+ return yield(self)
86
+ end
87
+ end
88
+
89
+ logger.debug("Mutex[#{key}] acquisition failed for Session[#{session.name}:#{session.id}]")
90
+ sleep 0.4
91
+ end
92
+ end
80
93
 
81
- logger.debug("Lock #{key} acquisition failed for session #{session.name}[#{session.id}]")
82
- sleep 1
94
+ def prepare_guard(session, key)
95
+ Lusnoc::Guard.new(build_url("/v1/kv/#{key}")) do |guard|
96
+ guard.condition do |body|
97
+ JSON.parse(body).first['Session'] == session.id rescue false
98
+ end
99
+
100
+ guard.then do
101
+ @owner = nil
102
+ logger.info("Mutex[#{key}] LOST for Session[#{session.name}:#{session.id}]")
103
+ @on_mutex_lost&.call(self)
104
+ end
83
105
  end
84
106
  end
85
107
 
86
108
  def wait_for_key_released(key, timeout = nil)
87
- logger.debug "Waiting for key #{key} to be fre of any session"
109
+ logger.debug("Mutex[#{key}] start waiting of key releasing...")
88
110
  Lusnoc::Watcher.new(build_url("/v1/kv/#{key}"),
89
111
  timeout: timeout,
90
112
  eclass: TimeoutError,
@@ -8,10 +8,14 @@ module Lusnoc
8
8
 
9
9
  attr_reader :id, :name, :ttl, :alive, :expired_at
10
10
 
11
- def initialize(name, ttl: 20)
11
+ def initialize(name, ttl: 20, &block)
12
12
  @name = name
13
13
  @ttl = ttl
14
14
 
15
+ run(&block) if block_given?
16
+ end
17
+
18
+ def run
15
19
  @id = create_session(name, ttl)
16
20
 
17
21
  prepare_guard(@id).run do
@@ -38,7 +42,7 @@ module Lusnoc
38
42
  end
39
43
 
40
44
  def alive!(exception_class = ExpiredError)
41
- alive? || (raise exception_class.new("Session[#{@name}:#{@id}] expired"))
45
+ @alive || (raise exception_class.new("Session[#{@name}:#{@id}] expired"))
42
46
  end
43
47
 
44
48
  def renew
@@ -50,6 +54,8 @@ module Lusnoc
50
54
 
51
55
  def on_session_die(&block)
52
56
  @session_die_cb = block
57
+ @session_die_cb&.call(self) if @alive == false
58
+ self
53
59
  end
54
60
 
55
61
  private
@@ -1,6 +1,6 @@
1
1
  module Lusnoc
2
2
 
3
- VERSION = '0.1.2'.freeze
3
+ VERSION = '0.9.0'.freeze
4
4
 
5
5
  end
6
6
 
@@ -12,19 +12,19 @@ module Lusnoc
12
12
  eclass: Lusnoc::TimeoutError,
13
13
  emessage: 'watch timeout')
14
14
  @base_url = base_url
15
- @timeout = timeout
16
- @eclass = eclass
15
+ @timeout = timeout
16
+ @eclass = eclass
17
17
  @emessage = emessage
18
18
  end
19
19
 
20
20
  # run Consul blocking request in a loop with timeout support.
21
21
  # break condition yielded by block call with response body
22
- def run
22
+ def run(max_consul_wait: nil)
23
23
  logger.debug "Watch #{@base_url} with #{@timeout.inspect} timeout"
24
24
  last_x_consul_index = 1
25
25
 
26
26
  Timeouter.loop!(@timeout, eclass: @eclass, message: @emessage) do |t|
27
- wait_condition = t.left ? "&wait=#{t.left.to_i}s" : ''
27
+ wait_condition = build_wait_condition(@base_url, t.left, max_consul_wait)
28
28
  url = "#{@base_url}?index=#{last_x_consul_index}#{wait_condition}"
29
29
 
30
30
  resp = Lusnoc.http_get(url, timeout: t.left)
@@ -34,7 +34,18 @@ module Lusnoc
34
34
 
35
35
  index = [Integer(resp['x-consul-index']), 1].max
36
36
  last_x_consul_index = (index < last_x_consul_index ? 1 : index)
37
- sleep 1
37
+ sleep 0.4
38
+ end
39
+ end
40
+
41
+ def build_wait_condition(_url, time_left, max_consul_wait)
42
+ if time_left
43
+ max = [time_left.to_i, max_consul_wait.to_i].max
44
+ "&wait=#{max}s"
45
+ elsif max_consul_wait
46
+ "&wait=#{max_consul_wait.to_i}s"
47
+ else
48
+ ''
38
49
  end
39
50
  end
40
51
 
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.2.16548
4
+ version: 0.9.0.44532
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-23 00:00:00.000000000 Z
11
+ date: 2021-01-13 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: bundler