/src/grpc-swift/Sources/GRPC/GRPCChannel/GRPCChannel.swift
Line | Count | Source |
1 | | /* |
2 | | * Copyright 2020, gRPC Authors All rights reserved. |
3 | | * |
4 | | * Licensed under the Apache License, Version 2.0 (the "License"); |
5 | | * you may not use this file except in compliance with the License. |
6 | | * You may obtain a copy of the License at |
7 | | * |
8 | | * http://www.apache.org/licenses/LICENSE-2.0 |
9 | | * |
10 | | * Unless required by applicable law or agreed to in writing, software |
11 | | * distributed under the License is distributed on an "AS IS" BASIS, |
12 | | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
13 | | * See the License for the specific language governing permissions and |
14 | | * limitations under the License. |
15 | | */ |
16 | | import NIOCore |
17 | | import NIOHTTP2 |
18 | | import SwiftProtobuf |
19 | | |
20 | | public protocol GRPCChannel: GRPCPreconcurrencySendable { |
21 | | /// Makes a gRPC call on the channel with requests and responses conforming to |
22 | | /// `SwiftProtobuf.Message`. |
23 | | /// |
24 | | /// Note: this is a lower-level construct that any of ``UnaryCall``, ``ClientStreamingCall``, |
25 | | /// ``ServerStreamingCall`` or ``BidirectionalStreamingCall`` and does not have an API to protect |
26 | | /// users against protocol violations (such as sending to requests on a unary call). |
27 | | /// |
28 | | /// After making the ``Call``, users must ``Call/invoke(onError:onResponsePart:)`` the call with a callback which is invoked |
29 | | /// for each response part (or error) received. Any call to ``Call/send(_:)`` prior to calling |
30 | | /// ``Call/invoke(onError:onResponsePart:)`` will fail and not be sent. Users are also responsible for closing the request stream |
31 | | /// by sending the `.end` request part. |
32 | | /// |
33 | | /// - Parameters: |
34 | | /// - path: The path of the RPC, e.g. "/echo.Echo/get". |
35 | | /// - type: The type of the RPC, e.g. ``GRPCCallType/unary``. |
36 | | /// - callOptions: Options for the RPC. |
37 | | /// - interceptors: A list of interceptors to intercept the request and response stream with. |
38 | | func makeCall<Request: SwiftProtobuf.Message, Response: SwiftProtobuf.Message>( |
39 | | path: String, |
40 | | type: GRPCCallType, |
41 | | callOptions: CallOptions, |
42 | | interceptors: [ClientInterceptor<Request, Response>] |
43 | | ) -> Call<Request, Response> |
44 | | |
45 | | /// Makes a gRPC call on the channel with requests and responses conforming to ``GRPCPayload``. |
46 | | /// |
47 | | /// Note: this is a lower-level construct that any of ``UnaryCall``, ``ClientStreamingCall``, |
48 | | /// ``ServerStreamingCall`` or ``BidirectionalStreamingCall`` and does not have an API to protect |
49 | | /// users against protocol violations (such as sending to requests on a unary call). |
50 | | /// |
51 | | /// After making the ``Call``, users must ``Call/invoke(onError:onResponsePart:)`` the call with a callback which is invoked |
52 | | /// for each response part (or error) received. Any call to ``Call/send(_:)`` prior to calling |
53 | | /// ``Call/invoke(onError:onResponsePart:)`` will fail and not be sent. Users are also responsible for closing the request stream |
54 | | /// by sending the `.end` request part. |
55 | | /// |
56 | | /// - Parameters: |
57 | | /// - path: The path of the RPC, e.g. "/echo.Echo/get". |
58 | | /// - type: The type of the RPC, e.g. ``GRPCCallType/unary``. |
59 | | /// - callOptions: Options for the RPC. |
60 | | /// - interceptors: A list of interceptors to intercept the request and response stream with. |
61 | | func makeCall<Request: GRPCPayload, Response: GRPCPayload>( |
62 | | path: String, |
63 | | type: GRPCCallType, |
64 | | callOptions: CallOptions, |
65 | | interceptors: [ClientInterceptor<Request, Response>] |
66 | | ) -> Call<Request, Response> |
67 | | |
68 | | /// Close the channel, and any connections associated with it. Any ongoing RPCs may fail. |
69 | | /// |
70 | | /// - Returns: Returns a future which will be resolved when shutdown has completed. |
71 | | func close() -> EventLoopFuture<Void> |
72 | | |
73 | | /// Close the channel, and any connections associated with it. Any ongoing RPCs may fail. |
74 | | /// |
75 | | /// - Parameter promise: A promise which will be completed when shutdown has completed. |
76 | | func close(promise: EventLoopPromise<Void>) |
77 | | |
78 | | /// Attempt to gracefully shutdown the channel. New RPCs will be failed immediately and existing |
79 | | /// RPCs may continue to run until they complete. |
80 | | /// |
81 | | /// - Parameters: |
82 | | /// - deadline: A point in time by which the graceful shutdown must have completed. If the |
83 | | /// deadline passes and RPCs are still active then the connection will be closed forcefully |
84 | | /// and any remaining in-flight RPCs may be failed. |
85 | | /// - promise: A promise which will be completed when shutdown has completed. |
86 | | func closeGracefully(deadline: NIODeadline, promise: EventLoopPromise<Void>) |
87 | | } |
88 | | |
89 | | // Default implementations to avoid breaking API. Implementations provided by GRPC override these. |
90 | | extension GRPCChannel { |
91 | 0 | public func close(promise: EventLoopPromise<Void>) { |
92 | 0 | promise.completeWith(self.close()) |
93 | 0 | } |
94 | | |
95 | 0 | public func closeGracefully(deadline: NIODeadline, promise: EventLoopPromise<Void>) { |
96 | 0 | promise.completeWith(self.close()) |
97 | 0 | } |
98 | | } |
99 | | |
100 | | extension GRPCChannel { |
101 | | /// Make a unary gRPC call. |
102 | | /// |
103 | | /// - Parameters: |
104 | | /// - path: Path of the RPC, e.g. "/echo.Echo/Get" |
105 | | /// - request: The request to send. |
106 | | /// - callOptions: Options for the RPC. |
107 | | /// - interceptors: A list of interceptors to intercept the request and response stream with. |
108 | | public func makeUnaryCall<Request: Message, Response: Message>( |
109 | | path: String, |
110 | | request: Request, |
111 | | callOptions: CallOptions, |
112 | | interceptors: [ClientInterceptor<Request, Response>] = [] |
113 | 0 | ) -> UnaryCall<Request, Response> { |
114 | 0 | let unary: UnaryCall<Request, Response> = UnaryCall( |
115 | 0 | call: self.makeCall( |
116 | 0 | path: path, |
117 | 0 | type: .unary, |
118 | 0 | callOptions: callOptions, |
119 | 0 | interceptors: interceptors |
120 | 0 | ) |
121 | 0 | ) |
122 | 0 | unary.invoke(request) |
123 | 0 | return unary |
124 | 0 | } |
125 | | |
126 | | /// Make a unary gRPC call. |
127 | | /// |
128 | | /// - Parameters: |
129 | | /// - path: Path of the RPC, e.g. "/echo.Echo/Get" |
130 | | /// - request: The request to send. |
131 | | /// - callOptions: Options for the RPC. |
132 | | /// - interceptors: A list of interceptors to intercept the request and response stream with. |
133 | | public func makeUnaryCall<Request: GRPCPayload, Response: GRPCPayload>( |
134 | | path: String, |
135 | | request: Request, |
136 | | callOptions: CallOptions, |
137 | | interceptors: [ClientInterceptor<Request, Response>] = [] |
138 | 0 | ) -> UnaryCall<Request, Response> { |
139 | 0 | let rpc: UnaryCall<Request, Response> = UnaryCall( |
140 | 0 | call: self.makeCall( |
141 | 0 | path: path, |
142 | 0 | type: .unary, |
143 | 0 | callOptions: callOptions, |
144 | 0 | interceptors: interceptors |
145 | 0 | ) |
146 | 0 | ) |
147 | 0 | rpc.invoke(request) |
148 | 0 | return rpc |
149 | 0 | } |
150 | | |
151 | | /// Makes a client-streaming gRPC call. |
152 | | /// |
153 | | /// - Parameters: |
154 | | /// - path: Path of the RPC, e.g. "/echo.Echo/Get" |
155 | | /// - callOptions: Options for the RPC. |
156 | | /// - interceptors: A list of interceptors to intercept the request and response stream with. |
157 | | public func makeClientStreamingCall<Request: Message, Response: Message>( |
158 | | path: String, |
159 | | callOptions: CallOptions, |
160 | | interceptors: [ClientInterceptor<Request, Response>] = [] |
161 | 0 | ) -> ClientStreamingCall<Request, Response> { |
162 | 0 | let rpc: ClientStreamingCall<Request, Response> = ClientStreamingCall( |
163 | 0 | call: self.makeCall( |
164 | 0 | path: path, |
165 | 0 | type: .clientStreaming, |
166 | 0 | callOptions: callOptions, |
167 | 0 | interceptors: interceptors |
168 | 0 | ) |
169 | 0 | ) |
170 | 0 | rpc.invoke() |
171 | 0 | return rpc |
172 | 0 | } |
173 | | |
174 | | /// Makes a client-streaming gRPC call. |
175 | | /// |
176 | | /// - Parameters: |
177 | | /// - path: Path of the RPC, e.g. "/echo.Echo/Get" |
178 | | /// - callOptions: Options for the RPC. |
179 | | /// - interceptors: A list of interceptors to intercept the request and response stream with. |
180 | | public func makeClientStreamingCall<Request: GRPCPayload, Response: GRPCPayload>( |
181 | | path: String, |
182 | | callOptions: CallOptions, |
183 | | interceptors: [ClientInterceptor<Request, Response>] = [] |
184 | 0 | ) -> ClientStreamingCall<Request, Response> { |
185 | 0 | let rpc: ClientStreamingCall<Request, Response> = ClientStreamingCall( |
186 | 0 | call: self.makeCall( |
187 | 0 | path: path, |
188 | 0 | type: .clientStreaming, |
189 | 0 | callOptions: callOptions, |
190 | 0 | interceptors: interceptors |
191 | 0 | ) |
192 | 0 | ) |
193 | 0 | rpc.invoke() |
194 | 0 | return rpc |
195 | 0 | } |
196 | | |
197 | | /// Make a server-streaming gRPC call. |
198 | | /// |
199 | | /// - Parameters: |
200 | | /// - path: Path of the RPC, e.g. "/echo.Echo/Get" |
201 | | /// - request: The request to send. |
202 | | /// - callOptions: Options for the RPC. |
203 | | /// - interceptors: A list of interceptors to intercept the request and response stream with. |
204 | | /// - handler: Response handler; called for every response received from the server. |
205 | | public func makeServerStreamingCall<Request: Message, Response: Message>( |
206 | | path: String, |
207 | | request: Request, |
208 | | callOptions: CallOptions, |
209 | | interceptors: [ClientInterceptor<Request, Response>] = [], |
210 | | handler: @escaping (Response) -> Void |
211 | 0 | ) -> ServerStreamingCall<Request, Response> { |
212 | 0 | let rpc: ServerStreamingCall<Request, Response> = ServerStreamingCall( |
213 | 0 | call: self.makeCall( |
214 | 0 | path: path, |
215 | 0 | type: .serverStreaming, |
216 | 0 | callOptions: callOptions, |
217 | 0 | interceptors: interceptors |
218 | 0 | ), |
219 | 0 | callback: handler |
220 | 0 | ) |
221 | 0 | rpc.invoke(request) |
222 | 0 | return rpc |
223 | 0 | } |
224 | | |
225 | | /// Make a server-streaming gRPC call. |
226 | | /// |
227 | | /// - Parameters: |
228 | | /// - path: Path of the RPC, e.g. "/echo.Echo/Get" |
229 | | /// - request: The request to send. |
230 | | /// - callOptions: Options for the RPC. |
231 | | /// - interceptors: A list of interceptors to intercept the request and response stream with. |
232 | | /// - handler: Response handler; called for every response received from the server. |
233 | | public func makeServerStreamingCall<Request: GRPCPayload, Response: GRPCPayload>( |
234 | | path: String, |
235 | | request: Request, |
236 | | callOptions: CallOptions, |
237 | | interceptors: [ClientInterceptor<Request, Response>] = [], |
238 | | handler: @escaping (Response) -> Void |
239 | 0 | ) -> ServerStreamingCall<Request, Response> { |
240 | 0 | let rpc: ServerStreamingCall<Request, Response> = ServerStreamingCall( |
241 | 0 | call: self.makeCall( |
242 | 0 | path: path, |
243 | 0 | type: .serverStreaming, |
244 | 0 | callOptions: callOptions, |
245 | 0 | interceptors: [] |
246 | 0 | ), |
247 | 0 | callback: handler |
248 | 0 | ) |
249 | 0 | rpc.invoke(request) |
250 | 0 | return rpc |
251 | 0 | } |
252 | | |
253 | | /// Makes a bidirectional-streaming gRPC call. |
254 | | /// |
255 | | /// - Parameters: |
256 | | /// - path: Path of the RPC, e.g. "/echo.Echo/Get" |
257 | | /// - callOptions: Options for the RPC. |
258 | | /// - interceptors: A list of interceptors to intercept the request and response stream with. |
259 | | /// - handler: Response handler; called for every response received from the server. |
260 | | public func makeBidirectionalStreamingCall<Request: Message, Response: Message>( |
261 | | path: String, |
262 | | callOptions: CallOptions, |
263 | | interceptors: [ClientInterceptor<Request, Response>] = [], |
264 | | handler: @escaping (Response) -> Void |
265 | 0 | ) -> BidirectionalStreamingCall<Request, Response> { |
266 | 0 | let rpc: BidirectionalStreamingCall<Request, Response> = BidirectionalStreamingCall( |
267 | 0 | call: self.makeCall( |
268 | 0 | path: path, |
269 | 0 | type: .bidirectionalStreaming, |
270 | 0 | callOptions: callOptions, |
271 | 0 | interceptors: interceptors |
272 | 0 | ), |
273 | 0 | callback: handler |
274 | 0 | ) |
275 | 0 | rpc.invoke() |
276 | 0 | return rpc |
277 | 0 | } |
278 | | |
279 | | /// Makes a bidirectional-streaming gRPC call. |
280 | | /// |
281 | | /// - Parameters: |
282 | | /// - path: Path of the RPC, e.g. "/echo.Echo/Get" |
283 | | /// - callOptions: Options for the RPC. |
284 | | /// - interceptors: A list of interceptors to intercept the request and response stream with. |
285 | | /// - handler: Response handler; called for every response received from the server. |
286 | | public func makeBidirectionalStreamingCall<Request: GRPCPayload, Response: GRPCPayload>( |
287 | | path: String, |
288 | | callOptions: CallOptions, |
289 | | interceptors: [ClientInterceptor<Request, Response>] = [], |
290 | | handler: @escaping (Response) -> Void |
291 | 0 | ) -> BidirectionalStreamingCall<Request, Response> { |
292 | 0 | let rpc: BidirectionalStreamingCall<Request, Response> = BidirectionalStreamingCall( |
293 | 0 | call: self.makeCall( |
294 | 0 | path: path, |
295 | 0 | type: .bidirectionalStreaming, |
296 | 0 | callOptions: callOptions, |
297 | 0 | interceptors: interceptors |
298 | 0 | ), |
299 | 0 | callback: handler |
300 | 0 | ) |
301 | 0 | rpc.invoke() |
302 | 0 | return rpc |
303 | 0 | } |
304 | | } |