UNPKG

@ambassify/neo4j-retried

Version:

Retry queries run against the neo4j driver. Great for handling deadlock exceptions.

111 lines (89 loc) 2.54 kB
/** * Check if a retry is allowed */ function retryAllowed(error, retriedAmount, options) { const { retries = 0, shouldRetry = [] } = options; if (retriedAmount >= retries) return false; if (Array.isArray(shouldRetry) && shouldRetry.includes(error.code)) return true; if (typeof shouldRetry == 'function') return shouldRetry(error); return false; } /** * Insert a timeout based on options and total attempts */ function wait(attempts, options) { let { delay } = options; delay = typeof delay === 'function' ? delay(attempts) : delay; delay = typeof delay === 'number' ? delay : 0; return new Promise(resolve => setTimeout(resolve, delay)); } /** * Proxy the run method on session or transaction */ function retriedRun(options) { return (session, ...args) => { let retries = 0; const run = () => session.run(...args).catch(e => { if (!retryAllowed(e, retries, options)) throw e; ++retries; return wait(retries, options).then(run); }); return run(); }; } /** * Proxy the run method on session */ function proxyTransaction(transaction, run) { return new Proxy(transaction, { get: (target, name) => { if (name == 'run') return (...args) => run(target, ...args); return target[name]; } }); } /** * Proxy the run and beginTransaction methods on session */ function proxySession(session, run) { return new Proxy(session, { get: (target, name) => { if (name == 'run') return (...args) => run(target, ...args); if (name == 'beginTransaction') return (...args) => proxyTransaction(target.beginTransaction(...args), run); return target[name]; } }); } /** * Proxy session method on driver */ function proxyDriver(driver, run) { return new Proxy(driver, { get: (target, name) => { if (name != 'session') return target[name]; return (...args) => proxySession(target.session(...args), run); } }); } /** * Return a wrapped neo4j driver that implements retries */ function wrap(driver, options = {}) { const { shouldRetry = [], retries = 0 } = options; if ( (Array.isArray(shouldRetry) && ! shouldRetry.length) || !retries ) return driver; return proxyDriver(driver, retriedRun(options)); } module.exports = wrap;