Tell me more ×
Code Review Stack Exchange is a question and answer site for peer programmer code reviews. It's 100% free, no registration required.

I have a user model.

It basically forwards get/create/delete requests into my database client.

The problem I have is the error handling, it screams not DRY to me, but I can't find an elegant way to clean it up.

var UserModel = pd.make(Model, {
    get: function _get(id, cb) {
        // nano is a database client
        this.nano.get(id, 
            // whitelist runs every error through the white list,
            // if it fails (false) throw it
            // if it succeeds (true) pass it to cb
            // if the return value is undefined it does nothing
            error.whitelist(function _errors(err) {
                // getaddrinfo is a random DNS error I have to swallow
                // no clue where the bug comes from, trying again is the easy fix
                if (err.syscall === 'getaddrinfo') {
                    UserModel.get(id, cb);
                } else if (err.error === "not_found") {
                    return true;
                } else {
                    return false;
                }
            }, cb)
        );
    },
    insert: function _create(json, cb) {
        this.nano.insert(json, json._id, 
            error.whitelist(function _errors(err) {
                if (err.syscall === 'getaddrinfo') {
                    UserModel.insert(json, cb);
                } else if (err.error === "conflict") {
                    return true;
                } else {
                    return false;
                }
            }, cb)
        );
    },
    delete: function _delete(name, cb) {
        var that = this;
        this.get(name, function _getRev(err, body) {
            that.nano.destroy(name, body._rev, 
                error.whitelist(function _errors(err) {
                    if (err.syscall === 'getaddrinfo') {
                        UserModel.delete(name, cb);
                    } else {
                        return false;
                    }
                }, cb)
            );
        });
    }
});

pd, error, nano

share|improve this question
add comment (requires an account with 50 reputation)

1 Answer

Based on feedback from JavaScript chat. Credit to @Zirak and @Chris

You want a hash of white listed error messages for each method

var whitelistMap = {
    "get": ["not_found"],
    "insert": ["conflict"],
    "delete": []
}

You want a whitelist error handler factory. This will include the "getaddrinfo" code for every method which is basically a try again short cutting.

It will check whether the error message is in the whitelistMap for that method and if so will let that error through.

otherwise it simply throws

function makeWhitelistCallback(method, thing, cb) {
    return error.whitelist(function _errors(err) {
        if (err.syscall === "getaddrinfo") {
            UserModel[method](thing, cb);
        } else if (whitelistMap[method].indexOf(err.error) !== -1) {
            return true;
        } else {
            return false;
        }
    }, cb);
}

And the rest of the code simply calls the whitelist callback factory

var UserModel = pd.make(Model,{
    get: function _get(id, cb) {
        this.nano.get(id, 
            makeWhitelistCallback("get", id, cb)
        );
    },
    insert: function _create(json, cb) {
        this.nano.insert(json, json._id, 
            makeWhitelistCallback("insert", json, cb)
        );
    },
    delete: function _delete(name, cb) {
        var that = this;
        this.get(name, function _getRev(err, body) {
            that.nano.destroy(name, body._rev, 
                makeWhitelistCallback("delete", name, cb)
            );
        });
    }
});
share|improve this answer
add comment (requires an account with 50 reputation)

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.