From 4df023f2d4e4ea93d3fbc6010f0460511ba45140 Mon Sep 17 00:00:00 2001 From: Chocobozzz Date: Sun, 15 Jan 2017 19:53:11 +0100 Subject: [PATCH] Server: create transaction refractoring --- scripts/reset-password.js | 1 - server/controllers/api/remote/videos.js | 18 +++----- server/controllers/api/videos.js | 38 +++++++---------- server/helpers/database-utils.js | 55 +++++++++++++++++++++++++ server/helpers/utils.js | 36 +--------------- 5 files changed, 75 insertions(+), 73 deletions(-) create mode 100644 server/helpers/database-utils.js diff --git a/scripts/reset-password.js b/scripts/reset-password.js index e5f59a267..6a00b37eb 100755 --- a/scripts/reset-password.js +++ b/scripts/reset-password.js @@ -6,7 +6,6 @@ const program = require('commander') -const constants = require('../server/initializers/constants') const db = require('../server/initializers/database') program diff --git a/server/controllers/api/remote/videos.js b/server/controllers/api/remote/videos.js index 9d007246f..33b521c5f 100644 --- a/server/controllers/api/remote/videos.js +++ b/server/controllers/api/remote/videos.js @@ -10,7 +10,7 @@ const secureMiddleware = middlewares.secure const videosValidators = middlewares.validators.remote.videos const signatureValidators = middlewares.validators.remote.signature const logger = require('../../../helpers/logger') -const utils = require('../../../helpers/utils') +const databaseUtils = require('../../../helpers/database-utils') const router = express.Router() @@ -71,7 +71,7 @@ function addRemoteVideoRetryWrapper (videoToCreateData, fromPod, finalCallback) errorMessage: 'Cannot insert the remote video with many retries.' } - utils.retryWrapper(addRemoteVideo, options, finalCallback) + databaseUtils.retryTransactionWrapper(addRemoteVideo, options, finalCallback) } function addRemoteVideo (videoToCreateData, fromPod, finalCallback) { @@ -79,11 +79,7 @@ function addRemoteVideo (videoToCreateData, fromPod, finalCallback) { waterfall([ - function startTransaction (callback) { - db.sequelize.transaction({ isolationLevel: 'SERIALIZABLE' }).asCallback(function (err, t) { - return callback(err, t) - }) - }, + databaseUtils.startSerializableTransaction, function findOrCreateAuthor (t, callback) { const name = videoToCreateData.author @@ -180,7 +176,7 @@ function updateRemoteVideoRetryWrapper (videoAttributesToUpdate, fromPod, finalC errorMessage: 'Cannot update the remote video with many retries' } - utils.retryWrapper(updateRemoteVideo, options, finalCallback) + databaseUtils.retryWrapper(updateRemoteVideo, options, finalCallback) } function updateRemoteVideo (videoAttributesToUpdate, fromPod, finalCallback) { @@ -188,11 +184,7 @@ function updateRemoteVideo (videoAttributesToUpdate, fromPod, finalCallback) { waterfall([ - function startTransaction (callback) { - db.sequelize.transaction({ isolationLevel: 'SERIALIZABLE' }).asCallback(function (err, t) { - return callback(err, t) - }) - }, + databaseUtils.startSerializableTransaction, function findVideo (t, callback) { fetchVideo(fromPod.host, videoAttributesToUpdate.remoteId, function (err, videoInstance) { diff --git a/server/controllers/api/videos.js b/server/controllers/api/videos.js index 9a50a29be..ebfdb32f9 100644 --- a/server/controllers/api/videos.js +++ b/server/controllers/api/videos.js @@ -20,6 +20,7 @@ const validatorsSort = validators.sort const validatorsVideos = validators.videos const search = middlewares.search const sort = middlewares.sort +const databaseUtils = require('../../helpers/database-utils') const utils = require('../../helpers/utils') const router = express.Router() @@ -111,7 +112,7 @@ function addVideoRetryWrapper (req, res, next) { errorMessage: 'Cannot insert the video with many retries.' } - utils.retryWrapper(addVideo, options, function (err) { + databaseUtils.retryTransactionWrapper(addVideo, options, function (err) { if (err) return next(err) // TODO : include Location of the new video -> 201 @@ -124,11 +125,7 @@ function addVideo (req, res, videoFile, callback) { waterfall([ - function startTransaction (callbackWaterfall) { - db.sequelize.transaction({ isolationLevel: 'SERIALIZABLE' }).asCallback(function (err, t) { - return callbackWaterfall(err, t) - }) - }, + databaseUtils.startSerializableTransaction, function findOrCreateAuthor (t, callbackWaterfall) { const user = res.locals.oauth.token.User @@ -243,7 +240,7 @@ function updateVideoRetryWrapper (req, res, next) { errorMessage: 'Cannot update the video with many retries.' } - utils.retryWrapper(updateVideo, options, function (err) { + databaseUtils.retryTransactionWrapper(updateVideo, options, function (err) { if (err) return next(err) // TODO : include Location of the new video -> 201 @@ -258,11 +255,7 @@ function updateVideo (req, res, finalCallback) { waterfall([ - function startTransaction (callback) { - db.sequelize.transaction({ isolationLevel: 'SERIALIZABLE' }).asCallback(function (err, t) { - return callback(err, t) - }) - }, + databaseUtils.startSerializableTransaction, function findOrCreateTags (t, callback) { if (videoInfosToUpdate.tags) { @@ -384,19 +377,16 @@ function listVideoAbuses (req, res, next) { } function reportVideoAbuseRetryWrapper (req, res, next) { - utils.transactionRetryer( - function (callback) { - return reportVideoAbuse(req, res, callback) - }, - function (err) { - if (err) { - logger.error('Cannot report abuse to the video with many retries.', { error: err }) - return next(err) - } + const options = { + arguments: [ req, res ], + errorMessage: 'Cannot report abuse to the video with many retries.' + } - return res.type('json').status(204).end() - } - ) + databaseUtils.retryTransactionWrapper(reportVideoAbuse, options, function (err) { + if (err) return next(err) + + return res.type('json').status(204).end() + }) } function reportVideoAbuse (req, res, finalCallback) { diff --git a/server/helpers/database-utils.js b/server/helpers/database-utils.js new file mode 100644 index 000000000..046717517 --- /dev/null +++ b/server/helpers/database-utils.js @@ -0,0 +1,55 @@ +'use strict' + +const retry = require('async/retry') + +const db = require('../initializers/database') +const logger = require('./logger') + +const utils = { + retryTransactionWrapper, + transactionRetryer, + startSerializableTransaction +} + +// { arguments, errorMessage } +function retryTransactionWrapper (functionToRetry, options, finalCallback) { + const args = options.arguments ? options.arguments : [] + + utils.transactionRetryer( + function (callback) { + return functionToRetry.apply(this, args.concat([ callback ])) + }, + function (err) { + if (err) { + logger.error(options.errorMessage, { error: err }) + } + + // Do not return the error, continue the process + return finalCallback(null) + } + ) +} + +function transactionRetryer (func, callback) { + retry({ + times: 5, + + errorFilter: function (err) { + const willRetry = (err.name === 'SequelizeDatabaseError') + logger.debug('Maybe retrying the transaction function.', { willRetry }) + return willRetry + } + }, func, callback) +} + +function startSerializableTransaction (callback) { + console.log(db) + db.sequelize.transaction({ isolationLevel: 'SERIALIZABLE' }).asCallback(function (err, t) { + // We force to return only two parameters + return callback(err, t) + }) +} + +// --------------------------------------------------------------------------- + +module.exports = utils diff --git a/server/helpers/utils.js b/server/helpers/utils.js index fb4dd08cc..9f4b14582 100644 --- a/server/helpers/utils.js +++ b/server/helpers/utils.js @@ -1,7 +1,6 @@ 'use strict' const crypto = require('crypto') -const retry = require('async/retry') const logger = require('./logger') @@ -10,9 +9,7 @@ const utils = { cleanForExit, generateRandomString, isTestInstance, - getFormatedObjects, - retryWrapper, - transactionRetryer + getFormatedObjects } function badRequest (req, res, next) { @@ -49,37 +46,6 @@ function getFormatedObjects (objects, objectsTotal) { } } -// { arguments, errorMessage } -function retryWrapper (functionToRetry, options, finalCallback) { - const args = options.arguments ? options.arguments : [] - - utils.transactionRetryer( - function (callback) { - return functionToRetry.apply(this, args.concat([ callback ])) - }, - function (err) { - if (err) { - logger.error(options.errorMessage, { error: err }) - } - - // Do not return the error, continue the process - return finalCallback(null) - } - ) -} - -function transactionRetryer (func, callback) { - retry({ - times: 5, - - errorFilter: function (err) { - const willRetry = (err.name === 'SequelizeDatabaseError') - logger.debug('Maybe retrying the transaction function.', { willRetry }) - return willRetry - } - }, func, callback) -} - // --------------------------------------------------------------------------- module.exports = utils -- 2.41.0