15

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.

asked Dec 15, 2014 at 12:43
2
  • Really good question. Never thought on this before but policies are the code which are executed before a controller action is called. You might wanna try wrapping the controller logic in a try catch block using a policy and applying that policy as default on all controller actions. I haven't tried this and its just a random thought that crossed my mind. Let me know if it works. I might give it a try later Commented Dec 17, 2014 at 9:00
  • It's not really an answer yet, but keep an eye on zones - among other things it solves the error handling problem in nodejs. Commented Dec 25, 2014 at 4:41

3 Answers 3

4
+25

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.

Joshua
3,6031 gold badge30 silver badges32 bronze badges
answered Dec 18, 2014 at 21:52
Sign up to request clarification or add additional context in comments.

4 Comments

Domains will likely be deprecated in the near future. github.com/iojs/io.js/issues/66
Define "near future", v0.11 doesn't even have a set release date, and v0.12 won't be seen for at least another year, and that's optimistic. AFAIK v1 isn't even being developed, its just a thought so far. Its even mentioned that domains will likely be moved to a package(out of the core) to keep backwards compatibility. If you use the middleware like suggested, then you'd easily be able to replace your exception handling.
By near future is ~one month. Node was recently forked into io.js and most of the core contributors have migrated (because of the release cycle). I said deprecated not removed.
I updated my answer to reflect your criticism. I believe Domains are still an option as we'll likely not see Domains deprecated for some time, they may not be "best practice" for the reason your mentioned. That said its hard to provide a "suit all" best practice for handling exceptions. I would recommend Joyents guide, provided in my answer, as a good guideline to figure out how you can develop exception tolerant applications.
1

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.
answered Dec 25, 2014 at 3:57

2 Comments

Upstart/init.d would be a great extension to your 4th recommendation. As forever alone cannot restart an application if the server restarts unexpectedly. PM2 offers a solution to this problem, however PM2 requires node v0.11 to work effectively and can have unexpected behavior on v0.10 or lower as it relies on experimental core modules.
@tsturzl Thanks. Updated in answer.
0

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.

answered Dec 23, 2014 at 17:16

5 Comments

I'm not downvoting, but this is very bad practice as your application is emitting an unhandled exception somewhere. This is lazy error handling, and any time this is suggested to anyone, you must accompany it with the fact that the process should be stopped and restarted and you should not attempt to continue what you were doing (uploading, writing file, db communication, etc). You must stop everything and restart the node process.
I assume you're referring to the non-promise solution, which I really should have prefaced with a "hey you can do this, but don't."
Not really, and I didn't mean to come down on you - but writing code with uncaught exceptions is just bad practice and catching it at the "top" of the app like this is just lazy. Most servers don't require you to restart the server process in these situations. Node does. If you catch the exception and don't restart the process, node can get stuck in an "unknown state" (is how the docs word it if I remember correctly).
Don't be sorry, as I said I've never personally done this, so i had no idea as to the repercussions or even how it really worked.
This is not handling exceptions, rather its choosing to not handle the exceptions. The idea is to make use of an error or an exception. This is an ignorant practice.

Your Answer

Draft saved
Draft discarded

Sign up or log in

Sign up using Google
Sign up using Email and Password

Post as a guest

Required, but never shown

Post as a guest

Required, but never shown

By clicking "Post Your Answer", you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.