check status of RabbitMQ, whether message is published? - ruby-on-rails

I have one resque job which is run at some event which finally publishes the message to RabbitMQ's exchange, how can I check in bunny(Rabbit MQ ruby client) that whether the message has been successfully published?
Using Acknowledgment or any way?
Thanks in advance!

When you execute the publish you are not sure that the message is published on the queue.
If you want to be sure you have to use you have to use publish confirm or tx transaction.
Read this post http://www.rabbitmq.com/blog/2011/02/10/introducing-publisher-confirms/
Note: By default the clients don't have any HA policy, you have to implement it. See the section Streaming Lightweight Publisher Confirms:
private volatile SortedSet<Long> unconfirmedSet =
Collections.synchronizedSortedSet(new TreeSet());
...
ch.setConfirmListener(new ConfirmListener() {
public void handleAck(long seqNo, boolean multiple) {
if (multiple) {
unconfirmedSet.headSet(seqNo+1).clear();
} else {
unconfirmedSet.remove(seqNo);
}
}
public void handleNack(long seqNo, boolean multiple) {
// handle the lost messages somehow
}
});
Note2: the message is never "put" inside an exchange, but always inside a queue.

Once the publish method returns, the message has published to the queue. There is no deferred action to publishing a message.

Related

Why XMLMessageProducer is closed when called by multiple threads?

I encapsulated JCSMP API in a class and provide methods for other classes to send and consume messages.
I have the following method:
public void send(byte[] data, String queueName) throws JCSMPException {
// Acquire a message producer
if (producer == null) { //producer is an instance of XMLMessageProducer
producer = session.getMessageProducer(new PublishCallback());
}
Queue queue = JCSMPFactory.onlyInstance().createQueue(queueName);
BytesMessage msg = JCSMPFactory.onlyInstance().createMessage(BytesMessage.class);
msg.setData(data);
msg.setDeliveryMode(DeliveryMode.PERSISTENT);
logger.info("Sending to \"{}\"", queueName);
producer.send(msg, queue);
}
When I have multiple threads calling this method, once in a while, I notice the following exception:
com.solacesystems.jcsmp.ClosedFacilityException: Tried to perform operation on a closed XML message producer
I wonder whether the producer is closed after each call to send(). How should I make this method thread-safe?
Thank you.
XMLMessageProducer does not close itself after each call to send.
The first step here is to investigate why your XMLMessageProducer is closed. The easiest option to do this is to enable the Solace API logging to INFO (or even DEBUG), and edit your question to include the Solace API logs prior to the first ClosedFacilityException.
One possible reason is that your application has disconnected, but was not able to automatically reconnect to the Solace appliance/VMR.

stomp disconnects its processing twice in channel interceptor and SimpleBrokerMessageHandler

I have modified to implement channel interceptor in spring-websocket-portfolio sample application (https://github.com/rstoyanchev/spring-websocket-portfolio). whenever the client disconnects, channel interceptor is processed twice. I have similar implementation in my production application. As it is being invoked twice so it has unwanted result for the 2nd invocation. I had put work around for the time being. But wondering why my channel interceptor is invoked twice? Any help would be highly appreciated.
modified items: WebSocketConfig.java:
#Override
public void configureClientInboundChannel(ChannelRegistration registration) {
registration.setInterceptors(channelInterceptor());
}
#Bean
public ChannelInterceptor channelInterceptor() {
return new ChannelInterceptor();
}
ChannelInterceptor :
package org.springframework.samples.portfolio.config;
import org.springframework.messaging.Message;
import org.springframework.messaging.MessageChannel;
import org.springframework.messaging.simp.stomp.StompHeaderAccessor;
import org.springframework.messaging.support.ChannelInterceptorAdapter;
public class ChannelInterceptor extends ChannelInterceptorAdapter {
#Override
public void postSend(Message<?> message, MessageChannel channel, boolean sent) {
StompHeaderAccessor sha = StompHeaderAccessor.wrap(message);
System.out.println(sha.getCommand() + " " + sha);
switch (sha.getCommand()) {
case CONNECT: {
System.out.println("connected:"+sha.getSessionId());
break;
}
case DISCONNECT: {
System.out.println("disconnected:"+sha.getSessionId());
break;
}
default:
System.out.println("default:"+sha.getCommand());
break;
}
}
}
logs:
**disconnected**:9k1hvln6
**disconnected**:9k1hvln6
Disconnect events may happen more than once for the same session, your interceptor should be idempotent and ignore duplicate events.
You may also consider using application events (SessionConnectEvent, SessionDisconnectEvent...) instead of a channel interceptor. Here's an example of an idempotent event listener: https://github.com/salmar/spring-websocket-chat/blob/master/src/main/java/com/sergialmar/wschat/event/PresenceEventListener.java
Generally a DISCONNECT frame comes the client side, is processed in the StompSubProtocolHandler, and is then propagated to the broker. However, a connection can also be closed or lost without a DISCONNECT frame. Regardless of how a connection is closed, the StompSubProtocolMessageHandler generates a DISCONNECT frame. So there is some redundancy on the server side to ensure the broker is aware the client connection is gone.
As Sergi mentioned you can either subscribe to listen for SessionDisconnectEvent (of which there should be only one) and other AbstractSubProtocol events or ensure your code is idempotent.

Spring AMQP publisher confirms in a amqp outbound gateway

I am using spring amqp publishing my messages to RabbitMQ using an outbound gateway. I have set publisher confirms on the connection factory and added my custom callback listener.
The problem is that my CorrelationData is always null and i can't add any correlation data on an outbound gateway. This is only applicable for an outbound channel adapter.
For an outbound gateway will publisher confirms even work?
EDIT
My configuration is below. I looked through the SI code and yes, publisher confirms, are enabled. The problem is what I do when I receive a NACK?
Because of the outbound gateway I don't need a correlation id to handle the response, there is already a thread listening on a temporary reply queue for the response.
What exactly is the point of using publisher confirms with an outbound gateway? If no response is coming or my Rabbit nodes go down I will encounter exceptions. Is there a scenario when I will lose messages?
<rabbit:connection-factory id="rabbitConnectionFactory"
host="someip" port="5672"
username="username"
password="password"
virtual-host="vhost"
publisher-confirms="true"/>
<rabbit:admin connection-factory="rabbitConnectionFactory"/>
<rabbit:template id="amqpTemplate" connection-factory="rabbitConnectionFactory"
confirm-callback="messagesConfirmCallback"/>
<int-amqp:outbound-gateway
request-channel="channel"
amqp-template="amqpTemplate"
exchange-name="exchange"
routing-key-expression="headers['queueSpecific']+'.queue'">
<amqp:request-handler-advice-chain>
<ref bean="retryAdvice"/>
</amqp:request-handler-advice-chain>
</int-amqp:outbound-gateway>
And my callback is also simple
#Component
public class MessagesConfirmCallback implements RabbitTemplate.ConfirmCallback {
private final static Logger LOGGER = LoggerFactory.getLogger(MessagesConfirmCallback.class);
#Override
public void confirm(CorrelationData correlationData, boolean ack) {
if(ack){
LOGGER.info("ACK received");
}
else{
LOGGER.info("NACK received");
}
}
}
This
Unfortunately, I don't see an easy work around with the gateway; the underlying RabbitTemplate only supports adding correlation data on send() methods, not the sendAndReceive methods.
The two options I can think of is to (1) use a pair of outbound and inbound adapters (instead of the gateway), but you'll have to do your own request/reply correlation in that case.
Alternatively (2), use the RabbitTemplate.execute() and in the doInRabbit callback, add code similar to that in the RabbitTempalate.doSendAndReceive, while setting the correlation data as is done in doSend().
I opened a JIRA Issue.

Controlling Start-Up and Shutdown of Camel Routes

I am trying to make kind of a polling service towards a activemq queue using camel routes.
I am using routing and routing-jsm plugins for grails.
I have my route configuration set like this.
class QueueRoute {
def configure = {
from("activemq:daemon").routeId("daemonRoute")
.noAutoStartup()
.shutdownRunningTask(ShutdownRunningTask.CompleteCurrentTaskOnly)
.to('bean:daemonCamelService?method=receive')
.end()
}
}
and I am basically trying to do .suspendRoute("daemonRoute") and .resumeRoute("daemonRoute") with some time inbetween. Though after issuing suspendRoute the route is not stopped.
Anyone have tried this?, I have read something about needing to kill the exchange in progress or something similar.
if you are just trying to periodically process all messages in a queue, then another option (instead of starting and stopping the route) is to use a timer and a polling consumer bean to do retrieve all the messages in the queue...
from("timer://processQueueTimer?fixedRate=true&period=30000")
.to("bean:myBean?method=poll");
public class MyBean {
public void poll() {
// loop to empty queue
while (true) {
// receive the message from the queue, wait at most 3 sec
Object msg = consumer.receiveBody("activemq:queue:daemon", 3000);
if (msg == null) {
// no more messages in queue
break;
}
// send it to the next endpoint
producer.sendBody("bean:daemonCamelService?method=receive", msg);
}
}
}
See this FAQ how to stop/suspend a route from a route
http://camel.apache.org/how-can-i-stop-a-route-from-a-route.html
An alternative is to use a route policy
http://camel.apache.org/routepolicy
For example as we do with the throttling route policy that is provided out of the box, take a look at how its implemented, you can do similar for your route as well.

Private messaging in a asp.net mvc app with email reply

We are currently implementing private messaging in our asp.net mvc app and we have come to the conclusion that we would like to make it work like github does... meaning we would like the user to receive the message both through our site and to his email inbox(this is somewhat easy to achieve with mvcmailer nuget).. but we would also like the option to have the user reply to the email (through his email client) and have that email be sent to our app (if you have used guthubs private messaging you should know what I mean)..... what is a common approach to implementing this feature?
See my comment regarding how to read emails from a mailbox.
I would use a message bus so that you are not limited to just internal and email notifications, for example you may wish to add SMS notifications in the future.
You may want to check out MassTransit or NServiceBus although for something like this it may be easier to just create your own.
public class Message {
public string Title {get;set;}
public string Body {get;set;}
}
public interface IMessageBus {
void Send(Message message);
}
public interface IMessageHandler {
void Handle(Message message);
}
public class InternalMessageHander : IMessageHandler {
public void Handle(Message message) {
// send internal message
}
}
public class EmailMessageHandler : IMessageHandler {
public void Handle(Message message) {
// send email
}
}
Your IMessageBus implementation would need to locate all the handlers (I would use an IoC container for this).
If you need to process large volumes of messages then I would recommend handing these off to a queue and processing these asynchronously (both MassTransit and NServiceBus support message queues but you could just as easily use a simple database table).
As far as reading emails, I would have background task that connects to the mailbox, downloads emails, parses them and updates your content.
Usually you put either something in the subject line or at the end of the body to track the email. Any UID will do.
Hope that helps.

Resources