zk 1.0.0 → 1.1.0
Sign up to get free protection for your applications and to get access to all the features.
- data/.gitignore +1 -0
- data/.travis.yml +6 -8
- data/Gemfile +4 -6
- data/README.markdown +39 -21
- data/Rakefile +4 -2
- data/lib/zk.rb +60 -5
- data/lib/zk/client/base.rb +31 -9
- data/lib/zk/client/threaded.rb +39 -20
- data/lib/zk/election.rb +42 -38
- data/lib/zk/event.rb +8 -0
- data/lib/zk/event_handler.rb +38 -7
- data/lib/zk/event_handler_subscription.rb +19 -55
- data/lib/zk/event_handler_subscription/actor.rb +38 -0
- data/lib/zk/event_handler_subscription/base.rb +76 -0
- data/lib/zk/threaded_callback.rb +56 -0
- data/lib/zk/threadpool.rb +1 -3
- data/lib/zk/version.rb +1 -1
- data/spec/event_catcher_spec.rb +29 -0
- data/spec/message_queue_spec.rb +2 -2
- data/spec/shared/client_contexts.rb +20 -10
- data/spec/shared/client_examples.rb +1 -1
- data/spec/spec_helper.rb +22 -7
- data/spec/support/00_test_port_attr.rb +20 -0
- data/spec/support/event_catcher.rb +73 -5
- data/spec/support/logging.rb +3 -1
- data/spec/support/pendings.rb +52 -0
- data/spec/support/wait_watchers.rb +10 -1
- data/spec/watch_spec.rb +143 -124
- data/spec/zk/client_spec.rb +15 -3
- data/spec/zk/election_spec.rb +12 -14
- data/spec/zk/locker_spec.rb +17 -12
- data/spec/zk/module_spec.rb +20 -12
- data/spec/zk/mongoid_spec.rb +3 -1
- data/spec/zk/pool_spec.rb +3 -3
- data/spec/zookeeper_spec.rb +2 -2
- metadata +13 -4
data/.gitignore
CHANGED
data/.travis.yml
CHANGED
@@ -3,15 +3,13 @@ notifications:
|
|
3
3
|
email:
|
4
4
|
- slyphon@gmail.com
|
5
5
|
|
6
|
+
env:
|
7
|
+
- SPAWN_ZOOKEEPER='true'
|
8
|
+
|
6
9
|
rvm:
|
7
|
-
- 1.8.7
|
8
|
-
- 1.9.2
|
9
10
|
- 1.9.3
|
10
|
-
-
|
11
|
-
|
12
|
-
before_install:
|
13
|
-
- sudo apt-get update
|
14
|
-
- sudo apt-get install zookeeperd
|
11
|
+
- 1.9.2
|
12
|
+
- 1.8.7
|
15
13
|
|
16
|
-
bundler_args: --without development
|
14
|
+
bundler_args: --without development docs
|
17
15
|
|
data/Gemfile
CHANGED
@@ -2,11 +2,8 @@ source :rubygems
|
|
2
2
|
|
3
3
|
# gem 'slyphon-zookeeper', :path => '~/zookeeper'
|
4
4
|
|
5
|
-
group :development
|
6
|
-
|
7
|
-
end
|
8
|
-
|
9
|
-
gem 'pry', :group => [:development, :test]
|
5
|
+
gem 'rake', :group => [:development, :test]
|
6
|
+
gem 'pry', :group => [:development]
|
10
7
|
|
11
8
|
group :docs do
|
12
9
|
gem 'yard', '~> 0.7.5'
|
@@ -19,7 +16,8 @@ end
|
|
19
16
|
group :test do
|
20
17
|
gem 'rspec', '~> 2.8.0'
|
21
18
|
gem 'flexmock', '~> 0.8.10'
|
22
|
-
|
19
|
+
# gem 'zk-server', :path => '~/mbox/zk-server'
|
20
|
+
gem 'zk-server', '~> 0.9.1'
|
23
21
|
end
|
24
22
|
|
25
23
|
# Specify your gem's dependencies in zk.gemspec
|
data/README.markdown
CHANGED
@@ -1,5 +1,7 @@
|
|
1
1
|
# ZK
|
2
2
|
|
3
|
+
[![Build Status (master)](https://secure.travis-ci.org/slyphon/zk.png?branch=master)](http://travis-ci.org/slyphon/zk)
|
4
|
+
|
3
5
|
ZK is a high-level interface to the Apache [ZooKeeper][] server. It is based on the [zookeeper gem][] which is a multi-Ruby low-level driver. Currently MRI 1.8.7, 1.9.2, 1.9.3, and JRuby are supported, rubinius 2.0.testing is supported-ish (it's expected to work, but upstream is unstable, so YMMV).
|
4
6
|
|
5
7
|
ZK is licensed under the [MIT][] license.
|
@@ -16,7 +18,13 @@ Development is sponsored by [Snapfish][] and has been generously released to the
|
|
16
18
|
[MIT]: http://www.gnu.org/licenses/license-list.html#Expat "MIT (Expat) License"
|
17
19
|
[Snapfish]: http://www.snapfish.com/ "Snapfish"
|
18
20
|
|
19
|
-
## New in 1.
|
21
|
+
## New in 1.1 !! ##
|
22
|
+
|
23
|
+
* NEW! Thread-per-Callback event delivery model! [Read all about it!](https://github.com/slyphon/zk/wiki/EventDeliveryModel). Provides a simple, sane way to increase the concurrency in your ZK-based app while maintaining the ordering guarantees ZooKeeper makes. Each callback can perform whatever work it needs to without blocking other callbacks from receiving events. Inspired by [Celluloid's](https://github.com/celluloid/celluloid) actor model.
|
24
|
+
|
25
|
+
* Use the [zk-server](https://github.com/slyphon/zk-server) gem to run a standalone ZooKeeper server for tests (`rake SPAWN_ZOOKEEPER=1`). Makes live-fire testing of any project that uses ZK easy to run anywhere!
|
26
|
+
|
27
|
+
## New in 1.0 ##
|
20
28
|
|
21
29
|
* Threaded client (the default one) will now automatically reconnect (i.e. `reopen()`) if a `SESSION_EXPIRED` or `AUTH_FAILED` event is received. Thanks to @eric for pointing out the _nose-on-your-face obviousness_ and importance of this. If users want to handle these events themselves, and not automatically reopen, you can pass `:reconnect => false` to the constructor.
|
22
30
|
|
@@ -24,39 +32,51 @@ Development is sponsored by [Snapfish][] and has been generously released to the
|
|
24
32
|
|
25
33
|
* add zk.register(:all) to recevie node updates for all nodes (i.e. not filtered on path)
|
26
34
|
|
27
|
-
* add 'interest' feature to zk.register, now you can indicate what kind of events should be delivered to the given block (previously you had to do that filtering inside the block). The default behavior is still the same, if no 'interest' is given, then all event types for the given path will be delivered to that block.
|
35
|
+
* add 'interest' feature to zk.register, now you can indicate what kind of events should be delivered to the given block (previously you had to do that filtering inside the block). The default behavior is still the same, if no 'interest' is given, then all event types for the given path will be delivered to that block.
|
28
36
|
|
29
|
-
|
30
|
-
|
31
|
-
|
37
|
+
```ruby
|
38
|
+
zk.register('/path', :created) do |event|
|
39
|
+
# event.node_created? will always be true
|
40
|
+
end
|
41
|
+
|
42
|
+
# or multiple kinds of events
|
32
43
|
|
33
|
-
|
44
|
+
zk.register('/path', [:created, :changed]) do |event|
|
45
|
+
# (event.node_created? or event.node_changed?) will always be true
|
46
|
+
end
|
34
47
|
|
35
|
-
|
36
|
-
|
37
|
-
|
48
|
+
# this will, however, be changed in 1.1 to (backwards compatible, with a deprecation warning)
|
49
|
+
|
50
|
+
zk.register('/path', :only => :created) do |event|
|
51
|
+
end
|
52
|
+
|
53
|
+
```
|
38
54
|
|
39
55
|
* create now allows you to pass a path and options, instead of requiring the blank string
|
40
56
|
|
41
|
-
|
57
|
+
```ruby
|
58
|
+
zk.create('/path', '', :sequential => true)
|
42
59
|
|
43
|
-
|
60
|
+
# now also
|
44
61
|
|
45
|
-
|
62
|
+
zk.create('/path', :sequential => true)
|
63
|
+
```
|
46
64
|
|
47
65
|
* fix for shutdown: close! called from threadpool will do the right thing
|
48
66
|
|
49
67
|
* Chroot users rejoice! By default, ZK.new will create a chrooted path for you.
|
50
68
|
|
51
|
-
|
69
|
+
```ruby
|
70
|
+
ZK.new('localhost:2181/path', :chroot => :create) # the default, create the path before returning connection
|
52
71
|
|
53
|
-
|
72
|
+
ZK.new('localhost:2181/path', :chroot => :check) # make sure the chroot exists, raise if not
|
54
73
|
|
55
|
-
|
74
|
+
ZK.new('localhost:2181/path', :chroot => :do_nothing) # old default behavior
|
56
75
|
|
57
|
-
|
58
|
-
|
59
|
-
|
76
|
+
# and, just for kicks
|
77
|
+
|
78
|
+
ZK.new('localhost:2181', :chroot => '/path') # equivalent to 'localhost:2181/path', :chroot => :create
|
79
|
+
```
|
60
80
|
|
61
81
|
* Most of the event functionality used is now in a ZK::Event module. This is still mixed into the underlying slyphon-zookeeper class, but now all of the important and relevant methods are documented, and Event appears as a first-class citizen.
|
62
82
|
|
@@ -115,8 +135,6 @@ ZK strives to be a complete, correct, and convenient way of interacting with Zoo
|
|
115
135
|
|
116
136
|
* ZK::Client supports asynchronous calls of all basic methods (get, set, delete, etc.) however these versions are kind of inconvenient to use. For a fully evented stack, try [zk-eventmachine][], which is designed to be compatible and convenient to use in event-driven code.
|
117
137
|
|
118
|
-
* ZooKeeper "chroot" [connection syntax][chroot] should work for most cases. Right now we require that the root path exist before the chrooted client is used, but that may change [in the near future](https://github.com/slyphon/zk/issues/7).
|
119
|
-
|
120
138
|
[twitter/zookeeper]: https://github.com/twitter/zookeeper
|
121
139
|
[async-branch]: https://github.com/slyphon/zk/tree/dev%2Fasync-conveniences
|
122
140
|
[chroot]: http://zookeeper.apache.org/doc/current/zookeeperProgrammers.html#ch_zkSessions
|
@@ -133,7 +151,7 @@ ZK strives to be a complete, correct, and convenient way of interacting with Zoo
|
|
133
151
|
|
134
152
|
## Dependencies
|
135
153
|
|
136
|
-
* The [slyphon-zookeeper gem][szk-gem] ([repo][szk-repo])
|
154
|
+
* The [slyphon-zookeeper gem][szk-gem] ([repo][szk-repo]).
|
137
155
|
|
138
156
|
* For JRuby, the [slyphon-zookeeper\_jar gem][szk-jar-gem] ([repo][szk-jar-repo]), which just wraps the upstream zookeeper driver jar in a gem for easy installation
|
139
157
|
|
data/Rakefile
CHANGED
@@ -33,7 +33,7 @@ GEMSPEC_NAME = 'zk.gemspec'
|
|
33
33
|
end
|
34
34
|
|
35
35
|
task rspec_task_name => bundle_task_name do
|
36
|
-
sh "rvm #{ruby_with_gemset} do env BUNDLE_GEMFILE=#{phony_gemfile_link_name} bundle exec rspec spec --fail-fast"
|
36
|
+
sh "rvm #{ruby_with_gemset} do env JRUBY_OPTS='--1.9' BUNDLE_GEMFILE=#{phony_gemfile_link_name} bundle exec rspec spec --fail-fast"
|
37
37
|
end
|
38
38
|
|
39
39
|
task "mb:#{ns_name}" => rspec_task_name
|
@@ -69,7 +69,9 @@ namespace :spec do
|
|
69
69
|
require 'bundler/setup'
|
70
70
|
require 'rspec/core/rake_task'
|
71
71
|
|
72
|
-
RSpec::Core::RakeTask.new('spec:runner')
|
72
|
+
RSpec::Core::RakeTask.new('spec:runner') do |t|
|
73
|
+
t.rspec_opts = '-f d'
|
74
|
+
end
|
73
75
|
end
|
74
76
|
|
75
77
|
task :run => :define do
|
data/lib/zk.rb
CHANGED
@@ -16,6 +16,7 @@ require 'zk/extensions'
|
|
16
16
|
require 'zk/event'
|
17
17
|
require 'zk/stat'
|
18
18
|
require 'zk/threadpool'
|
19
|
+
require 'zk/threaded_callback'
|
19
20
|
require 'zk/event_handler_subscription'
|
20
21
|
require 'zk/event_handler'
|
21
22
|
require 'zk/message_queue'
|
@@ -30,9 +31,6 @@ module ZK
|
|
30
31
|
silence_warnings do
|
31
32
|
# @private
|
32
33
|
ZK_ROOT = File.expand_path('../..', __FILE__).freeze
|
33
|
-
|
34
|
-
# @private
|
35
|
-
DEFAULT_SERVER = 'localhost:2181'.freeze
|
36
34
|
end
|
37
35
|
|
38
36
|
unless defined?(KILL_TOKEN)
|
@@ -40,10 +38,32 @@ module ZK
|
|
40
38
|
KILL_TOKEN = Object.new
|
41
39
|
end
|
42
40
|
|
43
|
-
|
44
41
|
unless @logger
|
45
42
|
@logger = Logger.new($stderr).tap { |n| n.level = Logger::ERROR }
|
46
43
|
end
|
44
|
+
|
45
|
+
@default_host = 'localhost' unless @default_host
|
46
|
+
@default_port = 2181 unless @default_port
|
47
|
+
@default_chroot = '' unless @default_chroot
|
48
|
+
|
49
|
+
class << self
|
50
|
+
# what host should ZK.new connect to when given no options
|
51
|
+
attr_accessor :default_host
|
52
|
+
|
53
|
+
# what port should ZK.new connect to when given no options
|
54
|
+
attr_accessor :default_port
|
55
|
+
|
56
|
+
# what chroot path should ZK.new connect to when given no options
|
57
|
+
attr_accessor :default_chroot
|
58
|
+
end
|
59
|
+
|
60
|
+
# @private
|
61
|
+
def self.default_connection_string
|
62
|
+
"#{default_host}:#{default_port}".tap do |str|
|
63
|
+
# XXX: this is seriously blech
|
64
|
+
str.replace(File.join(str, default_chroot)) if default_chroot != ''
|
65
|
+
end
|
66
|
+
end
|
47
67
|
|
48
68
|
# The logger used by the ZK library. uses a Logger stderr with Logger::ERROR
|
49
69
|
# level. The only thing that should ever be logged are exceptions that are
|
@@ -139,18 +159,22 @@ module ZK
|
|
139
159
|
# {ZK::Client::Threaded#initialize Threaded.new} directly. You probably
|
140
160
|
# also hate happiness and laughter.
|
141
161
|
#
|
162
|
+
# @option opts [:single,:per_callback] :thread (:single) see {ZK::Client::Threaded#initialize}
|
163
|
+
# for a discussion of what these options mean
|
164
|
+
#
|
142
165
|
# @raise [ChrootPathDoesNotExistError] if a chroot path is specified,
|
143
166
|
# `:chroot` is `:check`, and the path does not exist.
|
144
167
|
#
|
145
168
|
# @raise [ArgumentError] if both a chrooted `connection_str` is given *and* a
|
146
169
|
# `String` value for the `:chroot` option is given
|
147
170
|
#
|
171
|
+
#
|
148
172
|
def self.new(*args, &block)
|
149
173
|
opts = args.extract_options!
|
150
174
|
|
151
175
|
chroot_opt = opts.fetch(:chroot, :create)
|
152
176
|
|
153
|
-
args = [
|
177
|
+
args = [default_connection_string] if args.empty? # the ZK.new() case
|
154
178
|
|
155
179
|
if args.first.kind_of?(String)
|
156
180
|
if new_cnx_str = do_chroot_setup(args.first, chroot_opt)
|
@@ -174,6 +198,8 @@ module ZK
|
|
174
198
|
yield cnx
|
175
199
|
ensure
|
176
200
|
cnx.close! if cnx
|
201
|
+
# XXX: need some way of waiting for the connection to reach closed? state
|
202
|
+
# ensure there's no leakage
|
177
203
|
end
|
178
204
|
|
179
205
|
# creates a new ZK::Pool::Bounded with the default options.
|
@@ -186,6 +212,34 @@ module ZK
|
|
186
212
|
File.join(*paths)
|
187
213
|
end
|
188
214
|
|
215
|
+
# @private
|
216
|
+
def self.mri_19?
|
217
|
+
ruby_19? and not jruby? or rubinius?
|
218
|
+
end
|
219
|
+
|
220
|
+
def self.ruby_19?
|
221
|
+
(RUBY_VERSION =~ /\A1\.9\.[2-9]\Z/)
|
222
|
+
end
|
223
|
+
|
224
|
+
def self.ruby_187?
|
225
|
+
(RUBY_VERSION == '1.8.7')
|
226
|
+
end
|
227
|
+
|
228
|
+
# @private
|
229
|
+
def self.mri_187?
|
230
|
+
ruby_187? and not jruby? or rubinius?
|
231
|
+
end
|
232
|
+
|
233
|
+
# @private
|
234
|
+
def self.jruby?
|
235
|
+
defined?(::JRUBY_VERSION)
|
236
|
+
end
|
237
|
+
|
238
|
+
# @private
|
239
|
+
def self.rubinius?
|
240
|
+
defined?(::Rubinius)
|
241
|
+
end
|
242
|
+
|
189
243
|
private
|
190
244
|
# @return [String] a possibly modified connection string (with chroot info
|
191
245
|
# added)
|
@@ -226,6 +280,7 @@ module ZK
|
|
226
280
|
open(host) do |zk| # do path stuff with the virgin connection
|
227
281
|
unless zk.exists?(chroot_path) # someting must be done
|
228
282
|
if chroot_opt == :create # here, let me...
|
283
|
+
logger.debug { "creating chroot path #{chroot_path}" }
|
229
284
|
zk.mkdir_p(chroot_path) # ...get that for you
|
230
285
|
else # careful with that axe
|
231
286
|
raise Exceptions::ChrootPathDoesNotExistError.new(host, chroot_path) # ...eugene
|
data/lib/zk/client/base.rb
CHANGED
@@ -770,12 +770,22 @@ module ZK
|
|
770
770
|
#
|
771
771
|
# @example only creation events
|
772
772
|
#
|
773
|
-
# sub = zk.register('/path/to/znode', :created) do |event|
|
773
|
+
# sub = zk.register('/path/to/znode', :only => :created) do |event|
|
774
774
|
# # do something when the node is created
|
775
775
|
# end
|
776
776
|
#
|
777
777
|
# @example only changed or children events
|
778
778
|
#
|
779
|
+
# sub = zk.register('/path/to/znode', :only => [:changed, :child]) do |event|
|
780
|
+
# if event.node_changed?
|
781
|
+
# # do something on change
|
782
|
+
# else
|
783
|
+
# # we know it's a child event
|
784
|
+
# end
|
785
|
+
# end
|
786
|
+
#
|
787
|
+
# @example deprecated 1.0 style interests
|
788
|
+
#
|
779
789
|
# sub = zk.register('/path/to/znode', [:changed, :child]) do |event|
|
780
790
|
# if event.node_changed?
|
781
791
|
# # do something on change
|
@@ -787,12 +797,6 @@ module ZK
|
|
787
797
|
# @param [String,:all] path the znode path you want to listen to, or the
|
788
798
|
# special value :all, that will cause the block to be delivered events
|
789
799
|
# for all znode paths
|
790
|
-
#
|
791
|
-
# @param [Array,Symbol,nil] interests a symbol or array-of-symbols indicating
|
792
|
-
# which events you would like the block to be called for. Valid events
|
793
|
-
# are :created, :deleted, :changed, and :child. If nil, the block will
|
794
|
-
# receive all events
|
795
|
-
#
|
796
800
|
# @param [Block] block the block to execute when a watch event happpens
|
797
801
|
#
|
798
802
|
# @yield [event] We will call your block with the watch event object (which
|
@@ -801,12 +805,30 @@ module ZK
|
|
801
805
|
# @return [EventHandlerSubscription] the subscription object
|
802
806
|
# you can use to to unsubscribe from an event
|
803
807
|
#
|
808
|
+
# @overload register(path, interests=nil, &block)
|
809
|
+
# @since 1.0
|
810
|
+
#
|
811
|
+
# @deprecated use the `:only => :created` form
|
812
|
+
#
|
813
|
+
# @param [Array,Symbol,nil] interests a symbol or array-of-symbols indicating
|
814
|
+
# which events you would like the block to be called for. Valid events
|
815
|
+
# are :created, :deleted, :changed, and :child. If nil, the block will
|
816
|
+
# receive all events
|
817
|
+
#
|
818
|
+
# @overload register(path, opts={}, &block)
|
819
|
+
# @since 1.1
|
820
|
+
#
|
821
|
+
# @option opts [Array,Symbol,nil] :only (nil) a symbol or array-of-symbols indicating
|
822
|
+
# which events you would like the block to be called for. Valid events
|
823
|
+
# are :created, :deleted, :changed, and :child. If nil, the block will
|
824
|
+
# receive all events
|
825
|
+
#
|
804
826
|
# @see ZooKeeper::WatcherEvent
|
805
827
|
# @see ZK::EventHandlerSubscription
|
806
828
|
# @see https://github.com/slyphon/zk/wiki/Events the wiki page on using events effectively
|
807
829
|
#
|
808
|
-
def register(path,
|
809
|
-
event_handler.register(path,
|
830
|
+
def register(path, opts={}, &block)
|
831
|
+
event_handler.register(path, opts, &block)
|
810
832
|
end
|
811
833
|
|
812
834
|
# returns true if the caller is calling from the event dispatch thread
|
data/lib/zk/client/threaded.rb
CHANGED
@@ -15,23 +15,11 @@ module ZK
|
|
15
15
|
# unconfigurable, event dispatch thread. In 1.0 the number of event
|
16
16
|
# delivery threads is configurable, but still defaults to 1.
|
17
17
|
#
|
18
|
-
# The configurability is intended to allow users to easily dispatch events to
|
19
|
-
# event handlers that will perform (application specific) work. Be aware,
|
20
|
-
# the default will give you the guarantee that only one event will be delivered
|
21
|
-
# at a time. The advantage to this is that you can be sure that no event will
|
22
|
-
# be delivered "behind your back" while you're in an event handler. If you're
|
23
|
-
# comfortable with dealing with threads and concurrency, then feel free to
|
24
|
-
# set the `:threadpool_size` option to the constructor to a value you feel is
|
25
|
-
# correct for your app.
|
26
|
-
#
|
27
18
|
# If you use the threadpool/event callbacks to perform work, you may be
|
28
19
|
# interested in registering an `on_exception` callback that will receive
|
29
20
|
# all exceptions that occur on the threadpool that are not handled (i.e.
|
30
21
|
# that bubble up to top of a block).
|
31
22
|
#
|
32
|
-
# It is recommended that you not run any possibly long-running work on the
|
33
|
-
# event threadpool, as `close!` will attempt to shutdown the threadpool, and
|
34
|
-
# **WILL NOT WAIT FOREVER**. (TODO: more on this)
|
35
23
|
#
|
36
24
|
# @example Register on_connected callback.
|
37
25
|
#
|
@@ -67,8 +55,18 @@ module ZK
|
|
67
55
|
# @note The documentation for 0.9.0 was incorrect in stating the number
|
68
56
|
# of threads used to deliver events. There was one, unconfigurable,
|
69
57
|
# event dispatch thread. In 1.0 the number of event delivery threads is
|
70
|
-
# configurable, but still defaults to 1
|
71
|
-
#
|
58
|
+
# configurable, but still defaults to 1 and users are discouraged from
|
59
|
+
# adjusting the value due to the complexity this introduces. In 1.1
|
60
|
+
# there is a better option for achieving higher concurrency (see the
|
61
|
+
# `:thread` option)
|
62
|
+
#
|
63
|
+
# The Management apologizes for any confusion this may have caused.
|
64
|
+
#
|
65
|
+
# @since __1.1__: Instead of adjusting the threadpool, users are _strongly_ encouraged
|
66
|
+
# to use the `:thread => :per_callback` option to increase the
|
67
|
+
# parallelism of event delivery safely and sanely. Please see
|
68
|
+
# [this wiki article](https://github.com/slyphon/zk/wiki/EventDeliveryModel) for more
|
69
|
+
# information and a demonstration.
|
72
70
|
#
|
73
71
|
# @param [String] host (see ZK::Client::Base#initialize)
|
74
72
|
#
|
@@ -77,13 +75,34 @@ module ZK
|
|
77
75
|
# case of an expired session, we will keep trying to reestablish the
|
78
76
|
# connection.
|
79
77
|
#
|
80
|
-
# @option opts [
|
81
|
-
#
|
82
|
-
#
|
83
|
-
#
|
78
|
+
# @option opts [:single,:per_callback] :thread (:single) choose your event
|
79
|
+
# delivery model:
|
80
|
+
#
|
81
|
+
# * `:single`: There is one thread, and only one callback is called at
|
82
|
+
# a time. This is the default mode (for now), and will provide the most
|
83
|
+
# safety for your app. All events will be delivered as received, to
|
84
|
+
# callbacks in the order they were registered. This safety has the
|
85
|
+
# tradeoff that if one of your callbacks performs some action that blocks
|
86
|
+
# the delivery thread, you will not recieve other events until it returns.
|
87
|
+
# You're also limiting the concurrency of your app. This should be fine
|
88
|
+
# for most simple apps, and is a good choice to start with when
|
89
|
+
# developing your application
|
90
|
+
#
|
91
|
+
# * `:per_callback`: This option will use a new-style Actor model (inspired by
|
92
|
+
# [Celluloid](https://github.com/celluloid/celluloid)) that uses a
|
93
|
+
# per-callback queue and thread to allow for greater concurrency in
|
94
|
+
# your app, whille still maintaining some kind of sanity. By choosing
|
95
|
+
# this option your callbacks will receive events in order, and will
|
96
|
+
# receive only one at a time, but in parallel with other callbacks.
|
97
|
+
# This model has the advantage you can have all of your callbacks
|
98
|
+
# making progress in parallel, and if one of them happens to block,
|
99
|
+
# it will not affect the others.
|
100
|
+
#
|
101
|
+
# * see {https://github.com/slyphon/zk/wiki/EventDeliveryModel the wiki} for a
|
102
|
+
# discussion and demonstration of the effect of this setting.
|
84
103
|
#
|
85
104
|
# @option opts [Fixnum] :timeout how long we will wait for the connection
|
86
|
-
# to be established. If timeout is nil, we will wait forever *use
|
105
|
+
# to be established. If timeout is nil, we will wait forever: *use
|
87
106
|
# carefully*.
|
88
107
|
#
|
89
108
|
# @yield [self] calls the block with the new instance after the event
|
@@ -101,7 +120,7 @@ module ZK
|
|
101
120
|
@threadpool = Threadpool.new(tp_size)
|
102
121
|
|
103
122
|
@session_timeout = opts.fetch(:timeout, DEFAULT_TIMEOUT) # maybe move this into superclass?
|
104
|
-
@event_handler = EventHandler.new(self)
|
123
|
+
@event_handler = EventHandler.new(self, opts)
|
105
124
|
|
106
125
|
@reconnect = opts.fetch(:reconnect, true)
|
107
126
|
|