database-utils.ts 2.1 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182
  1. import * as retry from 'async/retry'
  2. import * as Bluebird from 'bluebird'
  3. import { Model } from 'sequelize-typescript'
  4. import { logger } from './logger'
  5. function retryTransactionWrapper <T, A, B, C> (
  6. functionToRetry: (arg1: A, arg2: B, arg3: C) => Promise<T> | Bluebird<T>,
  7. arg1: A,
  8. arg2: B,
  9. arg3: C
  10. ): Promise<T>
  11. function retryTransactionWrapper <T, A, B> (
  12. functionToRetry: (arg1: A, arg2: B) => Promise<T> | Bluebird<T>,
  13. arg1: A,
  14. arg2: B
  15. ): Promise<T>
  16. function retryTransactionWrapper <T, A> (
  17. functionToRetry: (arg1: A) => Promise<T> | Bluebird<T>,
  18. arg1: A
  19. ): Promise<T>
  20. function retryTransactionWrapper <T> (
  21. functionToRetry: () => Promise<T> | Bluebird<T>
  22. ): Promise<T>
  23. function retryTransactionWrapper <T> (
  24. functionToRetry: (...args: any[]) => Promise<T> | Bluebird<T>,
  25. ...args: any[]
  26. ): Promise<T> {
  27. return transactionRetryer<T>(callback => {
  28. functionToRetry.apply(null, args)
  29. .then((result: T) => callback(null, result))
  30. .catch(err => callback(err))
  31. })
  32. .catch(err => {
  33. logger.error(`Cannot execute ${functionToRetry.name} with many retries.`, { err })
  34. throw err
  35. })
  36. }
  37. function transactionRetryer <T> (func: (err: any, data: T) => any) {
  38. return new Promise<T>((res, rej) => {
  39. retry(
  40. {
  41. times: 5,
  42. errorFilter: err => {
  43. const willRetry = (err.name === 'SequelizeDatabaseError')
  44. logger.debug('Maybe retrying the transaction function.', { willRetry, err })
  45. return willRetry
  46. }
  47. },
  48. func,
  49. (err, data) => err ? rej(err) : res(data)
  50. )
  51. })
  52. }
  53. function updateInstanceWithAnother <T extends Model<T>> (instanceToUpdate: Model<T>, baseInstance: Model<T>) {
  54. const obj = baseInstance.toJSON()
  55. for (const key of Object.keys(obj)) {
  56. instanceToUpdate[key] = obj[key]
  57. }
  58. }
  59. function resetSequelizeInstance (instance: Model<any>, savedFields: object) {
  60. Object.keys(savedFields).forEach(key => {
  61. instance[key] = savedFields[key]
  62. })
  63. }
  64. // ---------------------------------------------------------------------------
  65. export {
  66. resetSequelizeInstance,
  67. retryTransactionWrapper,
  68. transactionRetryer,
  69. updateInstanceWithAnother
  70. }