Remove use of MonoProcessor.fromSinks

See gh-25884
This commit is contained in:
Rossen Stoyanchev
2020-10-09 20:45:27 +01:00
parent cdd48ddd7f
commit e73e489fd8
30 changed files with 300 additions and 227 deletions

View File

@@ -25,7 +25,6 @@ import java.util.function.Function;
import org.reactivestreams.Publisher;
import reactor.core.publisher.Flux;
import reactor.core.publisher.Mono;
import reactor.core.publisher.MonoProcessor;
import reactor.core.publisher.Sinks;
import org.springframework.core.io.buffer.DataBuffer;
@@ -64,11 +63,14 @@ public class MockServerHttpResponse extends AbstractServerHttpResponse {
public MockServerHttpResponse(DataBufferFactory dataBufferFactory) {
super(dataBufferFactory);
this.writeHandler = body -> {
// Avoid .then() which causes data buffers to be released
MonoProcessor<Void> completion = MonoProcessor.fromSink(Sinks.one());
this.body = body.doOnComplete(completion::onComplete).doOnError(completion::onError).cache();
// Avoid .then() that causes data buffers to be discarded and released
Sinks.Empty<Void> completion = Sinks.unsafe().empty();
this.body = body
.doOnComplete(completion::tryEmitEmpty) // Ignore error: cached + serialized
.doOnError(completion::tryEmitError)
.cache();
this.body.subscribe();
return completion;
return completion.asMono();
};
}

View File

@@ -24,7 +24,6 @@ import org.apache.commons.logging.LogFactory;
import org.reactivestreams.Publisher;
import reactor.core.publisher.Flux;
import reactor.core.publisher.Mono;
import reactor.core.publisher.MonoProcessor;
import reactor.core.publisher.Sinks;
import reactor.core.scheduler.Schedulers;
@@ -84,8 +83,8 @@ public class HttpHandlerConnector implements ClientHttpConnector {
private Mono<ClientHttpResponse> doConnect(
HttpMethod httpMethod, URI uri, Function<? super ClientHttpRequest, Mono<Void>> requestCallback) {
MonoProcessor<Void> requestWriteCompletion = MonoProcessor.fromSink(Sinks.one());
MonoProcessor<Void> handlerCompletion = MonoProcessor.fromSink(Sinks.one());
Sinks.Empty<Void> requestWriteCompletion = Sinks.empty();
Sinks.Empty<Void> handlerCompletion = Sinks.empty();
ClientHttpResponse[] savedResponse = new ClientHttpResponse[1];
MockClientHttpRequest mockClientRequest = new MockClientHttpRequest(httpMethod, uri);
@@ -95,7 +94,10 @@ public class HttpHandlerConnector implements ClientHttpConnector {
log("Invoking HttpHandler for ", httpMethod, uri);
ServerHttpRequest mockServerRequest = adaptRequest(mockClientRequest, requestBody);
ServerHttpResponse responseToUse = prepareResponse(mockServerResponse, mockServerRequest);
this.handler.handle(mockServerRequest, responseToUse).subscribe(handlerCompletion);
this.handler.handle(mockServerRequest, responseToUse).subscribe(
aVoid -> {},
handlerCompletion::tryEmitError, // Ignore error: cached + serialized
handlerCompletion::tryEmitEmpty);
return Mono.empty();
});
@@ -106,9 +108,12 @@ public class HttpHandlerConnector implements ClientHttpConnector {
}));
log("Writing client request for ", httpMethod, uri);
requestCallback.apply(mockClientRequest).subscribe(requestWriteCompletion);
requestCallback.apply(mockClientRequest).subscribe(
aVoid -> {},
requestWriteCompletion::tryEmitError, // Ignore error: cached + serialized
requestWriteCompletion::tryEmitEmpty);
return Mono.when(requestWriteCompletion, handlerCompletion)
return Mono.when(requestWriteCompletion.asMono(), handlerCompletion.asMono())
.onErrorMap(ex -> {
ClientHttpResponse response = savedResponse[0];
return response != null ? new FailureAfterResponseCompletedException(response, ex) : ex;

View File

@@ -24,9 +24,9 @@ import java.util.concurrent.atomic.AtomicReference;
import java.util.function.Function;
import org.reactivestreams.Publisher;
import reactor.core.Scannable;
import reactor.core.publisher.Flux;
import reactor.core.publisher.Mono;
import reactor.core.publisher.MonoProcessor;
import reactor.core.publisher.Sinks;
import org.springframework.core.io.buffer.DataBuffer;
@@ -138,7 +138,8 @@ class WiretapConnector implements ClientHttpConnector {
private final DataBuffer buffer = DefaultDataBufferFactory.sharedInstance.allocateBuffer();
private final MonoProcessor<byte[]> content = MonoProcessor.fromSink(Sinks.one());
// unsafe(): we're intercepting, already serialized Publisher signals
private final Sinks.One<byte[]> content = Sinks.unsafe().one();
private boolean hasContentConsumer;
@@ -167,7 +168,8 @@ class WiretapConnector implements ClientHttpConnector {
.doOnComplete(this::handleOnComplete) : null;
if (publisher == null && publisherNested == null) {
this.content.onComplete();
// Ignore result: OK or not relevant
this.content.tryEmitEmpty();
}
}
@@ -184,8 +186,8 @@ class WiretapConnector implements ClientHttpConnector {
public Mono<byte[]> getContent() {
return Mono.defer(() -> {
if (this.content.isTerminated()) {
return this.content;
if (this.content.scan(Scannable.Attr.TERMINATED) == Boolean.TRUE) {
return this.content.asMono();
}
if (!this.hasContentConsumer) {
// Couple of possible cases:
@@ -198,23 +200,21 @@ class WiretapConnector implements ClientHttpConnector {
"an error was raised while attempting to produce it.", ex))
.subscribe();
}
return this.content;
return this.content.asMono();
});
}
private void handleOnError(Throwable ex) {
if (!this.content.isTerminated()) {
this.content.onError(ex);
}
// Ignore result: OK or not relevant
this.content.tryEmitError(ex);
}
private void handleOnComplete() {
if (!this.content.isTerminated()) {
byte[] bytes = new byte[this.buffer.readableByteCount()];
this.buffer.read(bytes);
this.content.onNext(bytes);
}
byte[] bytes = new byte[this.buffer.readableByteCount()];
this.buffer.read(bytes);
// Ignore result: OK or not relevant
this.content.tryEmitValue(bytes);
}
}