• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

grpc / grpc-java / #19248

24 May 2024 08:02PM UTC coverage: 88.512% (+0.03%) from 88.484%
#19248

push

github

ejona86
core: Restore optimization for InProcess RPC order

fea577c80 disabled an optimization that some tests notice, as it can
change execution order. This restores the old behavior, at slight
expense to seeing relationship between in-use tracking and idle mode.

32074 of 36237 relevant lines covered (88.51%)

0.89 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

66.67
/../api/src/main/java/io/grpc/ClientCall.java
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> {
1✔
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> {
1✔
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
     */
124
    public void onHeaders(Metadata headers) {}
1✔
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
     */
132
    public void onMessage(T message) {}
1✔
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
     */
153
    public void onClose(Status status, Metadata trailers) {}
1✔
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
     */
171
    public void onReady() {}
1✔
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
   */
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
   */
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
   */
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
   */
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
   */
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
   */
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
  public void setMessageCompression(boolean enabled) {
274
    // noop
275
  }
×
276

277
  /**
278
   * Returns additional properties of the call. May only be called after {@link Listener#onHeaders}
279
   * or {@link Listener#onClose}. If called prematurely, the implementation may throw {@code
280
   * IllegalStateException} or return arbitrary {@code Attributes}.
281
   *
282
   * @return non-{@code null} attributes
283
   * @throws IllegalStateException (optional) if called before permitted
284
   */
285
  @ExperimentalApi("https://github.com/grpc/grpc-java/issues/2607")
286
  @Grpc.TransportAttr
287
  public Attributes getAttributes() {
288
    return Attributes.EMPTY;
×
289
  }
290
}
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2026 Coveralls, Inc