Class: DripDrop::Message

Inherits:
Object
  • Object
show all
Defined in:
lib/dripdrop/message.rb

Overview

DripDrop::Message messages are exchanged between all tiers in the architecture A Message is composed of a name, head, and body, and should be restricted to types that can be readily encoded to JSON. name: Any string head: A hash containing anything (should be used for metadata) body: anything you'd like, it can be null even

Hashes, arrays, strings, integers, symbols, and floats are probably what you should stick to. Internally, they're just stored using MsgPack, which is pretty much a super-fast, binary JSON

The basic message format is built to mimic HTTP (s/url_path/name/). Why? Because I'm a dumb web developer :) The name is kind of like the URL, its what kind of message this is, but it's a loose definition, use it as you see fit. head should be used for metadata, body for the actual data. These definitions are intentionally loose, because protocols tend to be used loosely.

Direct Known Subclasses

AutoMessageClass

Instance Attribute Summary collapse

Class Method Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(name, extra = {}) ⇒ Message

Creates a new message. example:

DripDrop::Message.new('mymessage', 'head' => {:timestamp => Time.now},
  :body => {:mykey => :myval,  :other_key => ['complex']})

Raises:

  • (ArgumentError)


36
37
38
39
40
41
42
43
44
45
# File 'lib/dripdrop/message.rb', line 36

def initialize(name,extra={})
  raise ArgumentError, "Message names may not be empty or null!" if name.nil? || name.empty?

  @head = extra[:head] || extra['head'] || {}
  raise ArgumentError, "Invalid head #{@head}. Head must be a hash!" unless @head.is_a?(Hash)
  @head['message_class'] = self.class.to_s

  @name = name
  @body = extra[:body] || extra['body']
end

Instance Attribute Details

#bodyObject

Returns the value of attribute body



30
31
32
# File 'lib/dripdrop/message.rb', line 30

def body
  @body
end

#headObject

Returns the value of attribute head



30
31
32
# File 'lib/dripdrop/message.rb', line 30

def head
  @head
end

#nameObject

Returns the value of attribute name



30
31
32
# File 'lib/dripdrop/message.rb', line 30

def name
  @name
end

Class Method Details

.constantize(str) ⇒ Object



107
108
109
110
111
112
113
114
115
# File 'lib/dripdrop/message.rb', line 107

def self.constantize(str)
  begin
    str.split('::').inject(Object) {|memo,name|
      memo =  memo.const_get(name); memo
    }
  rescue NameError => e
    nil
  end
end

.create_message(*args) ⇒ Object



73
74
75
76
77
78
# File 'lib/dripdrop/message.rb', line 73

def self.create_message(*args)
  case args[0]
    when Hash then self.from_hash(args[0])
    else self.new(args)
  end
end

.decode(msg) ⇒ Object

Parses an already encoded string



92
93
94
95
96
97
# File 'lib/dripdrop/message.rb', line 92

def self.decode(msg)
  return nil if msg.nil? || msg.empty?

  decoded = JSON.parse(msg)
  self.recreate_message(decoded)
end

.decode_json(str) ⇒ Object

(Deprecated) Decodes a string containing a JSON representation of a message



103
104
105
# File 'lib/dripdrop/message.rb', line 103

def self.decode_json(str)
  self.decode(str)
end

.from_hash(hash) ⇒ Object

Build a new Message from a hash that looks like

{:name => name, :body => body, 'head' => head}


67
68
69
70
71
# File 'lib/dripdrop/message.rb', line 67

def self.from_hash(hash)
  self.new(hash[:name] || hash['name'], 
           :head => hash[:head] || hash['head'],
           :body => hash[:body] || hash['body'])
end

.parse(msg) ⇒ Object

(Deprecated). Use decode instead



100
# File 'lib/dripdrop/message.rb', line 100

def self.parse(msg); self.decode(msg) end

.recreate_message(hash) ⇒ Object

Raises:

  • (ArgumentError)


80
81
82
83
84
85
86
87
88
89
# File 'lib/dripdrop/message.rb', line 80

def self.recreate_message(hash)
  raise ArgumentError, "Message missing head: #{hash.inspect}" unless hash['head']
   
  klass = (hash['head'] && hash['head']['message_class']) ? constantize(hash['head']['message_class']) : nil
  if klass && (!(klass == self) && !self.subclasses.include?(klass))
    raise DripDrop::WrongMessageClassError, "Wrong message class '#{klass}', expected '#{self}' for message #{hash.inspect}"
  end
   
  klass ? klass.from_hash(hash) : self.from_hash(hash)
end

.subclasses(direct = false) ⇒ Object

Used for reconstructing messages



118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
# File 'lib/dripdrop/message.rb', line 118

def self.subclasses(direct = false)
  classes = []
  if direct
    ObjectSpace.each_object(Class) do |c|
      next unless c.superclass == self
      classes << c
    end
  else
    ObjectSpace.each_object(Class) do |c|
      next unless c.ancestors.include?(self) and (c != self)
      classes << c
    end
  end
  classes
end

Instance Method Details

#encode_jsonObject

(Deprecated, use json_encoded)



57
# File 'lib/dripdrop/message.rb', line 57

def encode_json; json_encoded; end

#encodedObject

The encoded message, ready to be sent across the wire via ZMQ



48
49
50
# File 'lib/dripdrop/message.rb', line 48

def encoded
  self.to_hash.to_json
end

#json_encodedObject

(Deprecated) Encodes the hash represntation of the message to JSON



53
54
55
# File 'lib/dripdrop/message.rb', line 53

def json_encoded
  encoded
end

#to_hashObject

Convert the Message to a hash like: => @name, 'head' => @head, 'body' => @body



61
62
63
# File 'lib/dripdrop/message.rb', line 61

def to_hash
  {'name' => @name, 'head' => @head, 'body' => @body}
end