X-Git-Url: https://git.immae.eu/?a=blobdiff_plain;f=server%2Fhelpers%2Fdatabase-utils.ts;h=87f10f913ca37f3512ce5b139f55065485afceb1;hb=0984960345704c10256b40b78db1e4d9d7527e77;hp=4f49c58250abae92c230f737429008e7a287425e;hpb=4d4e5cd4dca78480ec7f40e747f424cd107376a4;p=github%2FChocobozzz%2FPeerTube.git diff --git a/server/helpers/database-utils.ts b/server/helpers/database-utils.ts index 4f49c5825..87f10f913 100644 --- a/server/helpers/database-utils.ts +++ b/server/helpers/database-utils.ts @@ -1,69 +1,100 @@ -// TODO: import from ES6 when retry typing file will include errorFilter function import * as retry from 'async/retry' - -import { database as db } from '../initializers/database' +import * as Bluebird from 'bluebird' +import { Model } from 'sequelize-typescript' import { logger } from './logger' +import { Transaction } from 'sequelize' + +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 commitTransaction (t, callback) { - return t.commit().asCallback(callback) +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 rollbackTransaction (err, t, callback) { - // Try to rollback transaction - if (t) { - // Do not catch err, report the original one - t.rollback().asCallback(function () { - return callback(err) - }) - } else { - return callback(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) + ) + }) } -// { arguments, errorMessage } -function retryTransactionWrapper (functionToRetry, options, finalCallback) { - const args = options.arguments ? options.arguments : [] +function updateInstanceWithAnother > (instanceToUpdate: Model, baseInstance: Model) { + const obj = baseInstance.toJSON() - transactionRetryer( - function (callback) { - return functionToRetry.apply(this, args.concat([ callback ])) - }, - function (err) { - if (err) { - logger.error(options.errorMessage, { error: err }) - } + for (const key of Object.keys(obj)) { + instanceToUpdate[key] = obj[key] + } +} - // Do not return the error, continue the process - return finalCallback(null) - } - ) +function resetSequelizeInstance (instance: Model, savedFields: object) { + Object.keys(savedFields).forEach(key => { + instance[key] = savedFields[key] + }) } -function transactionRetryer (func, callback) { - retry({ - times: 5, +function afterCommitIfTransaction (t: Transaction, fn: Function) { + if (t) return t.afterCommit(() => fn()) - errorFilter: function (err) { - const willRetry = (err.name === 'SequelizeDatabaseError') - logger.debug('Maybe retrying the transaction function.', { willRetry }) - return willRetry - } - }, func, callback) + return fn() } -function startSerializableTransaction (callback) { - db.sequelize.transaction(/* { isolationLevel: 'SERIALIZABLE' } */).asCallback(function (err, t) { - // We force to return only two parameters - return callback(err, t) - }) +function deleteNonExistingModels > ( + fromDatabase: T[], + newModels: T[], + t: Transaction +) { + return fromDatabase.filter(f => !newModels.find(newModel => newModel.hasSameUniqueKeysThan(f))) + .map(f => f.destroy({ transaction: t })) } // --------------------------------------------------------------------------- export { - commitTransaction, + resetSequelizeInstance, retryTransactionWrapper, - rollbackTransaction, - startSerializableTransaction, - transactionRetryer + transactionRetryer, + updateInstanceWithAnother, + afterCommitIfTransaction, + deleteNonExistingModels }