Home » Nodejs » Best practices to handle exception in SailsJS

Best practices to handle exception in SailsJS

Posted by: admin November 30, 2017 Leave a comment

Questions:

I just started trying out SailsJS a few days ago.
I’ve realized that the Node is terminated whenever I have an uncaught exception.
I have a list of controllers and each of them calls a specific service JS file (Containing logics and DB calls) in services/.
Can I write a global error handler for all services so that any type of error that occurs from these services should be handled by it and appropriate error response has to be communicated to front-end.

I tried using process.on(‘uncaughtexception’) or some of basic exceptions but it needs to be added to each service method.

Also can I have one common point for all service calls made from client to server through which all io.socket.post() and io..socket.get() goes through

I would appreciate any pointer/article that would show me the common best practices for handling uncaught exceptions in SailsJS and using shorter code rather than writing redundant code in all services.

Answers:

Best practice is using Domains in your controller. This will handle exceptions in async code, and its relatively straight forward.

You can use something like trycatch to simplify things a little, but domain based exceptions will be most effective. It’ll insure that exceptions do not crash your application. Just create a new domain in your controller and run your controller methods inside of that domain.

Sailsjs being based on express you can use connect middleware, and you can seamlessly create a new domain from middleware. There such thing as express-domain-middleware. This might be the most aesthetic option, and most convenient.

Update:
As mention by Benjamin Gruenbaum, Domains are planned to become deprecated in v1 of node. Perhaps you should read through Joyents Error Handling Best Practices. Its agnostic to the framework you are using.

Additonally you can still use Domains, while there isn’t a way to globally handle errors in node.js otherwise. Once deprecated you could always remove your dependence on Domains, relatively easily. That said, it may be best not to rely solely on domains.

Strongloop also provides a library inspired by domains called Zone. This is also an option.

Questions:
Answers:

Its OK to let node instance error out due to a programming error, else it may continue in an inconsistent state and mess-up business logic. In production environment the server can be restarted on crash, this will reset its state and keep it available, if the error is not frequent. And in all of it its very important to Log everything. This applies to most of Node setups, including SailsJS.

The following approach can be taken:

  1. Use a Logger : A dedicated logger should be accessible to server components. Should be connected to a service that notifies the developer (email ?) of very serious errors.
  2. Propagate per request errors to the end: Carefully forward errors from any step in request processing. In ExperssJs/ConnectJs/middle-ware based setup’s, the next(err) can be used to pass an error to the middle-ware chain. An error catching middle-ware at the end of the chain will get this error, log it verbose, and send a 500 status back. You can use Domains or Zones or Promises or async or whatever you like to process request and catch errors.
  3. Shutdown on process.on('uncaughtexception'): Log the erorr, do necessary clean-up, and throw the same error again to shutdown process.
  4. User PM2/Forever or Upstart/init.d on linux : Now when the process shuts down due to the bad exception, these tools will restart it and track how many time server has been crashing. If the server is crashing way too many time, its good to stop it and take immediate action.
Questions:
Answers:

I have not tried this, but I believe you should be able to set a catch-all exception handler in bootstrap.js using process.on('uncaughtexception').

Personally, I use promises via the bluebird library, and put a catch statement that passes all errors to a global error handling function.