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

net.pincette.mongo.streams.Delay Maven / Gradle / Ivy

The newest version!
package net.pincette.mongo.streams;

import static java.time.Duration.ofMillis;
import static net.pincette.json.JsonUtil.asLong;
import static net.pincette.json.JsonUtil.asString;
import static net.pincette.json.JsonUtil.isLong;
import static net.pincette.json.JsonUtil.isObject;
import static net.pincette.json.JsonUtil.isString;
import static net.pincette.mongo.Expression.function;
import static net.pincette.mongo.streams.Util.RETRY;
import static net.pincette.mongo.streams.Util.exceptionLogger;
import static net.pincette.rs.Box.box;
import static net.pincette.rs.Filter.filter;
import static net.pincette.rs.Mapper.map;
import static net.pincette.util.Pair.pair;
import static net.pincette.util.ScheduledCompletionStage.composeAsyncAfter;
import static net.pincette.util.Util.must;
import static net.pincette.util.Util.tryToGetForever;

import java.util.Optional;
import java.util.concurrent.Flow.Processor;
import java.util.function.Function;
import javax.json.JsonObject;
import javax.json.JsonValue;
import net.pincette.function.SideEffect;
import net.pincette.rs.streams.Message;

class Delay {
  private static final String DURATION = "duration";
  private static final String TOPIC = "topic";

  private Delay() {}

  private static void sendAfter(
      final Message message,
      final long duration,
      final String topic,
      final Context context) {
    composeAsyncAfter(
            () ->
                tryToGetForever(
                    () -> context.producer.apply(topic, message),
                    RETRY,
                    e -> exceptionLogger(e, "$delay", context)),
            ofMillis(duration))
        .thenApply(result -> must(result, r -> r));
  }

  static Processor, Message> stage(
      final JsonValue expression, final Context context) {
    must(isObject(expression));

    final JsonObject expr = expression.asJsonObject();
    final Function duration =
        function(expr.getValue("/" + DURATION), context.features);
    final Function topic =
        function(expr.getValue("/" + TOPIC), context.features);

    return box(
        map(
            m ->
                Optional.of(pair(duration.apply(m.value), topic.apply(m.value)))
                    .filter(pair -> isLong(pair.first) && isString(pair.second))
                    .map(
                        pair ->
                            SideEffect.>run(
                                    () ->
                                        sendAfter(
                                            m,
                                            asLong(pair.first),
                                            asString(pair.second).getString(),
                                            context))
                                .andThenGet(() -> m.withValue(null)))
                    .orElse(m)),
        filter(m -> m.value != null));
  }
}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy