io.quarkiverse.reactive.messaging.nats.jetstream.JetStreamIncomingMessage Maven / Gradle / Ivy
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