Class BeforeFinallyHttpOperator

java.lang.Object
io.servicetalk.http.utils.BeforeFinallyHttpOperator
All Implemented Interfaces:
SingleOperator<StreamingHttpResponse,StreamingHttpResponse>, Function<SingleSource.Subscriber<? super StreamingHttpResponse>,SingleSource.Subscriber<? super StreamingHttpResponse>>

public final class BeforeFinallyHttpOperator extends Object implements SingleOperator<StreamingHttpResponse,StreamingHttpResponse>
Helper operator for signaling the end of an HTTP Request/Response cycle.

StreamingHttpRequest and StreamingHttpResponse are nested sources (Single of meta-data containing a payload Publisher), which makes it non-trivial to get a single signal at the end of this Request/Response cycle. One needs to consider and coordinate between the multitude of outcomes: cancel/success/error across both sources.

This operator ensures that the provided callback is triggered just once whenever the sources reach a terminal state across both sources. An important question is when the ownership of the callback is transferred from the Single source and the payload Publisher. In this case ownership is transferred the first time the payload is subscribed to. This means that if a cancellation of the response Single occurs after the response has been emitted but before the message body has been subscribed to, the callback will observe a cancel. However, if the message payload has been subscribed to, the cancellation of the Single will have no effect and the result is dictated by the terminal event of the payload body. If the body is subscribed to multiple times, only the first subscribe will receive ownership of the terminal events.

Example usage tracking the begin and end of a request:

     // coarse grained, any terminal signal calls the provided `Runnable`
     return requester.request(strategy, request)
                     .beforeOnSubscribe(__ -> tracker.requestStarted())
                     .liftSync(new BeforeFinallyHttpOperator(tracker::requestFinished));

     // fine grained, `tracker` implements `TerminalSignalConsumer`, terminal signal indicated by the callback method
     return requester.request(strategy, request)
                     .beforeOnSubscribe(__ -> tracker.requestStarted())
                     .liftSync(new BeforeFinallyHttpOperator(tracker));