optimized getTopicsByTids, single db call to get topicData, added cache for privilege/category/user data

v1.18.x
barisusakli 11 years ago
parent 1568c50906
commit b4b9ed1841

@ -48,8 +48,8 @@
todo: fix this nesting if issue#1065 is a win todo: fix this nesting if issue#1065 is a win
todo: add a check for config.allowTopicsThumbnail if issue#1066 is a win todo: add a check for config.allowTopicsThumbnail if issue#1066 is a win
--> -->
<a href="../../user/{topics.userslug}" class="pull-left"> <a href="../../user/{topics.user.userslug}" class="pull-left">
<img src="<!-- IF topics.thumb -->{topics.thumb}<!-- ELSE -->{topics.picture}<!-- ENDIF topics.thumb -->" class="img-rounded user-img" title="{topics.username}"/> <img src="<!-- IF topics.thumb -->{topics.thumb}<!-- ELSE -->{topics.user.picture}<!-- ENDIF topics.thumb -->" class="img-rounded user-img" title="{topics.user.username}"/>
</a> </a>
<h3> <h3>

@ -26,8 +26,8 @@
<!-- BEGIN topics --> <!-- BEGIN topics -->
<li class="category-item <!-- IF topics.deleted --> deleted<!-- ENDIF topics.deleted --><!-- IF topics.unread --> unread<!-- ENDIF topics.unread -->"> <li class="category-item <!-- IF topics.deleted --> deleted<!-- ENDIF topics.deleted --><!-- IF topics.unread --> unread<!-- ENDIF topics.unread -->">
<div class="col-md-12 col-xs-12 panel panel-default topic-row"> <div class="col-md-12 col-xs-12 panel panel-default topic-row">
<a href="{relative_path}/user/{topics.userslug}" class="pull-left"> <a href="{relative_path}/user/{topics.user.userslug}" class="pull-left">
<img class="img-rounded user-img" src="{topics.picture}" title="{topics.username}" /> <img class="img-rounded user-img" src="{topics.user.picture}" title="{topics.user.username}" />
</a> </a>
<h3> <h3>

@ -27,8 +27,8 @@
<!-- BEGIN topics --> <!-- BEGIN topics -->
<li class="category-item <!-- IF topics.deleted --> deleted<!-- ENDIF topics.deleted --><!-- IF topics.unread --> unread<!-- ENDIF topics.unread -->"> <li class="category-item <!-- IF topics.deleted --> deleted<!-- ENDIF topics.deleted --><!-- IF topics.unread --> unread<!-- ENDIF topics.unread -->">
<div class="col-md-12 col-xs-12 panel panel-default topic-row"> <div class="col-md-12 col-xs-12 panel panel-default topic-row">
<a href="{relative_path}/user/{topics.userslug}" class="pull-left"> <a href="{relative_path}/user/{topics.user.userslug}" class="pull-left">
<img class="img-rounded user-img" src="{topics.picture}" title="{topics.username}" /> <img class="img-rounded user-img" src="{topics.user.picture}" title="{topics.user.username}" />
</a> </a>
<h3> <h3>

@ -21,8 +21,8 @@
<!-- BEGIN topics --> <!-- BEGIN topics -->
<li class="category-item<!-- IF topics.deleted --> deleted<!-- ENDIF topics.deleted -->" data-tid="{topics.tid}"> <li class="category-item<!-- IF topics.deleted --> deleted<!-- ENDIF topics.deleted -->" data-tid="{topics.tid}">
<div class="col-md-12 col-xs-12 panel panel-default topic-row"> <div class="col-md-12 col-xs-12 panel panel-default topic-row">
<a href="{relative_path}/user/{topics.userslug}" class="pull-left"> <a href="{relative_path}/user/{topics.user.userslug}" class="pull-left">
<img class="img-rounded user-img" src="{topics.picture}" title="{topics.username}" /> <img class="img-rounded user-img" src="{topics.user.picture}" title="{topics.user.username}" />
</a> </a>
<h3> <h3>
<a href="{relative_path}/topic/{topics.slug}"> <a href="{relative_path}/topic/{topics.slug}">

@ -323,17 +323,35 @@ var async = require('async'),
}; };
Topics.getTopicData = function(tid, callback) { Topics.getTopicData = function(tid, callback) {
db.getObject('topic:' + tid, function(err, data) { Topics.getTopicsData([tid], function(err, topics) {
if(err) { if (err) {
return callback(err, null); return callback(err);
}
callback(null, topics ? topics[0] : null);
});
};
Topics.getTopicsData = function(tids, callback) {
var keys = [];
for (var i=0; i<tids.length; ++i) {
keys.push('topic:' + tids[i]);
}
db.getObjects(keys, function(err, topics) {
if (err) {
return callback(err);
} }
if(data) { for (var i=0; i<tids.length; ++i) {
data.title = validator.escape(data.title); if(topics[i]) {
data.relativeTime = utils.toISOString(data.timestamp); topics[i].title = validator.escape(topics[i].title);
topics[i].relativeTime = utils.toISOString(topics[i].timestamp);
}
} }
callback(null, data); callback(null, topics);
}); });
}; };
@ -671,46 +689,53 @@ var async = require('async'),
return callback(null, []); return callback(null, []);
} }
function getTopicInfo(topicData, callback) { var categoryCache = {},
privilegeCache = {},
userCache = {};
function loadTopicInfo(topicData, next) {
function isTopicVisible(topicData, topicInfo) {
var deleted = parseInt(topicData.deleted, 10) !== 0;
return !deleted || (deleted && topicInfo.privileges.view_deleted) || parseInt(topicData.uid, 10) === parseInt(uid, 10);
}
async.parallel({ async.parallel({
hasread : function (next) { hasread: function(next) {
Topics.hasReadTopic(topicData.tid, uid, next); Topics.hasReadTopic(topicData.tid, uid, next);
}, },
teaser : function (next) { teaser: function(next) {
Topics.getTeaser(topicData.tid, next); Topics.getTeaser(topicData.tid, next);
}, },
privileges : function (next) { privileges: function(next) {
if (privilegeCache[topicData.cid]) {
return next(null, privilegeCache[topicData.cid])
}
categoryTools.privileges(topicData.cid, uid, next); categoryTools.privileges(topicData.cid, uid, next);
}, },
categoryData : function (next) { categoryData: function(next) {
categories.getCategoryFields(topicData.cid, ['name', 'slug', 'icon'], next); if (categoryCache[topicData.cid]) {
return next(null, categoryCache[topicData.cid]);
} }
}, callback); categories.getCategoryFields(topicData.cid, ['name', 'slug', 'icon'], next);
},
user: function(next) {
if (userCache[topicData.uid]) {
return next(null, userCache[topicData.uid]);
} }
user.getUserFields(topicData.uid, ['username', 'userslug', 'picture'], next);
function isTopicVisible(topicData, topicInfo) {
var deleted = parseInt(topicData.deleted, 10) !== 0;
return !deleted || (deleted && topicInfo.privileges.view_deleted) || parseInt(topicData.uid, 10) === parseInt(uid, 10);
} }
}, function(err, topicInfo) {
function loadTopic(tid, next) {
Topics.getTopicDataWithUser(tid, function(err, topicData) {
if(err) { if(err) {
return next(err); return next(err);
} }
if (!topicData) { privilegeCache[topicData.cid] = topicInfo.privileges;
return next(); categoryCache[topicData.cid] = topicInfo.categoryData;
} userCache[topicData.uid] = topicInfo.user;
getTopicInfo(topicData, function(err, topicInfo) {
if(err) {
return next(err);
}
if (!isTopicVisible(topicData, topicInfo)) { if (!isTopicVisible(topicData, topicInfo)) {
topicData = null;
return next(); return next();
} }
@ -722,13 +747,18 @@ var async = require('async'),
topicData.category = topicInfo.categoryData; topicData.category = topicInfo.categoryData;
topicData.teaser = topicInfo.teaser; topicData.teaser = topicInfo.teaser;
topicData.user = topicInfo.user;
next(null, topicData); next();
});
}); });
} }
async.map(tids, loadTopic, function(err, topics) { Topics.getTopicsData(tids, function(err, topics) {
if (err) {
return callback(err);
}
async.eachSeries(topics, loadTopicInfo, function(err) {
if(err) { if(err) {
return callback(err); return callback(err);
} }
@ -739,6 +769,7 @@ var async = require('async'),
callback(null, topics); callback(null, topics);
}); });
});
}; };
Topics.getTopicWithPosts = function(tid, uid, start, end, callback) { Topics.getTopicWithPosts = function(tid, uid, start, end, callback) {

Loading…
Cancel
Save