Module: Perennial::Protocols::JSONTransport::MessageHandling

Defined in:
lib/perennial/protocols/json_transport.rb

Defined Under Namespace

Modules: ClassMethods

Class Method Summary collapse

Instance Method Summary collapse

Class Method Details

.included(parent) ⇒ Object



20
21
22
23
24
25
26
27
28
29
30
31
32
# File 'lib/perennial/protocols/json_transport.rb', line 20

def self.included(parent)
  parent.class_eval do
    cattr_accessor :event_handlers
    extend  ClassMethods
    self.event_handlers = Hash.new { |h,k| h[k] = [] }

    # Simple built in Methods, applicable both ways.
    on_action :exception,   :handle_exception
    on_action :noop,        :handle_noop
    on_action :enable_ssl,  :handle_enable_ssl
    on_action :enabled_ssl,  :handle_enabled_ssl
  end
end

Instance Method Details

#callback_id(base, count) ⇒ Object



130
131
132
# File 'lib/perennial/protocols/json_transport.rb', line 130

def callback_id(base, count)
  Digest::SHA256.hexdigest([base, count].compact.join("-"))
end

#callbacksObject



79
80
81
# File 'lib/perennial/protocols/json_transport.rb', line 79

def callbacks
  @callbacks ||= {}
end

#connected?Boolean

Returns:



83
84
85
# File 'lib/perennial/protocols/json_transport.rb', line 83

def connected?
  instance_variable_defined?(:@connected) && @connected
end

#handle_enable_ssl(data) ⇒ Object



61
62
63
64
# File 'lib/perennial/protocols/json_transport.rb', line 61

def handle_enable_ssl(data)
  reply :enabled_ssl
  enable_ssl
end

#handle_enabled_ssl(data) ⇒ Object



66
67
68
# File 'lib/perennial/protocols/json_transport.rb', line 66

def handle_enabled_ssl(data)
  enable_ssl
end

#handle_exception(data) ⇒ Object

A remote exception in the processing



75
76
77
# File 'lib/perennial/protocols/json_transport.rb', line 75

def handle_exception(data)
  logger.warn "Got exception from remote call of #{data["action"]}: #{data["message"]}"
end

#handle_noop(data) ⇒ Object

Do Nothing



71
72
# File 'lib/perennial/protocols/json_transport.rb', line 71

def handle_noop(data)
end

#handle_receiving_exception(e) ⇒ Object

Typically you'd log a backtrace



58
59
# File 'lib/perennial/protocols/json_transport.rb', line 58

def handle_receiving_exception(e)
end

#handle_response(response) ⇒ Object



87
88
89
90
91
92
93
94
# File 'lib/perennial/protocols/json_transport.rb', line 87

def handle_response(response)
  return unless response.is_a?(Hash) && response.has_key?("action")
  payload = response["payload"] || {}
  @callback_id = response.delete("callback-id")
  process_callback(payload)
  process_action(response["action"], payload)
  @callback_id = nil
end

#message(name, data = {}, &blk) ⇒ Object



42
43
44
45
46
47
48
49
50
# File 'lib/perennial/protocols/json_transport.rb', line 42

def message(name, data = {}, &blk)
  payload = {
    "action"  => name.to_s,
    "payload" => data,
    "sent-at" => Time.now
  }
  payload.merge!(options_for_callback(blk))
  send_message JSON.dump(payload)
end

#options_for_callback(blk) ⇒ Object



111
112
113
114
115
116
117
118
119
120
121
# File 'lib/perennial/protocols/json_transport.rb', line 111

def options_for_callback(blk)
  return {} if blk.nil?
  cb_id = "callback-#{self.object_id}-#{Time.now.to_f}"
  full_id, count = nil, 0
  while full_id.nil? || @callbacks.has_key?(full_id)
    count += 1
    full_id = callback_id(base, count)
  end
  self.callbacks[full_id] = blk
  {"callback-id" => full_id}
end

#process_action(name, data) ⇒ Object



96
97
98
99
100
101
102
103
104
105
106
107
108
109
# File 'lib/perennial/protocols/json_transport.rb', line 96

def process_action(name, data)
  self.event_handlers[name.to_s].each do |handler|
    if handler.respond_to?(:call)
      instance_exec(data, &handler)
    elsif handler.respond_to?(:handle)
      handler.handle(data)
    else
      self.send(handler, data)
    end
  end
rescue Exception => e
  reply :exception, :name => e.class.name, :message => e.message,
        :action => name, :payload => data
end

#process_callback(data) ⇒ Object



123
124
125
126
127
128
# File 'lib/perennial/protocols/json_transport.rb', line 123

def process_callback(data)
  if data.is_a?(Hash) && data.has_key?("callback-id")
    callback = @callbacks.delete(data["callback-id"])
    callback.call(self, data) if callback.present?
  end
end

#receive_message(line) ⇒ Object



34
35
36
37
38
39
40
# File 'lib/perennial/protocols/json_transport.rb', line 34

def receive_message(line)
  response = JSON.parse(line)
  handle_response(response)
rescue Exception => e
  # Typically a problem parsing JSON
  handle_receiving_exception(e)
end

#reply(name, data = {}, &blk) ⇒ Object



52
53
54
55
# File 'lib/perennial/protocols/json_transport.rb', line 52

def reply(name, data = {}, &blk)
  data = data.merge("callback-id" => @callback_id) if instance_variable_defined?(:@callback_id) && @callback_id.present?
  message(name, data, &blk)
end