Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(207)

Side by Side Diff: third_party/grpc/src/ruby/lib/grpc/generic/service.rb

Issue 1932353002: Initial checkin of gRPC to third_party/ Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Created 4 years, 7 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
(Empty)
1 # Copyright 2015, Google Inc.
2 # All rights reserved.
3 #
4 # Redistribution and use in source and binary forms, with or without
5 # modification, are permitted provided that the following conditions are
6 # met:
7 #
8 # * Redistributions of source code must retain the above copyright
9 # notice, this list of conditions and the following disclaimer.
10 # * Redistributions in binary form must reproduce the above
11 # copyright notice, this list of conditions and the following disclaimer
12 # in the documentation and/or other materials provided with the
13 # distribution.
14 # * Neither the name of Google Inc. nor the names of its
15 # contributors may be used to endorse or promote products derived from
16 # this software without specific prior written permission.
17 #
18 # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
19 # "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
20 # LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
21 # A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
22 # OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
23 # SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
24 # LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
25 # DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
26 # THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
27 # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
28 # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
29
30 require 'grpc/generic/client_stub'
31 require 'grpc/generic/rpc_desc'
32
33 # GRPC contains the General RPC module.
34 module GRPC
35 # Provides behaviour used to implement schema-derived service classes.
36 #
37 # Is intended to be used to support both client and server
38 # IDL-schema-derived servers.
39 module GenericService
40 # creates a new string that is the underscore separate version of s.
41 #
42 # E.g,
43 # PrintHTML -> print_html
44 # AMethod -> a_method
45 # AnRpc -> an_rpc
46 #
47 # @param s [String] the string to be converted.
48 def self.underscore(s)
49 s.gsub!(/([A-Z]+)([A-Z][a-z])/, '\1_\2')
50 s.gsub!(/([a-z\d])([A-Z])/, '\1_\2')
51 s.tr!('-', '_')
52 s.downcase!
53 s
54 end
55
56 # Used to indicate that a name has already been specified
57 class DuplicateRpcName < StandardError
58 def initialize(name)
59 super("rpc (#{name}) is already defined")
60 end
61 end
62
63 # Provides a simple DSL to describe RPC services.
64 #
65 # E.g, a Maths service that uses the serializable messages DivArgs,
66 # DivReply and Num might define its endpoint uses the following way:
67 #
68 # rpc :div DivArgs, DivReply # single request, single response
69 # rpc :sum stream(Num), Num # streamed input, single response
70 # rpc :fib FibArgs, stream(Num) # single request, streamed response
71 # rpc :div_many stream(DivArgs), stream(DivReply)
72 # # streamed req and resp
73 #
74 # Each 'rpc' adds an RpcDesc to classes including this module, and
75 # #assert_rpc_descs_have_methods is used to ensure the including class
76 # provides methods with signatures that support all the descriptors.
77 module Dsl
78 # This configures the method names that the serializable message
79 # implementation uses to marshal and unmarshal messages.
80 #
81 # - unmarshal_class method must be a class method on the serializable
82 # message type that takes a string (byte stream) and produces and object
83 #
84 # - marshal_class_method is called on a serializable message instance
85 # and produces a serialized string.
86 #
87 # The Dsl verifies that the types in the descriptor have both the
88 # unmarshal and marshal methods.
89 attr_writer(:marshal_class_method, :unmarshal_class_method)
90
91 # This allows configuration of the service name.
92 attr_accessor(:service_name)
93
94 # Adds an RPC spec.
95 #
96 # Takes the RPC name and the classes representing the types to be
97 # serialized, and adds them to the including classes rpc_desc hash.
98 #
99 # input and output should both have the methods #marshal and #unmarshal
100 # that are responsible for writing and reading an object instance from a
101 # byte buffer respectively.
102 #
103 # @param name [String] the name of the rpc
104 # @param input [Object] the input parameter's class
105 # @param output [Object] the output parameter's class
106 def rpc(name, input, output)
107 fail(DuplicateRpcName, name) if rpc_descs.key? name
108 assert_can_marshal(input)
109 assert_can_marshal(output)
110 rpc_descs[name] = RpcDesc.new(name, input, output,
111 marshal_class_method,
112 unmarshal_class_method)
113 end
114
115 def inherited(subclass)
116 # Each subclass should have a distinct class variable with its own
117 # rpc_descs
118 subclass.rpc_descs.merge!(rpc_descs)
119 subclass.service_name = service_name
120 end
121
122 # the name of the instance method used to marshal events to a byte
123 # stream.
124 def marshal_class_method
125 @marshal_class_method ||= :marshal
126 end
127
128 # the name of the class method used to unmarshal from a byte stream.
129 def unmarshal_class_method
130 @unmarshal_class_method ||= :unmarshal
131 end
132
133 def assert_can_marshal(cls)
134 cls = cls.type if cls.is_a? RpcDesc::Stream
135 mth = unmarshal_class_method
136 unless cls.methods.include? mth
137 fail(ArgumentError, "#{cls} needs #{cls}.#{mth}")
138 end
139 mth = marshal_class_method
140 return if cls.methods.include? mth
141 fail(ArgumentError, "#{cls} needs #{cls}.#{mth}")
142 end
143
144 # @param cls [Class] the class of a serializable type
145 # @return cls wrapped in a RpcDesc::Stream
146 def stream(cls)
147 assert_can_marshal(cls)
148 RpcDesc::Stream.new(cls)
149 end
150
151 # the RpcDescs defined for this GenericService, keyed by name.
152 def rpc_descs
153 @rpc_descs ||= {}
154 end
155
156 # Creates a rpc client class with methods for accessing the methods
157 # currently in rpc_descs.
158 def rpc_stub_class
159 descs = rpc_descs
160 route_prefix = service_name
161 Class.new(ClientStub) do
162 # @param host [String] the host the stub connects to
163 # @param creds [Core::ChannelCredentials|Symbol] The channel
164 # credentials to use, or :this_channel_is_insecure otherwise
165 # @param kw [KeywordArgs] the channel arguments, plus any optional
166 # args for configuring the client's channel
167 def initialize(host, creds, **kw)
168 super(host, Core::CompletionQueue.new, creds, **kw)
169 end
170
171 # Used define_method to add a method for each rpc_desc. Each method
172 # calls the base class method for the given descriptor.
173 descs.each_pair do |name, desc|
174 mth_name = GenericService.underscore(name.to_s).to_sym
175 marshal = desc.marshal_proc
176 unmarshal = desc.unmarshal_proc(:output)
177 route = "/#{route_prefix}/#{name}"
178 if desc.request_response?
179 define_method(mth_name) do |req, **kw|
180 GRPC.logger.debug("calling #{@host}:#{route}")
181 request_response(route, req, marshal, unmarshal, **kw)
182 end
183 elsif desc.client_streamer?
184 define_method(mth_name) do |reqs, **kw|
185 GRPC.logger.debug("calling #{@host}:#{route}")
186 client_streamer(route, reqs, marshal, unmarshal, **kw)
187 end
188 elsif desc.server_streamer?
189 define_method(mth_name) do |req, **kw, &blk|
190 GRPC.logger.debug("calling #{@host}:#{route}")
191 server_streamer(route, req, marshal, unmarshal, **kw, &blk)
192 end
193 else # is a bidi_stream
194 define_method(mth_name) do |reqs, **kw, &blk|
195 GRPC.logger.debug("calling #{@host}:#{route}")
196 bidi_streamer(route, reqs, marshal, unmarshal, **kw, &blk)
197 end
198 end
199 end
200 end
201 end
202
203 # Asserts that the appropriate methods are defined for each added rpc
204 # spec. Is intended to aid verifying that server classes are correctly
205 # implemented.
206 def assert_rpc_descs_have_methods
207 rpc_descs.each_pair do |m, spec|
208 mth_name = GenericService.underscore(m.to_s).to_sym
209 unless instance_methods.include?(mth_name)
210 fail "#{self} does not provide instance method '#{mth_name}'"
211 end
212 spec.assert_arity_matches(instance_method(mth_name))
213 end
214 end
215 end
216
217 def self.included(o)
218 o.extend(Dsl)
219 # Update to the use the service name including module. Provide a default
220 # that can be nil e.g. when modules are declared dynamically.
221 return unless o.service_name.nil?
222 if o.name.nil?
223 o.service_name = 'GenericService'
224 else
225 modules = o.name.split('::')
226 if modules.length > 2
227 o.service_name = modules[modules.length - 2]
228 else
229 o.service_name = modules.first
230 end
231 end
232 end
233 end
234 end
OLDNEW
« no previous file with comments | « third_party/grpc/src/ruby/lib/grpc/generic/rpc_server.rb ('k') | third_party/grpc/src/ruby/lib/grpc/grpc.rb » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698