105105final class ExternalProcessorServerInterceptor implements ServerInterceptor {
106106 private final CachedChannelManager cachedChannelManager ;
107107 private final ExternalProcessorFilterConfig filterConfig ;
108- private final FilterContext context ;
109108 private final MetricRecorder metricsRecorder ;
110109
111110 ExternalProcessorServerInterceptor (
@@ -114,7 +113,6 @@ final class ExternalProcessorServerInterceptor implements ServerInterceptor {
114113 FilterContext context ) {
115114 this .filterConfig = checkNotNull (filterConfig , "filterConfig" );
116115 this .cachedChannelManager = checkNotNull (cachedChannelManager , "cachedChannelManager" );
117- this .context = checkNotNull (context , "context" );
118116 this .metricsRecorder = checkNotNull (context .metricsRecorder (), "metricsRecorder" );
119117 }
120118
@@ -332,7 +330,9 @@ private enum EventType {
332330 new AtomicReference <>(ExtProcStreamState .ACTIVE );
333331 final AtomicBoolean passThroughMode = new AtomicBoolean (false );
334332 final AtomicBoolean halfClosed = new AtomicBoolean (false );
335- final AtomicBoolean responseSideClosed = new AtomicBoolean (false );
333+ final AtomicBoolean requestSideClosed = new AtomicBoolean (false );
334+ final AtomicBoolean dataPlaneCallClosed = new AtomicBoolean (false );
335+
336336 final AtomicBoolean isProcessingTrailers = new AtomicBoolean (false );
337337 final AtomicBoolean responseHeadersSent = new AtomicBoolean (false );
338338 final AtomicBoolean terminationTriggered = new AtomicBoolean (false );
@@ -440,6 +440,9 @@ private void activateCall() {
440440 wrappedListener .setDelegate (appListener );
441441 drainPendingRequests ();
442442 wrappedListener .onReadyNotify ();
443+ if (wrappedListener .halfCloseDeferred ) {
444+ wrappedListener .handleDeferredHalfClose ();
445+ }
443446 }
444447
445448 private void recordDuration (DoubleHistogramMetricInstrument instrument , long durationNanos ) {
@@ -618,7 +621,7 @@ else if (response.hasResponseTrailers()) {
618621 proceedWithClose ();
619622 }
620623
621- checkEndOfStream (response );
624+ checkEndOfStream ();
622625 } catch (Throwable t ) {
623626 internalOnError (t );
624627 }
@@ -712,7 +715,9 @@ private void closeExtProcStream() {
712715 extProcClientCallRequestObserver .onCompleted ();
713716 }
714717 }
718+ expectedResponses .clear ();
715719 }
720+ proceedWithClose ();
716721 }
717722
718723 private void cancelExtProcStream (Throwable t ) {
@@ -726,6 +731,8 @@ private void cancelExtProcStream(Throwable t) {
726731 extProcClientCallRequestObserver = null ;
727732 }
728733 }
734+ expectedResponses .clear ();
735+ proceedWithClose ();
729736 }
730737 }
731738
@@ -740,6 +747,7 @@ private void internalOnError(Throwable t) {
740747 extProcClientCallRequestObserver = null ;
741748 }
742749 }
750+ expectedResponses .clear ();
743751 if (config .getFailureModeAllow ()) {
744752 handleFailOpen ();
745753 } else {
@@ -860,7 +868,7 @@ private void proceedWithSendHeaders(Metadata headers) {
860868
861869 @ Override
862870 public void sendMessage (InputStream message ) {
863- if (responseSideClosed .get ()) {
871+ if (dataPlaneCallClosed .get ()) {
864872 return ;
865873 }
866874
@@ -959,7 +967,8 @@ public void close(Status status, Metadata trailers) {
959967
960968 void proceedWithClose () {
961969 synchronized (rawCallLock ) {
962- if (savedStatus != null ) {
970+ if (savedStatus != null
971+ && (isExtProcStreamCompleted () || config .getObservabilityMode ())) {
963972 if (markDataPlaneCallClosed ()) {
964973 proceedWithClose (savedStatus , savedTrailers );
965974 }
@@ -970,12 +979,14 @@ void proceedWithClose() {
970979 }
971980
972981 private void proceedWithClose (Status status , Metadata trailers ) {
973- if (serverTrailersStartNanos > 0 ) {
974- long durationNanos = System .nanoTime () - serverTrailersStartNanos ;
975- recordDuration (serverTrailersDuration , durationNanos );
976- serverTrailersStartNanos = 0 ;
982+ if (dataPlaneCallClosed .compareAndSet (false , true )) {
983+ if (serverTrailersStartNanos > 0 ) {
984+ long durationNanos = System .nanoTime () - serverTrailersStartNanos ;
985+ recordDuration (serverTrailersDuration , durationNanos );
986+ serverTrailersStartNanos = 0 ;
987+ }
988+ super .close (status , trailers );
977989 }
978- super .close (status , trailers );
979990 }
980991
981992 private void triggerCloseHandshake () {
@@ -994,14 +1005,9 @@ private void triggerCloseHandshake() {
9941005 .build ())
9951006 .build ());
9961007 } else {
997- sendToExtProc (ProcessingRequest .newBuilder ()
998- .setResponseBody (HttpBody .newBuilder ()
999- .setEndOfStreamWithoutMessage (true )
1000- .build ())
1001- .build ());
1002-
1003- if (config .getObservabilityMode ()) {
1004- proceedWithClose ();
1008+ if (isRequestSideCompleted ()) {
1009+ unblockAfterStreamComplete ();
1010+ closeExtProcStream ();
10051011 }
10061012 }
10071013 }
@@ -1024,11 +1030,12 @@ private void sendResponseBodyToExtProc(@Nullable ByteString bodyByteString, bool
10241030 }
10251031
10261032 private void handleRequestBodyResponse (BodyResponse bodyResponse ) {
1027- if (bodyResponse .hasResponse () && bodyResponse .getResponse ().hasBodyMutation ()) {
1033+ if (bodyResponse .hasResponse ()
1034+ && bodyResponse .getResponse ().hasBodyMutation ()) {
10281035 BodyMutation mutation = bodyResponse .getResponse ().getBodyMutation ();
10291036 if (mutation .hasStreamedResponse ()) {
10301037 StreamedBodyResponse streamed = mutation .getStreamedResponse ();
1031- if (!streamed .getBody (). isEmpty ()) {
1038+ if (!streamed .getEndOfStreamWithoutMessage ()) {
10321039 wrappedListener .onExternalBody (streamed .getBody ());
10331040 }
10341041 if (streamed .getEndOfStream () || streamed .getEndOfStreamWithoutMessage ()) {
@@ -1039,18 +1046,14 @@ private void handleRequestBodyResponse(BodyResponse bodyResponse) {
10391046 }
10401047
10411048 private void handleResponseBodyResponse (BodyResponse bodyResponse ) {
1049+ if (dataPlaneCallClosed .get ()) {
1050+ return ;
1051+ }
10421052 if (bodyResponse .hasResponse () && bodyResponse .getResponse ().hasBodyMutation ()) {
10431053 BodyMutation mutation = bodyResponse .getResponse ().getBodyMutation ();
10441054 if (mutation .hasStreamedResponse ()) {
10451055 StreamedBodyResponse streamed = mutation .getStreamedResponse ();
1046- if (!streamed .getBody ().isEmpty ()) {
1047- super .sendMessage (new OutboundZeroCopyInputStream (streamed .getBody ()));
1048- }
1049- }
1050- }
1051- if (responseSideClosed .compareAndSet (false , true )) {
1052- if (terminationTriggered .get ()) {
1053- proceedWithClose ();
1056+ super .sendMessage (new OutboundZeroCopyInputStream (streamed .getBody ()));
10541057 }
10551058 }
10561059 }
@@ -1097,23 +1100,20 @@ private void handleFailOpen() {
10971100 closeExtProcStream ();
10981101 }
10991102
1100- private void checkEndOfStream (ProcessingResponse response ) {
1101- boolean terminal = false ;
1102- if (response .hasResponseTrailers ()) {
1103- terminal = true ;
1104- } else if (response .hasResponseHeaders () && savedStatus != null
1105- && currentProcessingMode .getResponseBodyMode () == ProcessingMode .BodySendMode .NONE ) {
1106- terminal = true ;
1107- } else if (response .hasResponseBody () && responseSideClosed .get ()) {
1108- terminal = true ;
1109- }
1110-
1111- if (terminal ) {
1103+ private void checkEndOfStream () {
1104+ if (terminationTriggered .get () && isRequestSideCompleted ()
1105+ && !expectedResponses .contains (EventType .RESPONSE_TRAILERS )) {
11121106 unblockAfterStreamComplete ();
11131107 closeExtProcStream ();
11141108 }
11151109 }
11161110
1111+ private boolean isRequestSideCompleted () {
1112+ return (currentProcessingMode .getRequestHeaderMode () != ProcessingMode .HeaderSendMode .SEND
1113+ && currentProcessingMode .getRequestBodyMode () != ProcessingMode .BodySendMode .GRPC )
1114+ || requestSideClosed .get ();
1115+ }
1116+
11171117 void unblockAfterStreamComplete () {
11181118 proceedWithSendHeaders ();
11191119 drainPendingDrainingMessages ();
@@ -1125,6 +1125,7 @@ private static final class DataPlaneServerListener extends ServerCall.Listener<I
11251125 private final DataPlaneServerCall dataPlaneServerCall ;
11261126 private final Queue <InputStream > savedMessages = new ConcurrentLinkedQueue <>();
11271127 private volatile boolean halfCloseReceived ;
1128+ private volatile boolean halfCloseDeferred ;
11281129 private volatile ServerCall .Listener <InputStream > delegate ;
11291130
11301131 private DataPlaneServerListener (DataPlaneServerCall dataPlaneServerCall ) {
@@ -1164,6 +1165,9 @@ void onReadyNotify() {
11641165 @ Override
11651166 public void onMessage (InputStream message ) {
11661167 dataPlaneServerCall .delegateExecutor .execute (() -> {
1168+ if (dataPlaneServerCall .requestSideClosed .get ()) {
1169+ return ;
1170+ }
11671171 ServerCall .Listener <InputStream > del = delegate ;
11681172 if (dataPlaneServerCall .passThroughMode .get () && del != null ) {
11691173 dataPlaneServerCall .callContext .run (() -> del .onMessage (message ));
@@ -1177,10 +1181,10 @@ public void onMessage(InputStream message) {
11771181 != ProcessingMode .BodySendMode .GRPC
11781182 || dataPlaneServerCall .config .getObservabilityMode ()) {
11791183
1180- if (dataPlaneServerCall . dataPlaneCallState . get () == DataPlaneCallState . IDLE ) {
1181- // We must buffer because the application call hasn't started yet
1184+ if (del == null ) {
1185+ // We must buffer because the application call hasn't started yet or delegate is not set
11821186 savedMessages .add (message );
1183- } else if ( del != null ) {
1187+ } else {
11841188 dataPlaneServerCall .callContext .run (() -> del .onMessage (message ));
11851189 }
11861190 return ;
@@ -1201,6 +1205,9 @@ public void onMessage(InputStream message) {
12011205 @ Override
12021206 public void onHalfClose () {
12031207 dataPlaneServerCall .delegateExecutor .execute (() -> {
1208+ if (dataPlaneServerCall .requestSideClosed .get ()) {
1209+ return ;
1210+ }
12041211 dataPlaneServerCall .clientHalfCloseStartNanos = System .nanoTime ();
12051212 dataPlaneServerCall .halfClosed .set (true );
12061213 ServerCall .Listener <InputStream > del = delegate ;
@@ -1210,7 +1217,7 @@ public void onHalfClose() {
12101217 }
12111218
12121219 if (dataPlaneServerCall .dataPlaneCallState .get () == DataPlaneCallState .IDLE ) {
1213- halfCloseReceived = true ;
1220+ halfCloseDeferred = true ;
12141221 return ;
12151222 }
12161223
@@ -1223,7 +1230,22 @@ public void onHalfClose() {
12231230 });
12241231 }
12251232
1233+ void handleDeferredHalfClose () {
1234+ dataPlaneServerCall .delegateExecutor .execute (() -> {
1235+ if (dataPlaneServerCall .currentProcessingMode .getRequestBodyMode () == ProcessingMode .BodySendMode .NONE
1236+ || dataPlaneServerCall .isExtProcStreamCompleted ()) {
1237+ proceedWithHalfClose ();
1238+ } else {
1239+ sendRequestBodyToExtProc (null , true );
1240+ }
1241+ });
1242+ }
1243+
12261244 void proceedWithHalfClose () {
1245+ if (!dataPlaneServerCall .requestSideClosed .compareAndSet (false , true )) {
1246+ return ;
1247+ }
1248+ halfCloseReceived = true ;
12271249 if (dataPlaneServerCall .clientHalfCloseStartNanos > 0 ) {
12281250 long durationNanos = System .nanoTime () - dataPlaneServerCall .clientHalfCloseStartNanos ;
12291251 dataPlaneServerCall .recordDuration (clientHalfCloseDuration , durationNanos );
@@ -1233,12 +1255,15 @@ void proceedWithHalfClose() {
12331255 if (del != null ) {
12341256 dataPlaneServerCall .callContext .run (del ::onHalfClose );
12351257 }
1258+ dataPlaneServerCall .checkEndOfStream ();
12361259 }
12371260
12381261 void onExternalBody (ByteString body ) {
12391262 ServerCall .Listener <InputStream > del = delegate ;
12401263 if (del != null ) {
12411264 dataPlaneServerCall .callContext .run (() -> del .onMessage (new InboundZeroCopyInputStream (body )));
1265+ } else {
1266+ savedMessages .add (new InboundZeroCopyInputStream (body ));
12421267 }
12431268 }
12441269
@@ -1252,8 +1277,10 @@ private void sendRequestBodyToExtProc(@Nullable ByteString bodyByteString, boole
12521277 HttpBody .Builder bodyBuilder = HttpBody .newBuilder ();
12531278 if (bodyByteString != null ) {
12541279 bodyBuilder .setBody (bodyByteString );
1280+ bodyBuilder .setEndOfStream (endOfStream );
1281+ } else {
1282+ bodyBuilder .setEndOfStreamWithoutMessage (true );
12551283 }
1256- bodyBuilder .setEndOfStream (endOfStream );
12571284
12581285 dataPlaneServerCall .sendToExtProc (ProcessingRequest .newBuilder ()
12591286 .setRequestBody (bodyBuilder .build ())
0 commit comments