zk 1.9.6 → 1.10.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (40) hide show
  1. checksums.yaml +5 -13
  2. data/.github/workflows/build.yml +55 -0
  3. data/Gemfile +15 -6
  4. data/README.markdown +9 -9
  5. data/RELEASES.markdown +10 -1
  6. data/lib/zk/client.rb +1 -1
  7. data/lib/zk/event_handler.rb +15 -7
  8. data/lib/zk/fork_hook.rb +2 -2
  9. data/lib/zk/locker/locker_base.rb +13 -0
  10. data/lib/zk/locker/semaphore.rb +1 -3
  11. data/lib/zk/node_deletion_watcher.rb +3 -4
  12. data/lib/zk/pool.rb +11 -11
  13. data/lib/zk/version.rb +1 -1
  14. data/spec/event_catcher_spec.rb +1 -1
  15. data/spec/message_queue_spec.rb +6 -6
  16. data/spec/shared/client_examples.rb +81 -81
  17. data/spec/shared/locker_examples.rb +13 -13
  18. data/spec/spec_helper.rb +10 -11
  19. data/spec/zk/00_forked_client_integration_spec.rb +3 -3
  20. data/spec/zk/client/locking_and_session_death_spec.rb +2 -2
  21. data/spec/zk/client_spec.rb +19 -19
  22. data/spec/zk/election_spec.rb +44 -44
  23. data/spec/zk/extensions_spec.rb +2 -2
  24. data/spec/zk/locker/exclusive_locker_spec.rb +41 -41
  25. data/spec/zk/locker/locker_basic_spec.rb +55 -33
  26. data/spec/zk/locker/semaphore_spec.rb +39 -32
  27. data/spec/zk/locker/shared_exclusive_integration_spec.rb +37 -37
  28. data/spec/zk/locker/shared_locker_spec.rb +43 -43
  29. data/spec/zk/locker_spec.rb +2 -2
  30. data/spec/zk/module_spec.rb +25 -25
  31. data/spec/zk/mongoid_spec.rb +47 -47
  32. data/spec/zk/node_deletion_watcher_spec.rb +39 -31
  33. data/spec/zk/pool_spec.rb +56 -65
  34. data/spec/zk/threaded_callback_spec.rb +10 -10
  35. data/spec/zk/threadpool_spec.rb +25 -25
  36. data/spec/zk/watch_spec.rb +67 -79
  37. data/spec/zk/zookeeper_spec.rb +31 -31
  38. data/zk.gemspec +1 -1
  39. metadata +23 -24
  40. data/.travis.yml +0 -30
@@ -20,47 +20,47 @@ describe 'ZK::Client#locker' do
20
20
  @zk.close!
21
21
  @zk2.close!
22
22
  @zk3.close!
23
- wait_until { @connections.all? { |c| c.closed? } }
23
+ wait_until { @connections.all? { |c| c.closed? } }
24
24
  end
25
25
 
26
26
  it "should be able to acquire the lock if no one else is locking it" do
27
- @zk.locker(@path_to_lock).lock.should be_true
27
+ expect(@zk.locker(@path_to_lock).lock).to be(true)
28
28
  end
29
29
 
30
30
  it "should not be able to acquire the lock if someone else is locking it" do
31
- @zk.locker(@path_to_lock).lock.should be_true
32
- @zk2.locker(@path_to_lock).lock.should be_false
31
+ expect(@zk.locker(@path_to_lock).lock).to be(true)
32
+ expect(@zk2.locker(@path_to_lock).lock).to be(false)
33
33
  end
34
34
 
35
35
  it "should assert properly if lock is acquired" do
36
- @zk.locker(@path_to_lock).assert.should be_false
36
+ expect(@zk.locker(@path_to_lock).assert).to be(false)
37
37
  l = @zk2.locker(@path_to_lock)
38
- l.lock.should be_true
39
- l.assert.should be_true
38
+ expect(l.lock).to be(true)
39
+ expect(l.assert).to be(true)
40
40
  end
41
41
 
42
42
  it "should be able to acquire the lock after the first one releases it" do
43
43
  lock1 = @zk.locker(@path_to_lock)
44
44
  lock2 = @zk2.locker(@path_to_lock)
45
-
46
- lock1.lock.should be_true
47
- lock2.lock.should be_false
45
+
46
+ expect(lock1.lock).to be(true)
47
+ expect(lock2.lock).to be(false)
48
48
  lock1.unlock
49
- lock2.lock.should be_true
49
+ expect(lock2.lock).to be(true)
50
50
  end
51
51
 
52
52
  it "should be able to acquire the lock if the first locker goes away" do
53
53
  lock1 = @zk.locker(@path_to_lock)
54
54
  lock2 = @zk2.locker(@path_to_lock)
55
55
 
56
- lock1.lock.should be_true
57
- lock2.lock.should be_false
56
+ expect(lock1.lock).to be(true)
57
+ expect(lock2.lock).to be(false)
58
58
  @zk.close!
59
- lock2.lock.should be_true
59
+ expect(lock2.lock).to be(true)
60
60
  end
61
61
 
62
62
  it "should be able to handle multi part path locks" do
63
- @zk.locker("my/multi/part/path").lock.should be_true
63
+ expect(@zk.locker("my/multi/part/path").lock).to be(true)
64
64
  end
65
65
 
66
66
  describe :with_lock do
@@ -70,23 +70,23 @@ describe 'ZK::Client#locker' do
70
70
  describe 'Client::Conveniences' do
71
71
  it %[should yield the lock instance to the block] do
72
72
  @zk.with_lock(@path_to_lock) do |lock|
73
- lock.should_not be_nil
74
- lock.should be_kind_of(ZK::Locker::LockerBase)
75
- lambda { lock.assert! }.should_not raise_error
73
+ expect(lock).not_to be_nil
74
+ expect(lock).to be_kind_of(ZK::Locker::LockerBase)
75
+ expect { lock.assert! }.not_to raise_error
76
76
  end
77
77
  end
78
78
 
79
79
  it %[should yield a shared lock when :mode => shared given] do
80
80
  @zk.with_lock(@path_to_lock, :mode => :shared) do |lock|
81
- lock.should_not be_nil
82
- lock.should be_kind_of(ZK::Locker::SharedLocker)
83
- lambda { lock.assert! }.should_not raise_error
81
+ expect(lock).not_to be_nil
82
+ expect(lock).to be_kind_of(ZK::Locker::SharedLocker)
83
+ expect { lock.assert! }.not_to raise_error
84
84
  end
85
85
  end
86
86
 
87
87
  it %[should take a timeout] do
88
88
  first_lock = @zk.locker(@path_to_lock)
89
- first_lock.lock.should be_true
89
+ expect(first_lock.lock).to be(true)
90
90
 
91
91
  thread = Thread.new do
92
92
  begin
@@ -98,8 +98,8 @@ describe 'ZK::Client#locker' do
98
98
  end
99
99
  end
100
100
 
101
- thread.join(2).should == thread
102
- @exc.should be_kind_of(ZK::Exceptions::LockWaitTimeoutError)
101
+ expect(thread.join(2)).to eq(thread)
102
+ expect(@exc).to be_kind_of(ZK::Exceptions::LockWaitTimeoutError)
103
103
  end
104
104
  end
105
105
 
@@ -107,26 +107,26 @@ describe 'ZK::Client#locker' do
107
107
  it "should blocking lock" do
108
108
  array = []
109
109
  first_lock = @zk.locker("mylock")
110
- first_lock.lock.should be_true
110
+ expect(first_lock.lock).to be(true)
111
111
  array << :first_lock
112
112
 
113
113
  thread = Thread.new do
114
114
  @zk.locker("mylock").with_lock do
115
115
  array << :second_lock
116
116
  end
117
- array.length.should == 2
117
+ expect(array.length).to eq(2)
118
118
  end
119
119
 
120
- array.length.should == 1
120
+ expect(array.length).to eq(1)
121
121
  first_lock.unlock
122
122
  thread.join(10)
123
- array.length.should == 2
123
+ expect(array.length).to eq(2)
124
124
  end
125
125
 
126
126
  it %[should accept a :wait option] do
127
127
  array = []
128
128
  first_lock = @zk.locker("mylock")
129
- first_lock.lock.should be_true
129
+ expect(first_lock.lock).to be(true)
130
130
 
131
131
  second_lock = @zk.locker("mylock")
132
132
 
@@ -140,10 +140,32 @@ describe 'ZK::Client#locker' do
140
140
  end
141
141
  end
142
142
 
143
- array.should be_empty
144
- thread.join(2).should == thread
145
- @exc.should_not be_nil
146
- @exc.should be_kind_of(ZK::Exceptions::LockWaitTimeoutError)
143
+ expect(array).to be_empty
144
+ expect(thread.join(2)).to eq(thread)
145
+ expect(@exc).not_to be_nil
146
+ expect(@exc).to be_kind_of(ZK::Exceptions::LockWaitTimeoutError)
147
+ end
148
+
149
+ it "should interrupt a blocked lock" do
150
+ first_lock = @zk.locker("mylock")
151
+ expect(first_lock.lock).to be(true)
152
+
153
+ second_lock = @zk.locker("mylock")
154
+ thread = Thread.new do
155
+ begin
156
+ second_lock.with_lock do
157
+ raise "NO NO NO!! should not have called the block!!"
158
+ end
159
+ rescue Exception => e
160
+ @exc = e
161
+ end
162
+ end
163
+
164
+ Thread.pass until second_lock.waiting?
165
+
166
+ second_lock.interrupt!
167
+ thread.join(2)
168
+ expect(@exc).to be_kind_of(ZK::Exceptions::WakeUpException)
147
169
  end
148
170
  end
149
171
  end # with_lock
@@ -10,25 +10,32 @@ shared_examples_for 'ZK::Locker::Semaphore' do
10
10
  it_should_behave_like 'LockerBase#assert!'
11
11
  end
12
12
 
13
+ context %[invalid semaphore_size] do
14
+ let(:semaphore_size) { :boom }
15
+ it 'should raise' do
16
+ expect{ locker }.to raise_error(ZK::Exceptions::BadArguments)
17
+ end
18
+ end
19
+
13
20
  describe :acquirable? do
14
21
  describe %[with default options] do
15
22
  it %[should work if the lock root doesn't exist] do
16
23
  zk.rm_rf(ZK::Locker::Semaphore.default_root_node)
17
- locker.should be_acquirable
24
+ expect(locker).to be_acquirable
18
25
  end
19
26
 
20
27
  it %[should check local state of lockedness] do
21
- locker.lock.should be_true
22
- locker.should be_acquirable
28
+ expect(locker.lock).to be(true)
29
+ expect(locker).to be_acquirable
23
30
  end
24
31
 
25
32
  it %[should check if any participants would prevent us from acquiring the lock] do
26
- locker3.lock.should be_true
27
- locker.should be_acquirable # total locks given less than semaphore_size
28
- locker2.lock.should be_true
29
- locker.should_not be_acquirable # total locks given equal to semaphore size
33
+ expect(locker3.lock).to be(true)
34
+ expect(locker).to be_acquirable # total locks given less than semaphore_size
35
+ expect(locker2.lock).to be(true)
36
+ expect(locker).not_to be_acquirable # total locks given equal to semaphore size
30
37
  locker3.unlock
31
- locker.should be_acquirable # total locks given less than semaphore_size
38
+ expect(locker).to be_acquirable # total locks given less than semaphore_size
32
39
  end
33
40
  end
34
41
  end
@@ -41,13 +48,13 @@ shared_examples_for 'ZK::Locker::Semaphore' do
41
48
  end
42
49
 
43
50
  it %[should acquire the first lock] do
44
- @rval.should be_true
45
- locker.should be_locked
51
+ expect(@rval).to be(true)
52
+ expect(locker).to be_locked
46
53
  end
47
54
 
48
55
  it %[should acquire the second lock] do
49
- @rval2.should be_true
50
- locker2.should be_locked
56
+ expect(@rval2).to be(true)
57
+ expect(locker2).to be_locked
51
58
  end
52
59
  end
53
60
 
@@ -61,15 +68,15 @@ shared_examples_for 'ZK::Locker::Semaphore' do
61
68
  end
62
69
 
63
70
  it %[should return false] do
64
- @rval.should be_false
71
+ expect(@rval).to be(false)
65
72
  end
66
73
 
67
74
  it %[should not be locked] do
68
- locker.should_not be_locked
75
+ expect(locker).not_to be_locked
69
76
  end
70
77
 
71
78
  it %[should not have a lock_path] do
72
- locker.lock_path.should be_nil
79
+ expect(locker.lock_path).to be_nil
73
80
  end
74
81
  end
75
82
 
@@ -87,7 +94,7 @@ shared_examples_for 'ZK::Locker::Semaphore' do
87
94
  it %[should acquire the lock after the write lock is released] do
88
95
  ary = []
89
96
 
90
- locker.lock.should be_false
97
+ expect(locker.lock).to be(false)
91
98
 
92
99
  th = Thread.new do
93
100
  locker.lock(:wait => true)
@@ -95,18 +102,18 @@ shared_examples_for 'ZK::Locker::Semaphore' do
95
102
  end
96
103
 
97
104
  locker.wait_until_blocked(5)
98
- locker.should be_waiting
99
- locker.should_not be_locked
100
- ary.should be_empty
105
+ expect(locker).to be_waiting
106
+ expect(locker).not_to be_locked
107
+ expect(ary).to be_empty
101
108
 
102
109
  zk.delete(@existing_locks.shuffle.first)
103
110
 
104
- th.join(2).should == th
111
+ expect(th.join(2)).to eq(th)
105
112
 
106
- ary.should_not be_empty
107
- ary.length.should == 1
113
+ expect(ary).not_to be_empty
114
+ expect(ary.length).to eq(1)
108
115
 
109
- locker.should be_locked
116
+ expect(locker).to be_locked
110
117
  end
111
118
  end
112
119
 
@@ -116,9 +123,9 @@ shared_examples_for 'ZK::Locker::Semaphore' do
116
123
 
117
124
  write_lock_dir = File.dirname(@existing_locks.first)
118
125
 
119
- zk.children(write_lock_dir).length.should == semaphore_size
126
+ expect(zk.children(write_lock_dir).length).to eq(semaphore_size)
120
127
 
121
- locker.lock.should be_false
128
+ expect(locker.lock).to be(false)
122
129
 
123
130
  th = Thread.new do
124
131
  begin
@@ -130,16 +137,16 @@ shared_examples_for 'ZK::Locker::Semaphore' do
130
137
  end
131
138
 
132
139
  locker.wait_until_blocked(5)
133
- locker.should be_waiting
134
- locker.should_not be_locked
135
- ary.should be_empty
140
+ expect(locker).to be_waiting
141
+ expect(locker).not_to be_locked
142
+ expect(ary).to be_empty
136
143
 
137
- th.join(2).should == th
144
+ expect(th.join(2)).to eq(th)
138
145
 
139
- zk.children(write_lock_dir).length.should == semaphore_size
146
+ expect(zk.children(write_lock_dir).length).to eq(semaphore_size)
140
147
 
141
- ary.should be_empty
142
- @exc.should be_kind_of(ZK::Exceptions::LockWaitTimeoutError)
148
+ expect(ary).to be_empty
149
+ expect(@exc).to be_kind_of(ZK::Exceptions::LockWaitTimeoutError)
143
150
  end
144
151
 
145
152
  end
@@ -8,12 +8,12 @@ shared_examples_for :shared_exclusive_integration do
8
8
 
9
9
  describe 'shared lock acquired first' do
10
10
  it %[should block exclusive locks from acquiring until released] do
11
- @sh_lock.lock.should be_true
12
- @ex_lock.lock.should be_false
11
+ expect(@sh_lock.lock).to be(true)
12
+ expect(@ex_lock.lock).to be(false)
13
13
 
14
14
  mutex = Monitor.new
15
15
  cond = mutex.new_cond
16
-
16
+
17
17
  th = Thread.new do
18
18
  logger.debug { "@ex_lock trying to acquire acquire lock" }
19
19
  @ex_lock.with_lock do
@@ -28,29 +28,29 @@ shared_examples_for :shared_exclusive_integration do
28
28
 
29
29
  mutex.synchronize do
30
30
  logger.debug { "unlocking the shared lock" }
31
- @sh_lock.unlock.should be_true
31
+ expect(@sh_lock.unlock).to be(true)
32
32
  cond.wait_until { th[:got_lock] } # make sure they actually received the lock (avoid race)
33
- th[:got_lock].should be_true
33
+ expect(th[:got_lock]).to be(true)
34
34
  logger.debug { "ok, they got the lock" }
35
35
  end
36
36
 
37
- th.join(5).should == th
37
+ expect(th.join(5)).to eq(th)
38
38
 
39
39
  logger.debug { "thread joined, exclusive lock should be releasd" }
40
40
 
41
- @ex_lock.should_not be_locked
41
+ expect(@ex_lock).not_to be_locked
42
42
  end
43
43
  end
44
44
 
45
45
  describe 'multiple shared locks acquired first' do
46
46
  before do
47
- zk3.should_not be_nil
48
- @sh_lock2 = ZK::Locker.shared_locker(zk3, path)
47
+ expect(zk3).not_to be_nil
48
+ @sh_lock2 = ZK::Locker.shared_locker(zk3, path)
49
49
  end
50
50
  it %[should not aquire a lock when highest-numbered released but others remain] do
51
- @sh_lock.lock.should be_true
52
- @sh_lock2.lock.should be_true
53
- @ex_lock.lock.should be_false
51
+ expect(@sh_lock.lock).to be(true)
52
+ expect(@sh_lock2.lock).to be(true)
53
+ expect(@ex_lock.lock).to be(false)
54
54
 
55
55
  mutex = Monitor.new
56
56
  cond = mutex.new_cond
@@ -75,28 +75,28 @@ shared_examples_for :shared_exclusive_integration do
75
75
  mutex.synchronize do
76
76
  @ex_lock.wait_until_blocked(1)
77
77
  logger.debug { "unlocking the highest shared lock" }
78
- @sh_lock2.unlock.should be_true
78
+ expect(@sh_lock2.unlock).to be(true)
79
79
  cond.wait_until { (!th[:got_lock].nil?) } # make sure they actually received the lock (avoid race)
80
- th[:got_lock].should be_false
80
+ expect(th[:got_lock]).to be(false)
81
81
  logger.debug { "they didn't get the lock." }
82
82
  end
83
83
 
84
- th.join(5).should == th
84
+ expect(th.join(5)).to eq(th)
85
85
 
86
86
  logger.debug { "thread joined, exclusive lock should be releasd" }
87
- @sh_lock.unlock.should be_true
88
- @ex_lock.should_not be_locked
87
+ expect(@sh_lock.unlock).to be(true)
88
+ expect(@ex_lock).not_to be_locked
89
89
  end
90
90
  end
91
91
 
92
92
  describe 'exclusive lock acquired first' do
93
93
  it %[should block shared lock from acquiring until released] do
94
- @ex_lock.lock.should be_true
95
- @sh_lock.lock.should be_false
94
+ expect(@ex_lock.lock).to be(true)
95
+ expect(@sh_lock.lock).to be(false)
96
96
 
97
97
  mutex = Monitor.new
98
98
  cond = mutex.new_cond
99
-
99
+
100
100
  th = Thread.new do
101
101
  logger.debug { "@ex_lock trying to acquire acquire lock" }
102
102
  @sh_lock.with_lock do
@@ -111,31 +111,31 @@ shared_examples_for :shared_exclusive_integration do
111
111
 
112
112
  mutex.synchronize do
113
113
  logger.debug { "unlocking the shared lock" }
114
- @ex_lock.unlock.should be_true
114
+ expect(@ex_lock.unlock).to be(true)
115
115
  cond.wait_until { th[:got_lock] } # make sure they actually received the lock (avoid race)
116
- th[:got_lock].should be_true
116
+ expect(th[:got_lock]).to be(true)
117
117
  logger.debug { "ok, they got the lock" }
118
118
  end
119
119
 
120
- th.join(5).should == th
120
+ expect(th.join(5)).to eq(th)
121
121
 
122
122
  logger.debug { "thread joined, exclusive lock should be releasd" }
123
123
 
124
- @sh_lock.should_not be_locked
124
+ expect(@sh_lock).not_to be_locked
125
125
  end
126
126
  end
127
127
 
128
128
  describe 'shared-exclusive-shared' do
129
129
  before do
130
- zk3.should_not be_nil
131
- @sh_lock2 = ZK::Locker.shared_locker(zk3, path)
130
+ expect(zk3).not_to be_nil
131
+ @sh_lock2 = ZK::Locker.shared_locker(zk3, path)
132
132
  end
133
133
 
134
134
  it %[should act something like a queue] do
135
135
  @array = []
136
136
 
137
- @sh_lock.lock.should be_true
138
- @sh_lock.should be_locked
137
+ expect(@sh_lock.lock).to be(true)
138
+ expect(@sh_lock).to be_locked
139
139
 
140
140
  ex_th = Thread.new do
141
141
  begin
@@ -150,15 +150,15 @@ shared_examples_for :shared_exclusive_integration do
150
150
  logger.debug { "about to wait for @ex_lock to be blocked" }
151
151
 
152
152
  @ex_lock.wait_until_blocked(5)
153
- @ex_lock.should be_waiting
153
+ expect(@ex_lock).to be_waiting
154
154
 
155
155
  logger.debug { "@ex_lock is waiting" }
156
156
 
157
- @ex_lock.should_not be_locked
157
+ expect(@ex_lock).not_to be_locked
158
158
 
159
159
  # this is the important one, does the second shared lock get blocked by
160
160
  # the exclusive lock
161
- @sh_lock2.lock.should_not be_true
161
+ expect(@sh_lock2.lock).not_to be(true)
162
162
 
163
163
  sh2_th = Thread.new do
164
164
  begin
@@ -173,19 +173,19 @@ shared_examples_for :shared_exclusive_integration do
173
173
  logger.debug { "about to wait for @sh_lock2 to be blocked" }
174
174
 
175
175
  @sh_lock2.wait_until_blocked(5)
176
- @sh_lock2.should be_waiting
176
+ expect(@sh_lock2).to be_waiting
177
177
 
178
178
  logger.debug { "@sh_lock2 is waiting" }
179
179
 
180
180
  # ok, now unlock the first in the chain
181
181
  @sh_lock.assert!
182
- @sh_lock.unlock.should be_true
182
+ expect(@sh_lock.unlock).to be(true)
183
183
 
184
- ex_th.join(5).should == ex_th
185
- sh2_th.join(5).should == sh2_th
184
+ expect(ex_th.join(5)).to eq(ex_th)
185
+ expect(sh2_th.join(5)).to eq(sh2_th)
186
186
 
187
- @array.length.should == 2
188
- @array.should == [:ex_lock, :sh_lock2]
187
+ expect(@array.length).to eq(2)
188
+ expect(@array).to eq([:ex_lock, :sh_lock2])
189
189
  end
190
190
  end
191
191
  end # shared_exclusive_integration