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:
Phillip Thelen
2024-08-12 23:45:35 +02:00
parent 91c810925a
commit 41fa200271
10 changed files with 23 additions and 23 deletions

View File

@@ -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 () { function buildFlatList () {
/* /*
The gear is exported as a tree (defined above), and a flat list The gear is exported as a tree (defined above), and a flat list

View File

@@ -106,7 +106,7 @@ function getTranslatedClassName (classType, language) {
shops.checkMarketGearLocked = function checkMarketGearLocked (user, items) { shops.checkMarketGearLocked = function checkMarketGearLocked (user, items) {
const result = filter(items, ['pinType', 'marketGear']); const result = filter(items, ['pinType', 'marketGear']);
const officialPinnedItems = getOfficialPinnedItems(user); 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(); const { pinnedSets } = seasonalShopConfig();
for (const gear of result) { for (const gear of result) {
if (gear.klass !== user.stats.class) { if (gear.klass !== user.stats.class) {

View File

@@ -13,7 +13,7 @@ const sortOrder = reduce(content.gearTypes, (accumulator, val, key) => {
return accumulator; return accumulator;
}, {}); }, {});
export default function updateStore (user) { export default function updateStore (user, items) {
let changes = []; let changes = [];
each(content.gearTypes, type => { each(content.gearTypes, type => {
@@ -26,6 +26,7 @@ export default function updateStore (user) {
}); });
changes = changes.concat(filter(content.gear.flat, val => { 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)) { if (['special', 'mystery', 'armoire'].indexOf(val.klass) !== -1 && !user.items.gear.owned[val.key] && (val.canOwn ? val.canOwn(user) : false)) {
return true; return true;
} }

View File

@@ -1299,12 +1299,17 @@ api.removeGroupManager = {
api.getGroupPlans = { api.getGroupPlans = {
method: 'GET', method: 'GET',
url: '/group-plans', url: '/group-plans',
middlewares: [authWithHeaders()], middlewares: [authWithHeaders({ userFieldsToInclude: ['guilds', 'party._id'] })],
async handler (req, res) { async handler (req, res) {
const { user } = res.locals; const { user } = res.locals;
const userGroups = user.getGroups(); const userGroups = user.getGroups();
if (userGroups.length === 0) {
res.respond(200, []);
return;
}
const groups = await Group const groups = await Group
.find({ .find({
_id: { $in: userGroups }, _id: { $in: userGroups },

View File

@@ -19,7 +19,7 @@ const api = {};
api.getInboxMessages = { api.getInboxMessages = {
method: 'GET', method: 'GET',
url: '/inbox/messages', url: '/inbox/messages',
middlewares: [authWithHeaders()], middlewares: [authWithHeaders({ userFieldsToInclude: ['profile', 'contributor', 'backer', 'inbox'] })],
async handler (req, res) { async handler (req, res) {
const { user } = res.locals; const { user } = res.locals;
const { page } = req.query; const { page } = req.query;

View File

@@ -751,7 +751,7 @@ api.updateTask = {
api.scoreTask = { api.scoreTask = {
method: 'POST', method: 'POST',
url: '/tasks/:taskId/score/:direction', 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) { async handler (req, res) {
// Parameters are validated in scoreTasks // Parameters are validated in scoreTasks

View File

@@ -168,7 +168,7 @@ api.getBuyList = {
*/ */
api.getInAppRewardsList = { api.getInAppRewardsList = {
method: 'GET', method: 'GET',
middlewares: [authWithHeaders()], middlewares: [authWithHeaders({ userFieldsToInclude: ['items', 'pinnedItems', 'unpinnedItems', 'pinnedItemsOrder', 'stats.class', 'achievements'] })],
url: '/user/in-app-rewards', url: '/user/in-app-rewards',
async handler (req, res) { async handler (req, res) {
const list = common.inAppRewards(res.locals.user); const list = common.inAppRewards(res.locals.user);
@@ -1537,7 +1537,7 @@ api.clearMessages = {
*/ */
api.markPmsRead = { api.markPmsRead = {
method: 'POST', method: 'POST',
middlewares: [authWithHeaders()], middlewares: [authWithHeaders({ userFieldsToInclude: ['inbox'] })],
url: '/user/mark-pms-read', url: '/user/mark-pms-read',
async handler (req, res) { async handler (req, res) {
const { user } = res.locals; const { user } = res.locals;

View File

@@ -106,7 +106,7 @@ api.clearMessages = {
*/ */
api.conversations = { api.conversations = {
method: 'GET', method: 'GET',
middlewares: [authWithHeaders()], middlewares: [authWithHeaders({ userFieldsToInclude: ['profile', 'contributor', 'backer', 'inbox'] })],
url: '/inbox/conversations', url: '/inbox/conversations',
async handler (req, res) { async handler (req, res) {
const { user } = res.locals; const { user } = res.locals;
@@ -134,7 +134,7 @@ api.conversations = {
api.getInboxMessages = { api.getInboxMessages = {
method: 'GET', method: 'GET',
url: '/inbox/paged-messages', url: '/inbox/paged-messages',
middlewares: [authWithHeaders()], middlewares: [authWithHeaders({ userFieldsToInclude: ['profile', 'contributor', 'backer', 'inbox'] })],
async handler (req, res) { async handler (req, res) {
const { user } = res.locals; const { user } = res.locals;
const { page, conversation } = req.query; const { page, conversation } = req.query;

View File

@@ -58,11 +58,13 @@ export async function getUserInbox (user, optionParams = getUserInboxDefaultOpti
query = query query = query
.skip(PM_PER_PAGE * Number(options.page)) .skip(PM_PER_PAGE * Number(options.page))
.limit(PM_PER_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 messages = (await query.lean().exec()).map(msgObj => {
const msgObj = msg.toJSON(); delete msgObj.__v;
if (options.mapProps) { if (options.mapProps) {
mapInboxMessage(msgObj, user); mapInboxMessage(msgObj, user);
} }

View File

@@ -250,7 +250,7 @@ async function getTasks (req, res, options = {}) {
if (limit) mQuery.limit(limit); if (limit) mQuery.limit(limit);
if (sort) mQuery.sort(sort); if (sort) mQuery.sort(sort);
const tasks = await mQuery.exec(); const tasks = await mQuery.lean().exec();
if (dueDate) { if (dueDate) {
tasks.forEach(task => { tasks.forEach(task => {
@@ -288,6 +288,8 @@ async function getTasks (req, res, options = {}) {
tasks.forEach((task, index) => { tasks.forEach((task, index) => {
const taskId = task._id; const taskId = task._id;
task.id = task._id;
delete task.__v;
const i = order[index] === taskId ? index : order.indexOf(taskId); const i = order[index] === taskId ? index : order.indexOf(taskId);
if (i === -1) { if (i === -1) {
unorderedTasks.push(task); unorderedTasks.push(task);