import * as retry from 'async/retry' import * as Bluebird from 'bluebird' import { Model, Sequelize } from 'sequelize-typescript' import { logger } from './logger' function retryTransactionWrapper ( functionToRetry: (arg1: A, arg2: B, arg3: C) => Promise | Bluebird, arg1: A, arg2: B, arg3: C ): Promise function retryTransactionWrapper ( functionToRetry: (arg1: A, arg2: B) => Promise | Bluebird, arg1: A, arg2: B ): Promise function retryTransactionWrapper ( functionToRetry: (arg1: A) => Promise | Bluebird, arg1: A ): Promise function retryTransactionWrapper ( functionToRetry: () => Promise | Bluebird ): Promise function retryTransactionWrapper ( functionToRetry: (...args: any[]) => Promise | Bluebird, ...args: any[] ): Promise { return transactionRetryer(callback => { functionToRetry.apply(null, args) .then((result: T) => callback(null, result)) .catch(err => callback(err)) }) .catch(err => { logger.error(`Cannot execute ${functionToRetry.name} with many retries.`, { err }) throw err }) } function transactionRetryer (func: (err: any, data: T) => any) { return new Promise((res, rej) => { retry( { times: 5, errorFilter: err => { const willRetry = (err.name === 'SequelizeDatabaseError') logger.debug('Maybe retrying the transaction function.', { willRetry, err }) return willRetry } }, func, (err, data) => err ? rej(err) : res(data) ) }) } function updateInstanceWithAnother > (instanceToUpdate: Model, baseInstance: Model) { const obj = baseInstance.toJSON() for (const key of Object.keys(obj)) { instanceToUpdate.set(key, obj[key]) } } // --------------------------------------------------------------------------- export { retryTransactionWrapper, transactionRetryer, updateInstanceWithAnother }