failboat

Generic error routing

Downloads in past

Stats

StarsIssuesVersionUpdatedCreatedSize
failboat
3.0.07 years ago10 years agoMinified + gzip package size for failboat in KB

Readme

Failboat
Your Shipment of Fail has Arrived
Failboat is the boat that transports your failures to the right destination.
The idea is that you tag your errors with information abort the error and the context they appeared in. This information is used to route the error to the correct error handler.
The only requirement for routing errors to their handlers is that the error contains a property tags that is a non-empty array of strings.

Installation

Node

Install it with NPM or add it to your package.json:
$ npm install failboat

Then:
var Failboat = require('failboat');

Browser

Include Failboat.js.
<script src="Failboat.js"></script>

this will expose the Failboat constructor under the following namespace:
var Failboat = com.one.Failboat;

RequireJS

Include the library with RequireJS the following way:
require.config({
    paths: {
        failboat: 'path/to/failboat/lib/Failboat.js'
    }
});

define(['failboat'], function (Failboat) {
   // Your code
});

Example

The routing is best explained by example.
var context = {
    showError: function (message) {
        console.log(message);
    }
};

var failboat = new Failboat({
    '404 FolderNotFound': function () {
        this.showError('Folder not found');
    },
    '404': function () {
        this.showError('Generic not found handler');
    },
    '409': function () {
        this.showError('Generic conflict handler');
    },
    '502, 503': function () {
        this.showError('Could not connect to the server');
    },
    '12029': '503'
}, context);

failboat = failboat.extend({
    '401': function () {
        this.showError('Unauthorized operation');
    }
});

failboat = failboat.extend({
    '404 FolderNotFound LoadMailsAction': function (err) {
        this.showError('Folder not found while loading mails');
    }
});

The above code defines a failboat with three levels. The first configuration is the base level. When a failboat is extended a new failboat is created with the given configuration. The child failboat will have a reference to the parent failboat.
Each error handler function is executed in the context given to the base failboat. When extending a failboat the execution context is inherited from the parent.
When you call handleError on a failboat it will try to route the error at the top level, if it does not find an appropiate handler it will call handleError on the parent failboat.
Routing an error will find the route where the words matches the longest prefix of the tags array.
Given the example code above the following errors will result in the output shown below:
var err = Failboat.tag(new Error(), '404', 'FolderNotFound', 'LoadMailsAction');
failboat.handleError(err);

will print Folder not found while loading mails to the console.
var err = Failboat.tag(new Error(), '404', 'FolderNotFound');
failboat.handleError(err);

will print Folder not found to the console.
var err = Failboat.tag(new Error(), '404');
failboat.handleError(err);

will print Generic not found handler to the console.
var err = Failboat.tag(new Error(), '404', 'MailNotFound', 'GetMailPartAction');
failboat.handleError(err);

will print Generic not found handler to the console.
var err = Failboat.tag(new Error(), '401', 'LoadMailsAction');
failboat.handleError(err);

will print Unauthorized operation to the console.
var err = Failboat.tag(new Error(), '404', 'FolderNotFound');
failboat.handleError(err);

will print Folder not found to the console.
var err = Failboat.tag(new Error(), '502');
failboat.handleError(err);

will print Could not connect to the server to the console.
var err = Failboat.tag(new Error(), '503');
failboat.handleError(err);

will print Could not connect to the server to the console.
var err = Failboat.tag(new Error(), '12029');
failboat.handleError(err);

will print Could not connect to the server to the console.

API

new Failboat()

Creates a new failboat without routes.
var failboat = new Failboat();

new Failboat(routes)

Creates a new failboat with the given routes.
var failboat = new Failboat({
    '404': function () {
        console.log('Generic not found handler');
    },
    '404 FolderNotFound': function () {
        console.log('Folder not found');
    },
    '409': function () {
        console.log('Generic conflict handler');
    }
});

If you make a route called * all error that can't be routed to a more specific will fallback use this route.

new Failboat(routes, context)

Creates a new failboat with the given routes. Each error handler will be executed in the given context. If the failboat is extended the context will be inherited.
var context = {
    showError: function (message) {
        console.log(message);
    }
};

var failboat = new Failboat({
    '404': function () {
        this.showError('Generic not found handler');
    },
    '404 FolderNotFound': function () {
        this.showError('Folder not found');
    },
    '409': function () {
        this.showError('Generic conflict handler');
    }
}, context);

Failboat.tag(err, tags...)

Add the given tags to the err. If the error has already been tagged the tags will be added to the list of tags.
Failboat.tag(err, 'this', 'is');
Failboat.tag(err, 'some', 'tags');

Now err.tags contains the tags ['this', 'is', 'some', 'tags'].

failboat.extend(routes)

Creates a new failboat with the given routes and a pointer to the failboat that is extended.
failboat = failboat.extend({
    '401': function () {
        console.log('Unauthorized operation');
    }
});

failboat.handleError(err)

Routes the given error to a handler based on the configured routes and the tags on the error.
Routing an error will find the route where the words matches the longest prefix of the tags array. If it does not find an appropiate handler it will delegate to it's parent failboat for handling the error.
Returns true if the error was handled by this failboat or one of it's ancestors; otherwise false is returned.
var err = Failboat.tag(new Error(), '404', 'FolderNotFound', 'LoadMailsAction');
failboat.handleError(err);

failboat.handleError(err, routes)

Syntaxtic sugar for:
failboat.extend(routes).handleError(err);

Event: failboat.onErrorRouted = handler

When an error has been routed an onErrorRouted will be called with the error and the matching route. That gives you the posibility to do logging and crash reporting in a central place.
The onErrorRouted will be called for each failboat where a handler has been attached. Usually the onErrorRouted handler should be attached to the base failboat.
failboat.onErrorRouted = function (err, matchingRoute) {
    if (matchingRoute) {
        console.log('Error: "' + err.message + '" handled by ' + matchingRoute);
        if (500 <= err.status && err.status < 600) {
            // Report server crash
        }
    } else {
        console.log('Missing handler for: "' + err.message + '"');
    }
};

License

Copyright © 2014, One.com
Failboat is licensed under the BSD 3-clause license, as given at http://opensource.org/licenses/BSD-3-Clause