Search in sources :

Example 61 with TopicMessageFilter

use of com.hedera.mirror.grpc.domain.TopicMessageFilter in project hedera-mirror-node by hashgraph.

the class TopicMessageServiceImpl method missingMessages.

/**
 * A flow can have missing messages if the importer is down for a long time when the client subscribes. When the
 * incoming flow catches up and receives the next message for the topic, it will fill in any missing messages from
 * when it was down.
 */
private Flux<TopicMessage> missingMessages(TopicContext topicContext, TopicMessage current) {
    if (topicContext.isNext(current)) {
        return Flux.just(current);
    }
    TopicMessage last = topicContext.getLast();
    long numMissingMessages = current.getSequenceNumber() - last.getSequenceNumber() - 1;
    // fail fast on out of order messages
    if (numMissingMessages < -1) {
        throw new IllegalStateException(String.format("Encountered out of order missing messages, last: %s, current: %s", last, current));
    }
    // ignore duplicate message already processed by larger subscribe context
    if (numMissingMessages == -1) {
        log.debug("Encountered duplicate missing message to be ignored, last: {}, current: {}", last, current);
        return Flux.empty();
    }
    TopicMessageFilter newFilter = topicContext.getFilter().toBuilder().endTime(current.getConsensusTimestampInstant()).limit(numMissingMessages).startTime(last.getConsensusTimestampInstant().plusNanos(1)).build();
    log.info("[{}] Querying topic {} for missing messages between sequence {} and {}", newFilter.getSubscriberId(), topicContext.getTopicId(), last.getSequenceNumber(), current.getSequenceNumber());
    return topicMessageRetriever.retrieve(newFilter, false).concatWithValues(current).name("findMissing").metrics();
}
Also used : TopicMessage(com.hedera.mirror.grpc.domain.TopicMessage) TopicMessageFilter(com.hedera.mirror.grpc.domain.TopicMessageFilter)

Example 62 with TopicMessageFilter

use of com.hedera.mirror.grpc.domain.TopicMessageFilter in project hedera-mirror-node by hashgraph.

the class PollingTopicListener method poll.

private Flux<TopicMessage> poll(PollingContext context) {
    TopicMessageFilter filter = context.getFilter();
    TopicMessage last = context.getLast();
    int limit = filter.hasLimit() ? (int) (filter.getLimit() - context.getCount().get()) : Integer.MAX_VALUE;
    int pageSize = Math.min(limit, listenerProperties.getMaxPageSize());
    Instant startTime = last != null ? last.getConsensusTimestampInstant().plusNanos(1) : filter.getStartTime();
    TopicMessageFilter newFilter = filter.toBuilder().limit(pageSize).startTime(startTime).build();
    return Flux.fromStream(topicMessageRepository.findByFilter(newFilter)).name("findByFilter").metrics();
}
Also used : TopicMessage(com.hedera.mirror.grpc.domain.TopicMessage) Instant(java.time.Instant) TopicMessageFilter(com.hedera.mirror.grpc.domain.TopicMessageFilter)

Aggregations

TopicMessageFilter (com.hedera.mirror.grpc.domain.TopicMessageFilter)62 TopicMessage (com.hedera.mirror.grpc.domain.TopicMessage)52 Test (org.junit.jupiter.api.Test)50 GrpcIntegrationTest (com.hedera.mirror.grpc.GrpcIntegrationTest)47 Instant (java.time.Instant)18 StepVerifier (reactor.test.StepVerifier)15 Duration (java.time.Duration)12 ParameterizedTest (org.junit.jupiter.params.ParameterizedTest)12 EntityId (com.hedera.mirror.common.domain.entity.EntityId)11 EntityType (com.hedera.mirror.common.domain.entity.EntityType)11 DomainBuilder (com.hedera.mirror.grpc.domain.DomainBuilder)11 Resource (javax.annotation.Resource)11 ValueSource (org.junit.jupiter.params.provider.ValueSource)11 Autowired (org.springframework.beans.factory.annotation.Autowired)11 Flux (reactor.core.publisher.Flux)11 AfterEach (org.junit.jupiter.api.AfterEach)10 BeforeEach (org.junit.jupiter.api.BeforeEach)10 ConstraintViolationException (javax.validation.ConstraintViolationException)9 GrpcProperties (com.hedera.mirror.grpc.GrpcProperties)6 EntityNotFoundException (com.hedera.mirror.grpc.exception.EntityNotFoundException)6