lib/invoker/ipc/message.rb
module Invoker
module IPC
module Message
module Serialization
def self.included(base)
base.extend ClassMethods
end
def as_json
attributes.merge(type: message_type)
end
def to_json
JSON.generate(as_json)
end
def message_attributes
self.class.message_attributes
end
def encoded_message
json_data = to_json
json_size = json_data.length.to_s
length_str = json_size.rjust(Invoker::IPC::INITIAL_PACKET_SIZE, '0')
length_str + json_data
end
def eql?(other)
other.class == self.class &&
compare_attributes(other)
end
def attributes
message_attribute_keys = message_attributes || []
message_attribute_keys.reduce({}) do |mem, obj|
value = send(obj)
if value.is_a?(Array)
mem[obj] = serialize_array(value)
elsif value.is_a?(Hash)
mem[obj] = serialize_hash(value)
else
mem[obj] = value.respond_to?(:as_json) ? value.as_json : encode_as_utf(value)
end
mem
end
end
private
def compare_attributes(other)
message_attributes.all? do |attribute_name|
send(attribute_name).eql?(other.send(attribute_name))
end
end
def encode_as_utf(value)
return value unless value.is_a?(String)
value.encode("utf-8", invalid: :replace, undef: :replace, replace: '_')
end
def serialize_array(attribute_array)
attribute_array.map do |x|
x.respond_to?(:as_json) ? x.as_json : encode_as_utf(x)
end
end
def serialize_hash(attribute_hash)
attribute_hash.inject({}) do |temp_mem, (temp_key, temp_value)|
if temp_value.respond_to?(:as_json)
temp_mem[temp_key] = temp_value.as_json
else
temp_mem[temp_key] = encode_as_utf(temp_value)
end
end
end
module ClassMethods
def message_attributes(*incoming_attributes)
if incoming_attributes.empty? && defined?(@message_attributes)
@message_attributes
else
@message_attributes ||= []
new_attributes = incoming_attributes.flatten
@message_attributes += new_attributes
attr_accessor *new_attributes
end
end
end
end
class Base
def initialize(options)
options.each do |key, value|
if self.respond_to?("#{key}=")
send("#{key}=", value)
end
end
end
def message_type
Invoker::IPC.underscore(self.class.name).split("/").last
end
def command_handler_klass
Invoker::IPC.const_get("#{IPC.camelize(message_type)}Command")
end
end
class Add < Base
include Serialization
message_attributes :process_name
end
class Tail < Base
include Serialization
message_attributes :process_names
end
class AddHttp < Base
include Serialization
message_attributes :process_name, :port, :ip
end
class Reload < Base
include Serialization
message_attributes :process_name, :signal
def remove_message
Remove.new(process_name: process_name, signal: signal)
end
end
class List < Base
include Serialization
end
class Process < Base
include Serialization
message_attributes :process_name, :shell_command, :dir, :pid, :port
end
class Remove < Base
include Serialization
message_attributes :process_name, :signal
end
class DnsCheck < Base
include Serialization
message_attributes :process_name
end
class DnsCheckResponse < Base
include Serialization
message_attributes :process_name, :port, :ip
end
class Ping < Base
include Serialization
end
class Pong < Base
include Serialization
message_attributes :status
end
end
end
end
require "invoker/ipc/message/list_response"
require "invoker/ipc/message/tail_response"