class NebulousStomp::Message
A class to encapsulate a Nebulous message (which is built on top of a STOMP message)
This class is entirely read-only, except for reply_id, which is set by Request
when the message is sent.
Much of this class is handled by two helper classes: the message headers are handled by Msg::Header
and the message body by Msg::Body
. You should look at them, too, for the full picture.
Public Class Methods
To build a Nebmessage from a record in the Redis cache.
See to_h
for details of the hash that Redis should be storing
# File lib/nebulous_stomp/message.rb, line 90 def from_cache(json) fail ArgumentError, "That can't be JSON, it's not a string" unless json.kind_of? String NebulousStomp.logger.debug(__FILE__){ "New message from cache" } # Note that the message body at this point, for a JSON message, is actually encoded to JSON # *twice* - the second time was when the cache hash as a whole was encoded for store in # Redis. the JSON gem copes with this so long as the whole string is not double-encoded. hash = JSON.parse(json, :symbolize_names => true) fail ArgumentError, 'Empty cache entry' if hash == {} # So now if the content type is JSON then the body is still JSON now. It's only the rest of # the cache hash that is a now a hash. Confused? Now join us for this weeks' episode... self.new( hash.clone ) rescue JSON::ParserError => err fail ArgumentError, "Bad JSON: #{err.message}" end
Build a Message
from a (presumably incoming) STOMP message; stompmessage must be a Stomp::Message.
# File lib/nebulous_stomp/message.rb, line 74 def from_stomp(stompMsg) fail ArgumentError, 'not a stomp message' unless stompMsg.kind_of? Stomp::Message NebulousStomp.logger.debug(__FILE__){ "New message from STOMP" } s = Marshal.load( Marshal.dump(stompMsg) ) self.new(stompHeaders: s.headers, stompBody: s.body) end
Build a Message
that replies to an existing Message
* msg - the Nebulous::Message that you are replying to * args - hash as per Message.new
See also respond
, respond_with_protocol
, etc, etc. (which you are probably better off calling, to be honest).
Note that this method absolutely enforces the protocol with regard to the content type and (of course) the id of the message it is replying to; for example, even if you pass a different content type it will take the content type of the msg in preference. If you want something weirder, you will have to use Message.new
.
# File lib/nebulous_stomp/message.rb, line 54 def in_reply_to(msg, args) fail ArgumentError, 'bad message' unless msg.kind_of? Message fail ArgumentError, 'bad hash' unless args.kind_of? Hash fail ArgumentError, 'message has no reply ID' unless msg.reply_id NebulousStomp.logger.debug(__FILE__){ "New message in reply to #{msg}" } hash = { inReplyTo: msg.reply_id, contentType: msg.content_type } self.new(args.merge hash) end
Create a new message,
There are three ways that a message could get created:
1. The user could create one directly. 2. A message could be created from an incoming STOMP message, in which case we should call Message.from_stomp to create it. 3. A message could be created because we have retreived it from the Redis cache, in which case we should call Message.from_cache to create it (and, note, it will originally have been created in one of the other two ways...)
The full list of useful hash keys is (as per Message.from_cache
, to_h
):
* :body -- the message body * :contentType -- Stomp content type string * :description / :desc -- part of The Protocol * :inReplyTo -- message ID that message is a response to * :parameters / :params -- part of The Protocol * :replyId -- the 'unique' ID of this Nebulous message * :replyTo -- for a request, the queue to be used for the response * :stompBody -- for a message from Stomp, the raw Stomp message body * :stompHeaders -- for a message from Stomp, the raw Stomp Headers string * :verb -- part of The Protocol
Note that body is taken to be a string if the content type is text, and is taken to be JSON if the content type is JSON.
# File lib/nebulous_stomp/message.rb, line 141 def initialize(hash) @header = Msg::Header.new(hash) @body = Msg::Body.new(content_is_json?, hash) end
Public Instance Methods
Repond with a message body (presumably a custom one that’s non-Protocol). If the content type is JSON, this can be an array or a Hash. If the content type is text, it must be a String.
# File lib/nebulous_stomp/message.rb, line 194 def respond(body) fail NebulousError, "Don't know which queue to reply to" unless reply_to # Easy to do by mistake, pain in the arse to work out what's going on if you do fail ArgumentError, "Respond takes a body, not a message" if body.is_a? Message mess = Message.in_reply_to(self, body: body) [ reply_to, mess ] end
Make a new ‘error verb’ message in response to this one.
Error can be a string or an exception. Fields is an arbitrary array of values, designed as a list of the parameter keys with problems; but of course you can use it for whatever you like.
# File lib/nebulous_stomp/message.rb, line 226 def respond_with_error(err, fields=[]) fail NebulousError, "Don't know which queue to reply to" unless reply_to respond_with_protocol('error', Array(fields).flatten.map(&:to_s), err.to_s) end
Repond with a message using The Protocol.
# File lib/nebulous_stomp/message.rb, line 180 def respond_with_protocol(verb, params=[], desc="") fail NebulousError, "Don't know which queue to reply to" unless reply_to hash = {verb: verb, params: params, desc: desc} [ reply_to, Message.in_reply_to(self, hash) ] end
Make a new ‘success verb’ message in response to this one.
# File lib/nebulous_stomp/message.rb, line 210 def respond_with_success fail NebulousError, "Don't know which queue to reply to" unless reply_to respond_with_protocol('success') end
Output a hash for serialization to the Redis cache.
Currently this looks like:
{ stompHeaders: @stomp_headers, stompBody: @stomp_body, body: @body verb: @verb, params: @params, desc: @desc, replyTo: @reply_to, replyId: @reply_id, inReplyTo: @in_reply_to, contentType: @content_type }
Note that if :stompBody is set then :body will be nil. This is to attempt to reduce duplication of what might be a rather large string.
# File lib/nebulous_stomp/message.rb, line 168 def to_h @header.to_h.merge @body.to_h end
# File lib/nebulous_stomp/message.rb, line 146 def to_s "<Message[#{reply_id}] to:#{reply_to} r-to:#{in_reply_to} v:#{verb}>" end