Auto-retry transient errors
With Neo4j v2's new error classifications, we now know which errors are transient and will likely go away with a simple retry:
http://neo4j.com/docs/stable/status-codes.html
We could/should implement (configurable) auto-retry for queries that hit transient errors.
https://groups.google.com/d/topic/neo4j-ecosystem/1apg9CK34e4/discussion
Aspects to consider/implement:
- [ ] Option to configure how many times to auto-retry, if any. Default to 2?
- [ ] Callback when a retry is happening, so the app can e.g. log a warning if it likes?
- [ ] Any delay or backoff between retries? Exponential backoff feels like overkill for only a couple of retries, but might still be wise?
An open issue here is that transactions seem to never ultimately commit if a TransientError is encountered within them. Asking the Neo team about this, but punting til that's resolved.
An open issue here is that transactions seem to never ultimately commit if a TransientError is encountered within them. Asking the Neo team about this, but punting til that's resolved.
This behavior has been improved, and the docs fixed. Transactions now roll back right away in the case of any errors. Issue https://github.com/neo4j/neo4j/issues/5258; pull https://github.com/neo4j/neo4j/pull/5394.
I currently handle this with the following wrapper code:
where graphObj is my connection to neo4j
Using a fixed 400ms retry with a maximum of 5 retries.
var cypher_wrapper = function(queryObj, callback){
// some code omitted... defining graphObj and loggerObj
// queryObj usually of the form { query:query, params:params }
var async = require('async');
var task = function (cb){
graphObj.cypher(queryObj, function(err, result){
if(err && err.name === "neo4j.TransientError"){
cb(err, {'_err':err, '_result':result});
} else {
cb(null, {'_err':err, '_result':result});
}
});
};
async.retry({ times: 5, interval: 400 }, task.bind(this), function(err, result) {
if (err) {
loggerObj.error(err);
}
callback(result._err, result._result);
});
};