use of com.rabbitmq.client.Channel in project cloudstack by apache.
the class RabbitMQEventBus method subscribe.
/** Call to subscribe to interested set of events
*
* @param topic defines category and type of the events being subscribed to
* @param subscriber subscriber that intends to receive event notification
* @return UUID that represents the subscription with event bus
* @throws EventBusException
*/
@Override
public UUID subscribe(EventTopic topic, EventSubscriber subscriber) throws EventBusException {
if (subscriber == null || topic == null) {
throw new EventBusException("Invalid EventSubscriber/EventTopic object passed.");
}
// create a UUID, that will be used for managing subscriptions and also used as queue name
// for on the queue used for the subscriber on the AMQP broker
UUID queueId = UUID.randomUUID();
String queueName = queueId.toString();
try {
String bindingKey = createBindingKey(topic);
// store the subscriber details before creating channel
s_subscribers.put(queueName, new Ternary(bindingKey, null, subscriber));
// create a channel dedicated for this subscription
Connection connection = getConnection();
Channel channel = createChannel(connection);
// create a queue and bind it to the exchange with binding key formed from event topic
createExchange(channel, amqpExchangeName);
channel.queueDeclare(queueName, false, false, false, null);
channel.queueBind(queueName, amqpExchangeName, bindingKey);
// register a callback handler to receive the events that a subscriber subscribed to
channel.basicConsume(queueName, s_autoAck, queueName, new DefaultConsumer(channel) {
@Override
public void handleDelivery(String queueName, Envelope envelope, AMQP.BasicProperties properties, byte[] body) throws IOException {
Ternary<String, Channel, EventSubscriber> queueDetails = s_subscribers.get(queueName);
if (queueDetails != null) {
EventSubscriber subscriber = queueDetails.third();
String routingKey = envelope.getRoutingKey();
String eventSource = getEventSourceFromRoutingKey(routingKey);
String eventCategory = getEventCategoryFromRoutingKey(routingKey);
String eventType = getEventTypeFromRoutingKey(routingKey);
String resourceType = getResourceTypeFromRoutingKey(routingKey);
String resourceUUID = getResourceUUIDFromRoutingKey(routingKey);
Event event = new Event(eventSource, eventCategory, eventType, resourceType, resourceUUID);
event.setDescription(new String(body));
// deliver the event to call back object provided by subscriber
subscriber.onEvent(event);
}
}
});
// update the channel details for the subscription
Ternary<String, Channel, EventSubscriber> queueDetails = s_subscribers.get(queueName);
queueDetails.second(channel);
s_subscribers.put(queueName, queueDetails);
} catch (AlreadyClosedException closedException) {
s_logger.warn("Connection to AMQP service is lost. Subscription:" + queueName + " will be active after reconnection");
} catch (ConnectException connectException) {
s_logger.warn("Connection to AMQP service is lost. Subscription:" + queueName + " will be active after reconnection");
} catch (Exception e) {
throw new EventBusException("Failed to subscribe to event due to " + e.getMessage());
}
return queueId;
}
use of com.rabbitmq.client.Channel in project cloudstack by apache.
the class RabbitMQEventBus method unsubscribe.
@Override
public void unsubscribe(UUID subscriberId, EventSubscriber subscriber) throws EventBusException {
try {
String classname = subscriber.getClass().getName();
String queueName = UUID.nameUUIDFromBytes(classname.getBytes()).toString();
Ternary<String, Channel, EventSubscriber> queueDetails = s_subscribers.get(queueName);
Channel channel = queueDetails.second();
channel.basicCancel(queueName);
s_subscribers.remove(queueName, queueDetails);
} catch (Exception e) {
throw new EventBusException("Failed to unsubscribe from event bus due to " + e.getMessage());
}
}
use of com.rabbitmq.client.Channel in project druid by druid-io.
the class RabbitMQFirehoseFactory method connect.
@Override
public Firehose connect(final ByteBufferInputRowParser firehoseParser) throws IOException {
ConnectionOptions lyraOptions = new ConnectionOptions(this.connectionFactory);
Config lyraConfig = new Config().withRecoveryPolicy(new RetryPolicy().withMaxRetries(config.getMaxRetries()).withRetryInterval(Duration.seconds(config.getRetryIntervalSeconds())).withMaxDuration(Duration.seconds(config.getMaxDurationSeconds())));
String queue = config.getQueue();
String exchange = config.getExchange();
String routingKey = config.getRoutingKey();
boolean durable = config.isDurable();
boolean exclusive = config.isExclusive();
boolean autoDelete = config.isAutoDelete();
final Connection connection = Connections.create(lyraOptions, lyraConfig);
connection.addShutdownListener(new ShutdownListener() {
@Override
public void shutdownCompleted(ShutdownSignalException cause) {
log.warn(cause, "Connection closed!");
}
});
final Channel channel = connection.createChannel();
channel.queueDeclare(queue, durable, exclusive, autoDelete, null);
channel.queueBind(queue, exchange, routingKey);
channel.addShutdownListener(new ShutdownListener() {
@Override
public void shutdownCompleted(ShutdownSignalException cause) {
log.warn(cause, "Channel closed!");
}
});
// We create a QueueingConsumer that will not auto-acknowledge messages since that
// happens on commit().
final QueueingConsumer consumer = new QueueingConsumer(channel);
channel.basicConsume(queue, false, consumer);
return new Firehose() {
/**
* Storing the latest delivery as a member variable should be safe since this will only be run
* by a single thread.
*/
private Delivery delivery;
/**
* Store the latest delivery tag to be able to commit (acknowledge) the message delivery up to
* and including this tag. See commit() for more detail.
*/
private long lastDeliveryTag;
@Override
public boolean hasMore() {
delivery = null;
try {
// Wait for the next delivery. This will block until something is available.
delivery = consumer.nextDelivery();
if (delivery != null) {
lastDeliveryTag = delivery.getEnvelope().getDeliveryTag();
// If delivery is non-null, we report that there is something more to process.
return true;
}
} catch (InterruptedException e) {
// A little unclear on how we should handle this.
// At any rate, we're in an unknown state now so let's log something and return false.
log.wtf(e, "Got interrupted while waiting for next delivery. Doubt this should ever happen.");
}
// nothing more to process.
return false;
}
@Override
public InputRow nextRow() {
if (delivery == null) {
//Just making sure.
log.wtf("I have nothing in delivery. Method hasMore() should have returned false.");
return null;
}
return firehoseParser.parse(ByteBuffer.wrap(delivery.getBody()));
}
@Override
public Runnable commit() {
// acknowledge values up to and including that value.
return new Runnable() {
// Store (copy) the last delivery tag to "become" thread safe.
final long deliveryTag = lastDeliveryTag;
@Override
public void run() {
try {
log.info("Acknowledging delivery of messages up to tag: " + deliveryTag);
// Acknowledge all messages up to and including the stored delivery tag.
channel.basicAck(deliveryTag, true);
} catch (IOException e) {
log.error(e, "Unable to acknowledge message reception to message queue.");
}
}
};
}
@Override
public void close() throws IOException {
log.info("Closing connection to RabbitMQ");
channel.close();
connection.close();
}
};
}
use of com.rabbitmq.client.Channel in project druid by druid-io.
the class RabbitMQProducerMain method main.
public static void main(String[] args) throws Exception {
// We use a List to keep track of option insertion order. See below.
final List<Option> optionList = new ArrayList<Option>();
optionList.add(OptionBuilder.withLongOpt("help").withDescription("display this help message").create("h"));
optionList.add(OptionBuilder.withLongOpt("hostname").hasArg().withDescription("the hostname of the AMQP broker [defaults to AMQP library default]").create("b"));
optionList.add(OptionBuilder.withLongOpt("port").hasArg().withDescription("the port of the AMQP broker [defaults to AMQP library default]").create("n"));
optionList.add(OptionBuilder.withLongOpt("username").hasArg().withDescription("username to connect to the AMQP broker [defaults to AMQP library default]").create("u"));
optionList.add(OptionBuilder.withLongOpt("password").hasArg().withDescription("password to connect to the AMQP broker [defaults to AMQP library default]").create("p"));
optionList.add(OptionBuilder.withLongOpt("vhost").hasArg().withDescription("name of virtual host on the AMQP broker [defaults to AMQP library default]").create("v"));
optionList.add(OptionBuilder.withLongOpt("exchange").isRequired().hasArg().withDescription("name of the AMQP exchange [required - no default]").create("e"));
optionList.add(OptionBuilder.withLongOpt("key").hasArg().withDescription("the routing key to use when sending messages [default: 'default.routing.key']").create("k"));
optionList.add(OptionBuilder.withLongOpt("type").hasArg().withDescription("the type of exchange to create [default: 'topic']").create("t"));
optionList.add(OptionBuilder.withLongOpt("durable").withDescription("if set, a durable exchange will be declared [default: not set]").create("d"));
optionList.add(OptionBuilder.withLongOpt("autodelete").withDescription("if set, an auto-delete exchange will be declared [default: not set]").create("a"));
optionList.add(OptionBuilder.withLongOpt("single").withDescription("if set, only a single message will be sent [default: not set]").create("s"));
optionList.add(OptionBuilder.withLongOpt("start").hasArg().withDescription("time to use to start sending messages from [default: 2010-01-01T00:00:00]").create());
optionList.add(OptionBuilder.withLongOpt("stop").hasArg().withDescription("time to use to send messages until (format: '2013-07-18T23:45:59') [default: current time]").create());
optionList.add(OptionBuilder.withLongOpt("interval").hasArg().withDescription("the interval to add to the timestamp between messages in seconds [default: 10]").create());
optionList.add(OptionBuilder.withLongOpt("delay").hasArg().withDescription("the delay between sending messages in milliseconds [default: 100]").create());
// An extremely silly hack to maintain the above order in the help formatting.
HelpFormatter formatter = new HelpFormatter();
// Add a comparator to the HelpFormatter using the ArrayList above to sort by insertion order.
formatter.setOptionComparator(new Comparator() {
@Override
public int compare(Object o1, Object o2) {
// I know this isn't fast, but who cares! The list is short.
return optionList.indexOf(o1) - optionList.indexOf(o2);
}
});
// Now we can add all the options to an Options instance. This is dumb!
Options options = new Options();
for (Option option : optionList) {
options.addOption(option);
}
CommandLine cmd = null;
try {
cmd = new BasicParser().parse(options, args);
} catch (ParseException e) {
formatter.printHelp("RabbitMQProducerMain", e.getMessage(), options, null);
System.exit(1);
}
if (cmd.hasOption("h")) {
formatter.printHelp("RabbitMQProducerMain", options);
System.exit(2);
}
ConnectionFactory factory = new ConnectionFactory();
if (cmd.hasOption("b")) {
factory.setHost(cmd.getOptionValue("b"));
}
if (cmd.hasOption("u")) {
factory.setUsername(cmd.getOptionValue("u"));
}
if (cmd.hasOption("p")) {
factory.setPassword(cmd.getOptionValue("p"));
}
if (cmd.hasOption("v")) {
factory.setVirtualHost(cmd.getOptionValue("v"));
}
if (cmd.hasOption("n")) {
factory.setPort(Integer.parseInt(cmd.getOptionValue("n")));
}
String exchange = cmd.getOptionValue("e");
String routingKey = "default.routing.key";
if (cmd.hasOption("k")) {
routingKey = cmd.getOptionValue("k");
}
boolean durable = cmd.hasOption("d");
boolean autoDelete = cmd.hasOption("a");
String type = cmd.getOptionValue("t", "topic");
boolean single = cmd.hasOption("single");
int interval = Integer.parseInt(cmd.getOptionValue("interval", "10"));
int delay = Integer.parseInt(cmd.getOptionValue("delay", "100"));
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss");
Date stop = sdf.parse(cmd.getOptionValue("stop", sdf.format(new Date())));
Random r = new Random();
Calendar timer = Calendar.getInstance();
timer.setTime(sdf.parse(cmd.getOptionValue("start", "2010-01-01T00:00:00")));
String msg_template = "{\"utcdt\": \"%s\", \"wp\": %d, \"gender\": \"%s\", \"age\": %d}";
Connection connection = factory.newConnection();
Channel channel = connection.createChannel();
channel.exchangeDeclare(exchange, type, durable, autoDelete, null);
do {
int wp = (10 + r.nextInt(90)) * 100;
String gender = r.nextBoolean() ? "male" : "female";
int age = 20 + r.nextInt(70);
String line = String.format(msg_template, sdf.format(timer.getTime()), wp, gender, age);
channel.basicPublish(exchange, routingKey, null, line.getBytes());
System.out.println("Sent message: " + line);
timer.add(Calendar.SECOND, interval);
Thread.sleep(delay);
} while ((!single && stop.after(timer.getTime())));
connection.close();
}
use of com.rabbitmq.client.Channel in project elasticsearch-river-rabbitmq by elastic.
the class RabbitMQIntegrationTest method launchTest.
private void launchTest(XContentBuilder river, final int numMessages, final int numDocsPerMessage, InjectorHook injectorHook, boolean delete, boolean update) throws Exception {
final String dbName = getDbName();
logger.info(" --> create index [{}]", dbName);
try {
client().admin().indices().prepareDelete(dbName).get();
} catch (IndexMissingException e) {
// No worries.
}
try {
createIndex(dbName);
} catch (IndexMissingException e) {
// No worries.
}
ensureGreen(dbName);
logger.info(" -> Checking rabbitmq running");
// We try to connect to RabbitMQ.
// If it's not launched, we don't fail the test but only log it
Channel channel = null;
Connection connection = null;
try {
logger.info(" --> connecting to rabbitmq");
ConnectionFactory factory = new ConnectionFactory();
factory.setHost("localhost");
factory.setPort(AMQP.PROTOCOL.PORT);
connection = factory.newConnection();
} catch (ConnectException ce) {
throw new Exception("RabbitMQ service is not launched on localhost:" + AMQP.PROTOCOL.PORT + ". Can not start Integration test. " + "Launch `rabbitmq-server`.", ce);
}
try {
logger.info(" -> Creating [{}] channel", dbName);
channel = connection.createChannel();
logger.info(" -> Creating queue [{}]", dbName);
channel.queueDeclare(getDbName(), true, false, false, null);
// We purge the queue in case of something is remaining there
logger.info(" -> Purging [{}] channel", dbName);
channel.queuePurge(getDbName());
logger.info(" -> Put [{}] messages with [{}] documents each = [{}] docs", numMessages, numDocsPerMessage, numMessages * numDocsPerMessage);
final Set<String> removed = new HashSet<String>();
int nbUpdated = 0;
for (int i = 0; i < numMessages; i++) {
StringBuffer message = new StringBuffer();
for (int j = 0; j < numDocsPerMessage; j++) {
if (logger.isTraceEnabled()) {
logger.trace(" -> Indexing document [{}] - [{}][{}]", i + "_" + j, i, j);
}
message.append("{ \"index\" : { \"_index\" : \"" + dbName + "\", \"_type\" : \"typex\", \"_id\" : \"" + i + "_" + j + "\" } }\n");
message.append("{ \"field\" : \"" + i + "_" + j + "\",\"numeric\" : " + i * j + " }\n");
// Sometime we update a document
if (update && rarely()) {
String id = between(0, i) + "_" + between(0, j);
// We can only update if it has not been removed :)
if (!removed.contains(id)) {
logger.debug(" -> Updating document [{}] - [{}][{}]", id, i, j);
message.append("{ \"update\" : { \"_index\" : \"" + dbName + "\", \"_type\" : \"typex\", \"_id\" : \"" + id + "\" } }\n");
message.append("{ \"doc\": { \"foo\" : \"bar\", \"field2\" : \"" + i + "_" + j + "\" }}\n");
nbUpdated++;
}
}
// Sometime we delete a document
if (delete && rarely()) {
String id = between(0, i) + "_" + between(0, j);
if (!removed.contains(id)) {
logger.debug(" -> Removing document [{}] - [{}][{}]", id, i, j);
message.append("{ \"delete\" : { \"_index\" : \"" + dbName + "\", \"_type\" : \"typex\", \"_id\" : \"" + id + "\" } }\n");
removed.add(id);
}
}
}
channel.basicPublish("", dbName, null, message.toString().getBytes(StandardCharsets.UTF_8));
}
logger.info(" -> We removed [{}] docs and updated [{}] docs", removed.size(), nbUpdated);
if (injectorHook != null) {
logger.info(" -> Injecting extra data");
injectorHook.inject();
}
logger.info(" --> create river");
IndexResponse indexResponse = index("_river", dbName, "_meta", river);
assertTrue(indexResponse.isCreated());
logger.info("--> checking that river [{}] was created", dbName);
assertThat(awaitBusy(new Predicate<Object>() {
public boolean apply(Object obj) {
GetResponse response = client().prepareGet(RiverIndexName.Conf.DEFAULT_INDEX_NAME, dbName, "_status").get();
return response.isExists();
}
}, 5, TimeUnit.SECONDS), equalTo(true));
// Check that docs are still processed by the river
logger.info(" --> waiting for expected number of docs: [{}]", numDocsPerMessage * numMessages - removed.size());
assertThat(awaitBusy(new Predicate<Object>() {
public boolean apply(Object obj) {
try {
refresh();
int expected = numDocsPerMessage * numMessages - removed.size();
CountResponse response = client().prepareCount(dbName).get();
logger.debug(" -> got {} docs, expected {}", response.getCount(), expected);
return response.getCount() == expected;
} catch (IndexMissingException e) {
return false;
}
}
}, 20, TimeUnit.SECONDS), equalTo(true));
} finally {
if (channel != null && channel.isOpen()) {
channel.close();
}
if (connection != null && connection.isOpen()) {
connection.close();
}
// Deletes the river
GetResponse response = client().prepareGet(RiverIndexName.Conf.DEFAULT_INDEX_NAME, dbName, "_status").get();
if (response.isExists()) {
client().prepareDelete(RiverIndexName.Conf.DEFAULT_INDEX_NAME, dbName, "_meta").get();
client().prepareDelete(RiverIndexName.Conf.DEFAULT_INDEX_NAME, dbName, "_status").get();
}
assertThat(awaitBusy(new Predicate<Object>() {
public boolean apply(Object obj) {
GetResponse response = client().prepareGet(RiverIndexName.Conf.DEFAULT_INDEX_NAME, dbName, "_status").get();
return response.isExists();
}
}, 5, TimeUnit.SECONDS), equalTo(false));
}
}
Aggregations