Module: Arborist::TreeAPI

Extended by:
HashUtilities, MethodUtilities, Loggability
Defined in:
lib/arborist/tree_api.rb

Constant Summary collapse

PROTOCOL_VERSION =

The version of the application protocol

1

Class Method Summary collapse

Methods included from HashUtilities

compact_hash, hash_matches, merge_recursively, stringify_keys, symbolify_keys

Methods included from MethodUtilities

attr_predicate, attr_predicate_accessor, dsl_accessor, singleton_attr_accessor, singleton_attr_reader, singleton_attr_writer, singleton_method_alias, singleton_predicate_accessor, singleton_predicate_reader

Class Method Details

.check_body(body) ⇒ Object

Check the given body for validity, raising an Arborist::MessageError if it isn’t.



108
109
110
111
112
113
114
115
# File 'lib/arborist/tree_api.rb', line 108

def self::check_body( body )
	unless body.is_a?( Hash ) ||
		   body.nil? ||
	       ( body.is_a?(Array) && body.all? {|obj| obj.is_a?(Hash) } )
		self.log.error "Invalid message body: %p" % [ body]
		raise Arborist::MessageError, "body must be Nil, a Map, or an Array of Maps"
	end
end

.check_header(header) ⇒ Object

Check the given header for validity, raising an Arborist::MessageError if it isn’t.



96
97
98
99
100
101
102
103
# File 'lib/arborist/tree_api.rb', line 96

def self::check_header( header )
	raise Arborist::MessageError, "header is not a Map" unless
		header.is_a?( Hash )
	version = header['version'] or
		raise Arborist::MessageError, "missing required header 'version'"
	raise Arborist::MessageError, "unknown protocol version %p" % [version] unless
		version == PROTOCOL_VERSION
end

.decode(msg) ⇒ Object

Return the header and body from the TreeAPI request or response in the specified msg (a CZTop::Message).



45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
# File 'lib/arborist/tree_api.rb', line 45

def self::decode( msg )
	raw_message = msg.pop or raise Arborist::MessageError, "empty message"

	parts = begin
		MessagePack.unpack( raw_message )
	rescue => err
		raise Arborist::MessageError, err.message
	end

	raise Arborist::MessageError, 'not an Array' unless parts.is_a?( Array )
	raise Arborist::MessageError,
		"malformed message: expected 1-2 parts, got %d" % [ parts.length ] unless
		parts.length.between?( 1, 2 )

	header = parts.shift or
		raise Arborist::MessageError, "no header"
	self.check_header( header )

	body = parts.shift
	self.check_body( body )

	return header, body
end

.encode(header, body = nil) ⇒ Object

Return a CZTop::Message with a payload containing the specified header and body.



25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
# File 'lib/arborist/tree_api.rb', line 25

def self::encode( header, body=nil )
	raise Arborist::MessageError, "header is not a Map" unless
		header.is_a?( Hash )

	self.log.debug "Encoding header: %p with body: %p" % [ header, body ]
	header = stringify_keys( header )
	header['version'] = PROTOCOL_VERSION

	self.check_header( header )
	self.check_body( body )

	payload = MessagePack.pack([ header, body ])

	self.log.debug "Making zmq message with payload: %p" % [ payload ]
	return CZTop::Message.new( payload )
end

.error_response(category, reason) ⇒ Object

Build an error response message for the specified category and reason.



83
84
85
# File 'lib/arborist/tree_api.rb', line 83

def self::error_response( category, reason )
	return self.encode({ category: category, reason: reason, success: false })
end

.request(verb, *data) ⇒ Object

Return a CZTop::Message containing a TreeAPI request with the specified verb and data.



72
73
74
75
76
77
78
79
# File 'lib/arborist/tree_api.rb', line 72

def self::request( verb, *data )
	body   = data.pop
	header = data.pop || {}

	header.merge!( action: verb )

	return self.encode( header, body )
end

.successful_response(body) ⇒ Object

Build a successful response with the specified body.



89
90
91
# File 'lib/arborist/tree_api.rb', line 89

def self::successful_response( body )
	return self.encode({ success: true }, body )
end