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]