@Inject public StreamSubscriber(HelloService helloService, StreamRepository repository) { // Create a subscriber helloService.helloEvents().subscribe() // And subscribe to it with at least once processing semantics. .atLeastOnce( // Create a flow that emits a Done for each message it processes Flow.<HelloEvent>create().mapAsync(1, event -> { if (event instanceof HelloEvent.GreetingMessageChanged) { HelloEvent.GreetingMessageChanged messageChanged = (HelloEvent.GreetingMessageChanged) event; // Update the message return repository.updateMessage(messageChanged.getName(), messageChanged.getMessage()); } else { // Ignore all other events return CompletableFuture.completedFuture(Done.getInstance()); } }) ); } }
/** * Create a processing unit from a function. * * @param self reference to the actor carrying the pre-enforcement. * @param processor function to call. * @return Akka stream graph. */ static Graph<FlowShape<WithSender, WithSender>, NotUsed> fromFunction( @Nullable final ActorRef self, final Function<WithDittoHeaders, CompletionStage<WithDittoHeaders>> processor) { final Attributes logLevels = Attributes.createLogLevels(Logging.DebugLevel(), Logging.DebugLevel(), Logging.ErrorLevel()); final Flow<WithSender<WithDittoHeaders>, WithSender, NotUsed> flow = Flow.<WithSender<WithDittoHeaders>>create() .mapAsync(1, wrapped -> { final Supplier<CompletionStage<Object>> futureSupplier = () -> processor.apply(wrapped.getMessage()) .<Object>thenApply(result -> WithSender.of(result, wrapped.getSender())); return handleErrorNowOrLater(futureSupplier, wrapped, self); }) .log("PreEnforcer") .withAttributes(logLevels) .flatMapConcat(PreEnforcer::keepResultAndLogErrors); return Pipe.joinUnhandledSink( Pipe.joinFilteredFlow(Filter.of(WithDittoHeaders.class), flow), unhandled()); }