Create a gist now

Instantly share code, notes, and snippets.

What would you like to do?
module Gateway
class GrpcGatewayError < StandardError; end
class HealthError < GrpcGatewayError; end
class ConfigurationError < GrpcGatewayError; end
class RpcNotFoundError < GrpcGatewayError; end
class Proxy
attr_reader :services
# @param stub_services [Hash] mapping of a service_name to an instance of a stub service.
# @param error_presenter [Proc] a method that turns exceptions into a hash.
def initialize(stub_services = {}, &block)
@function_map = {} # func name => hash containing details
@services = {}
@error_presenter = block
map_functions(stub_services)
end
# Return a hash of all the healthchecks from all the services.
def healthcheck
Hash[@services.map do |service_name, stub|
hc = stub.send(:healthcheck, Google::Protobuf::Empty.new)
raise HealthError, "#{service_name} is not healthy." unless hc && hc.processID > 0
[service_name, hc]
end]
end
def function(function_name, noisy = true)
func = @function_map[GRPC::GenericService.underscore(function_name.to_s).to_sym]
raise RpcNotFoundError, "#{function_name} does not exist." if noisy && !func
func
end
def graphql
@graphql ||= Graphql.new(self, @error_presenter)
end
# Execute a function with given params.
def rpc(function_name, params = {}, metadata = {})
function(function_name).call(params, metadata || {})
end
def respond_to_missing?(method, include_private=false)
!!function(method, false)
end
# Proxy methods through to the services, instead of calling rpc()
def method_missing(method, *args, &block)
return rpc(method, args.first, args.second) if function(method)
super
end
private
# Add to the function_map by inspecting each service for the RPCs it provides.
def map_functions(stub_services)
stub_services.keys.each do |service_name|
stub = @services[service_name] = stub_services[service_name]
stub.class.to_s.gsub('::Stub', '::Service').constantize.rpc_descs.values.each do |d|
if d.name.to_sym == :Healthcheck
next
end
grpc_func = Gateway::Function.new(service_name, stub, d)
if @function_map.key?(grpc_func.name)
sn = @function_map[grpc_func.name].service_name
raise ConfigurationError, "#{grpc_func.name} was already defined on #{sn}."
end
@function_map[grpc_func.name] = grpc_func
end
end
end
end
end
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment