4
\$\begingroup\$

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

\$\endgroup\$

1 Answer 1

2
\$\begingroup\$

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)
            );
        });
    }
});
\$\endgroup\$

Your Answer

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

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