All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.infinispan.reactive.RxJavaInterop Maven / Gradle / Ivy

There is a newer version: 15.1.0.Dev04
Show newest version
package org.infinispan.reactive;

import java.lang.invoke.MethodHandles;
import java.util.concurrent.CompletionStage;
import java.util.concurrent.atomic.AtomicBoolean;
import java.util.function.BiFunction;

import org.infinispan.commons.util.concurrent.CompletionStages;
import org.infinispan.util.logging.Log;
import org.infinispan.util.logging.LogFactory;

import io.reactivex.rxjava3.core.Flowable;
import io.reactivex.rxjava3.processors.AsyncProcessor;
import io.reactivex.rxjava3.processors.UnicastProcessor;

/**
 * Static factory class that provides methods to obtain commonly used instances for interoperation between RxJava
 * and standard JRE.
 * @author wburns
 * @since 10.0
 */
public class RxJavaInterop extends org.infinispan.commons.reactive.RxJavaInterop {
   private RxJavaInterop() { }

   protected final static Log log = LogFactory.getLog(MethodHandles.lookup().lookupClass());

   private static final BiFunction> combineBiFunction = (v1, v2) -> {
      if (v1 != null) {
         if (v2 != null) {
            return Flowable.just(v1, v2);
         }
         return Flowable.just(v1);
      } else if (v2 != null) {
         return Flowable.just(v2);
      }
      return Flowable.empty();
   };

   public static  Flowable voidCompletionStageToFlowable(CompletionStage stage) {
      if (CompletionStages.isCompletedSuccessfully(stage)) {
         return Flowable.empty();
      }
      AsyncProcessor ap = AsyncProcessor.create();

      stage.whenComplete((value, t) -> {
         if (t != null) {
            ap.onError(t);
         } else {
            ap.onComplete();
         }
      });

      return ap;
   }

   /**
    * Same as {@link #voidCompletionStageToFlowable(CompletionStage)} except that you can optionally have it so that if
    * a throwable occurs in the stage that it isn't propagated if the returned Flowable's subscription was cancelled.
    * 

* This method also only allows for a single subscriber to the Flowable, any additional subscribers will receive * an exception when subscribing to the returned Flowable. * {@link #voidCompletionStageToFlowable(CompletionStage)} can support any number of subscribers. * @param stage stage to complete * @param ignoreErrorIfCancelled whether to ignore an error if cancelled * @param stage type * @return a Flowable that is completed when the stage is */ public static Flowable voidCompletionStageToFlowable(CompletionStage stage, boolean ignoreErrorIfCancelled) { if (!ignoreErrorIfCancelled) { return voidCompletionStageToFlowable(stage); } if (CompletionStages.isCompletedSuccessfully(stage)) { return Flowable.empty(); } AtomicBoolean cancelled = new AtomicBoolean(); UnicastProcessor ap = UnicastProcessor.create(1, () -> cancelled.set(true)); stage.whenComplete((value, t) -> { if (t != null) { if (!cancelled.get()) { ap.onError(t); } else { log.debug("Ignoring throwable as the UnicastProcessor is already completed", t); } } else { ap.onComplete(); } }); return ap; } /** * Provides a {@link BiFunction} to be used with methods like {@link CompletionStage#thenCombine(CompletionStage, java.util.function.BiFunction)} * to convert the values to a {@link Flowable}. Note this is useful as Flowable does not allow null values * and this function will handle this properly by not publishing a value if it is null. So it is possible to have * an empty Flowable returned. * @return a function to be used to combine the possible values as a returned Flowable * @param user value type */ public static BiFunction> combinedBiFunction() { return (BiFunction) combineBiFunction; } }