- 
                Notifications
    
You must be signed in to change notification settings  - Fork 5.1k
 
ext_proc: closing the gRPC stream ASAP once no more external processing needed #41425
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Changes from 8 commits
755e111
              f6b536b
              f8eba26
              dcf5c6c
              07be305
              49fbe96
              33a1d74
              35ef112
              6d4aa09
              921c40b
              bf71363
              2e8ab46
              b8934d1
              4f6542b
              8986c15
              e713075
              1a55c23
              826a6cc
              422ec49
              713ca86
              d72caae
              ac44492
              ac0233f
              23a6c0f
              d40a260
              258aad1
              9a6fa7f
              86ea4b2
              File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change | 
|---|---|---|
| 
          
            
          
           | 
    @@ -715,6 +715,16 @@ void Filter::deferredCloseStream() { | |
| config_->threadLocalStreamManager().deferredErase(stream_, filter_callbacks_->dispatcher()); | ||
| } | ||
| 
     | 
||
| void Filter::closeStreamMaybeGraceful() { | ||
| processing_complete_ = true; | ||
| if (config_->gracefulGrpcClose()) { | ||
| halfCloseAndWaitForRemoteClose(); | ||
| } else { | ||
| // Perform immediate close on the stream otherwise. | ||
| closeStream(); | ||
| } | ||
| } | ||
| 
     | 
||
| void Filter::onDestroy() { | ||
| ENVOY_STREAM_LOG(debug, "onDestroy", *decoder_callbacks_); | ||
| // Make doubly-sure we no longer use the stream, as | ||
| 
          
            
          
           | 
    @@ -742,12 +752,7 @@ void Filter::onDestroy() { | |
| // Second, perform stream deferred closure. | ||
| deferredCloseStream(); | ||
| } else { | ||
| if (config_->gracefulGrpcClose()) { | ||
| halfCloseAndWaitForRemoteClose(); | ||
| } else { | ||
| // Perform immediate close on the stream otherwise. | ||
| closeStream(); | ||
| } | ||
| closeStreamMaybeGraceful(); | ||
| } | ||
| } | ||
| 
     | 
||
| 
          
            
          
           | 
    @@ -1237,6 +1242,12 @@ FilterHeadersStatus Filter::encodeHeaders(ResponseHeaderMap& headers, bool end_s | |
| // local reply. | ||
| mergePerRouteConfig(); | ||
| 
     | 
||
| // If there is no external processing configured in the encoding path, | ||
| // closing the gRPC stream if it is still open. | ||
| if (encoding_state_.noExternalProcess()) { | ||
| closeStreamMaybeGraceful(); | ||
| } | ||
| 
     | 
||
| if (encoding_state_.sendHeaders() && config_->observabilityMode()) { | ||
| return sendHeadersInObservabilityMode(headers, encoding_state_, end_stream); | ||
| } | ||
| 
          
            
          
           | 
    @@ -1547,8 +1558,94 @@ ProcessingMode effectiveModeOverride(const ProcessingMode& target_override, | |
| return mode_override; | ||
| } | ||
| 
     | 
||
| bool isLastBodyResponse(ProcessorState& state, | ||
| const envoy::service::ext_proc::v3::ProcessingResponse& response) { | ||
| switch (state.bodyMode()) { | ||
| case ProcessingMode::BUFFERED: | ||
| case ProcessingMode::BUFFERED_PARTIAL: | ||
                
      
                  yanjunxiang-google marked this conversation as resolved.
               
          
            Show resolved
            Hide resolved
         | 
||
| // TODO: - skip stream closing optimization for BUFFERED and BUFFERED_PARTIAL for now. | ||
| break; | ||
                
      
                  yanjunxiang-google marked this conversation as resolved.
               
              
                Outdated
          
            Show resolved
            Hide resolved
         | 
||
| case ProcessingMode::STREAMED: | ||
| if (!state.chunkQueue().empty()) { | ||
| return state.chunkQueue().queue().front()->end_stream; | ||
                
      
                  yanjunxiang-google marked this conversation as resolved.
               
          
            Show resolved
            Hide resolved
                
      
                  yanjunxiang-google marked this conversation as resolved.
               
          
            Show resolved
            Hide resolved
         | 
||
| } | ||
| break; | ||
| case ProcessingMode::FULL_DUPLEX_STREAMED: { | ||
| const envoy::service::ext_proc::v3::BodyResponse* body_response = nullptr; | ||
| if (response.has_request_body()) { | ||
| body_response = &response.request_body(); | ||
                
      
                  yanjunxiang-google marked this conversation as resolved.
               
              
                Outdated
          
            Show resolved
            Hide resolved
         | 
||
| } else if (response.has_response_body()) { | ||
| body_response = &response.response_body(); | ||
| } | ||
| if (body_response != nullptr && body_response->has_response()) { | ||
| const auto& common_response = body_response->response(); | ||
| if (common_response.has_body_mutation() && | ||
| common_response.body_mutation().has_streamed_response()) { | ||
| return common_response.body_mutation().streamed_response().end_of_stream(); | ||
| } | ||
| } | ||
| break; | ||
| } | ||
| default: | ||
| break; | ||
| } | ||
| return false; | ||
| } | ||
| 
     | 
||
| } // namespace | ||
| 
     | 
||
| // Close the gRPC stream if the last ProcessingResponse is received. | ||
| void Filter::closeGrpcStreamIfLastRespReceived( | ||
| const std::unique_ptr<envoy::service::ext_proc::v3::ProcessingResponse>& response) { | ||
| bool last_response = false; | ||
                
      
                  yanjunxiang-google marked this conversation as resolved.
               
          
            Show resolved
            Hide resolved
         | 
||
| 
     | 
||
| switch (response->response_case()) { | ||
| case ProcessingResponse::ResponseCase::kRequestHeaders: | ||
                
      
                  yanjunxiang-google marked this conversation as resolved.
               
          
            Show resolved
            Hide resolved
         | 
||
| if ((decoding_state_.hasNoBody() || | ||
| (decoding_state_.bodyMode() == ProcessingMode::NONE && !decoding_state_.sendTrailers())) && | ||
                
      
                  yanjunxiang-google marked this conversation as resolved.
               
          
            Show resolved
            Hide resolved
         | 
||
| encoding_state_.noExternalProcess()) { | ||
| last_response = true; | ||
| } | ||
| break; | ||
| case ProcessingResponse::ResponseCase::kRequestBody: | ||
                
      
                  yanjunxiang-google marked this conversation as resolved.
               
          
            Show resolved
            Hide resolved
         | 
||
| if (isLastBodyResponse(decoding_state_, *response) && encoding_state_.noExternalProcess()) { | ||
                
       | 
||
| last_response = true; | ||
| } | ||
| break; | ||
| case ProcessingResponse::ResponseCase::kRequestTrailers: | ||
| if (encoding_state_.noExternalProcess()) { | ||
| last_response = true; | ||
| } | ||
| break; | ||
| case ProcessingResponse::ResponseCase::kResponseHeaders: | ||
| if (encoding_state_.hasNoBody() || | ||
| (encoding_state_.bodyMode() == ProcessingMode::NONE && !encoding_state_.sendTrailers())) { | ||
                
      
                  yanjunxiang-google marked this conversation as resolved.
               
          
            Show resolved
            Hide resolved
         | 
||
| last_response = true; | ||
| } | ||
| break; | ||
| case ProcessingResponse::ResponseCase::kResponseBody: | ||
| if (isLastBodyResponse(encoding_state_, *response)) { | ||
| last_response = true; | ||
                
      
                  yanjunxiang-google marked this conversation as resolved.
               
          
            Show resolved
            Hide resolved
         | 
||
| } | ||
| break; | ||
| case ProcessingResponse::ResponseCase::kResponseTrailers: | ||
| last_response = true; | ||
| break; | ||
| case ProcessingResponse::ResponseCase::kImmediateResponse: | ||
| // Immediate response currently may close the stream immediately. | ||
| // Leave it as it is for now. | ||
| break; | ||
| default: | ||
| break; | ||
| } | ||
| 
     | 
||
| if (last_response) { | ||
| ENVOY_STREAM_LOG(debug, "Closing gRPC stream after receiving last response", | ||
| *decoder_callbacks_); | ||
| closeStreamMaybeGraceful(); | ||
| } | ||
| } | ||
| 
     | 
||
| void Filter::onReceiveMessage(std::unique_ptr<ProcessingResponse>&& r) { | ||
| 
     | 
||
| if (config_->observabilityMode()) { | ||
| 
          
            
          
           | 
    @@ -1616,6 +1713,10 @@ void Filter::onReceiveMessage(std::unique_ptr<ProcessingResponse>&& r) { | |
| 
     | 
||
| ENVOY_STREAM_LOG(debug, "Received {} response", *decoder_callbacks_, | ||
| responseCaseToString(response->response_case())); | ||
| 
     | 
||
| // Close the gRPC stream if this is the last response message. | ||
| closeGrpcStreamIfLastRespReceived(response); | ||
| 
     | 
||
| absl::Status processing_status; | ||
| switch (response->response_case()) { | ||
| case ProcessingResponse::ResponseCase::kRequestHeaders: | ||
| 
          
            
          
           | 
    @@ -1656,11 +1757,7 @@ void Filter::onReceiveMessage(std::unique_ptr<ProcessingResponse>&& r) { | |
| ENVOY_STREAM_LOG(debug, "Sending immediate response", *decoder_callbacks_); | ||
| processing_complete_ = true; | ||
| onFinishProcessorCalls(Grpc::Status::Ok); | ||
| if (config_->gracefulGrpcClose()) { | ||
| halfCloseAndWaitForRemoteClose(); | ||
| } else { | ||
| closeStream(); | ||
| } | ||
| closeStreamMaybeGraceful(); | ||
| if (on_processing_response_) { | ||
| on_processing_response_->afterReceivingImmediateResponse( | ||
| response->immediate_response(), absl::OkStatus(), decoder_callbacks_->streamInfo()); | ||
| 
          
            
          
           | 
    @@ -1739,6 +1836,10 @@ void Filter::onGrpcClose() { onGrpcCloseWithStatus(Grpc::Status::Aborted); } | |
| void Filter::onGrpcCloseWithStatus(Grpc::Status::GrpcStatus status) { | ||
| ENVOY_STREAM_LOG(debug, "Received gRPC stream close", *decoder_callbacks_); | ||
| 
     | 
||
| if (processing_complete_) { | ||
| return; | ||
| } | ||
| 
     | 
||
| processing_complete_ = true; | ||
| stats_.streams_closed_.inc(); | ||
| // Successful close. We can ignore the stream for the rest of our request | ||
| 
          
            
          
           | 
    ||
Uh oh!
There was an error while loading. Please reload this page.