Skip to content

Commit

Permalink
Improve the performance of some frequently used API calls (#15251)
Browse files Browse the repository at this point in the history
* 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
  • Loading branch information
phillipthelen authored Aug 12, 2024
1 parent 0069af7 commit 9aafd76
Show file tree
Hide file tree
Showing 10 changed files with 23 additions and 23 deletions.
10 changes: 0 additions & 10 deletions website/common/script/content/gear/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
2 changes: 1 addition & 1 deletion website/common/script/libs/shops.js
Original file line number Diff line number Diff line change
Expand Up @@ -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) {
Expand Down
3 changes: 2 additions & 1 deletion website/common/script/libs/updateStore.js
Original file line number Diff line number Diff line change
Expand Up @@ -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 => {
Expand All @@ -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;
}
Expand Down
7 changes: 6 additions & 1 deletion website/server/controllers/api-v3/groups.js
Original file line number Diff line number Diff line change
Expand Up @@ -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 },
Expand Down
2 changes: 1 addition & 1 deletion website/server/controllers/api-v3/inbox.js
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down
2 changes: 1 addition & 1 deletion website/server/controllers/api-v3/tasks.js
Original file line number Diff line number Diff line change
Expand Up @@ -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

Expand Down
4 changes: 2 additions & 2 deletions website/server/controllers/api-v3/user.js
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand Down Expand Up @@ -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;
Expand Down
4 changes: 2 additions & 2 deletions website/server/controllers/api-v4/inbox.js
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down Expand Up @@ -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;
Expand Down
8 changes: 5 additions & 3 deletions website/server/libs/inbox/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -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);
}
Expand Down
4 changes: 3 additions & 1 deletion website/server/libs/tasks/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -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 => {
Expand Down Expand Up @@ -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);
Expand Down

0 comments on commit 9aafd76

Please sign in to comment.