Skip to content

Commit 9a23086

Browse files
Add RPC#name.
1 parent 64a96db commit 9a23086

File tree

3 files changed

+86
-34
lines changed

3 files changed

+86
-34
lines changed

lib/protocol/grpc/interface.rb

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -11,8 +11,8 @@ module GRPC
1111
# Can be used by both client stubs and server implementations.
1212
class Interface
1313
# RPC method definition
14-
RPC = Struct.new(:request_class, :response_class, :streaming, :method, keyword_init: true) do
15-
def initialize(request_class:, response_class:, streaming: :unary, method: nil)
14+
RPC = Struct.new(:name, :request_class, :response_class, :streaming, :method, keyword_init: true) do
15+
def initialize(name:, request_class:, response_class:, streaming: :unary, method: nil)
1616
super
1717
end
1818

@@ -40,6 +40,8 @@ def self.inherited(subclass)
4040
# @parameter streaming [Symbol] Streaming type (:unary, :server_streaming, :client_streaming, :bidirectional)
4141
# @parameter method [Symbol | Nil] Optional explicit Ruby method name (snake_case). If not provided, automatically converts PascalCase to snake_case.
4242
def self.rpc(name, **options)
43+
options[:name] = name
44+
4345
# Ensure snake_case method name is always available
4446
options[:method] ||= pascal_case_to_snake_case(name.to_s).to_sym
4547

releases.md

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,9 @@
11
# Releases
22

3+
## Unreleased
4+
5+
- Add `RPC#name`.
6+
37
## v0.3.0
48

59
- **Breaking**: `Protocol::GRPC::Call` now takes a `response` object parameter instead of separate `response_headers`.

test/protocol/grpc/interface.rb

Lines changed: 78 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -14,10 +14,12 @@
1414
response_class = self.response_class
1515

1616
interface_class = Class.new(Protocol::GRPC::Interface) do
17-
rpc :say_hello, request_class: request_class, response_class: response_class
17+
rpc :SayHello, request_class: request_class, response_class: response_class
1818
end
1919

20-
rpc = interface_class.lookup_rpc(:say_hello)
20+
rpc = interface_class.lookup_rpc(:SayHello)
21+
expect(rpc.name).to be == :SayHello
22+
expect(rpc.method).to be == :say_hello
2123
expect(rpc.request_class).to be == request_class
2224
expect(rpc.response_class).to be == response_class
2325
expect(rpc.streaming).to be == :unary
@@ -35,42 +37,42 @@
3537
response_class = self.response_class
3638

3739
interface_class = Class.new(Protocol::GRPC::Interface) do
38-
rpc :method1, request_class: request_class, response_class: response_class
39-
rpc :method2, request_class: request_class, response_class: response_class, streaming: :server_streaming
40+
rpc :Method1, request_class: request_class, response_class: response_class
41+
rpc :Method2, request_class: request_class, response_class: response_class, streaming: :server_streaming
4042
end
4143

4244
rpcs = interface_class.rpcs
43-
expect(rpcs.keys.sort).to be == [:method1, :method2].sort
44-
expect(rpcs[:method1].streaming).to be == :unary
45-
expect(rpcs[:method2].streaming).to be == :server_streaming
45+
expect(rpcs.keys.sort).to be == [:Method1, :Method2].sort
46+
expect(rpcs[:Method1].streaming).to be == :unary
47+
expect(rpcs[:Method2].streaming).to be == :server_streaming
4648

4749
# Test streaming? method:
48-
expect(rpcs[:method1].streaming?).to be == false
49-
expect(rpcs[:method2].streaming?).to be == true
50+
expect(rpcs[:Method1].streaming?).to be == false
51+
expect(rpcs[:Method2].streaming?).to be == true
5052
end
5153

5254
it "inherits RPCs from parent class" do
5355
request_class = self.request_class
5456
response_class = self.response_class
5557

5658
base_class = Class.new(Protocol::GRPC::Interface) do
57-
rpc :base_method, request_class: request_class, response_class: response_class
59+
rpc :BaseMethod, request_class: request_class, response_class: response_class
5860
end
5961

6062
subclass = Class.new(base_class) do
61-
rpc :sub_method, request_class: request_class, response_class: response_class
63+
rpc :SubMethod, request_class: request_class, response_class: response_class
6264
end
6365

6466
# Subclass should have both methods
65-
expect(subclass.rpcs.keys.sort).to be == [:base_method, :sub_method].sort
67+
expect(subclass.rpcs.keys.sort).to be == [:BaseMethod, :SubMethod].sort
6668

6769
# Can retrieve inherited method
68-
base_rpc = subclass.lookup_rpc(:base_method)
70+
base_rpc = subclass.lookup_rpc(:BaseMethod)
6971
expect(base_rpc.request_class).to be == request_class
7072
expect(base_rpc.response_class).to be == response_class
7173

7274
# Can retrieve own method
73-
sub_rpc = subclass.lookup_rpc(:sub_method)
75+
sub_rpc = subclass.lookup_rpc(:SubMethod)
7476
expect(sub_rpc.request_class).to be == request_class
7577
expect(sub_rpc.response_class).to be == response_class
7678
end
@@ -82,22 +84,22 @@
8284
other_response_class = Class.new
8385

8486
base_class = Class.new(Protocol::GRPC::Interface) do
85-
rpc :method, request_class: request_class, response_class: response_class
87+
rpc :Method, request_class: request_class, response_class: response_class
8688
end
8789

8890
subclass = Class.new(base_class) do
89-
rpc :method, request_class: other_request_class, response_class: other_response_class, streaming: :bidirectional
91+
rpc :Method, request_class: other_request_class, response_class: other_response_class, streaming: :bidirectional
9092
end
9193

9294
# Subclass should use its own definition
93-
rpc = subclass.lookup_rpc(:method)
95+
rpc = subclass.lookup_rpc(:Method)
9496
expect(rpc.request_class).to be == other_request_class
9597
expect(rpc.response_class).to be == other_response_class
9698
expect(rpc.streaming).to be == :bidirectional
9799
expect(rpc.streaming?).to be == true
98100

99101
# Base class should still have original definition
100-
base_rpc = base_class.lookup_rpc(:method)
102+
base_rpc = base_class.lookup_rpc(:Method)
101103
expect(base_rpc.request_class).to be == request_class
102104
expect(base_rpc.response_class).to be == response_class
103105
expect(base_rpc.streaming).to be == :unary
@@ -109,24 +111,24 @@
109111
response_class = self.response_class
110112

111113
level1 = Class.new(Protocol::GRPC::Interface) do
112-
rpc :level1_method, request_class: request_class, response_class: response_class
114+
rpc :Level1Method, request_class: request_class, response_class: response_class
113115
end
114116

115117
level2 = Class.new(level1) do
116-
rpc :level2_method, request_class: request_class, response_class: response_class
118+
rpc :Level2Method, request_class: request_class, response_class: response_class
117119
end
118120

119121
level3 = Class.new(level2) do
120-
rpc :level3_method, request_class: request_class, response_class: response_class
122+
rpc :Level3Method, request_class: request_class, response_class: response_class
121123
end
122124

123125
# Level 3 should have all methods
124-
expect(level3.rpcs.keys.sort).to be == [:level1_method, :level2_method, :level3_method].sort
126+
expect(level3.rpcs.keys.sort).to be == [:Level1Method, :Level2Method, :Level3Method].sort
125127

126128
# Can retrieve methods from all levels
127-
expect(level3.lookup_rpc(:level1_method)).not.to be_nil
128-
expect(level3.lookup_rpc(:level2_method)).not.to be_nil
129-
expect(level3.lookup_rpc(:level3_method)).not.to be_nil
129+
expect(level3.lookup_rpc(:Level1Method)).not.to be_nil
130+
expect(level3.lookup_rpc(:Level2Method)).not.to be_nil
131+
expect(level3.lookup_rpc(:Level3Method)).not.to be_nil
130132
end
131133

132134
it "can build paths for methods" do
@@ -141,19 +143,19 @@
141143
response_class = self.response_class
142144

143145
class1 = Class.new(Protocol::GRPC::Interface) do
144-
rpc :method1, request_class: request_class, response_class: response_class
146+
rpc :Method1, request_class: request_class, response_class: response_class
145147
end
146148

147149
class2 = Class.new(Protocol::GRPC::Interface) do
148-
rpc :method2, request_class: request_class, response_class: response_class
150+
rpc :Method2, request_class: request_class, response_class: response_class
149151
end
150152

151153
# Each class should only have its own RPCs
152-
expect(class1.rpcs.keys).to be == [:method1]
153-
expect(class2.rpcs.keys).to be == [:method2]
154+
expect(class1.rpcs.keys).to be == [:Method1]
155+
expect(class2.rpcs.keys).to be == [:Method2]
154156

155-
expect(class1.lookup_rpc(:method2)).to be_nil
156-
expect(class2.lookup_rpc(:method1)).to be_nil
157+
expect(class1.lookup_rpc(:Method2)).to be_nil
158+
expect(class2.lookup_rpc(:Method1)).to be_nil
157159
end
158160

159161
it "supports explicit method name in RPC definition" do
@@ -168,6 +170,7 @@
168170

169171
rpc = explicit_interface.lookup_rpc(:XMLParser)
170172
expect(rpc).to be_a(Protocol::GRPC::Interface::RPC)
173+
expect(rpc.name).to be == :XMLParser
171174
expect(rpc.method).to be == :xml_parser
172175
expect(rpc.request_class).to be == request_class
173176
expect(rpc.response_class).to be == response_class
@@ -183,6 +186,7 @@
183186
end
184187

185188
rpc = interface_class.lookup_rpc(:SayHello)
189+
expect(rpc.name).to be == :SayHello
186190
expect(rpc.method).not.to be_nil
187191
expect(rpc.method).to be == :say_hello
188192
end
@@ -198,9 +202,13 @@
198202
rpc :XMLParser, request_class: request_class, response_class: response_class
199203
end
200204

205+
expect(interface_class.lookup_rpc(:SayHello).name).to be == :SayHello
201206
expect(interface_class.lookup_rpc(:SayHello).method).to be == :say_hello
207+
expect(interface_class.lookup_rpc(:UnaryCall).name).to be == :UnaryCall
202208
expect(interface_class.lookup_rpc(:UnaryCall).method).to be == :unary_call
209+
expect(interface_class.lookup_rpc(:ServerStreamingCall).name).to be == :ServerStreamingCall
203210
expect(interface_class.lookup_rpc(:ServerStreamingCall).method).to be == :server_streaming_call
211+
expect(interface_class.lookup_rpc(:XMLParser).name).to be == :XMLParser
204212
expect(interface_class.lookup_rpc(:XMLParser).method).to be == :xml_parser
205213
end
206214

@@ -215,7 +223,9 @@
215223
method: :parse_xml
216224
end
217225

226+
expect(interface_class.lookup_rpc(:SayHello).name).to be == :SayHello
218227
expect(interface_class.lookup_rpc(:SayHello).method).to be == :greet_user
228+
expect(interface_class.lookup_rpc(:XMLParser).name).to be == :XMLParser
219229
expect(interface_class.lookup_rpc(:XMLParser).method).to be == :parse_xml
220230
end
221231

@@ -233,6 +243,8 @@
233243
rpc1 = interface_class.lookup_rpc(:SayHello)
234244
rpc2 = interface_class.lookup_rpc(:UnaryCall)
235245

246+
expect(rpc1.name).to be == :SayHello
247+
expect(rpc2.name).to be == :UnaryCall
236248
expect(rpc1.method).not.to be_nil
237249
expect(rpc2.method).not.to be_nil
238250
expect(rpc1.method).to be_a(Symbol)
@@ -249,10 +261,44 @@
249261
rpc :GetUserByID, request_class: request_class, response_class: response_class
250262
end
251263

264+
expect(interface_class.lookup_rpc(:HTTPRequest).name).to be == :HTTPRequest
252265
expect(interface_class.lookup_rpc(:HTTPRequest).method).to be == :http_request
266+
expect(interface_class.lookup_rpc(:XMLHTTPRequest).name).to be == :XMLHTTPRequest
253267
expect(interface_class.lookup_rpc(:XMLHTTPRequest).method).to be == :xmlhttp_request
268+
expect(interface_class.lookup_rpc(:GetUserByID).name).to be == :GetUserByID
254269
expect(interface_class.lookup_rpc(:GetUserByID).method).to be == :get_user_by_id
255270
end
256271
end
272+
273+
with "name field" do
274+
it "always sets name field to the RPC definition name" do
275+
request_class = self.request_class
276+
response_class = self.response_class
277+
278+
interface_class = Class.new(Protocol::GRPC::Interface) do
279+
rpc :SayHello, request_class: request_class, response_class: response_class
280+
rpc :UnaryCall, request_class: request_class, response_class: response_class
281+
rpc :XMLParser, request_class: request_class, response_class: response_class,
282+
method: :xml_parser
283+
end
284+
285+
expect(interface_class.lookup_rpc(:SayHello).name).to be == :SayHello
286+
expect(interface_class.lookup_rpc(:UnaryCall).name).to be == :UnaryCall
287+
expect(interface_class.lookup_rpc(:XMLParser).name).to be == :XMLParser
288+
end
289+
290+
it "preserves name even when method is explicitly set" do
291+
request_class = self.request_class
292+
response_class = self.response_class
293+
294+
interface_class = Class.new(Protocol::GRPC::Interface) do
295+
rpc :SayHello, request_class: request_class, response_class: response_class,
296+
method: :greet_user
297+
end
298+
299+
rpc = interface_class.lookup_rpc(:SayHello)
300+
expect(rpc.name).to be == :SayHello
301+
expect(rpc.method).to be == :greet_user
302+
end
303+
end
257304
end
258-

0 commit comments

Comments
 (0)