zk 0.9.1 → 1.0.0.rc.1

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.
Files changed (63) hide show
  1. data/.gitignore +2 -2
  2. data/Gemfile +3 -4
  3. data/README.markdown +14 -5
  4. data/RELEASES.markdown +69 -1
  5. data/Rakefile +50 -18
  6. data/docs/examples/block_until_node_deleted_ex.rb +63 -0
  7. data/docs/examples/events_01.rb +36 -0
  8. data/docs/examples/events_02.rb +41 -0
  9. data/lib/{z_k → zk}/client/base.rb +87 -30
  10. data/lib/{z_k → zk}/client/conveniences.rb +0 -1
  11. data/lib/{z_k → zk}/client/state_mixin.rb +0 -0
  12. data/lib/zk/client/threaded.rb +196 -0
  13. data/lib/{z_k → zk}/client/unixisms.rb +0 -0
  14. data/lib/zk/client.rb +59 -0
  15. data/lib/zk/core_ext.rb +75 -0
  16. data/lib/{z_k → zk}/election.rb +0 -0
  17. data/lib/zk/event.rb +168 -0
  18. data/lib/{z_k → zk}/event_handler.rb +53 -28
  19. data/lib/zk/event_handler_subscription.rb +68 -0
  20. data/lib/{z_k → zk}/exceptions.rb +38 -23
  21. data/lib/zk/extensions.rb +79 -0
  22. data/lib/{z_k → zk}/find.rb +0 -0
  23. data/lib/{z_k → zk}/locker.rb +0 -0
  24. data/lib/{z_k → zk}/logging.rb +0 -0
  25. data/lib/{z_k → zk}/message_queue.rb +8 -4
  26. data/lib/{z_k → zk}/mongoid.rb +0 -0
  27. data/lib/{z_k → zk}/pool.rb +0 -0
  28. data/lib/zk/stat.rb +115 -0
  29. data/lib/{z_k → zk}/threadpool.rb +52 -4
  30. data/lib/zk/version.rb +3 -0
  31. data/lib/zk.rb +238 -1
  32. data/spec/message_queue_spec.rb +2 -2
  33. data/spec/shared/client_contexts.rb +8 -20
  34. data/spec/shared/client_examples.rb +136 -2
  35. data/spec/spec_helper.rb +4 -2
  36. data/spec/support/event_catcher.rb +11 -0
  37. data/spec/support/exist_matcher.rb +6 -0
  38. data/spec/support/logging.rb +2 -1
  39. data/spec/watch_spec.rb +194 -10
  40. data/spec/{z_k → zk}/client/locking_and_session_death_spec.rb +0 -32
  41. data/spec/zk/client_spec.rb +23 -0
  42. data/spec/{z_k → zk}/election_spec.rb +0 -0
  43. data/spec/{z_k → zk}/extensions_spec.rb +0 -0
  44. data/spec/{z_k → zk}/locker_spec.rb +0 -40
  45. data/spec/zk/module_spec.rb +185 -0
  46. data/spec/{z_k → zk}/mongoid_spec.rb +0 -2
  47. data/spec/{z_k → zk}/pool_spec.rb +0 -2
  48. data/spec/{z_k → zk}/threadpool_spec.rb +32 -4
  49. data/spec/zookeeper_spec.rb +1 -6
  50. data/zk.gemspec +2 -2
  51. metadata +64 -56
  52. data/lib/z_k/client/continuation_proxy.rb +0 -109
  53. data/lib/z_k/client/drop_box.rb +0 -98
  54. data/lib/z_k/client/multiplexed.rb +0 -28
  55. data/lib/z_k/client/threaded.rb +0 -76
  56. data/lib/z_k/client.rb +0 -35
  57. data/lib/z_k/event_handler_subscription.rb +0 -36
  58. data/lib/z_k/extensions.rb +0 -155
  59. data/lib/z_k/version.rb +0 -3
  60. data/lib/z_k.rb +0 -97
  61. data/spec/z_k/client/drop_box_spec.rb +0 -90
  62. data/spec/z_k/client/multiplexed_spec.rb +0 -20
  63. data/spec/z_k/client_spec.rb +0 -7
metadata CHANGED
@@ -1,13 +1,15 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: zk
3
3
  version: !ruby/object:Gem::Version
4
- hash: 57
5
- prerelease:
4
+ hash: 1457112361
5
+ prerelease: 6
6
6
  segments:
7
+ - 1
8
+ - 0
7
9
  - 0
8
- - 9
10
+ - rc
9
11
  - 1
10
- version: 0.9.1
12
+ version: 1.0.0.rc.1
11
13
  platform: ruby
12
14
  authors:
13
15
  - Jonathan D. Simms
@@ -16,7 +18,7 @@ autorequire:
16
18
  bindir: bin
17
19
  cert_chain: []
18
20
 
19
- date: 2012-04-26 00:00:00 Z
21
+ date: 2012-04-30 00:00:00 Z
20
22
  dependencies:
21
23
  - !ruby/object:Gem::Dependency
22
24
  name: slyphon-zookeeper
@@ -26,12 +28,12 @@ dependencies:
26
28
  requirements:
27
29
  - - ~>
28
30
  - !ruby/object:Gem::Version
29
- hash: 61
31
+ hash: 63
30
32
  segments:
31
33
  - 0
32
- - 8
33
- - 1
34
- version: 0.8.1
34
+ - 9
35
+ - 2
36
+ version: 0.9.2
35
37
  type: :runtime
36
38
  version_requirements: *id001
37
39
  description: |
@@ -57,30 +59,32 @@ files:
57
59
  - README.markdown
58
60
  - RELEASES.markdown
59
61
  - Rakefile
60
- - lib/z_k.rb
61
- - lib/z_k/client.rb
62
- - lib/z_k/client/base.rb
63
- - lib/z_k/client/continuation_proxy.rb
64
- - lib/z_k/client/conveniences.rb
65
- - lib/z_k/client/drop_box.rb
66
- - lib/z_k/client/multiplexed.rb
67
- - lib/z_k/client/state_mixin.rb
68
- - lib/z_k/client/threaded.rb
69
- - lib/z_k/client/unixisms.rb
70
- - lib/z_k/election.rb
71
- - lib/z_k/event_handler.rb
72
- - lib/z_k/event_handler_subscription.rb
73
- - lib/z_k/exceptions.rb
74
- - lib/z_k/extensions.rb
75
- - lib/z_k/find.rb
76
- - lib/z_k/locker.rb
77
- - lib/z_k/logging.rb
78
- - lib/z_k/message_queue.rb
79
- - lib/z_k/mongoid.rb
80
- - lib/z_k/pool.rb
81
- - lib/z_k/threadpool.rb
82
- - lib/z_k/version.rb
62
+ - docs/examples/block_until_node_deleted_ex.rb
63
+ - docs/examples/events_01.rb
64
+ - docs/examples/events_02.rb
83
65
  - lib/zk.rb
66
+ - lib/zk/client.rb
67
+ - lib/zk/client/base.rb
68
+ - lib/zk/client/conveniences.rb
69
+ - lib/zk/client/state_mixin.rb
70
+ - lib/zk/client/threaded.rb
71
+ - lib/zk/client/unixisms.rb
72
+ - lib/zk/core_ext.rb
73
+ - lib/zk/election.rb
74
+ - lib/zk/event.rb
75
+ - lib/zk/event_handler.rb
76
+ - lib/zk/event_handler_subscription.rb
77
+ - lib/zk/exceptions.rb
78
+ - lib/zk/extensions.rb
79
+ - lib/zk/find.rb
80
+ - lib/zk/locker.rb
81
+ - lib/zk/logging.rb
82
+ - lib/zk/message_queue.rb
83
+ - lib/zk/mongoid.rb
84
+ - lib/zk/pool.rb
85
+ - lib/zk/stat.rb
86
+ - lib/zk/threadpool.rb
87
+ - lib/zk/version.rb
84
88
  - spec/informal/close-in-event-thread.rb
85
89
  - spec/informal/lock_with_dead_session.rb
86
90
  - spec/informal/what-the-fork.rb
@@ -90,6 +94,8 @@ files:
90
94
  - spec/shared/client_examples.rb
91
95
  - spec/spec_helper.rb
92
96
  - spec/support/bogus_mongoid.rb
97
+ - spec/support/event_catcher.rb
98
+ - spec/support/exist_matcher.rb
93
99
  - spec/support/logging.rb
94
100
  - spec/support/logging_progress_bar_formatter.rb
95
101
  - spec/support/queuey_thread.rb
@@ -97,16 +103,15 @@ files:
97
103
  - spec/support/wait_watchers.rb
98
104
  - spec/test_file.txt
99
105
  - spec/watch_spec.rb
100
- - spec/z_k/client/drop_box_spec.rb
101
- - spec/z_k/client/locking_and_session_death_spec.rb
102
- - spec/z_k/client/multiplexed_spec.rb
103
- - spec/z_k/client_spec.rb
104
- - spec/z_k/election_spec.rb
105
- - spec/z_k/extensions_spec.rb
106
- - spec/z_k/locker_spec.rb
107
- - spec/z_k/mongoid_spec.rb
108
- - spec/z_k/pool_spec.rb
109
- - spec/z_k/threadpool_spec.rb
106
+ - spec/zk/client/locking_and_session_death_spec.rb
107
+ - spec/zk/client_spec.rb
108
+ - spec/zk/election_spec.rb
109
+ - spec/zk/extensions_spec.rb
110
+ - spec/zk/locker_spec.rb
111
+ - spec/zk/module_spec.rb
112
+ - spec/zk/mongoid_spec.rb
113
+ - spec/zk/pool_spec.rb
114
+ - spec/zk/threadpool_spec.rb
110
115
  - spec/zookeeper_spec.rb
111
116
  - zk.gemspec
112
117
  homepage: https://github.com/slyphon/zk
@@ -129,12 +134,14 @@ required_ruby_version: !ruby/object:Gem::Requirement
129
134
  required_rubygems_version: !ruby/object:Gem::Requirement
130
135
  none: false
131
136
  requirements:
132
- - - ">="
137
+ - - ">"
133
138
  - !ruby/object:Gem::Version
134
- hash: 3
139
+ hash: 25
135
140
  segments:
136
- - 0
137
- version: "0"
141
+ - 1
142
+ - 3
143
+ - 1
144
+ version: 1.3.1
138
145
  requirements: []
139
146
 
140
147
  rubyforge_project:
@@ -152,6 +159,8 @@ test_files:
152
159
  - spec/shared/client_examples.rb
153
160
  - spec/spec_helper.rb
154
161
  - spec/support/bogus_mongoid.rb
162
+ - spec/support/event_catcher.rb
163
+ - spec/support/exist_matcher.rb
155
164
  - spec/support/logging.rb
156
165
  - spec/support/logging_progress_bar_formatter.rb
157
166
  - spec/support/queuey_thread.rb
@@ -159,14 +168,13 @@ test_files:
159
168
  - spec/support/wait_watchers.rb
160
169
  - spec/test_file.txt
161
170
  - spec/watch_spec.rb
162
- - spec/z_k/client/drop_box_spec.rb
163
- - spec/z_k/client/locking_and_session_death_spec.rb
164
- - spec/z_k/client/multiplexed_spec.rb
165
- - spec/z_k/client_spec.rb
166
- - spec/z_k/election_spec.rb
167
- - spec/z_k/extensions_spec.rb
168
- - spec/z_k/locker_spec.rb
169
- - spec/z_k/mongoid_spec.rb
170
- - spec/z_k/pool_spec.rb
171
- - spec/z_k/threadpool_spec.rb
171
+ - spec/zk/client/locking_and_session_death_spec.rb
172
+ - spec/zk/client_spec.rb
173
+ - spec/zk/election_spec.rb
174
+ - spec/zk/extensions_spec.rb
175
+ - spec/zk/locker_spec.rb
176
+ - spec/zk/module_spec.rb
177
+ - spec/zk/mongoid_spec.rb
178
+ - spec/zk/pool_spec.rb
179
+ - spec/zk/threadpool_spec.rb
172
180
  - spec/zookeeper_spec.rb
@@ -1,109 +0,0 @@
1
- module ZK
2
- module Client
3
- # Wraps calls to zookeeper so that the requests are made asynchronously,
4
- # but still provides a blocking API
5
- #
6
- # @private
7
- class ContinuationProxy
8
- include ZK::Logging
9
-
10
- attr_accessor :zookeeper_cnx
11
-
12
- # @private
13
- def self.call_with_continuation(*syms)
14
- syms.each do |sym|
15
- class_eval(<<-EOS, __FILE__, __LINE__+1)
16
- def #{sym}(opts)
17
- logger.debug { "_call_continue(#{sym.inspect}, \#{opts.inspect})" }
18
- _call_continue(#{sym.inspect}, opts)
19
- end
20
- EOS
21
- end
22
- end
23
-
24
- call_with_continuation :get, :set, :stat, :children, :delete, :get_acl, :set_acl
25
-
26
- def initialize(zookeeper_cnx=nil)
27
- @zookeeper_cnx = zookeeper_cnx
28
- @mutex = Mutex.new
29
- @dropboxen = []
30
- end
31
-
32
- # create is "special" because the return hash doesn't have a :path, it has a :string
33
- def create(opts)
34
- logger.debug { "_call_continue(create, #{opts.inspect})" }
35
- _call_continue(:create, opts).tap do |rval|
36
- rval[:path] = rval.delete(:string)
37
- end
38
- end
39
-
40
- # called by the multiplxed client to wake up threads that are waiting for
41
- # results (with an exception)
42
- # @private
43
- def connection_closed!
44
- _oh_noes(ZookeeperExceptions::ZookeeperException::NotConnected, 'connection closed')
45
- end
46
-
47
- # called by the multiplxed client to wake up threads that are waiting for
48
- # results (with an exception)
49
- # @private
50
- def expired_session!
51
- _oh_noes(ZookeeperExceptions::ZookeeperException::SessionExpired, 'session expired')
52
- end
53
-
54
- private
55
- def method_missing(m, *a, &b)
56
- @zookeeper_cnx.respond_to?(m) ? @zookeeper_cnx.__send__(m, *a, &b) : super
57
- end
58
-
59
- def _oh_noes(exception, message)
60
- @mutex.synchronize do
61
- @dropboxen.each do |db|
62
- db.oh_noes!(exception, message)
63
- end
64
- end
65
- end
66
-
67
- # not really callcc, but close enough
68
- # opts should be an options hash as passed through to the Zookeeper
69
- # layer
70
- def _call_continue(meth, opts)
71
- _assert_not_async!(meth, opts)
72
-
73
- opts = opts.dup
74
-
75
- _with_drop_box do |db|
76
- cb = lambda do |hash|
77
- # logger.debug { "#{self.class}##{__method__} block pushing: #{hash.inspect}" }
78
- db.push(hash)
79
- end
80
-
81
- opts[:callback] = cb
82
-
83
- @zookeeper_cnx.__send__(meth, opts)
84
-
85
- # db.pop.tap do |obj|
86
- # logger.debug { "#{self.class}##{__method__} popped and returning: #{obj.inspect}" }
87
- # end
88
-
89
- db.pop
90
- end
91
- end
92
-
93
- def _with_drop_box
94
- db = DropBox.current
95
- @mutex.synchronize { @dropboxen << db }
96
- yield db
97
- ensure
98
- @mutex.synchronize { @dropboxen.delete(db) }
99
- db.clear
100
- end
101
-
102
- def _assert_not_async!(meth, opts)
103
- return unless opts.has_key?(:callback)
104
- raise ArgumentError, "you cannot use async callbacks with a Multiplexed client! meth: #{meth.inspect}, opts: #{opts.inspect}"
105
- end
106
- end # ContinuationProxy
107
- end
108
- end
109
-
@@ -1,98 +0,0 @@
1
- module ZK
2
- module Client
3
- # A simple threadsafe way of having a thread deliver a single value
4
- # to another thread.
5
- #
6
- # Each thread making requests will have a thread-local continuation
7
- # that can be accessed via DropBox.current and one can use
8
- # DropBox.with_current that will clear the result once the given block
9
- # exits (allowing for reuse)
10
- #
11
- # (this class is in no way related to dropbox.com or Dropbox Inc.)
12
- # @private
13
- class DropBox
14
- UNDEFINED = Object.new unless defined?(UNDEFINED)
15
- KILL_TOKEN = Object.new unless defined?(KILL_TOKEN)
16
- IMPOSSIBLE_TO_CONTINUE = Object.new unless defined?(IMPOSSIBLE_TO_CONTINUE)
17
-
18
- # represents an exception to raise. if the pop method sees the value as an instance
19
- # of this class, it will call the raise! method
20
- class ExceptionValue
21
- def initialize(exception_class, message)
22
- @exception_class, @message = exception_class, message
23
- end
24
-
25
- def raise!
26
- raise @exception_class, @message
27
- end
28
- end
29
-
30
- THREAD_LOCAL_KEY = :__zk_client_continuation_current__ unless defined?(THREAD_LOCAL_KEY)
31
-
32
- # @private
33
- attr_reader :value
34
-
35
- # sets the thread-local instance to nil, used by tests
36
- # @private
37
- def self.remove_current
38
- Thread.current[THREAD_LOCAL_KEY] = nil
39
- end
40
-
41
- # access the thread-local DropBox instance for the current thread
42
- def self.current
43
- Thread.current[THREAD_LOCAL_KEY] ||= self.new()
44
- end
45
-
46
- # yields the current thread's DropBox instance and clears its value
47
- # after the block returns
48
- def self.with_current
49
- yield current
50
- ensure
51
- current.clear
52
- end
53
-
54
- def initialize
55
- @mutex = Mutex.new
56
- @cond = ConditionVariable.new
57
- @value = UNDEFINED # allows us to return nil
58
- end
59
-
60
- def push(obj)
61
- @mutex.synchronize do
62
- @value = obj
63
- @cond.signal
64
- end
65
- end
66
-
67
- def pop
68
- @mutex.synchronize do
69
- @cond.wait(@mutex)
70
- @value.kind_of?(ExceptionValue) ? @value.raise! : @value
71
- end
72
- end
73
-
74
- def clear
75
- @mutex.synchronize do
76
- @value = UNDEFINED
77
- end
78
- end
79
-
80
- # we are done if value is defined, use clear to reset
81
- def done?
82
- @value != UNDEFINED
83
- end
84
-
85
- # called when you need the waiting thread to receive an exception
86
- # returns nil if a value has already been set
87
- def oh_noes!(exception_class, message)
88
- @mutex.synchronize do
89
- return if done?
90
- @value = ExceptionValue.new(exception_class, message)
91
- @cond.signal
92
- end
93
- true
94
- end
95
- end
96
- end
97
- end
98
-
@@ -1,28 +0,0 @@
1
- module ZK
2
- module Client
3
- # This client is an experimental implementation of a threaded and
4
- # multiplexed client. The idea is that each synchronous request represents
5
- # a continuation. This way, you can have multiple requests pending with the
6
- # server simultaneously, and the responses will be delivered on the event
7
- # thread (but run in the calling thread). This allows for higher throughput
8
- # for multi-threaded applications.
9
- #
10
- # Asynchronous requests are not supported through this client.
11
- #
12
- class Multiplexed < Threaded
13
- def close!
14
- @cnx.connection_closed!
15
- super
16
- end
17
-
18
- protected
19
- def create_connection(*args)
20
- ContinuationProxy.new.tap do |cp|
21
- on_expired_session { cp.expired_session! } # hook up client's session expired event listener
22
- cp.zookeeper_cnx = super(*args)
23
- end
24
- end
25
- end
26
- end
27
- end
28
-
@@ -1,76 +0,0 @@
1
- module ZK
2
- module Client
3
- # This is the default client that ZK will use. In the zk-eventmachine gem,
4
- # there is an Evented client.
5
- #
6
- class Threaded < Base
7
- include StateMixin
8
- include Unixisms
9
- include Conveniences
10
-
11
- DEFAULT_THREADPOOL_SIZE = 1
12
-
13
- # @note The `:timeout` argument here is *not* the session_timeout for the
14
- # connection. rather it is the amount of time we wait for the connection
15
- # to be established. The session timeout exchanged with the server is
16
- # set to 10s by default in the C implemenation, and as of version 0.8.0
17
- # of slyphon-zookeeper has yet to be exposed as an option. That feature
18
- # is planned.
19
- #
20
- # @param [String] host (see ZK::Client::Base#initialize)
21
- #
22
- # @option opts [Fixnum] :threadpool_size the size of the threadpool that
23
- # should be used to deliver events. In ZK 0.8.x this was set to 5, which
24
- # means that events could be delivered concurrently. As of 0.9, this will
25
- # be set to 1, so it's very important to _not block the event thread_.
26
- #
27
- # @option opts [Fixnum] :timeout how long we will wait for the connection
28
- # to be established.
29
- #
30
- # @yield [self] calls the block with the new instance after the event
31
- # handler has been set up, but before any connections have been made.
32
- # This allows the client to register watchers for session events like
33
- # `connected`. You *cannot* perform any other operations with the client
34
- # as you will get a NoMethodError (the underlying connection is nil).
35
- #
36
- def initialize(host, opts={}, &b)
37
- super(host, opts)
38
-
39
- @session_timeout = opts.fetch(:timeout, DEFAULT_TIMEOUT) # maybe move this into superclass?
40
- @event_handler = EventHandler.new(self)
41
-
42
- yield self if block_given?
43
-
44
- @cnx = create_connection(host, @session_timeout, @event_handler.get_default_watcher_block)
45
-
46
- tp_size = opts.fetch(:threadpool_size, DEFAULT_THREADPOOL_SIZE)
47
-
48
- @threadpool = Threadpool.new(tp_size)
49
- end
50
-
51
- # @see ZK::Client::Base#close!
52
- def close!
53
- if event_dispatch_thread?
54
- msg = ["ZK ERROR: You called #{self.class}#close! on the event dispatch thread!!",
55
- "This will cause the client to deadlock and possibly your main thread as well!"]
56
-
57
- warn_msg = [nil, msg, nil, "See ZK error log output (stderr by default) for a backtrace", nil].join("\n")
58
-
59
- Kernel.warn(warn_msg)
60
- assert_we_are_not_on_the_event_dispatch_thread!(msg.join(' '))
61
- end
62
-
63
- @threadpool.shutdown
64
- super
65
- nil
66
- end
67
-
68
- protected
69
- # allows for the Mutliplexed client to wrap the connection in its ContinuationProxy
70
- # @private
71
- def create_connection(*args)
72
- ::Zookeeper.new(*args)
73
- end
74
- end
75
- end
76
- end
data/lib/z_k/client.rb DELETED
@@ -1,35 +0,0 @@
1
- module ZK
2
- # A ruby-friendly wrapper around the low-level zookeeper drivers. This is the
3
- # class that you will likely interact with the most.
4
- #
5
- # @todo ACL support is pretty much unused currently.
6
- # If anyone has suggestions, hints, use-cases, examples, etc. by all means please file a bug.
7
- #
8
- module Client
9
- DEFAULT_TIMEOUT = 10
10
-
11
- # @private
12
- STATE_SYM_MAP = {
13
- Zookeeper::ZOO_CLOSED_STATE => :closed,
14
- Zookeeper::ZOO_EXPIRED_SESSION_STATE => :expired_session,
15
- Zookeeper::ZOO_AUTH_FAILED_STATE => :auth_failed,
16
- Zookeeper::ZOO_CONNECTING_STATE => :connecting,
17
- Zookeeper::ZOO_CONNECTED_STATE => :connected,
18
- Zookeeper::ZOO_ASSOCIATING_STATE => :associating,
19
- }.freeze
20
-
21
- def self.new(*a, &b)
22
- Threaded.new(*a, &b)
23
- end
24
- end
25
- end
26
-
27
- require 'z_k/client/drop_box'
28
- require 'z_k/client/state_mixin'
29
- require 'z_k/client/unixisms'
30
- require 'z_k/client/conveniences'
31
- require 'z_k/client/base'
32
- require 'z_k/client/threaded'
33
- require 'z_k/client/continuation_proxy'
34
- require 'z_k/client/multiplexed'
35
-
@@ -1,36 +0,0 @@
1
- module ZK
2
- # the subscription object that is passed back from subscribing
3
- # to events.
4
- # @see ZK::Client::Base#register
5
- class EventHandlerSubscription
6
- # the event handler associated with this subscription
7
- # @return [EventHandler]
8
- attr_accessor :event_handler
9
-
10
- # the path this subscription is for
11
- # @return [String]
12
- attr_accessor :path
13
-
14
- # the block associated with the path
15
- # @return [Proc]
16
- attr_accessor :callback
17
-
18
- # @private
19
- def initialize(event_handler, path, callback)
20
- @event_handler, @path, @callback = event_handler, path, callback
21
- end
22
-
23
- # unsubscribe from the path or state you were watching
24
- # @see ZK::Client::Base#register
25
- def unsubscribe
26
- @event_handler.unregister(self)
27
- end
28
- alias :unregister :unsubscribe
29
-
30
- # @private
31
- def call(event)
32
- callback.call(event)
33
- end
34
- end
35
- end
36
-