lizining1231 opened a new pull request, #3754:
URL: https://github.com/apache/dubbo-go/pull/3754

   ### Description
   
   Fixes #3753
   
   When a peer finishes a stream before the client closes its request side, the 
final buffered flush can return `io.EOF`. The gRPC and Triple `CloseRequest` 
paths returned that write-side EOF even when `CloseWrite` succeeded. As a 
result, callers could receive `unknown: EOF`, and the write-side error could 
replace the response status already sent by the peer.
   
   Treat `io.EOF` from the final buffered flush as a completed peer-side close. 
The underlying write side is still closed, its close error is still returned, 
and non-EOF flush errors retain precedence.
   
   Add a deterministic regression test for both wire formats. The test forces 
the buffered flush to return `io.EOF`; the server signals only after reading 
the request body to EOF, proving that `CloseRequest` still closes the write 
side without exposing the pipe error.
   
   ### Changes
   
   - Update `grpcClientConn.CloseRequest` and 
`tripleUnaryClientConn.CloseRequest` to tolerate `io.EOF` from the final 
buffered flush. Both paths still call `CloseWrite`, return its result after a 
buffered EOF, and continue to report every non-EOF flush error.
   - Add `TestCloseRequestIgnoresBufferedWriteEOF` to cover the fix on both 
gRPC and Triple. The test forces the final buffered flush to return `io.EOF` 
and verifies that `CloseRequest` succeeds while still closing the request write 
side.
   
   ### Verification
   
   #### Deterministic regression test
   
   The new `TestCloseRequestIgnoresBufferedWriteEOF` unit test writes pending 
bytes into a `streamBufferWriter` backed by an `errorWriter` that always 
returns `io.EOF`. This deterministically reproduces the final flush error 
without relying on client and server scheduling.
   
   The buffer is attached to a real `duplexHTTPCall` connected to an 
`httptest.Server`. The server drains the request body with `io.Copy` and sends 
its completion signal only after reading EOF. The test therefore verifies both 
parts of the contract: `CloseRequest` does not expose the buffered EOF, and it 
still calls `CloseWrite` so the server can observe the end of the request body. 
Table-driven cases cover both `grpcClientConn` and `tripleUnaryClientConn`.
   
   With the old `CloseRequest` condition restored, the new test fails 
deterministically:
   
   ```console
   $ go test ./protocol/triple/triple_protocol/ -run 
'^TestCloseRequestIgnoresBufferedWriteEOF$' -count=1
   --- FAIL: TestCloseRequestIgnoresBufferedWriteEOF (0.01s)
       buffered_writer_test.go:525: CloseRequest after buffered EOF: EOF
   FAIL
   FAIL    dubbo.apache.org/dubbo-go/v3/protocol/triple/triple_protocol    
0.041s
   FAIL
   ```
   
   After the fix, the new regression and the adjacent error-handling tests pass 
20 consecutive runs:
   
   ```console
   $ go test ./protocol/triple/triple_protocol/ -run 
'TestCloseRequestIgnoresBufferedWriteEOF|TestCloseRequestClosesWriteSideAfterFlushFailure|TestBufferedWriteEOFDoesNotMaskResponse'
 -count=20
   ok      dubbo.apache.org/dubbo-go/v3/protocol/triple/triple_protocol    
0.649s
   ```
   
   `TestCloseRequestClosesWriteSideAfterFlushFailure` remains in this test set 
to verify that non-EOF flush errors are still returned rather than being 
swallowed.
   
   #### Issue reproduction
   
   The narrowed reproduction from #3753 also failed before the fix:
   
   ```console
   $ go test ./protocol/triple/triple_protocol/ -run 
'TestStreamForServer|TestGRPCMissingTrailersError' -count=20
   --- FAIL: TestGRPCMissingTrailersError (0.00s)
       --- FAIL: TestGRPCMissingTrailersError/sum (0.00s)
           triple_ext_test.go:890:
               assertion:  assert.Equal
               got:        unknown
               want:       internal
   FAIL
   FAIL    dubbo.apache.org/dubbo-go/v3/protocol/triple/triple_protocol    
2.107s
   FAIL
   ```
   
   After the fix, the test is ok
   
   ```console
   $ for run in 1 2 3 4 5; do
   >   go test ./protocol/triple/triple_protocol/ -run 
'TestStreamForServer|TestGRPCMissingTrailersError' -count=20
   > done
   ok      dubbo.apache.org/dubbo-go/v3/protocol/triple/triple_protocol    
2.075s
   ok      dubbo.apache.org/dubbo-go/v3/protocol/triple/triple_protocol    
2.099s
   ok      dubbo.apache.org/dubbo-go/v3/protocol/triple/triple_protocol    
2.081s
   ok      dubbo.apache.org/dubbo-go/v3/protocol/triple/triple_protocol    
2.091s
   ok      dubbo.apache.org/dubbo-go/v3/protocol/triple/triple_protocol    
2.098s
   ```
   
   ### Checklist
   
   - [x] I confirm the target branch is `develop`
   - [x] I have run `make fmt` to format my code
   - [x] I have run `make test` to run local tests
   - [x] I have added tests that prove my fix is effective or that my feature 
works
   


-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: [email protected]

For queries about this service, please contact Infrastructure at:
[email protected]


---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]

Reply via email to