return splitter.via(Flow.fromGraph(GraphDSL.<FlowShape<F.Either<FlowIn, Out>, Out>>create(builder -> { UniformFanInShape<Out, Out> merge = builder.add(mergeStrategy); Flow<F.Either<FlowIn, Out>, FlowIn, ?> collectIn = Flow.<F.Either<FlowIn, Out>>create().collect(Scala.partialFunction(x -> { if (x.left.isPresent()) { return x.left.get(); Flow<F.Either<FlowIn, Out>, Out, ?> collectOut = Flow.<F.Either<FlowIn, Out>>create().collect(Scala.partialFunction(x -> { if (x.right.isPresent()) { return x.right.get();
@Override public CompletionStage<F.Either<Result, Flow<Message, Message, ?>>> apply(Http.RequestHeader request) { return f.apply(request).thenApply(resultOrFlow -> { if (resultOrFlow.left.isPresent()) { return F.Either.Left(resultOrFlow.left.get()); } else { Flow<Message, Message, ?> flow = AkkaStreams.bypassWith( Flow.<Message>create().collect(inMapper), play.api.libs.streams.AkkaStreams.onlyFirstCanFinishMerge(2), resultOrFlow.right.get().map(outMapper::apply) ); return F.Either.Right(flow); } }); } };
@Override public Accumulator<ByteString, F.Either<Result, A>> apply(Http.RequestHeader request) { Flow<ByteString, ByteString, Future<MaxSizeStatus>> takeUpToFlow = Flow.fromGraph(play.api.mvc.BodyParsers$.MODULE$.takeUpTo(maxLength)); Sink<ByteString, CompletionStage<F.Either<Result, A>>> result = apply1(request).toSink(); return Accumulator.fromSink(takeUpToFlow.toMat(result, (statusFuture, resultFuture) -> FutureConverters.toJava(statusFuture).thenCompose(status -> { if (status instanceof MaxSizeNotExceeded$) { return resultFuture; } else { return errorHandler.onClientError(request, Status$.MODULE$.REQUEST_ENTITY_TOO_LARGE(), "Request entity too large") .thenApply(F.Either::<Result, A>Left); } }) )); }
/** * Bypass the given flow using the given splitter function. * <p> * If the splitter function returns Left, they will go through the flow. If it returns Right, they will bypass the * flow. * <p> * Uses onlyFirstCanFinishMerge(2) by default. * * @param <In> the In type parameter for Flow * @param <FlowIn> the FlowIn type parameter for the left branch in Either. * @param <Out> the Out type parameter for Flow * @param flow the original flow * @param splitter the splitter function to use * * @return the flow with a bypass. */ public static <In, FlowIn, Out> Flow<In, Out, ?> bypassWith(Function<In, F.Either<FlowIn, Out>> splitter, Flow<FlowIn, Out, ?> flow) { return bypassWith(Flow.<In>create().map(splitter::apply), play.api.libs.streams.AkkaStreams.onlyFirstCanFinishMerge(2), flow); }
/** * Produces a Flow of escaped ByteString from a series of String elements. Calls * out to Comet.flow internally. * * @param callbackName the javascript callback method. * @return a flow of ByteString elements. */ public static Flow<String, ByteString, NotUsed> string(String callbackName) { return Flow.of(String.class).map(str -> { return ByteString.fromString("'" + StringEscapeUtils.escapeEcmaScript(str) + "'"); }).via(flow(callbackName)); }
/** * Chain a collection of flows one after another. * * @param flows collection of flows. * @param <A> type of messages through the flows. * @return joined flow. */ public static <A> Graph<FlowShape<A, A>, NotUsed> joinFlows( final Collection<Graph<FlowShape<A, A>, NotUsed>> flows) { Flow<A, A, NotUsed> overallFlow = Flow.create(); for (Graph<FlowShape<A, A>, NotUsed> flow : flows) { overallFlow = overallFlow.via(flow); } return overallFlow; } }
private Sink<Message, NotUsed> createSink(final Integer version, final String connectionCorrelationId, final AuthorizationContext connectionAuthContext, final DittoHeaders additionalHeaders, final ProtocolAdapter adapter) { return Flow.<Message>create() .filter(Message::isText) .map(Message::asTextMessage) .map(textMsg -> { if (textMsg.isStrict()) { return Source.single(textMsg.getStrictText()); } else { return textMsg.getStreamedText(); } }) .flatMapConcat(textMsg -> textMsg.<String>fold("", (str1, str2) -> str1 + str2)) .via(Flow.fromFunction(result -> { LogUtil.logWithCorrelationId(LOGGER, connectionCorrelationId, logger -> logger.debug("Received incoming WebSocket message: {}", result)); return result; })) .withAttributes(Attributes.createLogLevels(Logging.DebugLevel(), Logging.DebugLevel(), Logging.WarningLevel())) .filter(strictText -> processProtocolMessage(connectionAuthContext, connectionCorrelationId, strictText)) .map(buildSignal(version, connectionCorrelationId, connectionAuthContext, additionalHeaders, adapter)) .to(Sink.actorSubscriber( CommandSubscriber.props(streamingActor, subscriberBackpressureQueueSize, eventStream))); }
/** * Produces a flow of ByteString with a prepended block and a script wrapper. * * @param callbackName the javascript callback method. * @return a flow of ByteString elements. */ public static Flow<ByteString, ByteString, NotUsed> flow(String callbackName) { ByteString cb = ByteString.fromString(callbackName); return Flow.of(ByteString.class).map((msg) -> { return formatted(cb, msg); }).prepend(Source.single(initialChunk)); }
/** * A handler that treats incoming messages as a name, * and responds with a greeting to that name */ public static Flow<Message, Message, NotUsed> greeter() { return Flow.<Message>create() .collect(new JavaPartialFunction<Message, Message>() { @Override public Message apply(Message msg, boolean isCheck) throws Exception { if (isCheck) { if (msg.isText()) { return null; } else { throw noMatch(); } } else { return handleTextMessage(msg.asTextMessage()); } } }); }
/** * 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()); }
/** * Create an activity checker if duration is not null and a pipe otherwise. * * @param interval how often to check for activity. * @param self reference to the actor. * @param <A> type of messages that prevents actor termination. * @return an activity checker. */ public static <A> Graph<FlowShape<A, A>, NotUsed> ofNullable(@Nullable final Duration interval, final ActorRef self) { return interval == null ? Flow.create() : of(interval, self); }
@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()); } }) ); } }
public <D> Accumulator<D, A> through(Flow<D, E, ?> flow) { return new SinkAccumulator<>(flow.toMat(toSink, Keep.right())); }
private static Flow<Boolean, Boolean, NotUsed> stopTimer(final StartedTimer timer) { return Flow.fromFunction(foo -> { timer.stop(); // stop timer return foo; }); }
/** * Produces a flow of ByteString using `Json.stringify` from a Flow of JsonNode. Calls * out to Comet.flow internally. * * @param callbackName the javascript callback method. * @return a flow of ByteString elements. */ public static Flow<JsonNode, ByteString, NotUsed> json(String callbackName) { return Flow.of(JsonNode.class).map(json -> { return ByteString.fromString(Json.stringify(json)); }).via(flow(callbackName)); }
/** * Chain a collection of flows one after another. * * @param flows collection of flows. * @param <A> type of messages through the flows. * @return joined flow. */ public static <A> Graph<FlowShape<A, A>, NotUsed> joinFlows( final Collection<Graph<FlowShape<A, A>, NotUsed>> flows) { Flow<A, A, NotUsed> overallFlow = Flow.create(); for (Graph<FlowShape<A, A>, NotUsed> flow : flows) { overallFlow = overallFlow.via(flow); } return overallFlow; } }
/** * Bypass the given flow using the given splitter function. * <p> * If the splitter function returns Left, they will go through the flow. If it returns Right, they will bypass the * flow. * <p> * Uses onlyFirstCanFinishMerge(2) by default. * * @param <In> the In type parameter for Flow * @param <FlowIn> the FlowIn type parameter for the left branch in Either. * @param <Out> the Out type parameter for Flow * @param flow the original flow * @param splitter the splitter function to use * * @return the flow with a bypass. */ public static <In, FlowIn, Out> Flow<In, Out, ?> bypassWith(Function<In, F.Either<FlowIn, Out>> splitter, Flow<FlowIn, Out, ?> flow) { return bypassWith(Flow.<In>create().map(splitter::apply), play.api.libs.streams.AkkaStreams.onlyFirstCanFinishMerge(2), flow); }
/** * Produces a flow of ByteString with a prepended block and a script wrapper. * * @param callbackName the javascript callback method. * @return a flow of ByteString elements. */ public static Flow<ByteString, ByteString, NotUsed> flow(String callbackName) { ByteString cb = ByteString.fromString(callbackName); return Flow.of(ByteString.class).map((msg) -> { return formatted(cb, msg); }).prepend(Source.single(initialChunk)); }