zk 1.5.2 → 1.5.3

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.
data/Guardfile CHANGED
@@ -26,11 +26,20 @@ guard 'rspec', :version => 2 do
26
26
  when %r{^(?:zk/locker/locker_base|spec/shared/locker)}
27
27
  Dir["spec/zk/locker/*_spec.rb"]
28
28
 
29
+ when %r{^zk/client/(?:base|state_mixin)}
30
+ Dir['spec/zk/{client,client/*,zookeeper}_spec.rb']
31
+
29
32
  when 'zk' # .rb
30
33
  'spec' # run all tests
31
34
 
32
35
  else
33
- "spec/#{m[1]}_spec.rb"
36
+ generic = "spec/#{m[1]}_spec.rb"
37
+ if test(?f, generic)
38
+ generic
39
+ else
40
+ $stderr.puts "RUNNING ALL TESTS"
41
+ 'spec'
42
+ end
34
43
  end
35
44
  end
36
45
 
@@ -51,7 +51,7 @@ module ZK
51
51
  # the wrapped connection object
52
52
  # @private
53
53
  attr_reader :cnx
54
- protected :cnx
54
+ private :cnx
55
55
 
56
56
  # maps from a symbol given as an option, to the numeric error constant that should
57
57
  # not raise an exception
@@ -1020,7 +1020,7 @@ module ZK
1020
1020
  def raw_event_handler(event)
1021
1021
  end
1022
1022
 
1023
- protected
1023
+ private
1024
1024
  # does the current pid match the one that created us?
1025
1025
  def forked?
1026
1026
  Process.pid != @pid
@@ -1038,7 +1038,6 @@ module ZK
1038
1038
  check_rc(rv, opts)
1039
1039
  end
1040
1040
 
1041
- # @private
1042
1041
  # XXX: make this actually call the method on cnx
1043
1042
  def check_rc(rv_hash, inputs)
1044
1043
  code = rv_hash[:rc]
@@ -1078,7 +1077,6 @@ module ZK
1078
1077
  Set.new(ERROR_IGNORE_MAP.values_at(*sym_array))
1079
1078
  end
1080
1079
 
1081
- # @private
1082
1080
  def setup_watcher!(watch_type, opts, &b)
1083
1081
  event_handler.setup_watcher!(watch_type, opts, &b)
1084
1082
  end
@@ -78,7 +78,7 @@ module ZK
78
78
  watcher.register_state_handler(:expired_session, &block)
79
79
  end
80
80
 
81
- protected
81
+ private
82
82
  def wrap_state_closed_error
83
83
  yield
84
84
  rescue RuntimeError => e
@@ -45,10 +45,10 @@ module ZK
45
45
 
46
46
  # @private
47
47
  module Constants
48
- CLI_RUNNING = :running
49
- CLI_PAUSED = :paused
50
- CLI_CLOSE_REQ = :close_requested
51
- CLI_CLOSED = :closed
48
+ RUNNING = :running
49
+ PAUSED = :paused
50
+ CLOSE_REQ = :close_requested
51
+ CLOSED = :closed
52
52
  end
53
53
  include Constants
54
54
 
@@ -161,13 +161,12 @@ module ZK
161
161
 
162
162
  @reconnect = opts.fetch(:reconnect, true)
163
163
 
164
- @mutex = Monitor.new
165
- @cond = @mutex.new_cond
164
+ setup_locks
166
165
 
167
- @cli_state = CLI_RUNNING # this is to distinguish between *our* state and the underlying connection state
166
+ @client_state = RUNNING # this is to distinguish between *our* state and the underlying connection state
168
167
 
169
168
  # this is the last status update we've received from the underlying connection
170
- @last_cnx_state = Zookeeper::ZOO_CLOSED_STATE
169
+ @last_cnx_state = nil
171
170
 
172
171
  @retry_duration = opts.fetch(:retry_duration, nil).to_i
173
172
 
@@ -183,6 +182,15 @@ module ZK
183
182
 
184
183
  connect if opts.fetch(:connect, true)
185
184
  end
185
+
186
+ # ensure that the initializer and the reopen code set up the mutexes
187
+ # the same way (i.e. use a Monitor or a Mutex, no, really, I screwed
188
+ # this up once)
189
+ def setup_locks
190
+ @mutex = Monitor.new
191
+ @cond = @mutex.new_cond
192
+ end
193
+ private :setup_locks
186
194
 
187
195
  # @private
188
196
  def self.finalizer(hooks)
@@ -206,14 +214,18 @@ module ZK
206
214
 
207
215
  logger.debug { "reopening everything, fork detected!" }
208
216
 
209
- @mutex = Mutex.new
210
- @cond = ConditionVariable.new
217
+ setup_locks
218
+
211
219
  @pid = Process.pid
212
- @cli_state = CLI_RUNNING # reset state to running if we were paused
220
+ @client_state = RUNNING # reset state to running if we were paused
213
221
 
214
222
  old_cnx, @cnx = @cnx, nil
215
223
  old_cnx.close! if old_cnx # && !old_cnx.closed?
216
224
 
225
+ join_and_clear_reconnect_thread
226
+
227
+ @last_cnx_state = nil
228
+
217
229
  @mutex.synchronize do
218
230
  # it's important that we're holding the lock, as access to 'cnx' is
219
231
  # synchronized, and we want to avoid a race where event handlers
@@ -228,11 +240,12 @@ module ZK
228
240
  end
229
241
  else
230
242
  @mutex.synchronize do
231
- if @cli_state == CLI_PAUSED
243
+ if @client_state == PAUSED
232
244
  # XXX: what to do in this case? does it matter?
233
245
  end
234
246
 
235
247
  logger.debug { "reopening, no fork detected" }
248
+ @last_cnx_state = nil
236
249
  @cnx.reopen(timeout) # ok, we werent' forked, so just reopen
237
250
  end
238
251
  end
@@ -252,30 +265,37 @@ module ZK
252
265
  # @private
253
266
  def pause_before_fork_in_parent
254
267
  @mutex.synchronize do
255
- raise InvalidStateError, "client must be running? when you call #{__method__}" unless (@cli_state == CLI_RUNNING)
256
- @cli_state = CLI_PAUSED
268
+ raise InvalidStateError, "client must be running? when you call #{__method__}" unless (@client_state == RUNNING)
269
+ @client_state = PAUSED
257
270
 
258
271
  logger.debug { "#{self.class}##{__method__}" }
259
272
 
260
273
  @cond.broadcast
261
274
  end
262
275
 
276
+ join_and_clear_reconnect_thread
277
+
263
278
  # the compact is here because the @cnx *may* be nil when this callback is fired by the
264
279
  # ForkHook (in the case of ZK.open). The race is between the GC calling the finalizer
265
280
  [@event_handler, @threadpool, @cnx].compact.each(&:pause_before_fork_in_parent)
266
281
  ensure
267
- logger.debug { "#{self.class}##{__method__} returning" }
282
+ logger.debug { "##{__method__} returning" }
268
283
  end
269
284
 
270
285
  # @private
271
286
  def resume_after_fork_in_parent
272
287
  @mutex.synchronize do
273
- raise InvalidStateError, "client must be paused? when you call #{__method__}" unless (@cli_state == CLI_PAUSED)
274
- @cli_state = CLI_RUNNING
288
+ raise InvalidStateError, "client must be paused? when you call #{__method__}" unless (@client_state == PAUSED)
289
+ @client_state = RUNNING
275
290
 
276
- logger.debug { "#{self.class}##{__method__}" }
291
+ logger.debug { "##{__method__}" }
277
292
 
278
- [@cnx, @event_handler, @threadpool].compact.each(&:resume_after_fork_in_parent)
293
+ if @cnx
294
+ @cnx.resume_after_fork_in_parent
295
+ spawn_reconnect_thread
296
+ end
297
+
298
+ [@event_handler, @threadpool].compact.each(&:resume_after_fork_in_parent)
279
299
 
280
300
  @cond.broadcast
281
301
  end
@@ -291,12 +311,14 @@ module ZK
291
311
  #
292
312
  def close!
293
313
  @mutex.synchronize do
294
- return if [:closed, :close_requested].include?(@cli_state)
314
+ return if [:closed, :close_requested].include?(@client_state)
295
315
  logger.debug { "moving to :close_requested state" }
296
- @cli_state = CLI_CLOSE_REQ
316
+ @client_state = CLOSE_REQ
297
317
  @cond.broadcast
298
318
  end
299
319
 
320
+ join_and_clear_reconnect_thread
321
+
300
322
  on_tpool = on_threadpool?
301
323
 
302
324
  # Ok, so the threadpool will wait up to N seconds while joining each thread.
@@ -308,6 +330,7 @@ module ZK
308
330
  # and wait for it to exit
309
331
  #
310
332
  shutdown_thread = Thread.new do
333
+ Thread.current[:name] = 'shutdown'
311
334
  @threadpool.shutdown(10)
312
335
 
313
336
  # this will call #close
@@ -315,7 +338,8 @@ module ZK
315
338
 
316
339
  @mutex.synchronize do
317
340
  logger.debug { "moving to :closed state" }
318
- @cli_state = CLI_CLOSED
341
+ @client_state = CLOSED
342
+ @last_cnx_state = nil
319
343
  @cond.broadcast
320
344
  end
321
345
  end
@@ -348,15 +372,6 @@ module ZK
348
372
  @mutex.synchronize do
349
373
  @last_cnx_state = event.state
350
374
 
351
- if event.client_invalid? and @reconnect and not dead_or_dying?
352
- logger.error { "Got event #{event.state_name}, calling reopen(0)! things may be messed up until this works itself out!" }
353
-
354
- # reopen(0) means that we don't want to wait for the connection
355
- # to reach the connected state before returning as we're on the
356
- # event thread.
357
- reopen(0)
358
- end
359
-
360
375
  @cond.broadcast # wake anyone waiting for a connection state update
361
376
  end
362
377
  rescue Exception => e
@@ -364,26 +379,47 @@ module ZK
364
379
  end
365
380
 
366
381
  def closed?
367
- return true if @mutex.synchronize { @cli_state == CLI_CLOSED }
382
+ return true if @mutex.synchronize { @client_state == CLOSED }
368
383
  super
369
384
  end
370
385
 
371
386
  # are we in running (not-paused) state?
387
+ # @private
372
388
  def running?
373
- @mutex.synchronize { @cli_state == CLI_RUNNING }
389
+ @mutex.synchronize { @client_state == RUNNING }
374
390
  end
375
391
 
376
392
  # are we in paused state?
393
+ # @private
377
394
  def paused?
378
- @mutex.synchronize { @cli_state == CLI_PAUSED }
395
+ @mutex.synchronize { @client_state == PAUSED }
379
396
  end
380
397
 
381
398
  # has shutdown time arrived?
399
+ # @private
382
400
  def close_requested?
383
- @mutex.synchronize { @cli_state == CLI_CLOSE_REQ }
401
+ @mutex.synchronize { @client_state == CLOSE_REQ }
384
402
  end
385
403
 
386
- protected
404
+ # @private
405
+ def wait_until_connected_or_dying(timeout)
406
+ time_to_stop = Time.now + timeout
407
+
408
+ @mutex.synchronize do
409
+ while (@last_cnx_state != Zookeeper::ZOO_CONNECTED_STATE) && (Time.now < time_to_stop) && (@client_state == RUNNING)
410
+ @cond.wait(timeout)
411
+ end
412
+
413
+ logger.debug { "@last_cnx_state: #{@last_cnx_state.inspect}, time_left? #{Time.now.to_f < time_to_stop.to_f}, @client_state: #{@client_state.inspect}" }
414
+ end
415
+ end
416
+
417
+ private
418
+ # this is just here so we can see it in stack traces
419
+ def reopen_after_session_expired
420
+ reopen
421
+ end
422
+
387
423
  # in the threaded version of the client, synchronize access around cnx
388
424
  # so that callers don't wind up with a nil object when we're in the middle
389
425
  # of reopening it
@@ -391,6 +427,58 @@ module ZK
391
427
  @mutex.synchronize { @cnx }
392
428
  end
393
429
 
430
+ def reconnect_thread_body
431
+ Thread.current[:name] = 'reconnect'
432
+ while @reconnect # too clever?
433
+ @mutex.synchronize do
434
+ # either we havne't seen a valid session update from this
435
+ # connection yet, or we're doing fine, so just wait
436
+ @cond.wait_while { !seen_session_state_event? or (valid_session_state? and (@client_state == RUNNING)) }
437
+
438
+ # we've entered into a non-running state, so we exit
439
+ # note: need to restart this thread after a fork in parent
440
+ if @client_state != RUNNING
441
+ logger.debug { "session failure watcher thread exiting, @client_state: #{@client_state}" }
442
+ return
443
+ end
444
+
445
+ # if we know that this session was valid once and it has now
446
+ # become invalid we call reopen
447
+ #
448
+ if seen_session_state_event? and not valid_session_state?
449
+ logger.debug { "session state was invalid, calling reopen" }
450
+
451
+ # reopen will reset @last_cnx_state so that
452
+ # seen_session_state_event? will return false until the first
453
+ # event has been delivered on the new connection
454
+ rv = reopen_after_session_expired
455
+
456
+ logger.debug { "reopen returned: #{rv.inspect}" }
457
+ end
458
+ end
459
+ end
460
+ ensure
461
+ logger.debug { "reconnect thread exiting" }
462
+ end
463
+
464
+ def join_and_clear_reconnect_thread
465
+ return unless @reconnect_thread
466
+ begin
467
+ # this should never time out but, just to make sure we don't hang forever
468
+ unless @reconnect_thread.join(30)
469
+ logger.error { "timed out waiting for reconnect thread to join! something is hosed!" }
470
+ end
471
+ rescue Exception => e
472
+ logger.error { "caught exception joining reconnect thread" }
473
+ logger.error { e.to_std_format }
474
+ end
475
+ @reconnect_thread = nil
476
+ end
477
+
478
+ def spawn_reconnect_thread
479
+ @reconnect_thread ||= Thread.new(&method(:reconnect_thread_body))
480
+ end
481
+
394
482
  def call_and_check_rc(meth, opts)
395
483
  if retry_duration = (opts.delete(:retry_duration) || @retry_duration)
396
484
  begin
@@ -400,7 +488,7 @@ module ZK
400
488
 
401
489
  wait_until_connected_or_dying(retry_duration)
402
490
 
403
- if (@last_cnx_state != Zookeeper::ZOO_CONNECTED_STATE) || (Time.now > time_to_stop) || (@cli_state != CLI_RUNNING)
491
+ if (@last_cnx_state != Zookeeper::ZOO_CONNECTED_STATE) || (Time.now > time_to_stop) || (@client_state != RUNNING)
404
492
  raise e
405
493
  else
406
494
  retry
@@ -411,16 +499,20 @@ module ZK
411
499
  end
412
500
  end
413
501
 
414
- def wait_until_connected_or_dying(timeout)
415
- time_to_stop = Time.now + timeout
416
-
417
- @mutex.synchronize do
418
- while (@last_cnx_state != Zookeeper::ZOO_CONNECTED_STATE) && (Time.now < time_to_stop) && (@cli_state == CLI_RUNNING)
419
- @cond.wait(timeout)
420
- end
502
+ # have we gotten a status event for the current connection?
503
+ # this method is not synchronized
504
+ def seen_session_state_event?
505
+ !!@last_cnx_state
506
+ end
421
507
 
422
- logger.debug { "@last_cnx_state: #{@last_cnx_state}, time_left? #{Time.now.to_f < time_to_stop.to_f}, @cli_state: #{@cli_state.inspect}" }
423
- end
508
+ # we've seen a session state from the cnx, and it was not "omg we're screwed"
509
+ # will return false if we havne't gotten a session event yet
510
+ #
511
+ # this method is not synchronized
512
+ def valid_session_state?
513
+ # this is kind of icky, but the SESSION_INVALID and AUTH_FAILED states
514
+ # are both negative numbers
515
+ @last_cnx_state and (@last_cnx_state >= 0)
424
516
  end
425
517
 
426
518
  def create_connection(*args)
@@ -428,14 +520,14 @@ module ZK
428
520
  end
429
521
 
430
522
  def dead_or_dying?
431
- (@cli_state == CLI_CLOSE_REQ) || (@cli_state == CLI_CLOSED)
523
+ (@client_state == CLOSE_REQ) || (@client_state == CLOSED)
432
524
  end
433
525
 
434
- private
435
526
  def unlocked_connect(opts={})
436
527
  return if @cnx
437
528
  timeout = opts.fetch(:timeout, @connection_timeout)
438
529
  @cnx = create_connection(@host, timeout, @event_handler.get_default_watcher_block)
530
+ spawn_reconnect_thread
439
531
  end
440
532
  end
441
533
  end
data/lib/zk/election.rb CHANGED
@@ -150,7 +150,7 @@ module ZK
150
150
  end
151
151
  end
152
152
 
153
- protected
153
+ private
154
154
  def create_root_path!
155
155
  @zk.mkdir_p(root_vote_path)
156
156
  end
@@ -244,7 +244,7 @@ module ZK
244
244
  end
245
245
  end
246
246
 
247
- protected
247
+ private
248
248
  # the inauguration, as it were
249
249
  def acknowledge_win!
250
250
  @zk.create(leader_ack_path, @data, :ephemeral => true)
@@ -411,7 +411,7 @@ module ZK
411
411
  end
412
412
  end
413
413
 
414
- protected
414
+ private
415
415
  def the_king_is_dead
416
416
  synchronize do
417
417
  safe_call(*@leader_death_cbs)
@@ -196,7 +196,6 @@ module ZK
196
196
  end
197
197
 
198
198
  public
199
-
200
199
  # used during shutdown to clear registered listeners
201
200
  # @private
202
201
  def clear! #:nodoc:
@@ -303,13 +302,11 @@ module ZK
303
302
  end
304
303
  end
305
304
 
306
- protected
307
- # @private
305
+ private
308
306
  def watcher_callback
309
307
  Zookeeper::Callbacks::WatcherCallback.create { |event| process(event) }
310
308
  end
311
309
 
312
- # @private
313
310
  def state_key(arg)
314
311
  int =
315
312
  case arg
@@ -326,7 +323,6 @@ module ZK
326
323
  raise ArgumentError, "#{arg} is not a valid zookeeper state", caller
327
324
  end
328
325
 
329
- # @private
330
326
  def safe_call(callbacks, *args)
331
327
  callbacks.each do |cb|
332
328
  next unless cb.respond_to?(:call)
@@ -52,7 +52,7 @@ module ZK
52
52
  def resume_after_fork_in_parent
53
53
  end
54
54
 
55
- protected
55
+ private
56
56
  def prep_interests(a)
57
57
  # logger.debug { "prep_interests: #{a.inspect}" }
58
58
  return ALL_EVENT_SET if a.nil?
@@ -53,7 +53,7 @@ module ZK
53
53
  true
54
54
  end
55
55
 
56
- protected
56
+ private
57
57
  # the node that is next-lowest in sequence number to ours, the one we
58
58
  # watch for updates to
59
59
  def next_lowest_node
@@ -230,7 +230,7 @@ module ZK
230
230
  end
231
231
  end
232
232
 
233
- protected
233
+ private
234
234
  def synchronize
235
235
  @mutex.synchronize { yield }
236
236
  end
@@ -92,7 +92,7 @@ module ZK
92
92
  end
93
93
  alias got_lock? got_read_lock?
94
94
 
95
- protected
95
+ private
96
96
  # TODO: make this generic, can either block or non-block
97
97
  def block_until_read_lock!
98
98
  begin
data/lib/zk/mongoid.rb CHANGED
@@ -118,6 +118,7 @@ module ZK
118
118
  Thread.current.zk_mongoid_lock_registry ||= { :shared => Set.new, :exclusive => Set.new }
119
119
  end
120
120
 
121
+ private
121
122
  def zk_add_path_lock(opts={})
122
123
  mode, name = opts.values_at(:mode, :name)
123
124
 
data/lib/zk/pool.rb CHANGED
@@ -140,7 +140,7 @@ module ZK
140
140
  @state
141
141
  end
142
142
 
143
- protected
143
+ private
144
144
  def synchronize
145
145
  @mutex.synchronize { yield }
146
146
  end
@@ -255,7 +255,7 @@ module ZK
255
255
  @mutex.synchronize { @connections.size < @max_clients }
256
256
  end
257
257
 
258
- protected
258
+ private
259
259
  def populate_pool!(num_cnx)
260
260
  num_cnx.times { add_connection! }
261
261
  end
@@ -54,7 +54,7 @@ module ZK
54
54
  @mutex = Monitor.new
55
55
  end
56
56
 
57
- protected
57
+ private
58
58
  def synchronize
59
59
  @mutex.synchronize { yield }
60
60
  end
@@ -116,7 +116,7 @@ module ZK
116
116
  end
117
117
  end
118
118
 
119
- protected
119
+ private
120
120
  # intentionally *not* synchronized
121
121
  def spawn_dispatch_thread
122
122
  @thread = Thread.new(&method(:dispatch_thread_body))
@@ -133,7 +133,7 @@ module ZK
133
133
  @cond.wait(@mutex) while @array.empty? and @state == :running
134
134
 
135
135
  if @state != :running
136
- logger.warn { "ThreadedCallback, state is #{@state.inspect}, returning" }
136
+ logger.debug { "ThreadedCallback, state is #{@state.inspect}, returning" }
137
137
  return
138
138
  end
139
139
 
data/lib/zk/version.rb CHANGED
@@ -1,3 +1,3 @@
1
1
  module ZK
2
- VERSION = "1.5.2"
2
+ VERSION = "1.5.3"
3
3
  end
@@ -24,16 +24,11 @@ shared_context 'threaded client connection' do
24
24
  # raise @threadpool_exception if @threadpool_exception
25
25
  # logger.debug { "threaded client connection - after hook" }
26
26
 
27
- if @zk.closed?
28
- logger.debug { "zk was closed, calling reopen" }
29
- @zk.reopen
30
- end
27
+ @zk.close! if @zk and not @zk.closed?
31
28
 
32
- wait_until(5) { @zk.connected? }
33
-
34
- @zk.rm_rf(@base_path)
35
- @zk.close!
36
- wait_until(5) { @zk.closed? }
29
+ ZK.open(*connection_args) do |z|
30
+ z.rm_rf(@base_path)
31
+ end
37
32
 
38
33
  # logger.debug { "threaded client connection - end after hook" }
39
34
  end
@@ -298,15 +298,20 @@ shared_examples_for 'client' do
298
298
 
299
299
  describe 'reconnection' do
300
300
  it %[should if it receives a client_invalid? event] do
301
- flexmock(@zk) do |m|
302
- m.should_receive(:reopen).with(0).once
303
- end
301
+ logger.debug { "about to cause the reconnection" }
304
302
 
305
303
  props = { :session_event? => true, :client_invalid? => true, :state_name => 'ZOO_EXPIRED_SESSION_STATE', :state => Zookeeper::ZOO_EXPIRED_SESSION_STATE }
306
304
 
307
305
  bogus_event = flexmock(:expired_session_event, props)
308
306
 
309
- @zk.raw_event_handler(bogus_event)
307
+ th = Thread.new do
308
+ @zk.raw_event_handler(bogus_event)
309
+ end
310
+
311
+ @zk.wait_until_connected_or_dying(5)
312
+ @zk.should be_connected
313
+
314
+ th.join(2).should == th
310
315
  end
311
316
  end # reconnection
312
317
 
data/spec/spec_helper.rb CHANGED
@@ -110,8 +110,10 @@ class ::Thread
110
110
  end
111
111
 
112
112
  if RUBY_VERSION == '1.9.3'
113
+ Thread.current[:name] = 'main'
114
+
113
115
  trap('USR1') do
114
- threads = Thread.list.map { |th| { :inspect => th.inspect, :calback => th[:callback], :backtrace => th.backtrace } }
116
+ threads = Thread.list.map { |th| { :inspect => th.inspect, :name => th[:name], :calback => th[:callback], :backtrace => th.backtrace } }
115
117
  pp threads
116
118
  end
117
119
  end
@@ -3,14 +3,13 @@ module ZK
3
3
 
4
4
  def self.logging_gem_setup
5
5
  layout = ::Logging.layouts.pattern(
6
- :pattern => '%.1l, [%d #%p] %30.30c{2}: %m\n',
7
- :date_pattern => '%Y-%m-%d %H:%M:%S.%6N'
6
+ :pattern => '%.1l, [%d #%p] (%9.9T) %25.25c{2}: %m\n',
7
+ :date_pattern => '%H:%M:%S.%6N'
8
8
  )
9
9
 
10
-
11
10
  appender = ENV['ZK_DEBUG'] ? ::Logging.appenders.stderr : ::Logging.appenders.file(ZK::TEST_LOG_PATH)
12
11
  appender.layout = layout
13
- appender.immediate_at = "debug,info,warn,error,fatal"
12
+ # appender.immediate_at = "debug,info,warn,error,fatal"
14
13
  # appender.auto_flushing = true
15
14
  appender.auto_flushing = 25
16
15
  appender.flush_period = 5
metadata CHANGED
@@ -1,13 +1,13 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: zk
3
3
  version: !ruby/object:Gem::Version
4
- hash: 7
4
+ hash: 5
5
5
  prerelease:
6
6
  segments:
7
7
  - 1
8
8
  - 5
9
- - 2
10
- version: 1.5.2
9
+ - 3
10
+ version: 1.5.3
11
11
  platform: ruby
12
12
  authors:
13
13
  - Jonathan D. Simms