net.leanix.dropkit.amqp.QueueProducer Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of leanix-dropkit Show documentation
Show all versions of leanix-dropkit Show documentation
Base functionality for leanIX dropwizard-based services
package net.leanix.dropkit.amqp;
import com.google.inject.Inject;
import com.rabbitmq.client.AMQP;
import com.rabbitmq.client.Channel;
import com.rabbitmq.client.ShutdownSignalException;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.io.IOException;
import java.nio.charset.Charset;
import java.util.Collections;
import java.util.Map;
import java.util.UUID;
/**
* Manages submission of messages to a RabbitMQ message queue and creation of consumers.
*
* Important: Try to avoid unnecessary instantiation of this class and better use a singleton pattern (eg. @Singleton). The reason
* for this advice is, each new Instance of QueueProducer
will affect in estabilisching a new channel to rabbitMQ but rabbitMQ
* only support 65535 channels at all.
*
*/
public class QueueProducer {
private final Logger log = LoggerFactory.getLogger(QueueProducer.class);
private final Charset utf8 = Charset.forName("UTF-8");
private final ConnectionHolder connectionHolder;
private Channel channel;
private final ConsumerRegistry registry;
@Inject
public QueueProducer(ConnectionHolder connectionHolder, ConsumerRegistry consumerRegistry) {
this.connectionHolder = connectionHolder;
this.registry = consumerRegistry;
}
public UUID submit(String jsonString, String queueName) throws IOException {
byte[] msgContent = jsonString.getBytes(utf8);
// ensure having a consumer for the queue (workspace)
registry.consumerPresto(queueName);
return performPublish(queueName, msgContent);
}
/**
* Publish a message to a queue, creating a connection and a channel if needed.
*
* @param queueName
* name of the queue where the message will be published
* @param msgContent
* content of the message
*/
private UUID performPublish(String queueName, byte[] msgContent) throws IOException {
// Maybe too complicated -- should we instead just create a new channel here and
// close it at the end of this method?
// Channel creation is expensive, too.
if (channel == null || !channel.isOpen()) {
log.info("creating a channel to AMQP server for publishing");
channel = connectionHolder.createNewChannel();
}
try {
// declare (create if missing) the workspace queue as durable,
// which is not removed when the connection closes (exclusive flag)
// nor when there is temporarily no consumer (autodelete flag)
// queue shall be automatically deleted by the server after being unused
// for more than one day (unused means no consumers, no re-declares)
// note that the publishing queue here needs to be declared with the same
// parameters as the consuming queue in ConsumerRegistry.consumerPresto()!
// and, as it is a permanent queue, with the same parameters as ever before!
Map args = Collections. singletonMap("x-expires",
ConsumerRegistry.QUEUE_X_EXPIRY_MILLIS);
channel.queueDeclare(queueName, true, false, false, args);
UUID messageId = UUID.randomUUID();
log.debug("publishing message {} to queue {}", messageId, queueName);
AMQP.BasicProperties.Builder bldr = new AMQP.BasicProperties.Builder();
bldr.messageId(messageId.toString());
// FIXME encoding and content type should be set outside this method to be more flexible
bldr.contentEncoding(utf8.name());
bldr.contentType("application/json");
// Make the message persistent if server goes down
bldr.deliveryMode(2);
// The unnamed exchange puts the message to the queue with the name
// given by parameter routingKey.
// We just created the queue above, so don't go into the hassle
// of using the mandatory mechanism and its callback.
channel.basicPublish("", queueName, false, bldr.build(), msgContent);
return messageId;
} catch (ShutdownSignalException e) {
log.info("{} was shut down unexpectedly", e.isHardError() ? "Connection" : "Channel");
channel = null;
if (e.isHardError()) {
connectionHolder.closeConnection();
}
}
return null;
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy