Fix a bug where the trailers of a streaming response was dropped by RetryingClient - #6213
Conversation
…etryingClient Motivation: During the implementation of line#5714, `HttpResponse.split()` was used to extract the headers from a streaming response. After applying a `RetryRule`, the new response was reconstructed in https://github.com/line/armeria/blob/3a35abe68c80c0af8594600ce677df49e09a9e0e/core/src/main/java/com/linecorp/armeria/client/retry/RetryingClient.java#L429 However, because `SplitHttpResponse.body()` only publishes the data payloads and handles trailers separately, the trailers was missing in the reconstructed response, leading to a bug. Modifications: - Fixed `SurroundingPublisher` to allow emitting the last element asynchronously. - Added `SplitHttpRequest.unsplit()` and `SplitHttpResponse.unsplit()` to re-create an `HttpResponse` from the split headers, body and trailers. - Fixed `RetryingClient` to use `.unsplit()` for deliveriong trailers correctly. Result: Fix a regression where RetryingClient dropped trailers of streaming responses (since 1.32.4)
Codecov ReportAttention: Patch coverage is
Additional details and impacted files@@ Coverage Diff @@
## main #6213 +/- ##
============================================
+ Coverage 74.46% 74.61% +0.14%
- Complexity 22234 22484 +250
============================================
Files 1963 1974 +11
Lines 82437 83034 +597
Branches 10764 10802 +38
============================================
+ Hits 61385 61952 +567
- Misses 15918 15935 +17
- Partials 5134 5147 +13 ☔ View full report in Codecov by Sentry. 🚀 New features to boost your workflow:
|
| } | ||
| } | ||
|
|
||
| private void handleTail(@Nullable T tail, @Nullable Throwable cause) { |
There was a problem hiding this comment.
It seems like the cause is always null because tailFuture never completes exceptionally.
There was a problem hiding this comment.
tailFuture can be specified by a user.
armeria/core/src/main/java/com/linecorp/armeria/common/HttpResponse.java
Lines 537 to 539 in 54730fe
|
|
||
| SurroundingSubscriber(@Nullable T head, StreamMessage<T> publisher, | ||
| Function<@Nullable Throwable, ? extends @Nullable T> finalizer, | ||
| Function<@Nullable Throwable, ? extends @Nullable CompletableFuture<T>> finalizer, |
There was a problem hiding this comment.
Understood that the throwable can be null, the CF can be null, and the tail handeld by the CF can also be null.
There was a problem hiding this comment.
Correct. All can be null.
Motivation:
During the implementation of #5714,
HttpResponse.split()was used to extract the headers from a streaming response. After applying aRetryRule, the new response was reconstructed inarmeria/core/src/main/java/com/linecorp/armeria/client/retry/RetryingClient.java
Line 429 in 3a35abe
However, because
SplitHttpResponse.body()only publishes the data payloads and handles trailers separately, the trailers was missing in the reconstructed response, leading to a bug.Modifications:
SurroundingPublisherto allow the last element to be emitted asynchronously.SplitHttpRequest.unsplit()andSplitHttpResponse.unsplit()to re-create anHttpResponsefrom the split headers, body and trailers.RetryingClientto use.unsplit()for deliveriong trailers correctly.Result:
Fix a regression where RetryingClient dropped trailers of streaming responses (since 1.32.4)