mirror of
https://github.com/NodeBB/NodeBB.git
synced 2025-11-08 06:55:46 +01:00
batch.processArray
use batch.processArray in notifications.push and moveRecentReplies added notification tests added test for moveRecentReplies clear group cache if a group is deleted
This commit is contained in:
48
src/batch.js
48
src/batch.js
@@ -63,4 +63,52 @@ var async = require('async'),
|
|||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
Batch.processArray = function(array, process, options, callback) {
|
||||||
|
if (typeof options === 'function') {
|
||||||
|
callback = options;
|
||||||
|
options = {};
|
||||||
|
}
|
||||||
|
|
||||||
|
callback = typeof callback === 'function' ? callback : function() {};
|
||||||
|
options = options || {};
|
||||||
|
|
||||||
|
if (!Array.isArray(array) || !array.length) {
|
||||||
|
return callback();
|
||||||
|
}
|
||||||
|
if (typeof process !== 'function') {
|
||||||
|
return callback(new Error('[[error:process-not-a-function]]'));
|
||||||
|
}
|
||||||
|
|
||||||
|
var batch = options.batch || DEFAULT_BATCH_SIZE;
|
||||||
|
var start = 0;
|
||||||
|
var done = false;
|
||||||
|
|
||||||
|
async.whilst(
|
||||||
|
function() {
|
||||||
|
return !done;
|
||||||
|
},
|
||||||
|
function(next) {
|
||||||
|
var currentBatch = array.slice(start, start + batch);
|
||||||
|
if (!currentBatch.length) {
|
||||||
|
done = true;
|
||||||
|
return next();
|
||||||
|
}
|
||||||
|
process(currentBatch, function(err) {
|
||||||
|
if (err) {
|
||||||
|
return next(err);
|
||||||
|
}
|
||||||
|
start = start + batch;
|
||||||
|
if (options.interval) {
|
||||||
|
setTimeout(next, options.interval);
|
||||||
|
} else {
|
||||||
|
next();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
},
|
||||||
|
function(err) {
|
||||||
|
callback(err);
|
||||||
|
}
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
}(exports));
|
}(exports));
|
||||||
|
|||||||
@@ -10,6 +10,7 @@ var db = require('../database');
|
|||||||
var posts = require('../posts');
|
var posts = require('../posts');
|
||||||
var topics = require('../topics');
|
var topics = require('../topics');
|
||||||
var privileges = require('../privileges');
|
var privileges = require('../privileges');
|
||||||
|
var batch = require('../batch');
|
||||||
|
|
||||||
|
|
||||||
module.exports = function(Categories) {
|
module.exports = function(Categories) {
|
||||||
@@ -182,7 +183,8 @@ module.exports = function(Categories) {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
Categories.moveRecentReplies = function(tid, oldCid, cid) {
|
Categories.moveRecentReplies = function(tid, oldCid, cid, callback) {
|
||||||
|
callback = callback || function() {};
|
||||||
updatePostCount(tid, oldCid, cid);
|
updatePostCount(tid, oldCid, cid);
|
||||||
topics.getPids(tid, function(err, pids) {
|
topics.getPids(tid, function(err, pids) {
|
||||||
if (err) {
|
if (err) {
|
||||||
@@ -193,47 +195,31 @@ module.exports = function(Categories) {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
var start = 0,
|
batch.processArray(pids, function(pids, next) {
|
||||||
done = false,
|
async.waterfall([
|
||||||
batch = 50;
|
function(next) {
|
||||||
|
posts.getPostsFields(pids, ['timestamp'], next);
|
||||||
async.whilst(function() {
|
},
|
||||||
return !done;
|
function(postData, next) {
|
||||||
}, function(next) {
|
|
||||||
var movePids = pids.slice(start, start + batch);
|
|
||||||
if (!movePids.length) {
|
|
||||||
done = true;
|
|
||||||
return next();
|
|
||||||
}
|
|
||||||
|
|
||||||
posts.getPostsFields(movePids, ['timestamp'], function(err, postData) {
|
|
||||||
if (err) {
|
|
||||||
return next(err);
|
|
||||||
}
|
|
||||||
|
|
||||||
var timestamps = postData.map(function(post) {
|
var timestamps = postData.map(function(post) {
|
||||||
return post && post.timestamp;
|
return post && post.timestamp;
|
||||||
});
|
});
|
||||||
|
|
||||||
async.parallel([
|
async.parallel([
|
||||||
function(next) {
|
function(next) {
|
||||||
db.sortedSetRemove('cid:' + oldCid + ':pids', movePids, next);
|
db.sortedSetRemove('cid:' + oldCid + ':pids', pids, next);
|
||||||
},
|
},
|
||||||
function(next) {
|
function(next) {
|
||||||
db.sortedSetAdd('cid:' + cid + ':pids', timestamps, movePids, next);
|
db.sortedSetAdd('cid:' + cid + ':pids', timestamps, pids, next);
|
||||||
}
|
}
|
||||||
], function(err) {
|
], next);
|
||||||
if (err) {
|
|
||||||
return next(err);
|
|
||||||
}
|
}
|
||||||
start += batch;
|
], next);
|
||||||
next();
|
|
||||||
});
|
|
||||||
});
|
|
||||||
}, function(err) {
|
}, function(err) {
|
||||||
if (err) {
|
if (err) {
|
||||||
winston.error(err.stack);
|
winston.error(err.stack);
|
||||||
}
|
}
|
||||||
|
callback(err);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -16,6 +16,7 @@ module.exports = function(Groups) {
|
|||||||
return callback();
|
return callback();
|
||||||
}
|
}
|
||||||
var groupObj = groupsData[0];
|
var groupObj = groupsData[0];
|
||||||
|
|
||||||
plugins.fireHook('action:group.destroy', groupObj);
|
plugins.fireHook('action:group.destroy', groupObj);
|
||||||
|
|
||||||
async.parallel([
|
async.parallel([
|
||||||
@@ -40,7 +41,11 @@ module.exports = function(Groups) {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
], function(err) {
|
], function(err) {
|
||||||
callback(err);
|
if (err) {
|
||||||
|
return callback(err);
|
||||||
|
}
|
||||||
|
Groups.resetCache();
|
||||||
|
callback();
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -11,6 +11,7 @@ var db = require('./database');
|
|||||||
var User = require('./user');
|
var User = require('./user');
|
||||||
var groups = require('./groups');
|
var groups = require('./groups');
|
||||||
var meta = require('./meta');
|
var meta = require('./meta');
|
||||||
|
var batch = require('./batch');
|
||||||
var plugins = require('./plugins');
|
var plugins = require('./plugins');
|
||||||
var utils = require('../public/src/utils');
|
var utils = require('../public/src/utils');
|
||||||
|
|
||||||
@@ -168,36 +169,14 @@ var utils = require('../public/src/utils');
|
|||||||
return callback();
|
return callback();
|
||||||
}
|
}
|
||||||
|
|
||||||
var done = false;
|
|
||||||
var start = 0;
|
|
||||||
var batchSize = 50;
|
|
||||||
|
|
||||||
setTimeout(function() {
|
setTimeout(function() {
|
||||||
async.whilst(
|
batch.processArray(uids, function(uids, next) {
|
||||||
function() {
|
pushToUids(uids, notification, next);
|
||||||
return !done;
|
}, {interval: 1000}, function(err) {
|
||||||
},
|
|
||||||
function(next) {
|
|
||||||
var currentUids = uids.slice(start, start + batchSize);
|
|
||||||
if (!currentUids.length) {
|
|
||||||
done = true;
|
|
||||||
return next();
|
|
||||||
}
|
|
||||||
pushToUids(currentUids, notification, function(err) {
|
|
||||||
if (err) {
|
|
||||||
return next(err);
|
|
||||||
}
|
|
||||||
start = start + batchSize;
|
|
||||||
|
|
||||||
setTimeout(next, 1000);
|
|
||||||
});
|
|
||||||
},
|
|
||||||
function(err) {
|
|
||||||
if (err) {
|
if (err) {
|
||||||
winston.error(err.stack);
|
winston.error(err.stack);
|
||||||
}
|
}
|
||||||
}
|
});
|
||||||
);
|
|
||||||
}, 1000);
|
}, 1000);
|
||||||
|
|
||||||
callback();
|
callback();
|
||||||
|
|||||||
@@ -1,19 +1,30 @@
|
|||||||
'use strict';
|
'use strict';
|
||||||
/*global require, process, after*/
|
/*global require, after, before*/
|
||||||
|
|
||||||
var winston = require('winston');
|
|
||||||
|
|
||||||
process.on('uncaughtException', function (err) {
|
var async = require('async');
|
||||||
winston.error('Encountered error while running test suite: ' + err.message);
|
var assert = require('assert');
|
||||||
});
|
|
||||||
|
|
||||||
var assert = require('assert'),
|
|
||||||
db = require('./mocks/databasemock');
|
|
||||||
|
|
||||||
|
var db = require('./mocks/databasemock');
|
||||||
var Categories = require('../src/categories');
|
var Categories = require('../src/categories');
|
||||||
|
var Topics = require('../src/topics');
|
||||||
|
var User = require('../src/user');
|
||||||
|
|
||||||
describe('Categories', function() {
|
describe('Categories', function() {
|
||||||
var categoryObj;
|
var categoryObj;
|
||||||
|
var posterUid;
|
||||||
|
|
||||||
|
before(function(done) {
|
||||||
|
User.create({username: 'poster'}, function(err, _posterUid) {
|
||||||
|
if (err) {
|
||||||
|
return done(err);
|
||||||
|
}
|
||||||
|
|
||||||
|
posterUid = _posterUid;
|
||||||
|
|
||||||
|
done();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
describe('.create', function() {
|
describe('.create', function() {
|
||||||
it('should create a new category', function(done) {
|
it('should create a new category', function(done) {
|
||||||
@@ -115,6 +126,53 @@ describe('Categories', function() {
|
|||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
describe('Categories.moveRecentReplies', function() {
|
||||||
|
var moveCid;
|
||||||
|
var moveTid;
|
||||||
|
before(function(done) {
|
||||||
|
async.parallel({
|
||||||
|
category: function(next) {
|
||||||
|
Categories.create({
|
||||||
|
name: 'Test Category 2',
|
||||||
|
description: 'Test category created by testing script'
|
||||||
|
}, next);
|
||||||
|
},
|
||||||
|
topic: function(next) {
|
||||||
|
Topics.post({
|
||||||
|
uid: posterUid,
|
||||||
|
cid: categoryObj.cid,
|
||||||
|
title: 'Test Topic Title',
|
||||||
|
content: 'The content of test topic'
|
||||||
|
}, next);
|
||||||
|
}
|
||||||
|
}, function(err, results) {
|
||||||
|
if (err) {
|
||||||
|
return done(err);
|
||||||
|
}
|
||||||
|
moveCid = results.category.cid;
|
||||||
|
moveTid = results.topic.topicData.tid;
|
||||||
|
Topics.reply({uid: posterUid, content: 'test post', tid: moveTid}, function(err) {
|
||||||
|
done(err);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should move posts from one category to another', function(done) {
|
||||||
|
Categories.moveRecentReplies(moveTid, categoryObj.cid, moveCid, function(err) {
|
||||||
|
assert.ifError(err);
|
||||||
|
db.getSortedSetRange('cid:' + categoryObj.cid + ':pids', 0, -1, function(err, pids) {
|
||||||
|
assert.ifError(err);
|
||||||
|
assert.equal(pids.length, 0);
|
||||||
|
db.getSortedSetRange('cid:' + moveCid + ':pids', 0, -1, function(err, pids) {
|
||||||
|
assert.ifError(err);
|
||||||
|
assert.equal(pids.length, 2);
|
||||||
|
done();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
after(function(done) {
|
after(function(done) {
|
||||||
db.flushdb(done);
|
db.flushdb(done);
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -1,15 +1,16 @@
|
|||||||
'use strict';
|
'use strict';
|
||||||
/*global require, before, after*/
|
/*global require, before, after*/
|
||||||
|
|
||||||
var assert = require('assert'),
|
var assert = require('assert');
|
||||||
async = require('async'),
|
var async = require('async');
|
||||||
|
|
||||||
db = require('./mocks/databasemock'),
|
var db = require('./mocks/databasemock');
|
||||||
Groups = require('../src/groups'),
|
var Groups = require('../src/groups');
|
||||||
User = require('../src/user');
|
var User = require('../src/user');
|
||||||
|
|
||||||
describe('Groups', function() {
|
describe('Groups', function() {
|
||||||
before(function(done) {
|
before(function(done) {
|
||||||
|
Groups.resetCache();
|
||||||
async.parallel([
|
async.parallel([
|
||||||
function(next) {
|
function(next) {
|
||||||
// Create a group to play around with
|
// Create a group to play around with
|
||||||
@@ -35,8 +36,7 @@ describe('Groups', function() {
|
|||||||
describe('.list()', function() {
|
describe('.list()', function() {
|
||||||
it('should list the groups present', function(done) {
|
it('should list the groups present', function(done) {
|
||||||
Groups.getGroupsFromSet('groups:createtime', 0, 0, -1, function(err, groups) {
|
Groups.getGroupsFromSet('groups:createtime', 0, 0, -1, function(err, groups) {
|
||||||
if (err) return done(err);
|
assert.ifError(err);
|
||||||
|
|
||||||
assert.equal(groups.length, 3);
|
assert.equal(groups.length, 3);
|
||||||
done();
|
done();
|
||||||
});
|
});
|
||||||
|
|||||||
102
test/notifications.js
Normal file
102
test/notifications.js
Normal file
@@ -0,0 +1,102 @@
|
|||||||
|
'use strict';
|
||||||
|
/*global require, after, before*/
|
||||||
|
|
||||||
|
|
||||||
|
var assert = require('assert');
|
||||||
|
|
||||||
|
var db = require('./mocks/databasemock');
|
||||||
|
var user = require('../src/user');
|
||||||
|
var notifications = require('../src/notifications');
|
||||||
|
|
||||||
|
describe('Notifications', function() {
|
||||||
|
var uid;
|
||||||
|
var notification;
|
||||||
|
|
||||||
|
before(function(done) {
|
||||||
|
user.create({username: 'poster'}, function(err, _uid) {
|
||||||
|
if (err) {
|
||||||
|
return done(err);
|
||||||
|
}
|
||||||
|
|
||||||
|
uid = _uid;
|
||||||
|
done();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should create a notification', function(done) {
|
||||||
|
notifications.create({
|
||||||
|
bodyShort: 'bodyShort',
|
||||||
|
nid: 'notification_id'
|
||||||
|
}, function(err, _notification) {
|
||||||
|
notification = _notification;
|
||||||
|
assert.ifError(err);
|
||||||
|
assert(notification);
|
||||||
|
db.exists('notifications:' + notification.nid, function(err, exists) {
|
||||||
|
assert.ifError(err);
|
||||||
|
assert(exists);
|
||||||
|
db.isSortedSetMember('notifications', notification.nid, function(err, isMember) {
|
||||||
|
assert.ifError(err);
|
||||||
|
assert(isMember);
|
||||||
|
done();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should get notifications', function(done) {
|
||||||
|
notifications.getMultiple([notification.nid], function(err, notificationsData) {
|
||||||
|
assert.ifError(err);
|
||||||
|
assert(Array.isArray(notificationsData));
|
||||||
|
assert(notificationsData[0]);
|
||||||
|
assert.equal(notification.nid, notificationsData[0].nid);
|
||||||
|
done();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should push a notification to uid', function(done) {
|
||||||
|
notifications.push(notification, [uid], function(err) {
|
||||||
|
assert.ifError(err);
|
||||||
|
setTimeout(function() {
|
||||||
|
db.isSortedSetMember('uid:' + uid + ':notifications:unread', notification.nid, function(err, isMember) {
|
||||||
|
assert.ifError(err);
|
||||||
|
assert(isMember);
|
||||||
|
done();
|
||||||
|
});
|
||||||
|
}, 2000);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should mark a notification read', function(done) {
|
||||||
|
notifications.markRead(notification.nid, uid, function(err) {
|
||||||
|
assert.ifError(err);
|
||||||
|
db.isSortedSetMember('uid:' + uid + ':notifications:unread', notification.nid, function(err, isMember) {
|
||||||
|
assert.ifError(err);
|
||||||
|
assert.equal(isMember, false);
|
||||||
|
db.isSortedSetMember('uid:' + uid + ':notifications:read', notification.nid, function(err, isMember) {
|
||||||
|
assert.ifError(err);
|
||||||
|
assert.equal(isMember, true);
|
||||||
|
done();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should mark a notification unread', function(done) {
|
||||||
|
notifications.markUnread(notification.nid, uid, function(err) {
|
||||||
|
assert.ifError(err);
|
||||||
|
db.isSortedSetMember('uid:' + uid + ':notifications:unread', notification.nid, function(err, isMember) {
|
||||||
|
assert.ifError(err);
|
||||||
|
assert.equal(isMember, true);
|
||||||
|
db.isSortedSetMember('uid:' + uid + ':notifications:read', notification.nid, function(err, isMember) {
|
||||||
|
assert.ifError(err);
|
||||||
|
assert.equal(isMember, false);
|
||||||
|
done();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
after(function(done) {
|
||||||
|
db.flushdb(done);
|
||||||
|
});
|
||||||
|
});
|
||||||
Reference in New Issue
Block a user