gapic-common 0.0.1

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,19 @@
1
+ # Copyright 2019 Google LLC
2
+ #
3
+ # Licensed under the Apache License, Version 2.0 (the "License");
4
+ # you may not use this file except in compliance with the License.
5
+ # You may obtain a copy of the License at
6
+ #
7
+ # https://www.apache.org/licenses/LICENSE-2.0
8
+ #
9
+ # Unless required by applicable law or agreed to in writing, software
10
+ # distributed under the License is distributed on an "AS IS" BASIS,
11
+ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12
+ # See the License for the specific language governing permissions and
13
+ # limitations under the License.
14
+
15
+ module Gapic
16
+ module Common
17
+ VERSION = "0.0.1".freeze
18
+ end
19
+ end
@@ -0,0 +1,104 @@
1
+ # Copyright 2019 Google LLC
2
+ #
3
+ # Licensed under the Apache License, Version 2.0 (the "License");
4
+ # you may not use this file except in compliance with the License.
5
+ # You may obtain a copy of the License at
6
+ #
7
+ # https://www.apache.org/licenses/LICENSE-2.0
8
+ #
9
+ # Unless required by applicable law or agreed to in writing, software
10
+ # distributed under the License is distributed on an "AS IS" BASIS,
11
+ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12
+ # See the License for the specific language governing permissions and
13
+ # limitations under the License.
14
+
15
+ module Gapic
16
+ ##
17
+ # Config is a simple DSL for creating Configuration classes.
18
+ #
19
+ # @example
20
+ # require "gapic/config"
21
+ #
22
+ # class SampleConfig
23
+ # extend Gapic::Config
24
+ #
25
+ # config_attr :name, nil, String, nil
26
+ # config_attr :active, true, true, false
27
+ # config_attr :count, nil, Numeric, nil
28
+ # config_attr :env, :production, String, Symbol
29
+ #
30
+ # def initialize parent_config = nil
31
+ # @parent_config = parent_config unless parent_config.nil?
32
+ # yield self if block_given?
33
+ # end
34
+ # end
35
+ #
36
+ # config = SampleConfig.new
37
+ #
38
+ # config.name #=> nil
39
+ # config.name = "thor" #=> "thor"
40
+ # config.name #=> "thor"
41
+ # config.name = :thor # ArgumentError
42
+ #
43
+ module Config
44
+ ##
45
+ # Add configuration attribute methods to the configuratin class.
46
+ #
47
+ # @param [String, Symbol] key The name of the option
48
+ # @param [Object, nil] initial Initial value (nil is allowed)
49
+ # @param [Hash] opts Validation options
50
+ #
51
+ def config_attr name, default, *valid_values, &validator
52
+ name = String(name).to_sym
53
+ name_setter = "#{name}=".to_sym
54
+ raise NameError, "invalid config name #{name}" if name !~ /^[a-zA-Z]\w*$/ || name == :parent_config
55
+ raise NameError, "method #{name} already exists" if method_defined? name
56
+ raise NameError, "method #{name_setter} already exists" if method_defined? name_setter
57
+
58
+ raise ArgumentError, "validation must be provided" if validator.nil? && valid_values.empty?
59
+ validator ||= ->(value) { valid_values.any? { |v| v === value } }
60
+
61
+ name_ivar = "@#{name}".to_sym
62
+
63
+ create_getter name_ivar, name, default
64
+ create_setter name_ivar, name_setter, default, validator
65
+ end
66
+
67
+ private
68
+
69
+ def create_getter name_ivar, name, default
70
+ define_method name do
71
+ return instance_variable_get name_ivar if instance_variable_defined? name_ivar
72
+
73
+ if instance_variable_defined? :@parent_config
74
+ parent = instance_variable_get :@parent_config
75
+ return parent.send name if parent&.respond_to? name
76
+ end
77
+
78
+ default
79
+ end
80
+ end
81
+
82
+ def create_setter name_ivar, name_setter, default, validator
83
+ define_method name_setter do |new_value|
84
+ valid_value = validator.call new_value
85
+ if new_value.nil?
86
+ # Always allow nil when a default value is present
87
+ valid_value ||= !default.nil?
88
+ valid_value ||= begin
89
+ # Allow nil if parent config has the getter method.
90
+ parent = instance_variable_get :@parent_config if instance_variable_defined? :@parent_config
91
+ parent&.respond_to? name
92
+ end
93
+ end
94
+ raise ArgumentError unless valid_value
95
+
96
+ if new_value.nil?
97
+ remove_instance_variable name_ivar if instance_variable_defined? name_ivar
98
+ else
99
+ instance_variable_set name_ivar, new_value
100
+ end
101
+ end
102
+ end
103
+ end
104
+ end
@@ -0,0 +1,65 @@
1
+ # Copyright 2019 Google LLC
2
+ #
3
+ # Licensed under the Apache License, Version 2.0 (the "License");
4
+ # you may not use this file except in compliance with the License.
5
+ # You may obtain a copy of the License at
6
+ #
7
+ # https://www.apache.org/licenses/LICENSE-2.0
8
+ #
9
+ # Unless required by applicable law or agreed to in writing, software
10
+ # distributed under the License is distributed on an "AS IS" BASIS,
11
+ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12
+ # See the License for the specific language governing permissions and
13
+ # limitations under the License.
14
+
15
+ module Gapic
16
+ module Config
17
+ ##
18
+ # Config::Method is a configuration class that represents the configuration for an API RPC call.
19
+ #
20
+ # @example
21
+ # require "gapic/config"
22
+ #
23
+ # class ServiceConfig
24
+ # extend Gapic::Config
25
+ #
26
+ # config_attr :host, "localhost", String
27
+ # config_attr :port, 443, Integer
28
+ # config_attr :timeout, nil, Numeric, nil
29
+ # config_attr :metadata, nil, Hash, nil
30
+ #
31
+ # attr_reader :rpc_method
32
+ #
33
+ # def initialize parent_config = nil
34
+ # @parent_config = parent_config unless parent_config.nil?
35
+ # @rpc_method = Gapic::Config::Method.new
36
+ #
37
+ # yield self if block_given?
38
+ # end
39
+ # end
40
+ #
41
+ # config = ServiceConfig.new
42
+ #
43
+ # config.timeout = 60
44
+ # config.rpc_method.timeout = 120
45
+ #
46
+ class Method
47
+ extend Gapic::Config
48
+
49
+ config_attr :timeout, nil, Numeric, nil
50
+ config_attr :metadata, nil, Hash, nil
51
+ config_attr :retry_policy, nil, Hash, Proc, nil
52
+
53
+ ##
54
+ # Create a new Config::Method object instance.
55
+ #
56
+ # @param parent_method [Gapic::Config::Method, nil] The config to look to values for.
57
+ #
58
+ def initialize parent_method = nil
59
+ @parent_config = parent_method unless parent_method.nil?
60
+
61
+ yield self if block_given?
62
+ end
63
+ end
64
+ end
65
+ end
data/lib/gapic/grpc.rb ADDED
@@ -0,0 +1,17 @@
1
+ # Copyright 2019 Google LLC
2
+ #
3
+ # Licensed under the Apache License, Version 2.0 (the "License");
4
+ # you may not use this file except in compliance with the License.
5
+ # You may obtain a copy of the License at
6
+ #
7
+ # https://www.apache.org/licenses/LICENSE-2.0
8
+ #
9
+ # Unless required by applicable law or agreed to in writing, software
10
+ # distributed under the License is distributed on an "AS IS" BASIS,
11
+ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12
+ # See the License for the specific language governing permissions and
13
+ # limitations under the License.
14
+
15
+ require "grpc"
16
+ require "gapic/grpc/service_stub"
17
+ require "gapic/grpc/status_details"
@@ -0,0 +1,158 @@
1
+ # Copyright 2019 Google LLC
2
+ #
3
+ # Licensed under the Apache License, Version 2.0 (the "License");
4
+ # you may not use this file except in compliance with the License.
5
+ # You may obtain a copy of the License at
6
+ #
7
+ # https://www.apache.org/licenses/LICENSE-2.0
8
+ #
9
+ # Unless required by applicable law or agreed to in writing, software
10
+ # distributed under the License is distributed on an "AS IS" BASIS,
11
+ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12
+ # See the License for the specific language governing permissions and
13
+ # limitations under the License.
14
+
15
+ require "grpc"
16
+ require "googleauth"
17
+ require "gapic/grpc/service_stub/rpc_call"
18
+
19
+ module Gapic
20
+ ##
21
+ # Gapic gRPC Stub
22
+ #
23
+ # This class wraps the actual gRPC Stub object and it's RPC methods.
24
+ #
25
+ # @!attribute [r] grpc_stub
26
+ # @return [Object] The instance of the gRPC stub class (`grpc_stub_class`) constructor argument.
27
+ #
28
+ class ServiceStub
29
+ attr_reader :grpc_stub
30
+
31
+ ##
32
+ # Creates a Gapic gRPC stub object.
33
+ #
34
+ # @param grpc_stub_class [Class] gRPC stub class to create a new instance of.
35
+ # @param endpoint [String] The endpoint of the API.
36
+ # @param credentials [Google::Auth::Credentials, Signet::OAuth2::Client, String, Hash, Proc,
37
+ # GRPC::Core::Channel, GRPC::Core::ChannelCredentials] Provides the means for authenticating requests made by
38
+ # the client. This parameter can be many types:
39
+ #
40
+ # * A `Google::Auth::Credentials` uses a the properties of its represented keyfile for authenticating requests
41
+ # made by this client.
42
+ # * A `Signet::OAuth2::Client` object used to apply the OAuth credentials.
43
+ # * A `GRPC::Core::Channel` will be used to make calls through.
44
+ # * A `GRPC::Core::ChannelCredentials` for the setting up the RPC client. The channel credentials should
45
+ # already be composed with a `GRPC::Core::CallCredentials` object.
46
+ # * A `Proc` will be used as an updater_proc for the Grpc channel. The proc transforms the metadata for
47
+ # requests, generally, to give OAuth credentials.
48
+ # @param channel_args [Hash] The channel arguments. (This argument is ignored when `credentials` is
49
+ # provided as a `GRPC::Core::Channel`.)
50
+ # @param interceptors [Array<GRPC::ClientInterceptor>] An array of {GRPC::ClientInterceptor} objects that will
51
+ # be used for intercepting calls before they are executed Interceptors are an EXPERIMENTAL API.
52
+ #
53
+ def initialize grpc_stub_class, endpoint:, credentials:, channel_args: nil, interceptors: nil
54
+ raise ArgumentError, "grpc_stub_class is required" if grpc_stub_class.nil?
55
+ raise ArgumentError, "endpoint is required" if endpoint.nil?
56
+ raise ArgumentError, "credentials is required" if credentials.nil?
57
+
58
+ channel_args = Hash channel_args
59
+ interceptors = Array interceptors
60
+
61
+ @grpc_stub = if credentials.is_a? GRPC::Core::Channel
62
+ grpc_stub_class.new endpoint, nil, channel_override: credentials,
63
+ interceptors: interceptors
64
+ elsif credentials.is_a? GRPC::Core::ChannelCredentials
65
+ grpc_stub_class.new endpoint, credentials, channel_args: channel_args,
66
+ interceptors: interceptors
67
+ else
68
+ updater_proc = credentials.updater_proc if credentials.respond_to? :updater_proc
69
+ updater_proc ||= credentials if credentials.is_a? Proc
70
+ raise ArgumentError, "invalid credentials (#{credentials.class})" if updater_proc.nil?
71
+
72
+ call_creds = GRPC::Core::CallCredentials.new updater_proc
73
+ chan_creds = GRPC::Core::ChannelCredentials.new.compose call_creds
74
+ grpc_stub_class.new endpoint, chan_creds, channel_args: channel_args,
75
+ interceptors: interceptors
76
+ end
77
+ end
78
+
79
+ ##
80
+ # Invoke the specified RPC call.
81
+ #
82
+ # @param method_name [Symbol] The RPC method name.
83
+ # @param request [Object] The request object.
84
+ # @param options [Gapic::CallOptions, Hash] The options for making the RPC call. A Hash can be provided to
85
+ # customize the options object, using keys that match the arguments for {Gapic::CallOptions.new}. This object
86
+ # should only be used once.
87
+ #
88
+ # @yield [response, operation] Access the response along with the RPC operation.
89
+ # @yieldparam response [Object] The response object.
90
+ # @yieldparam operation [GRPC::ActiveCall::Operation] The RPC operation for the response.
91
+ #
92
+ # @return [Object] The response object.
93
+ #
94
+ # @example
95
+ # require "google/showcase/v1beta1/echo_pb"
96
+ # require "google/showcase/v1beta1/echo_services_pb"
97
+ # require "gapic"
98
+ # require "gapic/grpc"
99
+ #
100
+ # echo_channel = GRPC::Core::Channel.new(
101
+ # "localhost:7469", nil, :this_channel_is_insecure
102
+ # )
103
+ # echo_stub = Gapic::ServiceStub.new(
104
+ # Google::Showcase::V1beta1::Echo::Stub,
105
+ # endpoint: "localhost:7469", credentials: echo_channel
106
+ # )
107
+ #
108
+ # request = Google::Showcase::V1beta1::EchoRequest.new
109
+ # response = echo_stub.call_rpc :echo, request
110
+ #
111
+ # @example Using custom call options:
112
+ # require "google/showcase/v1beta1/echo_pb"
113
+ # require "google/showcase/v1beta1/echo_services_pb"
114
+ # require "gapic"
115
+ # require "gapic/grpc"
116
+ #
117
+ # echo_channel = GRPC::Core::Channel.new(
118
+ # "localhost:7469", nil, :this_channel_is_insecure
119
+ # )
120
+ # echo_stub = Gapic::ServiceStub.new(
121
+ # Google::Showcase::V1beta1::Echo::Stub,
122
+ # endpoint: "localhost:7469", credentials: echo_channel
123
+ # )
124
+ #
125
+ # request = Google::Showcase::V1beta1::EchoRequest.new
126
+ # options = Gapic::CallOptions.new(
127
+ # retry_policy = {
128
+ # retry_codes: [GRPC::Core::StatusCodes::UNAVAILABLE]
129
+ # }
130
+ # )
131
+ # response = echo_stub.call_rpc :echo, request
132
+ # options: options
133
+ #
134
+ # @example Accessing the response and RPC operation using a block:
135
+ # require "google/showcase/v1beta1/echo_pb"
136
+ # require "google/showcase/v1beta1/echo_services_pb"
137
+ # require "gapic"
138
+ # require "gapic/grpc"
139
+ #
140
+ # echo_channel = GRPC::Core::Channel.new(
141
+ # "localhost:7469", nil, :this_channel_is_insecure
142
+ # )
143
+ # echo_stub = Gapic::ServiceStub.new(
144
+ # Google::Showcase::V1beta1::Echo::Stub,
145
+ # endpoint: "localhost:7469", credentials: echo_channel
146
+ # )
147
+ #
148
+ # request = Google::Showcase::V1beta1::EchoRequest.new
149
+ # echo_stub.call_rpc :echo, request do |response, operation|
150
+ # operation.trailing_metadata
151
+ # end
152
+ #
153
+ def call_rpc method_name, request, options: nil, &block
154
+ rpc_call = RpcCall.new @grpc_stub.method method_name
155
+ rpc_call.call request, options: options, &block
156
+ end
157
+ end
158
+ end
@@ -0,0 +1,149 @@
1
+ # Copyright 2019 Google LLC
2
+ #
3
+ # Licensed under the Apache License, Version 2.0 (the "License");
4
+ # you may not use this file except in compliance with the License.
5
+ # You may obtain a copy of the License at
6
+ #
7
+ # https://www.apache.org/licenses/LICENSE-2.0
8
+ #
9
+ # Unless required by applicable law or agreed to in writing, software
10
+ # distributed under the License is distributed on an "AS IS" BASIS,
11
+ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12
+ # See the License for the specific language governing permissions and
13
+ # limitations under the License.
14
+
15
+ require "gapic/call_options"
16
+
17
+ module Gapic
18
+ class ServiceStub
19
+ class RpcCall
20
+ attr_reader :stub_method
21
+
22
+ ##
23
+ # Creates an API object for making a single RPC call.
24
+ #
25
+ # In typical usage, `stub_method` will be a proc used to make an RPC request. This will mostly likely be a bound
26
+ # method from a request Stub used to make an RPC call.
27
+ #
28
+ # The result is created by applying a series of function decorators defined in this module to `stub_method`.
29
+ #
30
+ # The result is another proc which has the same signature as the original.
31
+ #
32
+ # @param stub_method [Proc] Used to make a bare rpc call.
33
+ #
34
+ def initialize stub_method
35
+ @stub_method = stub_method
36
+ end
37
+
38
+ ##
39
+ # Invoke the RPC call.
40
+ #
41
+ # @param request [Object] The request object.
42
+ # @param options [Gapic::CallOptions, Hash] The options for making the RPC call. A Hash can be provided to
43
+ # customize the options object, using keys that match the arguments for {Gapic::CallOptions.new}. This object
44
+ # should only be used once.
45
+ #
46
+ # @yield [response, operation] Access the response along with the RPC operation.
47
+ # @yieldparam response [Object] The response object.
48
+ # @yieldparam operation [GRPC::ActiveCall::Operation] The RPC operation for the response.
49
+ #
50
+ # @return [Object] The response object.
51
+ #
52
+ # @example
53
+ # require "google/showcase/v1beta1/echo_pb"
54
+ # require "google/showcase/v1beta1/echo_services_pb"
55
+ # require "gapic"
56
+ # require "gapic/grpc"
57
+ #
58
+ # echo_channel = GRPC::Core::Channel.new(
59
+ # "localhost:7469", nil, :this_channel_is_insecure
60
+ # )
61
+ # echo_stub = Gapic::ServiceStub.new(
62
+ # Google::Showcase::V1beta1::Echo::Stub,
63
+ # endpoint: "localhost:7469", credentials: echo_channel
64
+ # )
65
+ # echo_call = Gapic::ServiceStub::RpcCall.new echo_stub.method :echo
66
+ #
67
+ # request = Google::Showcase::V1beta1::EchoRequest.new
68
+ # response = echo_call.call request
69
+ #
70
+ # @example Using custom call options:
71
+ # require "google/showcase/v1beta1/echo_pb"
72
+ # require "google/showcase/v1beta1/echo_services_pb"
73
+ # require "gapic"
74
+ # require "gapic/grpc"
75
+ #
76
+ # echo_channel = GRPC::Core::Channel.new(
77
+ # "localhost:7469", nil, :this_channel_is_insecure
78
+ # )
79
+ # echo_stub = Gapic::ServiceStub.new(
80
+ # Google::Showcase::V1beta1::Echo::Stub,
81
+ # endpoint: "localhost:7469", credentials: echo_channel
82
+ # )
83
+ # echo_call = Gapic::ServiceStub::RpcCall.new echo_stub.method :echo
84
+ #
85
+ # request = Google::Showcase::V1beta1::EchoRequest.new
86
+ # options = Gapic::CallOptions.new(
87
+ # retry_policy = {
88
+ # retry_codes: [GRPC::Core::StatusCodes::UNAVAILABLE]
89
+ # }
90
+ # )
91
+ # response = echo_call.call request, options: options
92
+ #
93
+ # @example Accessing the response and RPC operation using a block:
94
+ # require "google/showcase/v1beta1/echo_pb"
95
+ # require "google/showcase/v1beta1/echo_services_pb"
96
+ # require "gapic"
97
+ # require "gapic/grpc"
98
+ #
99
+ # echo_channel = GRPC::Core::Channel.new(
100
+ # "localhost:7469", nil, :this_channel_is_insecure
101
+ # )
102
+ # echo_stub = Gapic::ServiceStub.new(
103
+ # Google::Showcase::V1beta1::Echo::Stub,
104
+ # endpoint: "localhost:7469", credentials: echo_channel
105
+ # )
106
+ # echo_call = Gapic::ServiceStub::RpcCall.new echo_stub.method :echo
107
+ #
108
+ # request = Google::Showcase::V1beta1::EchoRequest.new
109
+ # echo_call.call request do |response, operation|
110
+ # operation.trailing_metadata
111
+ # end
112
+ #
113
+ def call request, options: nil
114
+ # Converts hash and nil to an options object
115
+ options = Gapic::CallOptions.new options.to_h if options.respond_to? :to_h
116
+ deadline = calculate_deadline options
117
+ metadata = options.metadata
118
+
119
+ begin
120
+ operation = stub_method.call request, deadline: deadline, metadata: metadata, return_op: true
121
+ response = operation.execute
122
+ yield response, operation if block_given?
123
+ response
124
+ rescue StandardError => e
125
+ if check_retry? deadline
126
+ retry if options.retry_policy.call e
127
+ end
128
+
129
+ raise e
130
+ end
131
+ end
132
+
133
+ private
134
+
135
+ def calculate_deadline options
136
+ return if options.timeout.nil?
137
+ return if options.timeout.negative?
138
+
139
+ Time.now + options.timeout
140
+ end
141
+
142
+ def check_retry? deadline
143
+ return true if deadline.nil?
144
+
145
+ deadline > Time.now
146
+ end
147
+ end
148
+ end
149
+ end