1

Using Node.js we might use domains to capture errors thrown in async code like so: https://medium.com/@the1mills/using-node-js-domains-in-production-797105a4c302

using Domains in this way allows us to pin an error to particular request so we can send a response and clean up, and allows our serve to keep chugging along.

And using Golang, there's error-handling middleware like this that we can use to capture an error and pin it to a particular request.

func Error() Adapter {
    return func(next http.HandlerFunc) http.HandlerFunc {
        return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
            defer func() {
                if err := recover(); err != nil {

                    log.Error("Caught error in defer/recover middleware: ", err)

                    // ...

                    json.NewEncoder(w).Encode(struct {
                        Message string
                    }{
                        message,
                    })

                }
            }()

            log.Info("We are handling errors with defer.")
            //next.ServeHTTP(w, r)
            next(w,r);
        })
    }
}

as you might already know, that Error middleware is simply registered before any other api routes are invoked and if panic happens the defer will catch it. I am not sure if it works with "sub-goroutines" but it works for the current goroutine that is running.

So my question is - when using Vertx - how do we keep our process from crashing if one request causes and error? Ideally we can just log the error, and send a response for that request and keep chugging.

Alexander Mills
  • 90,741
  • 139
  • 482
  • 817

1 Answers1

2

With Vert.x, you don't need to:

Vertx vertx = Vertx.vertx();

Router router = Router.router(vertx);

router.get("/").handler((req) -> {
    System.out.println("Got something");
    // We crash
    throw new RuntimeException();
});

vertx.createHttpServer().requestHandler(router).listen(8080);

Run this example and you'll see that Vert.x catches exceptions.

But let's say you want to do some error handling yourself. Then use errorHandler() for that:

router.errorHandler(500, (ctx) -> {
    ctx.response().end("Got something bad");
});
Alexey Soshin
  • 16,718
  • 2
  • 31
  • 40
  • what if the exception is thrown in an asynchronous bit of code? `vertx.runOnContext(h -> {throw new RuntimeException})`? – Alexander Mills Feb 04 '19 at 19:25
  • 1
    yeah as I suspected, this doesn't solve the problem, I was talking to @vietj on Github and he says there is a context-tracing feature coming to vertx soon which I believe solves this problem - I added an answer here explaining what I mean, thx. – Alexander Mills Feb 04 '19 at 19:49