# Copyright 2023 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # https://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. require "grpc" require "googleauth" require "gapic/grpc/service_stub/rpc_call" module Gapic class ServiceStub ## # @private # # Gapic gRPC ServiceStub Channel. # # This class wraps the gRPC stub object and its RPC methods. # class Channel attr_reader :concurrent_streams ## # Creates a new Channel instance # def initialize grpc_stub_class, endpoint:, credentials:, channel_args: nil, interceptors: nil, on_channel_create: nil, stub_logger: nil @grpc_stub_class = grpc_stub_class @endpoint = endpoint @credentials = credentials @channel_args = Hash channel_args @interceptors = Array interceptors @stub_logger = stub_logger @concurrent_streams = 0 @mutex = Mutex.new setup_grpc_stub on_channel_create&.call self end ## # Creates a gRPC stub object # def setup_grpc_stub raise ArgumentError, "grpc_stub_class is required" if @grpc_stub_class.nil? raise ArgumentError, "endpoint is required" if @endpoint.nil? raise ArgumentError, "credentials is required" if @credentials.nil? @grpc_stub = case @credentials when ::GRPC::Core::Channel @grpc_stub_class.new @endpoint, nil, channel_override: @credentials, interceptors: @interceptors when ::GRPC::Core::ChannelCredentials, Symbol @grpc_stub_class.new @endpoint, @credentials, channel_args: @channel_args, interceptors: @interceptors else updater_proc = @credentials.updater_proc if @credentials.respond_to? :updater_proc updater_proc ||= @credentials if @credentials.is_a? Proc raise ArgumentError, "invalid credentials (#{credentials.class})" if updater_proc.nil? call_creds = ::GRPC::Core::CallCredentials.new updater_proc chan_creds = ::GRPC::Core::ChannelCredentials.new.compose call_creds @grpc_stub_class.new @endpoint, chan_creds, channel_args: @channel_args, interceptors: @interceptors end end ## # Invoke the specified RPC call. # # @param method_name [Symbol] The RPC method name. # @param request [Object] The request object. # @param options [Gapic::CallOptions, Hash] The options for making the RPC call. A Hash can be provided to # customize the options object, using keys that match the arguments for {Gapic::CallOptions.new}. This object # should only be used once. # # @yield [response, operation] Access the response along with the RPC operation. # @yieldparam response [Object] The response object. # @yieldparam operation [::GRPC::ActiveCall::Operation] The RPC operation for the response. # # @return [Object] The response object. # def call_rpc method_name, request, options: nil, &block @mutex.synchronize { @concurrent_streams += 1 } begin meth = @grpc_stub.method method_name rpc_call = RpcCall.new meth, stub_logger: @stub_logger, method_name: method_name response = rpc_call.call request, options: options, &block response ensure @mutex.synchronize { @concurrent_streams -= 1 } end end end end end