Class: Protod::Rpc::Handler

Inherits:
Object
  • Object
show all
Defined in:
lib/protod/rpc/handler.rb

Defined Under Namespace

Classes: InvalidArgument, RequestPacket, ResponsePacket

Constant Summary collapse

SERVICE_NAME =
'Handler'
PROCEDURE_NAME =
'handle'
ONEOF_NAME =
'receiver'

Class Method Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(package, logger: ::Logger.new(nil)) ⇒ Handler

Returns a new instance of Handler.



38
39
40
41
42
43
44
45
46
47
48
49
50
# File 'lib/protod/rpc/handler.rb', line 38

def initialize(package, logger: ::Logger.new(nil))
  @package = package
  @logger  = logger

  @procedure = @package
                 .find(SERVICE_NAME, by: :ident, as: 'Protod::Proto::Service')
                 .find(Protod::Proto::Procedure.new(ident: PROCEDURE_NAME), by: :ident)

  @request_receiver_fields  = request_proto_message.find(ONEOF_NAME, by: :ident, as: 'Protod::Proto::Oneof')
  @response_receiver_fields = response_proto_message.find(ONEOF_NAME, by: :ident, as: 'Protod::Proto::Oneof')

  @loaded_objects = {}
end

Class Method Details

.build_in(package) ⇒ Object



9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
# File 'lib/protod/rpc/handler.rb', line 9

def build_in(package)
  package
    .find_or_push(SERVICE_NAME, by: :ident, into: :services)
    .find_or_push(Protod::Proto::Procedure.new(ident: PROCEDURE_NAME, streaming_request: true, streaming_response: true), by: :ident, into: :procedures)
    .tap do |procedure|
    package
      .find_or_push(procedure.request_ident, by: :ident, into: :messages)
      .find_or_push(Protod::Proto::Oneof.new(ident: ONEOF_NAME), by: :ident, into: :fields)

    package
      .find_or_push(procedure.response_ident, by: :ident, into: :messages)
      .find_or_push(Protod::Proto::Oneof.new(ident: ONEOF_NAME), by: :ident, into: :fields)
  end

  new(package)
end

.find_packageObject



26
27
28
29
30
31
# File 'lib/protod/rpc/handler.rb', line 26

def find_package
  Protod::Proto::Package.roots.flat_map(&:all_packages).find do
    _1.find(SERVICE_NAME, by: :ident, as: 'Protod::Proto::Service')
      &.find(Protod::Proto::Procedure.new(ident: PROCEDURE_NAME), by: :ident)
  end
end

.find_service_in(package) ⇒ Object



33
34
35
# File 'lib/protod/rpc/handler.rb', line 33

def find_service_in(package)
  package.find(Protod::Rpc::Handler::SERVICE_NAME, by: :ident, as: 'Protod::Proto::Service')
end

Instance Method Details

#handle(req_pb) ⇒ Object

Raises:



65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
# File 'lib/protod/rpc/handler.rb', line 65

def handle(req_pb)
  receiver_name = req_pb.public_send(ONEOF_NAME)

  return unless receiver_name

  req_packet = @request_receiver_fields.find(receiver_name, by: :ident, as: 'Protod::Proto::Field').then do |f|
    raise InvalidArgument, "Not found acceptable receiver : #{receiver_name}" unless f

    f.interpreter.to_rb_from(req_pb.public_send(receiver_name))
  end

  receiver = if req_packet.receiver_id
               @loaded_objects[req_packet.receiver_id.to_s] or raise InvalidArgument, "Invalid object_id in request for #{receiver_name}"
             else
               req_packet.receiver
             end

  raise InvalidArgument, "Not found receiver in request for #{receiver_name}" unless receiver
  raise InvalidArgument, "Not found #{req_packet.procedure} in receiver public methods for #{receiver_name}" unless receiver.respond_to?(req_packet.procedure)

  @logger.debug("protod/handle call #{receiver_name}##{req_packet.procedure} : #{req_packet.args} #{req_packet.kwargs}")
  rb = receiver.public_send(req_packet.procedure, *req_packet.args, **req_packet.kwargs)

  memorize_object_id_of(rb)

  res_pb = @response_receiver_fields.find(receiver_name, by: :ident, as: 'Protod::Proto::Field').then do |f|
    f.interpreter.to_pb_from(ResponsePacket.new(procedure: req_packet.procedure, object: rb))
  end

  response_pb_const.new(receiver_name.to_sym => res_pb)
end

#register_receiver(request_field, response_field) ⇒ Object



60
61
62
63
# File 'lib/protod/rpc/handler.rb', line 60

def register_receiver(request_field, response_field)
  @request_receiver_fields.find_or_push(request_field, by: :ident, into: :fields)
  @response_receiver_fields.find_or_push(response_field, by: :ident, into: :fields)
end

#request_proto_messageObject



52
53
54
# File 'lib/protod/rpc/handler.rb', line 52

def request_proto_message
  @package.find(@procedure.request_ident, by: :ident, as: 'Protod::Proto::Message')
end

#response_proto_messageObject



56
57
58
# File 'lib/protod/rpc/handler.rb', line 56

def response_proto_message
  @package.find(@procedure.response_ident, by: :ident, as: 'Protod::Proto::Message')
end