Merge branch 'upgrade-progress-bar' into develop

v1.18.x
Julian Lam 8 years ago
commit 7a0db03d99

@ -21,6 +21,17 @@ exports.processSortedSet = function (setKey, process, options, callback) {
return callback(new Error('[[error:process-not-a-function]]')); return callback(new Error('[[error:process-not-a-function]]'));
} }
// Progress bar handling (upgrade scripts)
if (options.progress) {
db.sortedSetCard(setKey, function (err, total) {
if (err) {
// Unable to get total, do nothing.
} else {
options.progress.total = total;
}
});
}
// use the fast path if possible // use the fast path if possible
if (db.processSortedSet && typeof options.doneIf !== 'function' && !utils.isNumber(options.alwaysStartAt)) { if (db.processSortedSet && typeof options.doneIf !== 'function' && !utils.isNumber(options.alwaysStartAt)) {
return db.processSortedSet(setKey, process, options.batch || DEFAULT_BATCH_SIZE, callback); return db.processSortedSet(setKey, process, options.batch || DEFAULT_BATCH_SIZE, callback);
@ -53,6 +64,7 @@ exports.processSortedSet = function (setKey, process, options, callback) {
} }
start += utils.isNumber(options.alwaysStartAt) ? options.alwaysStartAt : batch + 1; start += utils.isNumber(options.alwaysStartAt) ? options.alwaysStartAt : batch + 1;
stop = start + batch; stop = start + batch;
next(); next();
}); });
}); });

@ -7,7 +7,7 @@ var path = require('path');
var semver = require('semver'); var semver = require('semver');
var db = require('./database'); var db = require('./database');
var utils = require('../public/src/utils'); var file = require('../src/file');
/* /*
* Need to write an upgrade script for NodeBB? Cool. * Need to write an upgrade script for NodeBB? Cool.
@ -23,7 +23,7 @@ var Upgrade = {};
Upgrade.getAll = function (callback) { Upgrade.getAll = function (callback) {
async.waterfall([ async.waterfall([
async.apply(utils.walk, path.join(__dirname, './upgrades')), async.apply(file.walk, path.join(__dirname, './upgrades')),
function (files, next) { function (files, next) {
// Sort the upgrade scripts based on version // Sort the upgrade scripts based on version
var versionA; var versionA;
@ -93,7 +93,7 @@ Upgrade.runSingle = function (query, callback) {
process.stdout.write('\nParsing upgrade scripts... '); process.stdout.write('\nParsing upgrade scripts... ');
async.waterfall([ async.waterfall([
async.apply(utils.walk, path.join(__dirname, './upgrades')), async.apply(file.walk, path.join(__dirname, './upgrades')),
function (files, next) { function (files, next) {
next(null, files.filter(function (file) { next(null, files.filter(function (file) {
return path.basename(file, '.js') === query; return path.basename(file, '.js') === query;
@ -123,6 +123,13 @@ Upgrade.process = function (files, skipCount, callback) {
var scriptExport = require(file); var scriptExport = require(file);
var date = new Date(scriptExport.timestamp); var date = new Date(scriptExport.timestamp);
var version = path.dirname(file).split('/').pop(); var version = path.dirname(file).split('/').pop();
var progress = {
current: 0,
total: 0,
incr: Upgrade.incrementProgress,
script: scriptExport,
date: date,
};
process.stdout.write(' → '.white + String('[' + [date.getUTCFullYear(), date.getUTCMonth() + 1, date.getUTCDate()].join('/') + '] ').gray + String(scriptExport.name).reset + '... '); process.stdout.write(' → '.white + String('[' + [date.getUTCFullYear(), date.getUTCMonth() + 1, date.getUTCDate()].join('/') + '] ').gray + String(scriptExport.name).reset + '... ');
@ -134,11 +141,20 @@ Upgrade.process = function (files, skipCount, callback) {
} }
// Do the upgrade... // Do the upgrade...
scriptExport.method(function (err) { scriptExport.method.bind({
progress: progress,
})(function (err) {
if (err) { if (err) {
process.stdout.write('error\n'.red); process.stdout.write('error\n'.red);
return next(err); return next(err);
} }
if (progress.total > 0) {
process.stdout.clearLine();
process.stdout.cursorTo(0);
process.stdout.write(' → '.white + String('[' + [date.getUTCFullYear(), date.getUTCMonth() + 1, date.getUTCDate()].join('/') + '] ').gray + String(scriptExport.name).reset + '... ');
}
process.stdout.write('OK\n'.green); process.stdout.write('OK\n'.green);
// Record success in schemaLog // Record success in schemaLog
db.sortedSetAdd('schemaLog', Date.now(), path.basename(file, '.js'), next); db.sortedSetAdd('schemaLog', Date.now(), path.basename(file, '.js'), next);
@ -152,4 +168,23 @@ Upgrade.process = function (files, skipCount, callback) {
], callback); ], callback);
}; };
Upgrade.incrementProgress = function () {
this.current += 1;
// Redraw the progress bar
var percentage = 0;
var filled = 0;
var unfilled = 15;
if (this.total) {
percentage = Math.floor((this.current / this.total) * 100) + '%';
filled = Math.floor((this.current / this.total) * 15);
unfilled = 15 - filled;
}
process.stdout.clearLine();
process.stdout.cursorTo(0);
process.stdout.write(' → '.white + String('[' + [this.date.getUTCFullYear(), this.date.getUTCMonth() + 1, this.date.getUTCDate()].join('/') + '] ').gray + String(this.script.name).reset + '... ');
process.stdout.write('[' + (filled ? new Array(filled).join('#') : '') + new Array(unfilled).join(' ') + '] (' + this.current + '/' + (this.total || '??') + ') ' + percentage);
};
module.exports = Upgrade; module.exports = Upgrade;

@ -12,6 +12,7 @@ module.exports = {
timestamp: Date.UTC(2016, 0, 14), timestamp: Date.UTC(2016, 0, 14),
method: function (callback) { method: function (callback) {
var batch = require('../../batch'); var batch = require('../../batch');
var progress = this.progress;
batch.processSortedSet('posts:pid', function (ids, next) { batch.processSortedSet('posts:pid', function (ids, next) {
async.eachSeries(ids, function (id, next) { async.eachSeries(ids, function (id, next) {
@ -24,8 +25,11 @@ module.exports = {
} }
winston.verbose('processing pid: ' + postData.pid + ' uid: ' + postData.uid + ' votes: ' + postData.votes); winston.verbose('processing pid: ' + postData.pid + ' uid: ' + postData.uid + ' votes: ' + postData.votes);
db.sortedSetAdd('uid:' + postData.uid + ':posts:votes', postData.votes, postData.pid, next); db.sortedSetAdd('uid:' + postData.uid + ':posts:votes', postData.votes, postData.pid, next);
progress.incr();
}); });
}, next); }, next);
}, {}, callback); }, {
progress: progress,
}, callback);
}, },
}; };

@ -14,6 +14,8 @@ module.exports = {
var batch = require('../../batch'); var batch = require('../../batch');
var posts = require('../../posts'); var posts = require('../../posts');
var count = 0; var count = 0;
var progress = this.progress;
batch.processSortedSet('posts:pid', function (pids, next) { batch.processSortedSet('posts:pid', function (pids, next) {
winston.verbose('upgraded ' + count + ' posts'); winston.verbose('upgraded ' + count + ' posts');
count += pids.length; count += pids.length;
@ -43,8 +45,12 @@ module.exports = {
} else { } else {
next(); next();
} }
progress.incr();
}, next); }, next);
}, next); }, next);
}, {}, callback); }, {
progress: progress,
}, callback);
}, },
}; };

@ -10,11 +10,15 @@ module.exports = {
name: 'Favourites to Bookmarks', name: 'Favourites to Bookmarks',
timestamp: Date.UTC(2016, 9, 8), timestamp: Date.UTC(2016, 9, 8),
method: function (callback) { method: function (callback) {
var progress = this.progress;
function upgradePosts(next) { function upgradePosts(next) {
var batch = require('../../batch'); var batch = require('../../batch');
batch.processSortedSet('posts:pid', function (ids, next) { batch.processSortedSet('posts:pid', function (ids, next) {
async.each(ids, function (id, next) { async.each(ids, function (id, next) {
progress.incr();
async.waterfall([ async.waterfall([
function (next) { function (next) {
db.rename('pid:' + id + ':users_favourited', 'pid:' + id + ':users_bookmarked', next); db.rename('pid:' + id + ':users_favourited', 'pid:' + id + ':users_bookmarked', next);
@ -34,7 +38,9 @@ module.exports = {
}, },
], next); ], next);
}, next); }, next);
}, {}, next); }, {
progress: progress,
}, next);
} }
function upgradeUsers(next) { function upgradeUsers(next) {

@ -13,12 +13,16 @@ module.exports = {
method: function (callback) { method: function (callback) {
var posts = require('../../posts'); var posts = require('../../posts');
var batch = require('../../batch'); var batch = require('../../batch');
var progress = this.progress;
batch.processSortedSet('posts:pid', function (ids, next) { batch.processSortedSet('posts:pid', function (ids, next) {
posts.getPostsFields(ids, ['pid', 'toPid', 'timestamp'], function (err, data) { posts.getPostsFields(ids, ['pid', 'toPid', 'timestamp'], function (err, data) {
if (err) { if (err) {
return next(err); return next(err);
} }
progress.incr();
async.eachSeries(data, function (postData, next) { async.eachSeries(data, function (postData, next) {
if (!parseInt(postData.toPid, 10)) { if (!parseInt(postData.toPid, 10)) {
return next(null); return next(null);
@ -30,6 +34,8 @@ module.exports = {
], next); ], next);
}, next); }, next);
}); });
}, {
progress: progress,
}, callback); }, callback);
}, },
}; };

@ -13,6 +13,7 @@ module.exports = {
var batch = require('../../batch'); var batch = require('../../batch');
var posts = require('../../posts'); var posts = require('../../posts');
var flags = require('../../flags'); var flags = require('../../flags');
var progress = this.progress;
batch.processSortedSet('posts:pid', function (ids, next) { batch.processSortedSet('posts:pid', function (ids, next) {
posts.getPostsByPids(ids, 1, function (err, posts) { posts.getPostsByPids(ids, 1, function (err, posts) {
@ -80,10 +81,14 @@ module.exports = {
} else { } else {
next(err); next(err);
} }
progress.incr();
}); });
}); });
}, next); }, next);
}); });
}, {
progress: this.progress,
}, callback); }, callback);
}, },
}; };

@ -11,6 +11,8 @@ module.exports = {
name: 'Update moderation notes to zset', name: 'Update moderation notes to zset',
timestamp: Date.UTC(2017, 2, 22), timestamp: Date.UTC(2017, 2, 22),
method: function (callback) { method: function (callback) {
var progress = this.progress;
batch.processSortedSet('users:joindate', function (ids, next) { batch.processSortedSet('users:joindate', function (ids, next) {
async.each(ids, function (uid, next) { async.each(ids, function (uid, next) {
db.getObjectField('user:' + uid, 'moderationNote', function (err, moderationNote) { db.getObjectField('user:' + uid, 'moderationNote', function (err, moderationNote) {
@ -22,9 +24,13 @@ module.exports = {
note: moderationNote, note: moderationNote,
timestamp: Date.now(), timestamp: Date.now(),
}; };
progress.incr();
db.sortedSetAdd('uid:' + uid + ':moderation:notes', note.timestamp, JSON.stringify(note), next); db.sortedSetAdd('uid:' + uid + ':moderation:notes', note.timestamp, JSON.stringify(note), next);
}); });
}, next); }, next);
}, {
progress: this.progress,
}, callback); }, callback);
}, },
}; };

@ -10,6 +10,8 @@ module.exports = {
name: 'New sorted set posts:votes', name: 'New sorted set posts:votes',
timestamp: Date.UTC(2017, 1, 27), timestamp: Date.UTC(2017, 1, 27),
method: function (callback) { method: function (callback) {
var progress = this.progress;
require('../../batch').processSortedSet('posts:pid', function (pids, next) { require('../../batch').processSortedSet('posts:pid', function (pids, next) {
async.each(pids, function (pid, next) { async.each(pids, function (pid, next) {
db.getObjectFields('post:' + pid, ['upvotes', 'downvotes'], function (err, postData) { db.getObjectFields('post:' + pid, ['upvotes', 'downvotes'], function (err, postData) {
@ -17,10 +19,13 @@ module.exports = {
return next(err); return next(err);
} }
progress.incr();
var votes = parseInt(postData.upvotes || 0, 10) - parseInt(postData.downvotes || 0, 10); var votes = parseInt(postData.upvotes || 0, 10) - parseInt(postData.downvotes || 0, 10);
db.sortedSetAdd('posts:votes', votes, pid, next); db.sortedSetAdd('posts:votes', votes, pid, next);
}); });
}, next); }, next);
}, {}, callback); }, {
progress: this.progress,
}, callback);
}, },
}; };

Loading…
Cancel
Save