• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright 2014 The gRPC Authors
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 
17 package io.grpc;
18 
19 import javax.annotation.Nullable;
20 
21 /**
22  * An instance of a call to a remote method. A call will send zero or more
23  * request messages to the server and receive zero or more response messages back.
24  *
25  * <p>Instances are created
26  * by a {@link Channel} and used by stubs to invoke their remote behavior.
27  *
28  * <p>More advanced usages may consume this interface directly as opposed to using a stub. Common
29  * reasons for doing so would be the need to interact with flow-control or when acting as a generic
30  * proxy for arbitrary operations.
31  *
32  * <p>{@link #start} must be called prior to calling any other methods, with the exception of
33  * {@link #cancel}. Whereas {@link #cancel} must not be followed by any other methods,
34  * but can be called more than once, while only the first one has effect.
35  *
36  * <p>No generic method for determining message receipt or providing acknowledgement is provided.
37  * Applications are expected to utilize normal payload messages for such signals, as a response
38  * naturally acknowledges its request.
39  *
40  * <p>Methods are guaranteed to be non-blocking. Not thread-safe except for {@link #request}, which
41  * may be called from any thread.
42  *
43  * <p>There is no interaction between the states on the {@link Listener Listener} and {@link
44  * ClientCall}, i.e., if {@link Listener#onClose Listener.onClose()} is called, it has no bearing on
45  * the permitted operations on {@code ClientCall} (but it may impact whether they do anything).
46  *
47  * <p>There is a race between {@link #cancel} and the completion/failure of the RPC in other ways.
48  * If {@link #cancel} won the race, {@link Listener#onClose Listener.onClose()} is called with
49  * {@link Status#CANCELLED CANCELLED}. Otherwise, {@link Listener#onClose Listener.onClose()} is
50  * called with whatever status the RPC was finished. We ensure that at most one is called.
51  *
52  * <h3>Usage examples</h3>
53  * <h4>Simple Unary (1 request, 1 response) RPC</h4>
54  * <pre>
55  *   call = channel.newCall(unaryMethod, callOptions);
56  *   call.start(listener, headers);
57  *   call.sendMessage(message);
58  *   call.halfClose();
59  *   call.request(1);
60  *   // wait for listener.onMessage()
61  * </pre>
62  *
63  * <h4>Flow-control in Streaming RPC</h4>
64  *
65  * <p>The following snippet demonstrates a bi-directional streaming case, where the client sends
66  * requests produced by a fictional <code>makeNextRequest()</code> in a flow-control-compliant
67  * manner, and notifies gRPC library to receive additional response after one is consumed by
68  * a fictional <code>processResponse()</code>.
69  *
70  * <p><pre>
71  *   call = channel.newCall(bidiStreamingMethod, callOptions);
72  *   listener = new ClientCall.Listener&lt;FooResponse&gt;() {
73  *     &#64;Override
74  *     public void onMessage(FooResponse response) {
75  *       processResponse(response);
76  *       // Notify gRPC to receive one additional response.
77  *       call.request(1);
78  *     }
79  *
80  *     &#64;Override
81  *     public void onReady() {
82  *       while (call.isReady()) {
83  *         FooRequest nextRequest = makeNextRequest();
84  *         if (nextRequest == null) {  // No more requests to send
85  *           call.halfClose();
86  *           return;
87  *         }
88  *         call.sendMessage(nextRequest);
89  *       }
90  *     }
91  *   }
92  *   call.start(listener, headers);
93  *   // Notify gRPC to receive one response. Without this line, onMessage() would never be called.
94  *   call.request(1);
95  * </pre>
96  *
97  * <p>DO NOT MOCK: Use InProcessServerBuilder and make a test server instead.
98  *
99  * @param <ReqT> type of message sent one or more times to the server.
100  * @param <RespT> type of message received one or more times from the server.
101  */
102 public abstract class ClientCall<ReqT, RespT> {
103   /**
104    * Callbacks for receiving metadata, response messages and completion status from the server.
105    *
106    * <p>Implementations are free to block for extended periods of time. Implementations are not
107    * required to be thread-safe, but they must not be thread-hostile. The caller is free to call
108    * an instance from multiple threads, but only one call simultaneously. A single thread may
109    * interleave calls to multiple instances, so implementations using ThreadLocals must be careful
110    * to avoid leaking inappropriate state (e.g., clearing the ThreadLocal before returning).
111    *
112    * @param <T> type of message received.
113    */
114   public abstract static class Listener<T> {
115 
116     /**
117      * The response headers have been received. Headers always precede messages.
118      *
119      * <p>Since {@link Metadata} is not thread-safe, the caller must not access (read or write)
120      * {@code headers} after this point.
121      *
122      * @param headers containing metadata sent by the server at the start of the response.
123      */
onHeaders(Metadata headers)124     public void onHeaders(Metadata headers) {}
125 
126     /**
127      * A response message has been received. May be called zero or more times depending on whether
128      * the call response is empty, a single message or a stream of messages.
129      *
130      * @param message returned by the server
131      */
onMessage(T message)132     public void onMessage(T message) {}
133 
134     /**
135      * The ClientCall has been closed. Any additional calls to the {@code ClientCall} will not be
136      * processed by the server. No further receiving will occur and no further notifications will be
137      * made.
138      *
139      * <p>Since {@link Metadata} is not thread-safe, the caller must not access (read or write)
140      * {@code trailers} after this point.
141      *
142      * <p>If {@code status} returns false for {@link Status#isOk()}, then the call failed.
143      * An additional block of trailer metadata may be received at the end of the call from the
144      * server. An empty {@link Metadata} object is passed if no trailers are received.
145      *
146      * <p>This method should not throw. If this method throws, there is no way to be notified of the
147      * exception. Implementations should therefore be careful of exceptions which can accidentally
148      * leak resources.
149      *
150      * @param status the result of the remote call.
151      * @param trailers metadata provided at call completion.
152      */
onClose(Status status, Metadata trailers)153     public void onClose(Status status, Metadata trailers) {}
154 
155     /**
156      * This indicates that the ClientCall may now be capable of sending additional messages (via
157      * {@link #sendMessage}) without requiring excessive buffering internally. This event is
158      * just a suggestion and the application is free to ignore it, however doing so may
159      * result in excessive buffering within the ClientCall.
160      *
161      * <p>Because there is a processing delay to deliver this notification, it is possible for
162      * concurrent writes to cause {@code isReady() == false} within this callback. Handle "spurious"
163      * notifications by checking {@code isReady()}'s current value instead of assuming it is now
164      * {@code true}. If {@code isReady() == false} the normal expectations apply, so there would be
165      * <em>another</em> {@code onReady()} callback.
166      *
167      * <p>If the type of a call is either {@link MethodDescriptor.MethodType#UNARY} or
168      * {@link MethodDescriptor.MethodType#SERVER_STREAMING}, this callback may not be fired. Calls
169      * that send exactly one message should not await this callback.
170      */
onReady()171     public void onReady() {}
172   }
173 
174   /**
175    * Start a call, using {@code responseListener} for processing response messages.
176    *
177    * <p>It must be called prior to any other method on this class, except for {@link #cancel} which
178    * may be called at any time.
179    *
180    * <p>Since {@link Metadata} is not thread-safe, the caller must not access (read or write) {@code
181    * headers} after this point.
182    *
183    * @param responseListener receives response messages
184    * @param headers which can contain extra call metadata, e.g. authentication credentials.
185    * @throws IllegalStateException if a method (including {@code start()}) on this class has been
186    *                               called.
187    */
start(Listener<RespT> responseListener, Metadata headers)188   public abstract void start(Listener<RespT> responseListener, Metadata headers);
189 
190   /**
191    * Requests up to the given number of messages from the call to be delivered to
192    * {@link Listener#onMessage(Object)}. No additional messages will be delivered.
193    *
194    * <p>Message delivery is guaranteed to be sequential in the order received. In addition, the
195    * listener methods will not be accessed concurrently. While it is not guaranteed that the same
196    * thread will always be used, it is guaranteed that only a single thread will access the listener
197    * at a time.
198    *
199    * <p>If it is desired to bypass inbound flow control, a very large number of messages can be
200    * specified (e.g. {@link Integer#MAX_VALUE}).
201    *
202    * <p>If called multiple times, the number of messages able to delivered will be the sum of the
203    * calls.
204    *
205    * <p>This method is safe to call from multiple threads without external synchronization.
206    *
207    * @param numMessages the requested number of messages to be delivered to the listener. Must be
208    *                    non-negative.
209    * @throws IllegalStateException if call is not {@code start()}ed
210    * @throws IllegalArgumentException if numMessages is negative
211    */
request(int numMessages)212   public abstract void request(int numMessages);
213 
214   /**
215    * Prevent any further processing for this {@code ClientCall}. No further messages may be sent or
216    * will be received. The server is informed of cancellations, but may not stop processing the
217    * call. Cancellation is permitted even if previously {@link #halfClose}d. Cancelling an already
218    * {@code cancel()}ed {@code ClientCall} has no effect.
219    *
220    * <p>No other methods on this class can be called after this method has been called.
221    *
222    * <p>It is recommended that at least one of the arguments to be non-{@code null}, to provide
223    * useful debug information. Both argument being null may log warnings and result in suboptimal
224    * performance. Also note that the provided information will not be sent to the server.
225    *
226    * @param message if not {@code null}, will appear as the description of the CANCELLED status
227    * @param cause if not {@code null}, will appear as the cause of the CANCELLED status
228    */
cancel(@ullable String message, @Nullable Throwable cause)229   public abstract void cancel(@Nullable String message, @Nullable Throwable cause);
230 
231   /**
232    * Close the call for request message sending. Incoming response messages are unaffected.  This
233    * should be called when no more messages will be sent from the client.
234    *
235    * @throws IllegalStateException if call is already {@code halfClose()}d or {@link #cancel}ed
236    */
halfClose()237   public abstract void halfClose();
238 
239   /**
240    * Send a request message to the server. May be called zero or more times depending on how many
241    * messages the server is willing to accept for the operation.
242    *
243    * @param message message to be sent to the server.
244    * @throws IllegalStateException if call is {@link #halfClose}d or explicitly {@link #cancel}ed
245    */
sendMessage(ReqT message)246   public abstract void sendMessage(ReqT message);
247 
248   /**
249    * If {@code true}, indicates that the call is capable of sending additional messages
250    * without requiring excessive buffering internally. This event is
251    * just a suggestion and the application is free to ignore it, however doing so may
252    * result in excessive buffering within the call.
253    *
254    * <p>If {@code false}, {@link Listener#onReady()} will be called after {@code isReady()}
255    * transitions to {@code true}.
256    *
257    * <p>If the type of the call is either {@link MethodDescriptor.MethodType#UNARY} or
258    * {@link MethodDescriptor.MethodType#SERVER_STREAMING}, this method may persistently return
259    * false. Calls that send exactly one message should not check this method.
260    *
261    * <p>This abstract class's implementation always returns {@code true}. Implementations generally
262    * override the method.
263    */
isReady()264   public boolean isReady() {
265     return true;
266   }
267 
268   /**
269    * Enables per-message compression, if an encoding type has been negotiated.  If no message
270    * encoding has been negotiated, this is a no-op. By default per-message compression is enabled,
271    * but may not have any effect if compression is not enabled on the call.
272    */
273   @ExperimentalApi("https://github.com/grpc/grpc-java/issues/1703")
setMessageCompression(boolean enabled)274   public void setMessageCompression(boolean enabled) {
275     // noop
276   }
277 
278   /**
279    * Returns additional properties of the call. May only be called after {@link Listener#onHeaders}
280    * or {@link Listener#onClose}. If called prematurely, the implementation may throw {@code
281    * IllegalStateException} or return arbitrary {@code Attributes}.
282    *
283    * @return non-{@code null} attributes
284    * @throws IllegalStateException (optional) if called before permitted
285    */
286   @ExperimentalApi("https://github.com/grpc/grpc-java/issues/2607")
287   @Grpc.TransportAttr
getAttributes()288   public Attributes getAttributes() {
289     return Attributes.EMPTY;
290   }
291 }
292