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)
);
});
}
});
1 Answer 1
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)
);
});
}
});