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);
}
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);
}
Aggregations