@@ -245,6 +245,12 @@ static final class KeyAwareClientCall<RequestT, ResponseT>
245245 @ Nullable private ChannelEndpoint selectedEndpoint ;
246246 @ Nullable private ByteString transactionIdToClear ;
247247 private boolean allowDefaultAffinity ;
248+ private long pendingRequests ;
249+ private boolean pendingHalfClose ;
250+ @ Nullable private Boolean pendingMessageCompression ;
251+ private boolean cancelled ;
252+ @ Nullable private String cancelMessage ;
253+ @ Nullable private Throwable cancelCause ;
248254
249255 KeyAwareClientCall (
250256 KeyAwareChannel parentChannel ,
@@ -268,11 +274,22 @@ protected ClientCall<RequestT, ResponseT> delegate() {
268274 public void start (Listener <ResponseT > responseListener , Metadata headers ) {
269275 this .responseListener = new KeyAwareClientCallListener <>(responseListener , this );
270276 this .headers = headers ;
277+ if (cancelled ) {
278+ this .responseListener .onClose (
279+ io .grpc .Status .CANCELLED .withDescription (cancelMessage ).withCause (cancelCause ),
280+ new Metadata ());
281+ }
271282 }
272283
273284 @ Override
274285 @ SuppressWarnings ("unchecked" )
275286 public void sendMessage (RequestT message ) {
287+ if (cancelled ) {
288+ return ;
289+ }
290+ if (responseListener == null || headers == null ) {
291+ throw new IllegalStateException ("start must be called before sendMessage" );
292+ }
276293 ChannelEndpoint endpoint = null ;
277294 ChannelFinder finder = null ;
278295
@@ -326,16 +343,23 @@ public void sendMessage(RequestT message) {
326343 this .channelFinder = finder ;
327344
328345 delegate = endpoint .getChannel ().newCall (methodDescriptor , callOptions );
346+ if (pendingMessageCompression != null ) {
347+ delegate .setMessageCompression (pendingMessageCompression );
348+ }
329349 delegate .start (responseListener , headers );
350+ drainPendingRequests ();
330351 delegate .sendMessage (message );
352+ if (pendingHalfClose ) {
353+ delegate .halfClose ();
354+ }
331355 }
332356
333357 @ Override
334358 public void halfClose () {
335359 if (delegate != null ) {
336360 delegate .halfClose ();
337361 } else {
338- throw new IllegalStateException ( "halfClose called before sendMessage" ) ;
362+ pendingHalfClose = true ;
339363 }
340364 }
341365
@@ -346,6 +370,56 @@ public void cancel(@Nullable String message, @Nullable Throwable cause) {
346370 } else if (responseListener != null ) {
347371 responseListener .onClose (
348372 io .grpc .Status .CANCELLED .withDescription (message ).withCause (cause ), new Metadata ());
373+ cancelled = true ;
374+ cancelMessage = message ;
375+ cancelCause = cause ;
376+ } else {
377+ cancelled = true ;
378+ cancelMessage = message ;
379+ cancelCause = cause ;
380+ }
381+ }
382+
383+ @ Override
384+ public void request (int numMessages ) {
385+ if (delegate != null ) {
386+ delegate .request (numMessages );
387+ return ;
388+ }
389+ if (numMessages <= 0 ) {
390+ return ;
391+ }
392+ long updated = pendingRequests + numMessages ;
393+ if (updated < 0L ) {
394+ updated = Long .MAX_VALUE ;
395+ }
396+ pendingRequests = updated ;
397+ }
398+
399+ @ Override
400+ public boolean isReady () {
401+ if (delegate == null ) {
402+ return false ;
403+ }
404+ return delegate .isReady ();
405+ }
406+
407+ @ Override
408+ public void setMessageCompression (boolean enabled ) {
409+ if (delegate != null ) {
410+ delegate .setMessageCompression (enabled );
411+ } else {
412+ pendingMessageCompression = enabled ;
413+ }
414+ }
415+
416+ private void drainPendingRequests () {
417+ long requests = pendingRequests ;
418+ pendingRequests = 0L ;
419+ while (requests > 0 ) {
420+ int batch = requests > Integer .MAX_VALUE ? Integer .MAX_VALUE : (int ) requests ;
421+ delegate .request (batch );
422+ requests -= batch ;
349423 }
350424 }
351425
0 commit comments