All Downloads are FREE. Search and download functionalities are using the official Maven repository.

io.quarkiverse.reactive.messaging.nats.jetstream.JetStreamIncomingMessage Maven / Gradle / Ivy

There is a newer version: 3.17.0
Show newest version
package io.quarkiverse.reactive.messaging.nats.jetstream;

import static io.quarkiverse.reactive.messaging.nats.jetstream.mapper.HeaderMapper.toMessageHeaders;
import static io.smallrye.reactive.messaging.providers.locals.ContextAwareMessage.captureContextMetadata;

import java.time.Duration;
import java.util.List;
import java.util.Map;
import java.util.concurrent.CompletionStage;
import java.util.concurrent.TimeoutException;
import java.util.function.Function;
import java.util.function.Supplier;

import org.eclipse.microprofile.reactive.messaging.Metadata;

import io.nats.client.Message;
import io.smallrye.reactive.messaging.providers.helpers.VertxContext;
import io.vertx.mutiny.core.Context;

public class JetStreamIncomingMessage implements JetStreamMessage {
    private final Message message;
    private Metadata metadata;
    private final JetStreamIncomingMessageMetadata incomingMetadata;
    private final T payload;
    private final Context context;
    private final ExponentialBackoff exponentialBackoff;
    private final Duration ackTimeout;

    public JetStreamIncomingMessage(final Message message,
            final T payload,
            Context context,
            ExponentialBackoff exponentialBackoff,
            Duration ackTimeout) {
        this.message = message;
        this.incomingMetadata = JetStreamIncomingMessageMetadata.of(message);
        this.exponentialBackoff = exponentialBackoff;
        this.metadata = captureContextMetadata(incomingMetadata);
        this.payload = payload;
        this.context = context;
        this.ackTimeout = ackTimeout;
    }

    @Override
    public Metadata getMetadata() {
        return metadata;
    }

    public String getMessageId() {
        return incomingMetadata.messageId();
    }

    public byte[] getData() {
        return message.getData();
    }

    public String getSubject() {
        return incomingMetadata.subject();
    }

    public String getStream() {
        return incomingMetadata.stream();
    }

    public Map> getHeaders() {
        return toMessageHeaders(message.getHeaders());
    }

    @Override
    public T getPayload() {
        return payload;
    }

    @Override
    public Supplier> getAck() {
        return this::ack;
    }

    @Override
    public CompletionStage ack() {
        return VertxContext.runOnContext(context.getDelegate(), f -> {
            try {
                message.ackSync(ackTimeout);
                this.runOnMessageContext(() -> f.complete(null));
            } catch (TimeoutException | InterruptedException e) {
                this.runOnMessageContext(() -> f.completeExceptionally(e));
            }
        });
    }

    @Override
    public CompletionStage nack(Throwable reason, Metadata metadata) {
        return VertxContext.runOnContext(context.getDelegate(), f -> {
            if (exponentialBackoff.enabled()) {
                metadata.get(JetStreamIncomingMessageMetadata.class)
                        .ifPresentOrElse(m -> message.nakWithDelay(exponentialBackoff.getDuration(m.deliveredCount())),
                                message::nak);
            } else {
                message.nak();
            }
            this.runOnMessageContext(() -> f.complete(null));
        });
    }

    @Override
    public Function> getNack() {
        return this::nack;
    }

    @Override
    public synchronized void injectMetadata(Object metadataObject) {
        this.metadata = metadata.with(metadataObject);
    }

    @Override
    public String toString() {
        return "IncomingNatsMessage{" +
                "metadata=" + incomingMetadata +
                ", payload=" + payload +
                '}';
    }
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy