Class: ZK::ZKEventMachine::Callback::Base

Inherits:
Object
  • Object
show all
Includes:
Deferred, Logging
Defined in:
lib/z_k/z_k_event_machine/callback.rb

Overview

Used by ZooKeeper to return an asynchronous result.

If callbacks or errbacks are set on the instance, they will be called with just the data returned from the call (much like their synchronous versions).

If a block was given to #new or #on_result, then that block is called with a ZK::Exceptions::KeeperException instance or nil, then the rest of the arguments defined for that callback type

the node-style and deferred-style results are NOT exclusive, so if you use both _you will be called with results in both formats_.

Instance Attribute Summary collapse

Class Method Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(prok = nil, &block) ⇒ Base

Returns a new instance of Base.



42
43
44
# File 'lib/z_k/z_k_event_machine/callback.rb', line 42

def initialize(prok=nil, &block)
  on_result(prok, &block)
end

Instance Attribute Details

#contextObject

save a context object, used for associating delivered events with the request that created them



37
38
39
# File 'lib/z_k/z_k_event_machine/callback.rb', line 37

def context
  @context
end

#req_idObject (readonly)

saves the request id of this call



40
41
42
# File 'lib/z_k/z_k_event_machine/callback.rb', line 40

def req_id
  @req_id
end

Class Method Details

.async_result_keys(*syms) ⇒ Object

set the result keys that should be used by node_style_result and to call the deferred_style_result blocks



28
29
30
31
32
33
34
# File 'lib/z_k/z_k_event_machine/callback.rb', line 28

def self.async_result_keys(*syms)
  if syms.empty? 
    @async_result_keys || []
  else
    @async_result_keys = syms.map { |n| n.to_sym }
  end
end

Instance Method Details

#async_result_keysObject (protected)



136
137
138
# File 'lib/z_k/z_k_event_machine/callback.rb', line 136

def async_result_keys
  self.class.async_result_keys
end

#call(result) ⇒ Object

ZK will call this instance with a hash of data, which is the result of the asynchronous call. Depending on the style of callback in use, we take the appropriate actions

delegates to #deferred_style_result and #node_style_result



71
72
73
74
75
76
77
# File 'lib/z_k/z_k_event_machine/callback.rb', line 71

def call(result)
  logger.debug { "\n#{self.class.name}##{__method__}\n\treq_id: #{req_id.inspect}\n\tcontext: #{context.inspect}\n\tresult: #{result.inspect}" }
  EM.schedule do
    deferred_style_result(result) 
    node_style_result(result)
  end
end

#check_async_rc(hash) ⇒ Object

Checks the return code from the async call. If the return code was not ZOK, then fire the errbacks and do the node-style error call otherwise, does nothing

in this call we also stash the outgoing req_id so we can sync it up



60
61
62
63
64
# File 'lib/z_k/z_k_event_machine/callback.rb', line 60

def check_async_rc(hash)
  @req_id = hash[:req_id]
  logger.debug { "#{__method__}: got #{hash.inspect}" } 
  call(hash) unless success?(hash)
end

#deferred_style_result(hash) ⇒ Object

This method is abstract.

should call set_deferred_status with the appropriate args for the result and type of call



109
110
111
112
113
114
115
116
117
118
119
# File 'lib/z_k/z_k_event_machine/callback.rb', line 109

def deferred_style_result(hash)
  # ensure this calls the callback on the reactor

  if success?(hash)
    vals = hash.values_at(*async_result_keys)
#             logger.debug { "#{self.class.name}#deferred_style_result async_result_keys: #{async_result_keys.inspect}, vals: #{vals.inspect}" }
    self.succeed(*hash.values_at(*async_result_keys))
  else
    self.fail(exception_for(hash))
  end
end

#exception_for(hash) ⇒ ZK::Exceptions::KeeperException?

Returns an instance of a sublcass ZK::Exceptions::KeeperException based on the asynchronous return_code.

facilitates using case statements for error handling

Parameters:

  • hash (Hash)

    the result of the async call

Returns:

  • (ZK::Exceptions::KeeperException, nil)

    subclass based on return_code if there was an error, nil otherwise

Raises:

  • (RuntimeError)

    if the return_code is not known by ZK (this should never happen and if it does, you should report a bug)



101
102
103
104
105
# File 'lib/z_k/z_k_event_machine/callback.rb', line 101

def exception_for(hash)
  return nil if success?(hash)
  return_code = hash.fetch(:rc)
  ZK::Exceptions::KeeperException.by_code(return_code).new
end

#node_style_result(hash) ⇒ Object

call the user block with the correct Exception class as the first arg (or nil if no error) and then the appropriate args for the type of asynchronous call



124
125
126
127
128
129
130
131
132
133
# File 'lib/z_k/z_k_event_machine/callback.rb', line 124

def node_style_result(hash)
  return unless @block
  vals = hash.values_at(*async_result_keys)
#           logger.debug { "#{self.class.name}#node_style_result async_result_keys: #{async_result_keys.inspect}, vals: #{vals.inspect}" }
  if exc = exception_for(hash)
    @block.call(exc)
  else
    @block.call(nil, *vals)
  end
end

#on_result(prok = nil, &block) ⇒ Object

Note:

replaces the block given to #new

register a block that should be called (node.js style) with the results



51
52
53
# File 'lib/z_k/z_k_event_machine/callback.rb', line 51

def on_result(prok=nil, &block)
  @block = (prok || block)
end

#success?(hash) ⇒ true, false

returns true if the request was successful (if return_code was Zookeeper::ZOK)

Parameters:

  • hash (Hash)

    the result of the async call

Returns:

  • (true, false)

    for success, failure



84
85
86
# File 'lib/z_k/z_k_event_machine/callback.rb', line 84

def success?(hash)
  hash[:rc] == Zookeeper::ZOK
end