akka.stream.Attributes Java Examples

The following examples show how to use akka.stream.Attributes. You can vote up the ones you like or vote down the ones you don't like, and go to the original project or source file by following the links above each example. You may check out the related API usage on the sidebar.
Example #1
Source File: SearchUpdaterStream.java    From ditto with Eclipse Public License 2.0 6 votes vote down vote up
private Sink<Source<AbstractWriteModel, NotUsed>, NotUsed> createRestartSink() {
    final StreamConfig streamConfig = searchConfig.getStreamConfig();
    final PersistenceStreamConfig persistenceConfig = streamConfig.getPersistenceConfig();

    final int parallelism = persistenceConfig.getParallelism();
    final int maxBulkSize = persistenceConfig.getMaxBulkSize();
    final Duration writeInterval = streamConfig.getWriteInterval();
    final Sink<Source<AbstractWriteModel, NotUsed>, NotUsed> sink =
            mongoSearchUpdaterFlow.start(parallelism, maxBulkSize, writeInterval)
                    .via(bulkWriteResultAckFlow.start())
                    .log("SearchUpdaterStream/BulkWriteResult")
                    .withAttributes(Attributes.logLevels(
                            Attributes.logLevelInfo(),
                            Attributes.logLevelWarning(),
                            Attributes.logLevelError()))
                    .to(Sink.ignore());

    final ExponentialBackOffConfig backOffConfig = persistenceConfig.getExponentialBackOffConfig();

    return RestartSink.withBackoff(backOffConfig.getMax(), backOffConfig.getMax(), backOffConfig.getRandomFactor(),
            () -> sink);
}
 
Example #2
Source File: MongoTimestampPersistence.java    From ditto with Eclipse Public License 2.0 6 votes vote down vote up
private static Source<Success, NotUsed> repeatableCreateCappedCollectionSource(
        final MongoDatabase database,
        final String collectionName,
        final long cappedCollectionSizeInBytes) {

    final CreateCollectionOptions collectionOptions = new CreateCollectionOptions()
            .capped(true)
            .sizeInBytes(cappedCollectionSizeInBytes)
            .maxDocuments(1);

    return Source.lazily(
            () -> Source.fromPublisher(database.createCollection(collectionName, collectionOptions)))
            .mapMaterializedValue(whatever -> NotUsed.getInstance())
            .withAttributes(Attributes.inputBuffer(1, 1))
            .recoverWithRetries(1, new PFBuilder<Throwable, Source<Success, NotUsed>>()
                    .match(MongoCommandException.class,
                            MongoTimestampPersistence::isCollectionAlreadyExistsError,
                            error -> Source.single(Success.SUCCESS))
                    .build());

}
 
Example #3
Source File: WebSocketRoute.java    From ditto with Eclipse Public License 2.0 6 votes vote down vote up
private Flow<Message, String, NotUsed> getStrictifyFlow(final HttpRequest request,
        final CharSequence correlationId) {
    return Flow.<Message>create()
            .via(Flow.fromFunction(msg -> {
                IN_COUNTER.increment();
                return msg;
            }))
            .filter(Message::isText)
            .map(Message::asTextMessage)
            .map(textMsg -> {
                if (textMsg.isStrict()) {
                    return Source.single(textMsg.getStrictText());
                } else {
                    return textMsg.getStreamedText();
                }
            })
            .flatMapConcat(textMsg -> textMsg.fold("", (str1, str2) -> str1 + str2))
            .via(incomingMessageSniffer.toAsyncFlow(request))
            .via(Flow.fromFunction(result -> {
                LOGGER.withCorrelationId(correlationId).debug("Received incoming WebSocket message: {}", result);
                return result;
            }))
            .withAttributes(Attributes.createLogLevels(Logging.DebugLevel(), Logging.DebugLevel(),
                    Logging.WarningLevel()));

}
 
Example #4
Source File: MongoReadJournal.java    From ditto with Eclipse Public License 2.0 6 votes vote down vote up
private <T> Source<List<T>, NotUsed> unfoldBatchedSource(
        final String lowerBound,
        final ActorMaterializer mat,
        final Function<T, String> seedCreator,
        final Function<String, Source<T, ?>> sourceCreator) {

    return Source.unfoldAsync("",
            start -> {
                final String actualStart = lowerBound.compareTo(start) >= 0 ? lowerBound : start;
                return sourceCreator.apply(actualStart)
                        .runWith(Sink.seq(), mat)
                        .thenApply(list -> {
                            if (list.isEmpty()) {
                                return Optional.empty();
                            } else {
                                return Optional.of(Pair.create(seedCreator.apply(list.get(list.size() - 1)), list));
                            }
                        });
            })
            .withAttributes(Attributes.inputBuffer(1, 1));
}
 
Example #5
Source File: ResumeSourceTest.java    From ditto with Eclipse Public License 2.0 6 votes vote down vote up
@Test
public void testFailureAfterMaxRestarts() {
    // disable logging to suppress expected stacktrace
    system.eventStream().setLogLevel(Attributes.logLevelOff());
    new TestKit(system) {{
        final Source<Integer, NotUsed> underTest = createResumeSource(getRef(), 0);

        underTest.runWith(testSink, mat);

        // start stream with demand
        sinkProbe.request(100L);
        expectMsg(0);
        reply(testSource);

        // send some elements followed by failure
        sourceProbe.sendNext(1).sendNext(2);
        sinkProbe.expectNext(1, 2);
        final Throwable error = new IllegalStateException("Expected error");
        sourceProbe.sendError(error);

        // expect stream failed
        assertThat(sinkProbe.expectError()).isInstanceOf(StreamLimitReachedException.class);
    }};
}
 
Example #6
Source File: ResumeSourceTest.java    From ditto with Eclipse Public License 2.0 6 votes vote down vote up
@Test
public void testCompletion() {
    // TODO: delete this
    system.eventStream().setLogLevel(Attributes.logLevelDebug());
    new TestKit(system) {{
        final Source<Integer, NotUsed> underTest = createResumeSource(getRef(), -1);

        underTest.runWith(testSink, mat);

        // start stream with demand
        sinkProbe.request(2L);
        expectMsg(0);
        reply(testSource);

        // send some elements followed by completion
        sourceProbe.sendNext(1).sendNext(2);
        sourceProbe.sendComplete();
        sinkProbe.expectNext(1, 2);
        sinkProbe.expectComplete();
    }};
}
 
Example #7
Source File: AbstractGraphActor.java    From ditto with Eclipse Public License 2.0 6 votes vote down vote up
private SourceQueueWithComplete<T> getSourceQueue(final ActorMaterializer materializer) {
    // Log stream completion and failure at level ERROR because the stream is supposed to survive forever.
    final Attributes streamLogLevels =
            Attributes.logLevels(Attributes.logLevelDebug(), Attributes.logLevelError(),
                    Attributes.logLevelError());

    return Source.<T>queue(getBufferSize(), OverflowStrategy.dropNew())
            .map(this::incrementDequeueCounter)
            .log("graph-actor-stream-1-dequeued", logger)
            .withAttributes(streamLogLevels)
            .via(Flow.fromFunction(this::beforeProcessMessage))
            .log("graph-actor-stream-2-preprocessed", logger)
            .withAttributes(streamLogLevels)
            .via(processMessageFlow())
            .log("graph-actor-stream-3-processed", logger)
            .withAttributes(streamLogLevels)
            .to(processedMessageSink())
            .run(materializer);
}
 
Example #8
Source File: SubscriptionActorTest.java    From ditto with Eclipse Public License 2.0 6 votes vote down vote up
@Test
public void partialFailure() {
    // comment the next line to get logs for debugging
    actorSystem.eventStream().setLogLevel(Attributes.logLevelOff());
    new TestKit(actorSystem) {{
        final ActorRef underTest = watch(newSubscriptionActor(Duration.ofMinutes(1L), this));
        final String subscriptionId = underTest.path().name();
        final DittoRuntimeException error =
                InvalidRqlExpressionException.fromMessage("mock error", DittoHeaders.empty());
        // not possible to use Source.concat -- it forces the second source immediately.
        final Source<JsonArray, NotUsed> lazilyFailingSource =
                Source.from(List.of(Source.single(JsonArray.of(1)),
                        Source.lazily(() -> Source.<JsonArray>failed(error))))
                        .flatMapConcat(x -> x);
        connect(underTest, lazilyFailingSource, this);
        underTest.tell(RequestFromSubscription.of(subscriptionId, 1L, DittoHeaders.empty()), getRef());
        expectMsg(SubscriptionHasNextPage.of(subscriptionId, JsonArray.of(1), DittoHeaders.empty()));
        expectMsg(SubscriptionFailed.of(subscriptionId, error, DittoHeaders.empty()));
    }};
}
 
Example #9
Source File: BlockedNamespacesTest.java    From ditto with Eclipse Public License 2.0 5 votes vote down vote up
@Test
public void startWithWrongRole() {
    // logging disabled to not print expected stacktrace; re-enable logging to debug.
    actorSystem.eventStream().setLogLevel(Attributes.logLevelOff());
    new TestKit(actorSystem) {{
        final BlockedNamespaces underTest = BlockedNamespaces.create(DistributedData.createConfig(actorSystem,
                "replicator", "wrong-role"), actorSystem);
        watch(underTest.getReplicator());
        expectTerminated(underTest.getReplicator());
    }};
}
 
Example #10
Source File: MongoSearchUpdaterFlow.java    From ditto with Eclipse Public License 2.0 5 votes vote down vote up
/**
 * Create a new flow through the search persistence.
 * No logging or recovery is attempted.
 *
 * @param parallelism How many write operations may run in parallel for this sink.
 * @param maxBulkSize How many writes to perform in one bulk.
 * @param writeInterval Delay between bulk operation requests. MongoDB backpressure is insufficient.
 * @return the sink.
 */
public Flow<Source<AbstractWriteModel, NotUsed>, WriteResultAndErrors, NotUsed> start(
        final int parallelism,
        final int maxBulkSize,
        final Duration writeInterval) {

    final Flow<List<AbstractWriteModel>, List<AbstractWriteModel>, NotUsed> throttleFlow;
    if (Duration.ZERO.minus(writeInterval).isNegative()) {
        throttleFlow = Flow.<List<AbstractWriteModel>>create()
                .delay(writeInterval, DelayOverflowStrategy.backpressure());
    } else {
        throttleFlow = Flow.create();
    }

    final Flow<Source<AbstractWriteModel, NotUsed>, List<AbstractWriteModel>, NotUsed> batchFlow =
            Flow.<Source<AbstractWriteModel, NotUsed>>create()
                    .flatMapConcat(source -> source.grouped(maxBulkSize))
                    .via(throttleFlow);

    final Flow<List<AbstractWriteModel>, WriteResultAndErrors, NotUsed> writeFlow =
            Flow.<List<AbstractWriteModel>>create()
                    .flatMapMerge(parallelism, this::executeBulkWrite)
                    // never initiate more than "parallelism" writes against the persistence
                    .withAttributes(Attributes.inputBuffer(parallelism, parallelism));

    return Flow.fromGraph(assembleFlows(batchFlow, writeFlow, createStartTimerFlow(), createStopTimerFlow()));
}
 
Example #11
Source File: ChangeQueueActor.java    From ditto with Eclipse Public License 2.0 5 votes vote down vote up
/**
 * Create a source of nonempty queue snapshots such that the queue content is cleared after each snapshot.
 *
 * @param changeQueueActor reference to this actor
 * @param writeInterval minimum delays between cache dumps.
 * @return source of queue snapshots.
 */
public static Source<Map<ThingId, Metadata>, NotUsed> createSource(
        final ActorRef changeQueueActor,
        final Duration writeInterval) {
    return Source.repeat(Control.DUMP)
            .delay(writeInterval, DelayOverflowStrategy.backpressure())
            .withAttributes(Attributes.inputBuffer(1, 1))
            .flatMapConcat(ChangeQueueActor.askSelf(changeQueueActor))
            .filter(map -> !map.isEmpty());
}
 
Example #12
Source File: BackgroundSyncStream.java    From ditto with Eclipse Public License 2.0 5 votes vote down vote up
/**
 * Discover inconsistencies between the persisted and indexed metadata and emit extra/nonexistent/mismatched
 * entries of the search index.
 *
 * @param metadataFromSnapshots metadata streamed from the things snapshot store.
 * @param metadataFromSearchIndex metadata streamed from the search index.
 * @return source of inconsistent entries.
 */
public Source<Metadata, NotUsed> filterForInconsistencies(final Source<Metadata, ?> metadataFromSnapshots,
        final Source<Metadata, ?> metadataFromSearchIndex) {


    final Comparator<Metadata> comparator = BackgroundSyncStream::compareMetadata;
    return MergeSortedAsPair.merge(dummyMetadata(), comparator, metadataFromSnapshots, metadataFromSearchIndex)
            .throttle(throttleThroughput, throttlePeriod)
            .flatMapConcat(this::filterForInconsistency)
            // log elements at warning level because out-of-date metadata are detected
            .withAttributes(Attributes.logLevels(
                    Attributes.logLevelWarning(),
                    Attributes.logLevelDebug(),
                    Attributes.logLevelError()));
}
 
Example #13
Source File: PolicyEventForwarder.java    From ditto with Eclipse Public License 2.0 5 votes vote down vote up
private void restartPolicyReferenceTagStream() {
    terminateStream();
    final ActorRef self = getSelf();
    killSwitch = Source.repeat(Control.DUMP_POLICY_REVISIONS)
            .delay(interval, DelayOverflowStrategy.backpressure())
            .withAttributes(Attributes.inputBuffer(1, 1))
            .viaMat(KillSwitches.single(), Keep.right())
            .mapAsync(1, message ->
                    PatternsCS.ask(self, message, ASK_SELF_TIMEOUT).exceptionally(Function.identity()))
            .flatMapConcat(this::mapDumpResult)
            .to(Sink.actorRef(self, Control.STREAM_COMPLETED))
            .run(materializer);
}
 
Example #14
Source File: SubscriptionActorTest.java    From ditto with Eclipse Public License 2.0 5 votes vote down vote up
@Test
public void failure() {
    // comment the next line to get logs for debugging
    actorSystem.eventStream().setLogLevel(Attributes.logLevelOff());
    new TestKit(actorSystem) {{
        final ActorRef underTest = watch(newSubscriptionActor(Duration.ofMinutes(1L), this));
        final DittoRuntimeException error =
                InvalidRqlExpressionException.fromMessage("mock error", DittoHeaders.empty());
        connect(underTest, Source.failed(error), this);
        expectMsg(SubscriptionFailed.of(underTest.path().name(), error, DittoHeaders.empty()));
    }};
}
 
Example #15
Source File: SearchSourceTest.java    From ditto with Eclipse Public License 2.0 5 votes vote down vote up
@Test
public void cursorDeleted() {
    // Turn off logging to suppress stack trace. Comment out to debug.
    actorSystem.eventStream().setLogLevel(Attributes.logLevelOff());

    startTestSearchSource(null, null);
    sinkProbe.request(200L);
    conciergeForwarderProbe.expectMsg(streamThings(null));
    conciergeForwarderProbe.reply(materializeSourceProbe());

    // GIVEN: first search result goes through
    sourceProbe.expectRequest();
    sourceProbe.sendNext("t:3");
    conciergeForwarderProbe.expectMsg(retrieveThing("t:3", null));
    conciergeForwarderProbe.reply(retrieveThingResponse(3));
    sinkProbe.expectNext(getThing(3).toJson());

    // WHEN: search persistence deleted the cursor
    sourceProbe.sendError(new IllegalStateException("mock cursor-not-found error"));

    // THEN: the final thing is retrieved again to compute the cursor
    conciergeForwarderProbe.expectMsg(retrieveThing("t:3", SORT_FIELDS));
    conciergeForwarderProbe.reply(retrieveThingResponse(3));

    // THEN: stream resumes from the last result
    conciergeForwarderProbe.expectMsg(streamThings(JsonArray.of(997, "t:3")));
    conciergeForwarderProbe.reply(materializeSourceProbe());
    sourceProbe.expectRequest();
    sourceProbe.sendNext("t:2").sendComplete();
    conciergeForwarderProbe.expectMsg(retrieveThing("t:2", null));
    conciergeForwarderProbe.reply(retrieveThingResponse(2));
    sinkProbe.expectNext(getThing(2).toJson())
            .expectComplete();
}
 
Example #16
Source File: MongoReadJournal.java    From ditto with Eclipse Public License 2.0 5 votes vote down vote up
/**
 * Retrieve all latest snapshots with unique PIDs in snapshot store above a lower bound.
 * Does not limit database access in any way.
 *
 * @param lowerBoundPid the lower-bound PID.
 * @param batchSize how many snapshots to read in 1 query.
 * @param mat the materializer.
 * @param snapshotFields snapshot fields to project out.
 * @return source of newest snapshots with unique PIDs.
 */
public Source<Document, NotUsed> getNewestSnapshotsAbove(final String lowerBoundPid,
        final int batchSize,
        final ActorMaterializer mat,
        final String... snapshotFields) {

    return getSnapshotStore()
            .withAttributes(Attributes.inputBuffer(1, 1))
            .flatMapConcat(snapshotStore ->
                    listNewestSnapshots(snapshotStore, lowerBoundPid, batchSize, mat,
                            snapshotFields)
            )
            .mapConcat(pids -> pids);
}
 
Example #17
Source File: MongoReadJournal.java    From ditto with Eclipse Public License 2.0 5 votes vote down vote up
/**
 * Retrieve all unique PIDs in journals above a lower bound. Does not limit database access in any way.
 *
 * @param lowerBoundPid the lower-bound PID.
 * @param batchSize how many events to read in 1 query.
 * @param mat the materializer.
 * @return all unique PIDs in journals above a lower bound.
 */
public Source<String, NotUsed> getJournalPidsAbove(final String lowerBoundPid, final int batchSize,
        final ActorMaterializer mat) {

    return getJournal()
            .withAttributes(Attributes.inputBuffer(1, 1))
            .flatMapConcat(journal ->
                    listPidsInJournal(journal, lowerBoundPid, batchSize, mat, MAX_BACK_OFF_DURATION, 0)
            )
            .mapConcat(pids -> pids);
}
 
Example #18
Source File: PushPullOutputStreamAdapter.java    From ts-reaktive with MIT License 5 votes vote down vote up
@Override
public GraphStageLogic createLogic(Attributes attr) throws Exception {
    ByteStringOutputStream stream = new ByteStringOutputStream();
    W writer = factory.apply(attr, stream);
    return new GraphStageLogic(shape) {{
        setHandler(out, new AbstractOutHandler() {
            @Override
            public void onPull() throws Exception {
                if (stream.hasBytes()) {
                    push(out, stream.getBytesAndReset());
                } else {
                    pull(in);
                }
            }
        });
        
        setHandler(in, new AbstractInHandler() {
            @Override
            public void onPush() throws Exception {
                T t = grab(in);
                write.accept(writer, t);
                if (stream.hasBytes()) {
                    push(out, stream.getBytesAndReset());
                } else {
                    pull(in);
                }
            }
        });
    }};
}
 
Example #19
Source File: BrokerServiceImpl.java    From reactive-stock-trader with Apache License 2.0 5 votes vote down vote up
private Flow<OrderPlaced, Done, NotUsed> processPortfolioOrders() {
    return Flow.<OrderPlaced>create()
            .log("orderPlaced")
            .addAttributes(Attributes.createLogLevels(
                    Attributes.logLevelInfo(), // onElement
                    Attributes.logLevelInfo(), // onFinish
                    Attributes.logLevelError()) // onFailure
            )
            // Note that order processing is asynchronous, so the parallelism parameter only limits how many
            // orders place at once before we get acknowledgement that they have been placed (which should be
            // essentially instant. It is not the maximum number of orders we can process concurrently.
            .mapAsync(10, this::processOrder);
}
 
Example #20
Source File: TransferProcess.java    From reactive-stock-trader with Apache License 2.0 5 votes vote down vote up
@Override
public Flow<Pair<TransferEvent, Offset>, Done, ?> handle() {
    return Flow.<Pair<TransferEvent, Offset>>create()
            .log("transferEvent")
            .withAttributes(
                    Attributes.createLogLevels(
                            Attributes.logLevelInfo(),
                            Attributes.logLevelInfo(),
                            Attributes.logLevelInfo()
                    )
            )
            .mapAsyncUnordered(concurrentSteps,
                    e -> e.first().visit(transferEventVisitor));
}
 
Example #21
Source File: DropUntilNext.java    From ts-reaktive with MIT License 4 votes vote down vote up
@Override
public GraphStageLogic createLogic(Attributes attr) throws Exception {
    return new GraphStageLogic(shape) {
        boolean open = false;
        T last = null;
        {
            setHandler(in, new AbstractInHandler() {
                @Override
                public void onPush() {
                    T t = grab(in);
                    if (open) {
                        push(out, last);
                    } else if (predicate.test(t)) {
                        open = true;
                        if (last != null) {
                            push(out, last);
                        } else {
                            pull(in);
                        }
                    } else {
                        pull(in);
                    }
                    last = t;
                }
                
                @Override
                public void onUpstreamFinish() {
                    if ((open || includeLastIfNoMatch) && last != null) {
                        emit(out, last);
                    }
                    completeStage();
                };
            });
            
            setHandler(out, new AbstractOutHandler() {
                @Override
                public void onPull() {
                    pull(in);
                }
            });
        }
    };
}
 
Example #22
Source File: CsvWriter.java    From ts-reaktive with MIT License 4 votes vote down vote up
@Override
public GraphStageLogic createLogic(Attributes arg0) {
    return new GraphStageLogic(shape) {
        boolean startedValue = false;
        boolean needSeparator = false;
        
        {
            setHandlers(in, out, new AbstractInOutHandler() {
                @Override
                public void onPull() {
                    pull(in);
                }
                
                @Override
                public void onPush() throws CharacterCodingException {
                    CsvEvent e = grab(in);
                    if (e instanceof CsvEvent.EndRecord) {
                        if (startedValue) {
                            emit(out, quote);
                        }
                        emit(out, "\n");
                        startedValue = false;
                        needSeparator = false;
                    } else if (e instanceof CsvEvent.EndValue) {
                        if (startedValue) {
                            emit(out, quote);
                        } else {
                            // empty field
                            if (needSeparator) {
                                emit(out, separator);
                            } else {
                                pull(in);
                            }
                        }
                        startedValue = false;
                        needSeparator = true;
                    } else {
                        String s = CsvEvent.Text.class.cast(e).getText();
                        if (s.length() > 0) {
                            if (!startedValue) {
                                if (needSeparator) {
                                    emit(out, separator);
                                }
                                emit(out, quote);
                            }
                            emit(out, settings.escape(s));
                            startedValue = true;
                        } else {
                            pull(in);
                        }
                    }
                }
            });
        }
    };
}
 
Example #23
Source File: CharsetDecoderFlow.java    From ts-reaktive with MIT License 4 votes vote down vote up
@Override
public GraphStageLogic createLogic(Attributes arg0) throws Exception {
    return new GraphStageLogic(shape) {
        final CharsetDecoder decoder = encoding.newDecoder();
        ByteString buf = ByteString.empty();
        {
            setHandlers(in, out, new AbstractInOutHandler() {
                @Override
                public void onPull() {
                    pull(in);
                }
                
                @Override
                public void onPush() throws CharacterCodingException {
                    deliver(buf.concat(grab(in)).asByteBuffer());
                }

                @Override
                public void onUpstreamFinish() throws CharacterCodingException {
                    deliver(buf.asByteBuffer());
                    if (!buf.isEmpty()) {
                        throw new IllegalArgumentException("Stray bytes at end of input that could not be decoded: " + buf);
                    }
                    completeStage();
                }
                
                private void deliver(ByteBuffer bytes) throws CharacterCodingException {
                    CharBuffer chars = CharBuffer.allocate(bytes.limit());
                    CoderResult result = decoder.decode(bytes, chars, false);
                    if (result.isOverflow()) {
                        failStage(new IllegalArgumentException("Incoming bytes decoded into more characters. Huh?"));
                        return;
                    }
                    if (result.isError()) {
                        result.throwException();
                    }
                    
                    int count = chars.position();
                    chars.rewind();
                    if (count > 0) {
                        push(out, new String(chars.array(), chars.position(), count));
                    } else if (!isClosed(in)) {
                        pull(in);
                    }
                    
                    // save the remaining bytes for later
                    buf = ByteString.fromByteBuffer(bytes);
                }
            });
        }
    };
}
 
Example #24
Source File: DelimitedProtobufFraming.java    From ts-reaktive with MIT License 4 votes vote down vote up
@Override
public GraphStageLogic createLogic(Attributes attr) {
    return new GraphStageLogic(shape) {
        ByteString buf = ByteString.empty();
        List<ByteString> deframed = new ArrayList<>();
        {
            setHandler(in, new AbstractInHandler() {
                @Override
                public void onPush() {
                    ByteString b = grab(in);
                    buf = buf.concat(b);
                    deliverBuf();
                }

                @Override
                public void onUpstreamFinish() {
                    if (buf.size() > 0 || !deframed.isEmpty()) {
                        deliverBuf();
                    }
                    completeStage();
                }

                private void deliverBuf() {
                    log.debug("Buf now {}", buf);
                    try {
                        while (buf.size() > 0) {
                            CodedInputStream i = CodedInputStream.newInstance(buf.iterator().asInputStream());
                            long contentLength = i.readUInt64();
                            int delimiterLength = i.getTotalBytesRead();
                            log.debug("Got content {}, delimiter {}", contentLength, delimiterLength);
                            if (buf.size() >= delimiterLength + contentLength) {
                                buf = buf.drop(delimiterLength); // cast OK, delimiter will be a few bytes at most
                                if (contentLength > Integer.MAX_VALUE) {
                                    throw new IOException("Only support protobuf messages up to 2G each. And that's a lot.");
                                }
                                Tuple2<ByteString, ByteString> t = buf.splitAt((int)contentLength);
                                deframed.add(t._1);
                                buf = t._2;
                            } else {
                                // not received enough bytes yet
                                break;
                            }
                        }

                        if (deframed.isEmpty()) {
                            if (!isClosed(in)) {
                                pull(in);
                            }
                        } else {
                            emitMultiple(out, deframed.iterator());
                            deframed = new ArrayList<>();
                        }
                    } catch (IOException x) {
                        log.debug("Protobuf unhappy at length {}", buf.size());
                        if (buf.size() < 10) {
                            // this is possibly because there are not enough bytes to read a full varint. Pull to be safe.
                            pull(in);
                        } else {
                            failStage(x);
                        }
                    }
                }
            });

            setHandler(out, new AbstractOutHandler() {
                @Override
                public void onPull() {
                    pull(in);
                }
            });
        }
    };
}
 
Example #25
Source File: GroupWhile.java    From ts-reaktive with MIT License 4 votes vote down vote up
@Override
public GraphStageLogic createLogic(Attributes inheritedAttributes) {
    return new TimerGraphStageLogic(shape) {
        Seq<T> buffer = Vector.empty();

        {
            setHandler(in, new AbstractInHandler() {
                @Override
                public void onPush() {
                    T t = grab(in);

                    if (buffer.isEmpty() || test.apply(buffer.get(buffer.size() - 1), t)) {
                        buffer = buffer.append(t);
                        scheduleOnce("idle", idleEmitTimeout);
                        pull(in);
                    } else {
                        emitBuffer();
                        scheduleOnce("idle", idleEmitTimeout);
                        buffer = buffer.append(t);
                    }
                    if (buffer.size() > maxGroupSize) {
                        failStage(new BufferOverflowException("Exceeded configured GroupWhile buffer size of " + maxGroupSize));
                        return;
                    }
                }

                @Override
                public void onUpstreamFinish() {
                    emitBuffer();
                    completeStage();
                }
            });

            setHandler(out, new AbstractOutHandler() {
                @Override
                public void onPull() {
                    if (!hasBeenPulled(in)) {
                        pull(in);
                    }
                }
            });
        }

        private void emitBuffer() {
            if (!buffer.isEmpty() && isAvailable(out)) {
                emit(out, buffer);
                buffer = Vector.empty();
                cancelTimer("idle");
            }
        }

        @Override
        public void onTimer(Object timerKey) {
            log.debug("Idle timeout reached with {} elements waiting", buffer.size());
            emitBuffer();
        }
    };
}
 
Example #26
Source File: SchemaValidatorFlow.java    From ts-reaktive with MIT License 4 votes vote down vote up
@Override
public GraphStageLogic createLogic(Attributes attr) throws Exception {
    ValidatorHandler handler = schema.newValidatorHandler();
    return new GraphStageLogic(shape) {
        int lineNumber = -1;
        int columnNumber = -1;
    {
        handler.setDocumentLocator(new Locator() {
            @Override
            public String getPublicId() {
                return null;
            }

            @Override
            public String getSystemId() {
                return null;
            }

            @Override
            public int getLineNumber() {
                return lineNumber;
            }

            @Override
            public int getColumnNumber() {
                return columnNumber;
            }
        });
        
        setHandler(out, new AbstractOutHandler() {
            @Override
            public void onPull() {
                pull(in);
            }
        });
        
        setHandler(in, new AbstractInHandler() {
            @Override
            public void onPush() throws Exception {
                XMLEvent event = grab(in);
                if (event.getLocation() != null) {
                    lineNumber = event.getLocation().getLineNumber();
                    columnNumber = event.getLocation().getColumnNumber();
                }
                try {
                    Stax.apply(event, handler);
                    push(out, event);
                } catch (SAXParseException x) {
                    failStage(x);
                }
            }
        });
    }};
}
 
Example #27
Source File: ProtocolFilter.java    From ts-reaktive with MIT License 4 votes vote down vote up
/**
 * Inserts marker objects into the stream whenever [selector] starts or stops selecting.
 *  - inserts SELECTED before events where [selector] started selecting
 *  - inserts NOT_SELECTED before events where [selector] stopped selecting
 * The output stream will always start with a marker object.
 */
private static <E> GraphStage<FlowShape<E,Object>> insertMarkers(ReadProtocol<E,E> selector) {
    return new GraphStage<FlowShape<E,Object>>() {
        private final Inlet<E> in = Inlet.create("in");
        private final Outlet<Object> out = Outlet.create("out");
        private final FlowShape<E, Object> shape = FlowShape.of(in, out);

        @Override
        public FlowShape<E, Object> shape() {
            return shape;
        }

        @Override
        public GraphStageLogic createLogic(Attributes attr) {
            return new GraphStageLogic(shape) {
                private final Reader<E,E> reader = selector.reader();
                private Option<Boolean> prevSelected = none();
                {
                    setHandler(in, new AbstractInHandler(){
                        @Override
                        public void onPush() {
                            final E event = grab(in);
                            final Try<E> result = reader.apply(event);
                            final boolean selected = !ReadProtocol.isNone(result);
                            log.debug("in {}, reader {}", event, result);
                            
                            if (selected && result.isFailure()) {
                                failStage(result.failed().get());
                            } else {
                                if (prevSelected.filter(p -> p == selected).isDefined()) {
                                    // no new marker needed
                                    if (selected) {
                                        push(out, result.get());
                                    } else {
                                        push(out, event);
                                    }
                                } else {
                                    log.debug("New marker! selected={}", selected);
                                    // insert a marker since the selector has changed outputting
                                    if (selected) {
                                        emitMultiple(out, Vector.of(SELECTED, result.get()).iterator());
                                    } else {
                                        emitMultiple(out, Vector.of(NOT_SELECTED, event).iterator());
                                    }
                                }
                                prevSelected = some(selected);
                            }
                        }
                    });
                    
                    setHandler(out, new AbstractOutHandler() {
                        @Override
                        public void onPull() {
                            pull(in);
                        }
                    });
                }
            };
        }
    };
}
 
Example #28
Source File: PersistenceActorTestBase.java    From ditto with Eclipse Public License 2.0 4 votes vote down vote up
/**
 * Disable logging for 1 test to hide stacktrace or other logs on level ERROR. Comment out to debug the test.
 */
protected void disableLogging() {
    actorSystem.eventStream().setLogLevel(Attributes.logLevelOff());
}
 
Example #29
Source File: MergeSortedAsPair.java    From ditto with Eclipse Public License 2.0 4 votes vote down vote up
@Override
public GraphStageLogic createLogic(final Attributes inheritedAttributes) {
    return new MergeSortAsPairLogic();
}
 
Example #30
Source File: Transistor.java    From ditto with Eclipse Public License 2.0 4 votes vote down vote up
@Override
public GraphStageLogic createLogic(final Attributes inheritedAttributes) {
    return new TransistorLogic();
}