mirror of
https://github.com/HabitRPG/habitica.git
synced 2025-12-18 15:17:25 +01:00
Improve the performance of some frequently used API calls (#15251)
* use lean for getting task lists * Only load necessary user data for group-plans call Also don’t make a db request for groups if the user is in none * Only load necessary user fields for in app rewards * Optimize updateStore by not checking every item * Only load necessary user data for task scoring * improve performance of inbox request calls * merge fix * fix scoring task call * add quests to scoring call * fix showing official pinned items * also load achievements
This commit is contained in:
@@ -49,16 +49,6 @@ function populateGear (key, klass, type, index, item) {
|
||||
}
|
||||
}
|
||||
|
||||
each(GEAR_TYPES, type => {
|
||||
const allGearTypes = CLASSES.concat(['base', 'special', 'mystery', 'armoire']);
|
||||
each(allGearTypes, klass => {
|
||||
each(gear[type][klass], (item, index) => {
|
||||
const key = `${type}_${klass}_${index}`;
|
||||
populateGear(key, klass, type, index, item);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
function buildFlatList () {
|
||||
/*
|
||||
The gear is exported as a tree (defined above), and a flat list
|
||||
|
||||
@@ -106,7 +106,7 @@ function getTranslatedClassName (classType, language) {
|
||||
shops.checkMarketGearLocked = function checkMarketGearLocked (user, items) {
|
||||
const result = filter(items, ['pinType', 'marketGear']);
|
||||
const officialPinnedItems = getOfficialPinnedItems(user);
|
||||
const availableGear = map(updateStore(user), item => getItemInfo(user, 'marketGear', item, officialPinnedItems).path);
|
||||
const availableGear = map(updateStore(user, result.map(item => item.key)), item => getItemInfo(user, 'marketGear', item, officialPinnedItems).path);
|
||||
const { pinnedSets } = seasonalShopConfig();
|
||||
for (const gear of result) {
|
||||
if (gear.klass !== user.stats.class) {
|
||||
|
||||
@@ -13,7 +13,7 @@ const sortOrder = reduce(content.gearTypes, (accumulator, val, key) => {
|
||||
return accumulator;
|
||||
}, {});
|
||||
|
||||
export default function updateStore (user) {
|
||||
export default function updateStore (user, items) {
|
||||
let changes = [];
|
||||
|
||||
each(content.gearTypes, type => {
|
||||
@@ -26,6 +26,7 @@ export default function updateStore (user) {
|
||||
});
|
||||
|
||||
changes = changes.concat(filter(content.gear.flat, val => {
|
||||
if (items && items.indexOf(val.key) === -1) return false;
|
||||
if (['special', 'mystery', 'armoire'].indexOf(val.klass) !== -1 && !user.items.gear.owned[val.key] && (val.canOwn ? val.canOwn(user) : false)) {
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -1299,12 +1299,17 @@ api.removeGroupManager = {
|
||||
api.getGroupPlans = {
|
||||
method: 'GET',
|
||||
url: '/group-plans',
|
||||
middlewares: [authWithHeaders()],
|
||||
middlewares: [authWithHeaders({ userFieldsToInclude: ['guilds', 'party._id'] })],
|
||||
async handler (req, res) {
|
||||
const { user } = res.locals;
|
||||
|
||||
const userGroups = user.getGroups();
|
||||
|
||||
if (userGroups.length === 0) {
|
||||
res.respond(200, []);
|
||||
return;
|
||||
}
|
||||
|
||||
const groups = await Group
|
||||
.find({
|
||||
_id: { $in: userGroups },
|
||||
|
||||
@@ -19,7 +19,7 @@ const api = {};
|
||||
api.getInboxMessages = {
|
||||
method: 'GET',
|
||||
url: '/inbox/messages',
|
||||
middlewares: [authWithHeaders()],
|
||||
middlewares: [authWithHeaders({ userFieldsToInclude: ['profile', 'contributor', 'backer', 'inbox'] })],
|
||||
async handler (req, res) {
|
||||
const { user } = res.locals;
|
||||
const { page } = req.query;
|
||||
|
||||
@@ -751,7 +751,7 @@ api.updateTask = {
|
||||
api.scoreTask = {
|
||||
method: 'POST',
|
||||
url: '/tasks/:taskId/score/:direction',
|
||||
middlewares: [authWithHeaders()],
|
||||
middlewares: [authWithHeaders({ userFieldsToInclude: ['stats', 'guilds', 'items.equipped', 'items.eggs', 'items.food', 'items.hatchingPotions', 'items.lastDrop', 'items.quests', 'achievements', 'tasksOrder', 'webhooks', 'party'] })],
|
||||
async handler (req, res) {
|
||||
// Parameters are validated in scoreTasks
|
||||
|
||||
|
||||
@@ -168,7 +168,7 @@ api.getBuyList = {
|
||||
*/
|
||||
api.getInAppRewardsList = {
|
||||
method: 'GET',
|
||||
middlewares: [authWithHeaders()],
|
||||
middlewares: [authWithHeaders({ userFieldsToInclude: ['items', 'pinnedItems', 'unpinnedItems', 'pinnedItemsOrder', 'stats.class', 'achievements'] })],
|
||||
url: '/user/in-app-rewards',
|
||||
async handler (req, res) {
|
||||
const list = common.inAppRewards(res.locals.user);
|
||||
@@ -1537,7 +1537,7 @@ api.clearMessages = {
|
||||
*/
|
||||
api.markPmsRead = {
|
||||
method: 'POST',
|
||||
middlewares: [authWithHeaders()],
|
||||
middlewares: [authWithHeaders({ userFieldsToInclude: ['inbox'] })],
|
||||
url: '/user/mark-pms-read',
|
||||
async handler (req, res) {
|
||||
const { user } = res.locals;
|
||||
|
||||
@@ -106,7 +106,7 @@ api.clearMessages = {
|
||||
*/
|
||||
api.conversations = {
|
||||
method: 'GET',
|
||||
middlewares: [authWithHeaders()],
|
||||
middlewares: [authWithHeaders({ userFieldsToInclude: ['profile', 'contributor', 'backer', 'inbox'] })],
|
||||
url: '/inbox/conversations',
|
||||
async handler (req, res) {
|
||||
const { user } = res.locals;
|
||||
@@ -134,7 +134,7 @@ api.conversations = {
|
||||
api.getInboxMessages = {
|
||||
method: 'GET',
|
||||
url: '/inbox/paged-messages',
|
||||
middlewares: [authWithHeaders()],
|
||||
middlewares: [authWithHeaders({ userFieldsToInclude: ['profile', 'contributor', 'backer', 'inbox'] })],
|
||||
async handler (req, res) {
|
||||
const { user } = res.locals;
|
||||
const { page, conversation } = req.query;
|
||||
|
||||
@@ -58,11 +58,13 @@ export async function getUserInbox (user, optionParams = getUserInboxDefaultOpti
|
||||
query = query
|
||||
.skip(PM_PER_PAGE * Number(options.page))
|
||||
.limit(PM_PER_PAGE);
|
||||
} else {
|
||||
// Limit for legacy calls that are not paginated to prevent database issues
|
||||
query = query.limit(200);
|
||||
}
|
||||
|
||||
const messages = (await query.exec()).map(msg => {
|
||||
const msgObj = msg.toJSON();
|
||||
|
||||
const messages = (await query.lean().exec()).map(msgObj => {
|
||||
delete msgObj.__v;
|
||||
if (options.mapProps) {
|
||||
mapInboxMessage(msgObj, user);
|
||||
}
|
||||
|
||||
@@ -250,7 +250,7 @@ async function getTasks (req, res, options = {}) {
|
||||
if (limit) mQuery.limit(limit);
|
||||
if (sort) mQuery.sort(sort);
|
||||
|
||||
const tasks = await mQuery.exec();
|
||||
const tasks = await mQuery.lean().exec();
|
||||
|
||||
if (dueDate) {
|
||||
tasks.forEach(task => {
|
||||
@@ -288,6 +288,8 @@ async function getTasks (req, res, options = {}) {
|
||||
|
||||
tasks.forEach((task, index) => {
|
||||
const taskId = task._id;
|
||||
task.id = task._id;
|
||||
delete task.__v;
|
||||
const i = order[index] === taskId ? index : order.indexOf(taskId);
|
||||
if (i === -1) {
|
||||
unorderedTasks.push(task);
|
||||
|
||||
Reference in New Issue
Block a user