net.pincette.mongo.streams.Probe Maven / Gradle / Ivy
The newest version!
package net.pincette.mongo.streams;
import static java.time.Duration.between;
import static java.time.Instant.now;
import static java.time.temporal.ChronoUnit.MINUTES;
import static java.util.Optional.empty;
import static net.pincette.json.JsonUtil.createObjectBuilder;
import static net.pincette.json.JsonUtil.isObject;
import static net.pincette.rs.Async.mapAsyncSequential;
import static net.pincette.rs.Filter.filter;
import static net.pincette.rs.Mapper.map;
import static net.pincette.rs.Pipe.pipe;
import static net.pincette.rs.Util.pull;
import static net.pincette.rs.Util.tap;
import static net.pincette.util.Util.must;
import java.time.Instant;
import java.util.Optional;
import java.util.concurrent.Flow.Processor;
import javax.json.JsonObject;
import javax.json.JsonValue;
import net.pincette.rs.streams.Message;
/**
* The $probe
operator.
*
* @author Werner Donné
*/
class Probe {
private Probe() {}
private static Processor, Boolean> probe(
final String name, final String topic, final Context context) {
final Running running = new Running();
return pipe(map(
(Message m) ->
m.withValue(updateRunning(running, name).orElse(null))))
.then(filter(m -> m.value != null))
.then(mapAsyncSequential(m -> context.producer.apply(topic, m)));
}
static Processor, Message> stage(
final JsonValue expression, final Context context) {
must(isObject(expression));
return tap(
pull(
probe(
expression.asJsonObject().getString("name"),
expression.asJsonObject().getString("topic"),
context)));
}
private static JsonObject toJson(final Running running, final String name) {
return createObjectBuilder()
.add("name", name)
.add("minute", running.minute.toString())
.add("count", running.count)
.build();
}
private static Optional updateRunning(final Running running, final String name) {
final Instant now = now().truncatedTo(MINUTES);
if (between(running.minute, now).getSeconds() > 59) {
final JsonObject result = toJson(running, name);
running.count = 0;
running.minute = now;
return Optional.of(result);
}
++running.count;
return empty();
}
private static class Running {
private long count = 0;
private Instant minute = now().truncatedTo(MINUTES);
}
}