Run a function when a ClientEmitter has an error - node.js

I'm using an event handler, where each event code is in it's own files. I'm attaching the events to the client, so when that file has the event emitted, it will run that code:
// looping through all event files
client.on(file.split('.')[0], require(`events/${file}`).bind(null, client, Util);
If the event file was message.js, it would be similar to:
client.on('message', require('events/message.js').bind(null, client, Util);
So when the message event is emitted, it runs the message.js file, passing along the client and Util classes.
I also have a function that is attached to the client called report. It basically reports when there is an error. I would like it so whenever any event from the client has an error, it will run that function.
I've done this slightly with the commands: command.run(...).catch(error => client.report(error)).
Is there a similar way to do this, instead of having to put a try-catch around all code in all the event files?

Try this way
client.on('error', require('events/report.js').bind(null, client, Util);

Error handling should be context driven. This means your bot's response to the error should be dependent on what it was doing, in what channel, etc - both for debugging and for the end user's information on what happened. You'll miss out on all of the context by letting errors just travel all the way up into an uncaught exception, and without the ability to create an error message, the user will just see the bot not respond and think it's down or the command is broken.
My suggestion: Create helper methods for your most common error producing functions that wrap them with error handling. I did this mostly for sending messages, as there's a myriad of things that could cause a message send to fail out of your control and the handling consists of generating an error message and attempting to send it in the channel or DM it to the user if that fails.

Related

Proper way to handle 412 Precondition failure from cosmosdb in an event driven system with application implemented in nodejs

I have an event-driven system with my application implemented in nodejs using cosmosdb (azure-cosmosdb-sqlapi) to store the events. I have planning data coming via various events from kafka broker, to complete a planning documnet I need to combine data from 5 different events, I combine the events using planning id. In such a system for upsert operation we encounter 412 Precondition failure error very often, as we receive many events for a planning id.
The official Microsoft link says to retry. I am confused about which approach to take to retry
Handle the error code using a try catch and call the method handling the event from catch block for n number of times. If the retry fails after n times throw the exception back to broker, in that case the event is send again by the broker. The issue with this is I am not able to add test for the same. Secondly I need to manage all the retry logic in my code base. The advantage here is that I know that an event is failed and I can retry directly without sending the event back to broker. Below is the the snippet from planningservice.ts handlePlanningEvents method
try {
await repository.upsert(planningEntry, etag)
} catch (e: any) {
if (e.code === 412 and retries) {
this.handlePlanningEvents(event, retries-1)
} else {
throw e // throws exception back to broker
}
}
Not using try catch to handle the error in service code but propagating the error to controller where it sends a 500 error response to broker and the broker sends the event again. The issue with this case is that it's longer path as compared to using try catch where I can retry directly. But the advantage here is that I don't to worry about retry logic anymore its handled by broker, less and cleaner code.
Not sure which approach to take, also open to other suggestions.

Can a sync message have an async message as a response instead of a reply message?

The first picture shows the sync message exportDeclaration(id) waiting for a reply message download(file).
The second picture, I used an async call as a response to the sync message exportDeclaration(id).
I couldn't find anything to know which method is the right one.
Sure it can. When you send an async message it will not take notice of the receiver looking at it. It's fire and forget. A sychronous message has a direct response so you know the receiver got it. In case you expect not the result directly (but only the receipt confirmation) you can go on in the code and react to some later async message from the receiver of the message. It's just more difficult to implement but perfectly possible.

The remote server returned an error: (404) Not Found While deleting message from queue

We are using Azure Queue for our printing job but when deleting message from queue by queue.DeleteMessage(message), the method throws below exception.
The remote server returned an error: (404) Not Found
Above exception was handled but still looking for workaround.
Can anyone please suggest how to fix it.
Thanks,
Sneh
According to this article, we can find that:
After a client retrieves a message with the Get Messages operation,
the client is expected to process and delete the message. To delete
the message, you must have two items of data returned in the response
body of the Get Messages operation:
The message ID, an opaque GUID value that identifies the message in the queue.
A valid pop receipt, an opaque value that indicates that the message has been retrieved.
If a message with a matching pop receipt is not found, the service returns error code 404 (Not Found). And Pop receipts remain valid until one of the following events occurs:
The message has expired.
The message has been deleted using the last pop receipt received
either from Get Messages or Update Message.
The invisibility timeout has elapsed and the message has been
dequeued by a Get Messages request. When the invisibility timeout
elapses, the message becomes visible again. If it is retrieved by
another Get Messages request, the returned pop receipt can be used
to delete or update the message.
The message has been updated with a new visibility timeout. When the
message is updated, a new pop receipt will be returned.
I ran into this issue today and the root cause was ownership issues between two different queues. We had setup two queues, one to hold our message awaiting processing and one for messages that had errored out. The problem came with the logic of how the message was moved between queues.
If our processing failed, we would perform the following logic:
_errorQueue.AddMessage(msg);
_queue.DeleteMessage(msg);
The DeleteMessage would also return a (404) Not Found because the msg had been moved to the errorQueue. There were two solutions that I found to this issue:
1. Switch Logic
If you switch the logic than the msg will be deleted before being added to the errorQueue which will avoid the ownership swap.
_queue.DeleteMessage(msg);
_errorQueue.AddMessage(msg);
2. Insert Copy of Message
Solution #1 has the potential to lose the message if something happens between deletion and insertion (small chance but a chance nonetheless). The solution I went with inserted a copy of the msg with the same payload so it didn't run into this ownership issue because it was a different object.
_errorQueue.AddMessage(new CloudQueueMessage(msg.AsString));
_queue.DeleteMessage(msg);
Debugging Tip
One useful tip I encountered while debugging it making sure the exception your catching isn't the default Exception. Catch the StorageException instead to get access to Azure Storage related error information.
try
{
_queue.DeleteMessage(msg);
}
catch (StorageException ex) //use this instead of base Exception
{
var info = ex.RequestInformation; //has useful information
}
If can provide more information to help you debug your real issue.

SoapHttpClientProtocol automatically retry after exception?

I am just curious about this. I am making a change in this project, that is using NetSuite web service, and sometimes it throws a SoapException at random, "Only one request may be made against a session at a time".
private NetSuiteService _service;
SessionResponse response = _service.login(passport); //if SoapException, retries??
Status status = response.status;
Reference.cs:
public partial class NetSuiteService :
System.Web.Services.Protocols.SoapHttpClientProtocol
My question is: If I am in debug mode, I trace this, and I hit F5, and it seems to automatically retry after exception is thrown (the code keeps running, with no try catch block implemented, no while loop) until successful (status.isSuccess == true). When I run it in release mode, as a windows service, the log shows it stops running after exception is thrown.
How is this possible? Is it better to catch this exception in a try catch block and retry?
NS Server refuses a request if its already processing one from the same user.
If you want to make sure that your request succeeds than you have to catch this exception and retry.
This was not the experience I had. We thought this related to netsuite sessions but turned out to be nothing to do with that at all and in fact was not even hitting netsuite (according to netsuite log)​​. Turned out we were trying to execute too many commands in a single request and it totally refused to send it to netsuite. Never seen this error before, may be it is a new thing with the new version!

Node Exception Handling

What is the best way in node to handle unhandled expections that are coming out of core node code? I have a background process that runs and crawls web content and will run for long periods of time without issue, but every so often an unexpected exception occurs and I can't seem to gracefully handle it. The usual culprit appears to be some networking issue (lost connectivity) where the http calls I'm making fail. All of the functions that I have created follow the pattern of FUNCTION_NAME(error, returned_data), but in the situations where the error occurs I'm not seeing any of the functions I created in the call stack that is printed out, instead its showing some of the core node modules. I'm not really worried about these infrequent errors and their root cause, the purpose of this posting is just trying to find a graceful way of handling these exceptions.
I've tried putting a try/catch at the top level of my code where everything runs under but it doesn't seem to capture these exceptions. Is it good practice in node to use try/catch within all the lower level functions that use any core code? Or is there some way to globally capture all unhandled exceptions?
Thanks
Chris
UPDATED TO ADD STACK
node.js:201
throw e; // process.nextTick error, or 'error' event on first tick
^
Error: connect Unknown system errno 10060
at errnoException (net.js:642:11)
at Object.afterConnect [as oncomplete] (net.js:633:18)
is there some way to globally capture all unhandled exceptions?
You can catch all exceptions using process.on('uncaughtException'). Listening to this event will avoid the default action of printing the stack and exiting. However be conscious that ignoring exceptions may lead to problems in your app execution.
Link: http://nodejs.org/docs/latest/api/process.html#process_event_uncaughtexception
Pay attention to the documentation advice:
Note that uncaughtException is a very crude mechanism for exception handling. Using try / catch in your program will give you more control over your program's flow. Especially for server programs that are designed to stay running forever, uncaughtException can be a useful safety mechanism.
To catch network errors and avoid the default behavior (printing stack and exit) you have to listen to "error" events.
For example
var net = require('net');
var client = net.connect(80, 'invalid.host', function () {
console.log("Worked");
})
client.on('error', console.log);
I wrote about this recently at http://snmaynard.com/2012/12/21/node-error-handling/. A new feature of node in version 0.8 is domains and allow you to combine all the forms of error handling into one easier manage form. You can read about them in my post and in the docs.
You can use domains to handle callback error arguments, error event emitters and exceptions all in one place. The problem in this specific case is that when you dont handle an error event emitter, node by default will print the stack trace and exit the app.
I've put together a quick error handling file which logs and emails me whenever an unhandled exception is thrown. it then (optionally) tries to restart the server.
Check it out!

Resources