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