
org.reactivecommons.async.rabbit.RabbitDirectAsyncGateway Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of async-rabbit Show documentation
Show all versions of async-rabbit Show documentation
Abstract your broker with semantic async messages
The newest version!
package org.reactivecommons.async.rabbit;
import io.cloudevents.CloudEvent;
import io.micrometer.core.instrument.MeterRegistry;
import org.reactivecommons.api.domain.Command;
import org.reactivecommons.async.api.AsyncQuery;
import org.reactivecommons.async.api.DirectAsyncGateway;
import org.reactivecommons.async.api.From;
import org.reactivecommons.async.commons.config.BrokerConfig;
import org.reactivecommons.async.commons.converters.MessageConverter;
import org.reactivecommons.async.commons.reply.ReactiveReplyRouter;
import org.reactivecommons.async.rabbit.communications.ReactiveMessageSender;
import reactor.core.observability.micrometer.Micrometer;
import reactor.core.publisher.Flux;
import reactor.core.publisher.Mono;
import reactor.rabbitmq.OutboundMessageResult;
import reactor.util.function.Tuple2;
import reactor.util.function.Tuples;
import java.time.Duration;
import java.util.Collections;
import java.util.HashMap;
import java.util.Map;
import java.util.UUID;
import java.util.concurrent.TimeoutException;
import java.util.function.Function;
import static java.lang.Boolean.TRUE;
import static org.reactivecommons.async.api.HandlerRegistry.DEFAULT_DOMAIN;
import static org.reactivecommons.async.commons.Headers.COMPLETION_ONLY_SIGNAL;
import static org.reactivecommons.async.commons.Headers.CORRELATION_ID;
import static org.reactivecommons.async.commons.Headers.REPLY_ID;
import static org.reactivecommons.async.commons.Headers.REPLY_TIMEOUT_MILLIS;
import static org.reactivecommons.async.commons.Headers.SERVED_QUERY_ID;
public class RabbitDirectAsyncGateway implements DirectAsyncGateway {
private final BrokerConfig config;
private final ReactiveReplyRouter router;
private final ReactiveMessageSender sender;
private final String exchange;
private final MessageConverter converter;
private final boolean persistentCommands;
private final boolean persistentQueries;
private final Duration replyTimeout;
private final MeterRegistry meterRegistry;
public RabbitDirectAsyncGateway(BrokerConfig config, ReactiveReplyRouter router, ReactiveMessageSender sender,
String exchange, MessageConverter converter, MeterRegistry meterRegistry) {
this.config = config;
this.router = router;
this.sender = sender;
this.exchange = exchange;
this.converter = converter;
this.persistentCommands = config.isPersistentCommands();
this.persistentQueries = config.isPersistentQueries();
this.replyTimeout = config.getReplyTimeout();
this.meterRegistry = meterRegistry;
}
@Override
public Mono sendCommand(Command command, String targetName) {
return sendCommand(command, targetName, 0, DEFAULT_DOMAIN);
}
@Override
public Mono sendCommand(Command command, String targetName, long delayMillis) {
return sendCommand(command, targetName, delayMillis, DEFAULT_DOMAIN);
}
@Override
public Mono sendCommand(Command command, String targetName, String domain) {
return sendCommand(command, targetName, 0, domain);
}
@Override
public Mono sendCommand(Command command, String targetName, long delayMillis, String domain) {
Tuple2> targetAndHeaders = validateDelay(targetName, delayMillis);
return resolveSender(domain).sendWithConfirm(command, exchange, targetAndHeaders.getT1(),
targetAndHeaders.getT2(), persistentCommands);
}
@Override
public Mono sendCommand(CloudEvent command, String targetName) {
return sendCommand(command, targetName, 0, DEFAULT_DOMAIN);
}
@Override
public Mono sendCommand(CloudEvent command, String targetName, long delayMillis) {
return sendCommand(command, targetName, delayMillis, DEFAULT_DOMAIN);
}
@Override
public Mono sendCommand(CloudEvent command, String targetName, String domain) {
return sendCommand(command, targetName, 0, domain);
}
@Override
public Mono sendCommand(CloudEvent command, String targetName, long delayMillis, String domain) {
Tuple2> targetAndHeaders = validateDelay(targetName, delayMillis);
return resolveSender(domain).sendWithConfirm(command, exchange, targetAndHeaders.getT1(),
targetAndHeaders.getT2(), persistentCommands);
}
public Flux sendCommands(Flux> commands, String targetName) {
return sender.sendWithConfirmBatch(commands, exchange, targetName, Collections.emptyMap(), persistentCommands);
}
@Override
public Mono requestReply(AsyncQuery query, String targetName, Class type) {
return requestReply(query, targetName, type, DEFAULT_DOMAIN);
}
@Override
public Mono requestReply(AsyncQuery query, String targetName, Class type, String domain) {
return requestReplyInternal(query, targetName, type, domain, AsyncQuery::getResource);
}
@Override
public Mono requestReply(CloudEvent query, String targetName, Class type) {
return requestReplyInternal(query, targetName, type, DEFAULT_DOMAIN, CloudEvent::getType);
}
@Override
public Mono requestReply(CloudEvent query, String targetName, Class type, String domain) {
return requestReplyInternal(query, targetName, type, domain, CloudEvent::getType);
}
private Mono requestReplyInternal(T query, String targetName, Class type, String domain, Function queryTypeExtractor) {
final String correlationID = UUID.randomUUID().toString().replaceAll("-", "");
final Mono replyHolder = router.register(correlationID)
.timeout(replyTimeout)
.doOnError(TimeoutException.class, e -> router.deregister(correlationID))
.map(s -> converter.readValue(s, type));
Map headers = new HashMap<>();
headers.put(REPLY_ID, config.getRoutingKey());
headers.put(SERVED_QUERY_ID, queryTypeExtractor.apply(query));
headers.put(CORRELATION_ID, correlationID);
headers.put(REPLY_TIMEOUT_MILLIS, replyTimeout.toMillis());
return resolveSender(domain).sendNoConfirm(query, exchange, targetName + ".query", headers, persistentQueries)
.then(replyHolder)
.name("async_query")
.tag("operation", queryTypeExtractor.apply(query))
.tag("target", targetName)
.tap(Micrometer.metrics(meterRegistry));
}
@Override
public Mono reply(T response, From from) {
final HashMap headers = new HashMap<>();
headers.put(CORRELATION_ID, from.getCorrelationID());
if (response == null) {
headers.put(COMPLETION_ONLY_SIGNAL, TRUE.toString());
}
return sender.sendNoConfirm(response, "globalReply", from.getReplyID(), headers, false);
}
protected ReactiveMessageSender resolveSender(String domain) { // NOSONAR
return sender;
}
private Tuple2> validateDelay(String targetName, long delayMillis) {
Map headers = new HashMap<>();
String realTarget = targetName;
if (delayMillis > 0) {
headers.put(DELAYED, String.valueOf(delayMillis));
realTarget = targetName + "-delayed";
}
return Tuples.of(realTarget, headers);
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy