Search in sources :

Example 1 with UniqueKillSwitch

use of akka.stream.UniqueKillSwitch in project play-java-websocket-example by playframework.

the class UserActor method addStock.

/**
 * Adds a single stock to the hub.
 */
private void addStock(Stock stock) {
    logger.info("Adding stock {}", stock);
    // We convert everything to JsValue so we get a single stream for the websocket.
    // Make sure the history gets written out before the updates for this stock...
    final Source<JsonNode, NotUsed> historySource = stock.history(50).map(Json::toJson);
    final Source<JsonNode, NotUsed> updateSource = stock.update().map(Json::toJson);
    final Source<JsonNode, NotUsed> stockSource = historySource.concat(updateSource);
    // Set up a flow that will let us pull out a killswitch for this specific stock,
    // and automatic cleanup for very slow subscribers (where the browser has crashed, etc).
    final Flow<JsonNode, JsonNode, UniqueKillSwitch> killswitchFlow = Flow.of(JsonNode.class).joinMat(KillSwitches.singleBidi(), Keep.right());
    // Set up a complete runnable graph from the stock source to the hub's sink
    String name = "stock-" + stock.symbol + "-" + id;
    final RunnableGraph<UniqueKillSwitch> graph = stockSource.viaMat(killswitchFlow, Keep.right()).to(hubSink).named(name);
    // Start it up!
    UniqueKillSwitch killSwitch = graph.run(mat);
    // Pull out the kill switch so we can stop it when we want to unwatch a stock.
    stocksMap.put(stock.symbol, killSwitch);
}
Also used : UniqueKillSwitch(akka.stream.UniqueKillSwitch) JsonNode(com.fasterxml.jackson.databind.JsonNode) NotUsed(akka.NotUsed) Json(play.libs.Json)

Example 2 with UniqueKillSwitch

use of akka.stream.UniqueKillSwitch in project torodb by torodb.

the class DefaultOplogApplier method apply.

@Override
public ApplyingJob apply(OplogFetcher fetcher, ApplierContext applierContext) {
    Materializer materializer = ActorMaterializer.create(actorSystem);
    RunnableGraph<Pair<UniqueKillSwitch, CompletionStage<Done>>> graph = createOplogSource(fetcher).async().via(createBatcherFlow(applierContext)).viaMat(KillSwitches.single(), Keep.right()).async().map(analyzedElem -> {
        for (AnalyzedOplogBatch analyzedOplogBatch : analyzedElem.analyzedBatch) {
            batchExecutor.apply(analyzedOplogBatch, applierContext);
        }
        return analyzedElem;
    }).map(this::metricExecution).toMat(Sink.foreach(this::storeLastAppliedOp), (killSwitch, completionStage) -> new Pair<>(killSwitch, completionStage));
    Pair<UniqueKillSwitch, CompletionStage<Done>> pair = graph.run(materializer);
    UniqueKillSwitch killSwitch = pair.first();
    CompletableFuture<Empty> whenComplete = pair.second().toCompletableFuture().thenApply(done -> Empty.getInstance()).whenComplete((done, t) -> {
        fetcher.close();
        if (done != null) {
            LOGGER.trace("Oplog replication stream finished normally");
        } else {
            Throwable cause;
            if (t instanceof CompletionException) {
                cause = t.getCause();
            } else {
                cause = t;
            }
            //the completable future has been cancelled
            if (cause instanceof CancellationException) {
                LOGGER.debug("Oplog replication stream has been cancelled");
                killSwitch.shutdown();
            } else {
                //in this case the exception should came from the stream
                cause = Throwables.getRootCause(cause);
                LOGGER.error("Oplog replication stream finished exceptionally: " + cause.getLocalizedMessage(), cause);
                //the stream should be finished exceptionally, but just in case we
                //notify the kill switch to stop the stream.
                killSwitch.shutdown();
            }
        }
    });
    return new DefaultApplyingJob(killSwitch, whenComplete);
}
Also used : AnalyzedOplogBatch(com.torodb.mongodb.repl.oplogreplier.batch.AnalyzedOplogBatch) BatchAnalyzerFactory(com.torodb.mongodb.repl.oplogreplier.batch.BatchAnalyzer.BatchAnalyzerFactory) BiFunction(java.util.function.BiFunction) Flow(akka.stream.javadsl.Flow) Source(akka.stream.javadsl.Source) Supplier(com.google.common.base.Supplier) KillSwitch(akka.stream.KillSwitch) Materializer(akka.stream.Materializer) CompletableFuture(java.util.concurrent.CompletableFuture) UniqueKillSwitch(akka.stream.UniqueKillSwitch) OplogManager(com.torodb.mongodb.repl.OplogManager) BatchAnalyzer(com.torodb.mongodb.repl.oplogreplier.batch.BatchAnalyzer) Inject(javax.inject.Inject) ActorMaterializer(akka.stream.ActorMaterializer) Keep(akka.stream.javadsl.Keep) RunnableGraph(akka.stream.javadsl.RunnableGraph) OplogOperation(com.eightkdata.mongowp.server.api.oplog.OplogOperation) Empty(com.eightkdata.mongowp.server.api.tools.Empty) OplogManagerPersistException(com.torodb.mongodb.repl.OplogManager.OplogManagerPersistException) AnalyzedOplogBatchExecutor(com.torodb.mongodb.repl.oplogreplier.batch.AnalyzedOplogBatchExecutor) ConcurrentToolsFactory(com.torodb.core.concurrent.ConcurrentToolsFactory) AnalyzedOplogBatch(com.torodb.mongodb.repl.oplogreplier.batch.AnalyzedOplogBatch) OplogFetcher(com.torodb.mongodb.repl.oplogreplier.fetcher.OplogFetcher) Shutdowner(com.torodb.core.Shutdowner) Done(akka.Done) CancellationException(java.util.concurrent.CancellationException) FiniteDuration(scala.concurrent.duration.FiniteDuration) Predicate(java.util.function.Predicate) ToIntFunction(java.util.function.ToIntFunction) Sink(akka.stream.javadsl.Sink) Throwables(com.google.common.base.Throwables) CompletionException(java.util.concurrent.CompletionException) KillSwitches(akka.stream.KillSwitches) WriteOplogTransaction(com.torodb.mongodb.repl.OplogManager.WriteOplogTransaction) ExecutionContexts(akka.dispatch.ExecutionContexts) Pair(akka.japi.Pair) TimeUnit(java.util.concurrent.TimeUnit) Duration(scala.concurrent.duration.Duration) List(java.util.List) Logger(org.apache.logging.log4j.Logger) CompletionStage(java.util.concurrent.CompletionStage) NotUsed(akka.NotUsed) BatchFlow(com.torodb.concurrent.akka.BatchFlow) ActorSystem(akka.actor.ActorSystem) Optional(java.util.Optional) LogManager(org.apache.logging.log4j.LogManager) Await(scala.concurrent.Await) Done(akka.Done) UniqueKillSwitch(akka.stream.UniqueKillSwitch) Empty(com.eightkdata.mongowp.server.api.tools.Empty) CancellationException(java.util.concurrent.CancellationException) CompletionException(java.util.concurrent.CompletionException) Materializer(akka.stream.Materializer) ActorMaterializer(akka.stream.ActorMaterializer) CompletionStage(java.util.concurrent.CompletionStage) Pair(akka.japi.Pair)

Aggregations

NotUsed (akka.NotUsed)2 UniqueKillSwitch (akka.stream.UniqueKillSwitch)2 Done (akka.Done)1 ActorSystem (akka.actor.ActorSystem)1 ExecutionContexts (akka.dispatch.ExecutionContexts)1 Pair (akka.japi.Pair)1 ActorMaterializer (akka.stream.ActorMaterializer)1 KillSwitch (akka.stream.KillSwitch)1 KillSwitches (akka.stream.KillSwitches)1 Materializer (akka.stream.Materializer)1 Flow (akka.stream.javadsl.Flow)1 Keep (akka.stream.javadsl.Keep)1 RunnableGraph (akka.stream.javadsl.RunnableGraph)1 Sink (akka.stream.javadsl.Sink)1 Source (akka.stream.javadsl.Source)1 OplogOperation (com.eightkdata.mongowp.server.api.oplog.OplogOperation)1 Empty (com.eightkdata.mongowp.server.api.tools.Empty)1 JsonNode (com.fasterxml.jackson.databind.JsonNode)1 Supplier (com.google.common.base.Supplier)1 Throwables (com.google.common.base.Throwables)1