Catch a disconnect event from ActiveMQ - activemq

Using the 1.6 version of NMS (1.6.3 activemq)
I'm setting up a listener to wait for messages.
The listener has a thread of it's own (not mine) and my code get out of scope (until the listener's function is being called).
If the ActiveMQ server disconnects, I get a global exception which I can only catch globally.
(my thread that created the listener will not catch it. I have nothing to wrap with "try" and "catch").
Is there a way to set a callback function like - OnError += ErrorHandlingFunction() as I use the listener to deal with this issue in a local way and not by global exception catcher ?
Is there a better way to deal with this issue (I can't use Transport Failure as I don't have any other options, but to wait a while, and disconnect, maybe log something or send a message that the server is offline).

There is no mechanism in the client for hooking in the async message listener to find out if the connection dropped during the processing of a message. You should really examine why you think you need such a thing there.
NMS API methods you use in the async callback will throw an exception when not connected so if you did something like try to ACK a message in the async message event handler then it would throw an exception if the connection was down.

Related

Creating new channels after RabbitMQ connection was blocked

I have a very basic demo application for testing the RabbitMQ blocking behaviour. I use RabbitMQ 3.10.6 with the .NET library RabbitMQ.Client 6.2.4 in .NET Framework 4.8.
The disk is filled until the configured threshold in the RabbitMQ config file is exceeded. The connection state is "blocking".
I queue a message this way:
AMQP properties are added to the message using channel.CreateBasicProperties() with Persistent = true. It is then queued:
sendChannel.BasicPublish("", "sendQueueName", amqpProperties, someBytes);
sendChannel.WaitForConfirmsOrDie(TimeSpan.FromSeconds(5));
WaitForConfirmsOrDie() closes the underlying channel when the broker is blocking or blocked. Because this is the case the channel is closed and I need to create a new one if I want to queue messages again.
The connection state is "blocked".
First example: I catch the TimeoutException that is thrown, remove the resource alarm by providing enough disk space and create a new channel in the catch block. This works.
Second example: I catch the TimeoutException that is thrown but do nothing in the catch block. I remove the resource alarm by providing enough disk space and wait for the ConnectionUnblocked event to be fired. In here I create a new channel. But here it doesn't work. I get a TimeoutException.
Why can't I create any more channels outside the catch block once the connection was blocked?
The connection is created using ConnectionFactory.CreateConnection() and uses AutomaticRecoveryEnabled = true (although this doesn't seem to make any difference).
A channel is created using Connection.CreateModel().

How to handle network time-out exception with rabbit mq while sending messages asynchronously using spring-amqp library

I have written a program which requires multiple queues interaction - means consumer of one queue writes message to another queue and same program has consumer to take action on that queue.
Problem: How to handle network time-out issues with queue while sending messages asynchronously using spring rabbit ampq library?or RabbitTemplate.send() function must throw an exception if there are network issues.
Currently, I have implemented RabbitTemplate.send() that returns immediately and working fine. But, If network is down, send function returns immediately, doesn't throw any exception and client code assumes success. As a result, i have in-consistent state in DB that message is successfully processed. Please note that call to send function is wrapped inside transactional block and goal is if queue writing fails, DB commit must also rollback. I am exploring following solutions but no success:
Can we configure rabbitTemplate to throw run-time exception if any network connectivity issue so that client call is notified? Please suggest how to do this.
Shall we use synchronous SendAndReceive function call but it leads to delay in processing? Another problem, observed with this function, my consumer code gets notification while sendAndReceive function is still blocked for writing message to queue. Please advise if we can delay notification to queue unless sendAndReceive function is returned. But call to SendAndReceive() was throwing an amqp exception if network was down which we were able to capture, but it has cost associated related to performance.
My application is multi-threaded, if multiple threads are sending message using sendAndReceive(), how spring-amqp library manages queue communication? Does it internally creates channel per request? If messages are delivered via same channel, it would impact performance a lot for multi-threaded application.
Can some-one share sample code for using SendAndReceive function with best-practices?
Do we have any function in spring-amqp library to check health of RabbitMQ server before submitting send function call? I explored rabbitTemplate.isRunning() but not getting proper result. If any specific configuration required, please suggest.
Any other solution to consider for guaranteed message delivery or handle network time-out issues to throw runtime exceptions to client..
As per Gary comment below, I have set: rabbitTemplate.setChannelTransacted(true); and it makes call sync. Next part of problem is that if I have transaction block on outer block, call to RabbitTemplate.send() returns immediately. I expect transaction block of outer function must wait for inner function to return, otherwise, ii don't get expected result as my DB changes are persisted though we enabled setChannelTransacted to true. I tried various Transaction propagation level but no success. Please advise if I am doing anything wrong and review transactional propagation settings as below
#Transactional
public void notifyQueueAndDB(DBRequest dbRequest) {
logger.info("Updating Request in DB");
dbService.updateRequest(dbRequest));
//Below is call to RabbitMQ library
mqService.sendmessage(dbRequest); //If sendMessage fails because of network outage, I want DB commit also to be rolled-back.
}
MQService defined in another library of project, snippet below.
#Transactional( propagation = Propagation.NESTED)
private void sendMessage(......) {
....
rabbitTemplate.send(this.queueExchange, queueName, amqpMessage);
}catch (Exception exception) {
throw exception
}
Enable transactions so that the send is synchronous.
or
Use Publisher confirms and wait for the confirmation to be received.
Either one will be quite a bit slower.

Can I Change the Behavior of MSMQ Message Error Handling by a Workflow Service?

I have a Workflow Service that has a few receives that listen to MSMQ queues. I would like to implement the following behavior:
If a correlation exception occurs (ie - workflow instance is gone), throw away the message.
If an InstanceLockException occurs (ie - this workflow instance is doing something on another server), put the message in the retry queue.
I have tried putting TransactedReceiveScope around the Receive activities, but it will put the message in the retry queue on a correlation error. Plus, it causes a lot of problems under heavy load.
Without the TransactedReceiveScope, the message is thrown away if there is an InstanceLockException.
Is there a way to implement this behavior (maybe via behavior extensions)?
You can implement a IErrorHandler for WCF to catch all unhandled exceptions whether thrown by your app or by WCF. The thing you have to be careful about with the netMsmqBinding is that throwing a fault in this handler means the message has been "successfully" processed and it will taken off the queue. In your case when InstanceLockException occurs, you'll have to let it remain unhandled if you want the built-in MSMQ 4 retry handling to occur. You'll also need to allow the PoisonMessageException to remain unhandled for proper MSMQ retrying to occur.
I'm not familiar with using Workflow, but knowing how MSMQ and WCF work you could try this
When a CorrelationException occurs:
Catch the exception
Return from your service method
Since your service method doesn't throw an exception it will think the message was successfully processed and remove it from the queue.
When a InstanceLockException occurs:
Catch the exception
rethrow the exception
Since your service method throws and exception it will think the message was not successfully processed and move it to the retry queue.
I think you'll have to create a WCF custom behavior to catch those exceptions.

Uncatchable errors in node.js

So I'm trying to write a simple TCP socket server that broadcasts information to all connected clients. So when a user connects, they get added to the list of clients, and when the stream emits the close event, they get removed from the client list.
This works well, except that sometimes I'm sending a message just as a user disconnects.
I've tried wrapping stream.write() in a try/catch block, but no luck. It seems like the error is uncatchable.
The solution is to add a listener for the stream's 'error' event. This might seem counter-intuitive at first, but the justification for it is sound.
stream.write() sends data asynchronously. By the time that node has realized that writing to the socket has raised an error your code has moved on, past the call to stream.write, so there's no way for it to raise the error there.
Instead, what node does in this situation is emit an 'error' event from the stream, and EventEmitter is coded such that if there are no listeners for an 'error' event, the error is raised as a toplevel exception, and the process ends.
Peter is quite right,
and there is also another way, you can also make a catch all error handler with
process.on('uncaughtException',function(error){
// process error
})
this will catch everything which is thrown...
it's usually better to do this peter's way, if possible, however if you where writing, say, a test framework, it may be a good idea to use process.on('uncaughtException',...
here is a gist which covers (i think) all the different aways of handling errors in nodejs
http://gist.github.com/636290
I had the same problem with the time server example from here
My clients get killed and the time server then tries to write to closed socket.
Setting an error handler does not work as the error event only fires on reception. The time server does no receiving, (see stream event documentation).
My solution is to set a handler on the stream close event.
stream.on('close', function() {
subscribers.remove(stream);
stream.end();
console.log('Subscriber CLOSE: ' + subscribers.length + " total.\n");
});

How to be notified if WCF Duplex session is prematurely closed

I have a publish/subscribe scenario in WCF using net.tcp and Duplex callbacks. I have a number of clients that subscribe to the service, and this works fine. However, sometimes a client will close without unsubsribing (Client computer goes to sleep, computer crashes, network connection is aborted, etc..), this causes an exception to be thrown when I callback via my callback list.
Now, I can certainly catch the exception and remove the offending callback, but this seems less like an exception scenario to me and further along the lines of "expected behavior".
Is there an event that gets fired on connection close that will notify me so that I can remove the callback from my list? Consider that this is net.tcp and not HTTP, so connection state should be known.
Clearly the framework knows the connection has been closed and disposed because the exception is something along the lines of "attempt to call a disposed object".
EDIT:
I should point out, that this is not a long running transaction. It's a long running connection in a publish/subscribe scenario. Basically, the callback is used to notify transient subscribers of various events as they happen. Each event is isolated and not long running.
It has been a while, this is from memory so I could be wrong, but I think perhaps if you make an IEndpointBehavior that goes an pokes at the DispatchRuntime to add an IInputSessionShutdown, then you can get notified when the session channel ends.
http://msdn.microsoft.com/en-us/library/system.servicemodel.dispatcher.dispatchruntime.inputsessionshutdownhandlers.aspx