Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with
or
.
Download ZIP
Browse files

Introduced Message and Reference classes: first alpha draft for the M…

…essage implementation, with serialization/deserialization
  • Loading branch information...
commit a58c09c4db9fb77bf49fe3b7a670b7a0002dc75f 1 parent 509d3df
@krakatoa krakatoa authored
View
60 lib/message.rb
@@ -1,23 +1,67 @@
+# Casos de uso
+#* normal serialization is done with msgpack
+#1) Create message with not serialized data: Header + Body.
+# => Message.new(from, to, respond_to, action, additionals)
+# > Message.header = Header
+# > Message.body = Body (with attrs loaded, not crypted, not normally serialized)
+#2) Serialize message: returns the serialized message, and sets the serialization flags on the Message instance.
+#3) Create message with normally serialized data:
+# => Message.parse(msg)
+# > Message.header = Header
+# > Message.body = Body (without attrs loaded, crypted/serialized string)
+#
+
+require './lib/message/header'
+require './lib/message/body'
+
module Cucub
class Message
- attr_reader :id
+
+ attr_reader :header
attr_reader :body
- def initialize(agent, id, body)
- @id = id
- @body = body
+ def initialize(opts={})
+ if opts.has_key?("header") && opts.has_key?("body")
+ @header = Cucub::Message::Header.parse(opts["header"])
+ @body = Cucub::Message::Body.load(opts["body"])
+ else
+ opts_for_header = opts.select{|key| ["from", "to", "respond_to"].include?(key)}
+ @header = Cucub::Message::Header.new(opts_for_header)
+ @body = Cucub::Message::Body.new(opts["action"], opts["additionals"])
+ end
end
- def self.encode(agent, id, body)
+ def serialize
{
- "id" => id,
- "body" => body
+ :header => @header.serialize,
+ :body => @body.serialize!
}.to_msgpack
end
+ def locked?
+ @body.locked?
+ end
+
+ def unlock(mechanism)
+ @body.unlock(mechanism)
+ end
+
+ def action
+ @body.action
+ end
+
+ def additionals
+ @body.additionals
+ end
+
+ def self.parse(msg)
+ hash = MessagePack.unpack(msg)
+ message = Cucub::Message.new(hash)
+ end
+
def self.decode(msg)
decoded = MessagePack.unpack(msg)
- return Cucub::Message.new(decoded["id"], decoded["body"])
+ return Cucub::Message.new(decoded["agent"], decoded["id"], decoded["body"])
end
end
end
View
65 lib/message/body.rb
@@ -0,0 +1,65 @@
+module Cucub
+ class Message
+ class Body
+
+ attr_reader :action
+ attr_reader :additionals
+
+ def initialize(action=nil, additionals=nil, serialized=nil)
+ @action = action
+ @additionals = additionals
+ @serialized = serialized
+ end
+
+ def self.attrs
+ [:action, :additionals]
+ end
+
+ def lock(&block)
+ puts "Locking..."
+ yield
+ @action = nil
+ @additionals = nil
+ end
+
+ def locked?
+ puts "Locked?: #{!(@serialized == nil)}"
+ !(@serialized == nil)
+ end
+
+ def serialize!
+ return @serialized unless @serialized == nil
+ lock {
+ @serialized = self.class.attrs.inject({}) { |h, attr|
+ value = instance_variable_get("@#{attr}")
+ h[attr] = value
+ h
+ }.to_msgpack
+ }
+ return @serialized
+ end
+
+ def self.load(body)
+ body = Cucub::Message::Body.new(nil, nil, body)
+ end
+
+ #def self.decode(serialized, decode_params={})
+ # decoded = MessagePack.unpack(msg)
+ # return Cucub::Body.new(decoded["action"], decoded["additionals"])
+ #end
+
+ def unlock(mechanism)
+ return false if not locked?
+ puts "Unlocking..."
+ case mechanism
+ when :msgpack
+ decoded = MessagePack.unpack(@serialized)
+ @action = decoded["action"]
+ @additionals = decoded["additionals"]
+ @serialized = nil
+ end
+ end
+
+ end
+ end
+end
View
41 lib/message/header.rb
@@ -0,0 +1,41 @@
+module Cucub
+ class Message
+ class Header
+
+ attr_reader :from
+ attr_reader :to
+ attr_reader :respond_to
+
+ def initialize(opts={})
+ @from = opts["from"]
+ @to = opts["to"]
+ @respond_to = opts["respond_to"]
+ end
+
+ def self.attrs
+ [:from, :to, :respond_to]
+ end
+
+ def serialize
+ self.class.attrs.inject({}) { |h, attr|
+ value = instance_variable_get("@#{attr}")
+ if value.is_a? Cucub::Reference
+ h[attr] = value.to_hash
+ elsif attr.is_a? String
+ h[attr] = value
+ end
+ h
+ }
+ end
+
+ def self.parse(hash)
+ Cucub::Message::Header.new(
+ "from" => Cucub::Reference.new(hash["from"]),
+ "to" => Cucub::Reference.new(hash["to"]),
+ "respond_to" => Cucub::Reference.new(hash["respond_to"])
+ )
+ end
+
+ end
+ end
+end
View
18 lib/reference.rb
@@ -0,0 +1,18 @@
+module Cucub
+ class Reference
+ attr_reader :object_uuid
+ attr_reader :class_name
+
+ def initialize(opts={})
+ @object_uuid = opts[:object_uuid]
+ @class_name = opts[:class_name]
+ end
+
+ def to_hash
+ {
+ "object_uuid" => self.object_uuid,
+ "class_name" => self.class_name
+ }
+ end
+ end
+end
View
20 msg_testing.rb
@@ -0,0 +1,20 @@
+require './lib/message'
+require './lib/reference'
+require 'msgpack'
+
+ref = Cucub::Reference.new({:object_uuid => 1, :class_name => "Core"})
+ref2 = Cucub::Reference.new({:object_uuid => 2, :class_name => "Engine"})
+
+puts "Message with from, to, respond_to, action, additionals params:\n"
+message = Cucub::Message.new("from" => ref, "to" => ref2, "respond_to" => ref, "action" => "state", "additionals" => 1)
+message.locked?
+serialized = message.serialize
+message.locked?
+
+puts "==="
+puts "Message by parsing serialized data:\n"
+message2 = Cucub::Message.parse(serialized)
+message2.locked?
+message2.unlock(:msgpack)
+puts "action: #{message2.action} | additionals: #{message2.additionals}"
+message2.locked?
View
58 protocol.yml
@@ -0,0 +1,58 @@
+---
+To Write Classes: Reference, Protocol, Message, Namespace-CP-Zone
+
+
+Protocol:
+========
+object_class:
+ [blocking: true]
+ role: emmiter/receiver/both
+ uses_box: true (tipo ventanilla)
+ uses_mailbox: true (tipo mailbox)
+ uses_schedules_mailbox: true (mailbox alternativo)
+ uses_board: true (lista de novedades, broadcast)
+ [only_accept_schedules_from: [reference, reference, reference] it means that it can receive messages which try to schedule a receiving of messages from that kind of objects.]
+
+<blocking on same tune at remote (rule: try to never implemente this kind of communication)>
+- so no block is default :)
+
+message types:
+(void) know informative accion sin esperar una respuesta (*)
+(mensaje) do! imperative accion esperando una respuesta (*)
+(<result>) mensaje.ipa? interrogative pedir cual es el nuevo estado de un mensaje
+
+(*): puede haber o no cambio de estado en el objeto receptor
+
+message transfer reliability:
+
+1) do! not waiting for ack. not-reliable PUSH/PULL dejar mensaje en el buzon
+2) know, not waiting for ack. not-reliable PUSH/PULL dejar mensaje en el buzon
+3) do! waiting for ack. reliable REQ/REP dejar mensaje por ventanilla (se obtiene una respuesta de recibido)
+4) ipa? (waiting for ack, obvio) reliable REQ/REP preguntar por ventanilla
+5) do! + reply_to, ipa? (revisar en buzon local) reliable revisar mailbox local
+
+use_received_evidence: true / false
+# acknowledgment
+
+TODO: retries?
+TODO: scheduled response
+
+Message:
+=======
+uuid: unique ID set on local (sirve para preguntar por el nuevo estado de un mensaje)
+from: reference the current Object and Class which is sending the message.
+to: reference the Class or the specific Object to which the message should be sent.
+type: informative/imperative/interrogative the kind of action required for the object/class to do.
+[chain]: Ticket/s the trace of messaging so specific routing can be done.
+reply-to*: reference/broadcast
+
+action: action name
+additional: hash with additional info (it is always a hash)
+
+An available Router in the CP handles this messages and tries to forward it to the specific Object.
+
+[] = not in milestone 0.0.1
+* = optional
+neighbourhood = the namespace where the Object which takes the message should exist.
+CP = ID for a namespace.
+reference = CP+Class+Object, or Class+Object, or Class
Please sign in to comment.
Something went wrong with that request. Please try again.