org.neo4j.driver.internal.reactive.RxUtils Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of neo4j-java-driver Show documentation
Show all versions of neo4j-java-driver Show documentation
Access to the Neo4j graph database through Java
The newest version!
/*
* Copyright (c) "Neo4j"
* Neo4j Sweden AB [https://neo4j.com]
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.neo4j.driver.internal.reactive;
import static java.util.Objects.requireNonNull;
import java.util.Optional;
import java.util.concurrent.CompletionStage;
import java.util.function.Consumer;
import java.util.function.Supplier;
import org.neo4j.driver.internal.util.Futures;
import org.reactivestreams.Publisher;
import reactor.core.publisher.Mono;
public class RxUtils {
/**
* The publisher created by this method will either succeed without publishing anything or fail with an error.
*
* @param supplier supplies a {@link CompletionStage}.
* @return A publisher that publishes nothing on completion or fails with an error.
*/
public static Publisher createEmptyPublisher(Supplier> supplier) {
return Mono.create(sink -> supplier.get().whenComplete((ignore, completionError) -> {
var error = Futures.completionExceptionCause(completionError);
if (error != null) {
sink.error(error);
} else {
sink.success();
}
}));
}
/**
* The publisher created by this method will either succeed with exactly one item or fail with an error.
*
* @param supplier supplies a {@link CompletionStage} that MUST produce a non-null result when completed successfully.
* @param nullResultThrowableSupplier supplies a {@link Throwable} that is used as an error when the supplied completion stage completes successfully with
* null.
* @param cancellationHandler handles cancellation, may be used to release associated resources
* @param the type of the item to publish.
* @return A publisher that succeeds exactly one item or fails with an error.
*/
public static Mono createSingleItemPublisher(
Supplier> supplier,
Supplier nullResultThrowableSupplier,
Consumer cancellationHandler) {
requireNonNull(supplier, "supplier must not be null");
requireNonNull(nullResultThrowableSupplier, "nullResultThrowableSupplier must not be null");
requireNonNull(cancellationHandler, "cancellationHandler must not be null");
return Mono.create(sink -> {
var state = new SinkState();
sink.onRequest(ignored -> {
CompletionStage stage;
synchronized (state) {
if (state.isCancelled()) {
return;
}
if (state.getStage() != null) {
return;
}
stage = supplier.get();
state.setStage(stage);
}
stage.whenComplete((item, completionError) -> {
if (completionError == null) {
if (item != null) {
sink.success(item);
} else {
sink.error(nullResultThrowableSupplier.get());
}
} else {
var error = Optional.ofNullable(Futures.completionExceptionCause(completionError))
.orElse(completionError);
sink.error(error);
}
});
});
sink.onCancel(() -> {
CompletionStage stage;
synchronized (state) {
if (state.isCancelled()) {
return;
}
state.setCancelled(true);
stage = state.getStage();
}
if (stage != null) {
stage.whenComplete((value, ignored) -> cancellationHandler.accept(value));
}
});
});
}
private static class SinkState {
private CompletionStage stage;
private boolean cancelled;
public CompletionStage getStage() {
return stage;
}
public void setStage(CompletionStage stage) {
this.stage = stage;
}
public boolean isCancelled() {
return cancelled;
}
public void setCancelled(boolean cancelled) {
this.cancelled = cancelled;
}
}
}
© 2015 - 2024 Weber Informatics LLC | Privacy Policy