Better-scoped queries for currentUserOwnsThis etc
I hypothesize that loading people's full trade lists more often than necessary is part of the cause of the recent mega slowdown! My hypothesis is that we're clogging up the MySQL connection socket with a ton of data, which blocks all other queries until the big ones come through and parse out. (I haven't actually validated my assumption that MySQL connections send query results in serial like that, but it makes sense to me, and fits what I've been seeing.) There's more places we could potentially optimize, like the trade list page itself… (we currently aggressively load everything when we could limit it and load the rest on the followup pages, or even paginate the followup pages…) …but my hope is that this helps enough, by relieving the load on the homepage (latest items) and on item searches!
This commit is contained in:
parent
6ce8a5aea2
commit
e051290df4
2 changed files with 38 additions and 10 deletions
|
@ -1245,6 +1245,25 @@ const buildUserClosetHangersLoader = (db) =>
|
|||
);
|
||||
});
|
||||
|
||||
const buildUserItemClosetHangersLoader = (db) =>
|
||||
new DataLoader(async (userIdAndItemIdPairs) => {
|
||||
const conditions = userIdAndItemIdPairs
|
||||
.map((_) => `(user_id = ? AND item_id = ?)`)
|
||||
.join(` OR `);
|
||||
const params = userIdAndItemIdPairs
|
||||
.map(({ userId, itemId }) => [userId, itemId])
|
||||
.flat();
|
||||
const [rows] = await db.execute(
|
||||
`SELECT * FROM closet_hangers WHERE ${conditions};`,
|
||||
params
|
||||
);
|
||||
const entities = rows.map(normalizeRow);
|
||||
|
||||
return userIdAndItemIdPairs.map(({ userId, itemId }) =>
|
||||
entities.filter((e) => e.userId === userId && e.itemId === itemId)
|
||||
);
|
||||
});
|
||||
|
||||
const buildUserClosetListsLoader = (db, loaders) =>
|
||||
new DataLoader(async (userIds) => {
|
||||
const qs = userIds.map((_) => "?").join(",");
|
||||
|
@ -1481,6 +1500,7 @@ function buildLoaders(db) {
|
|||
loaders.userByNameLoader = buildUserByNameLoader(db);
|
||||
loaders.userByEmailLoader = buildUserByEmailLoader(db);
|
||||
loaders.userClosetHangersLoader = buildUserClosetHangersLoader(db);
|
||||
loaders.userItemClosetHangersLoader = buildUserItemClosetHangersLoader(db);
|
||||
loaders.userClosetListsLoader = buildUserClosetListsLoader(db, loaders);
|
||||
loaders.userNumTotalOutfitsLoader = buildUserNumTotalOutfitsLoader(db);
|
||||
loaders.userOutfitsLoader = buildUserOutfitsLoader(db, loaders);
|
||||
|
|
|
@ -348,30 +348,38 @@ const resolvers = {
|
|||
currentUserOwnsThis: async (
|
||||
{ id },
|
||||
_,
|
||||
{ currentUserId, userClosetHangersLoader }
|
||||
{ currentUserId, userItemClosetHangersLoader }
|
||||
) => {
|
||||
if (currentUserId == null) return false;
|
||||
const closetHangers = await userClosetHangersLoader.load(currentUserId);
|
||||
return closetHangers.some((h) => h.itemId === id && h.owned);
|
||||
const closetHangers = await userItemClosetHangersLoader.load({
|
||||
userId: currentUserId,
|
||||
itemId: id,
|
||||
});
|
||||
return closetHangers.some((h) => h.owned);
|
||||
},
|
||||
currentUserWantsThis: async (
|
||||
{ id },
|
||||
_,
|
||||
{ currentUserId, userClosetHangersLoader }
|
||||
{ currentUserId, userItemClosetHangersLoader }
|
||||
) => {
|
||||
if (currentUserId == null) return false;
|
||||
const closetHangers = await userClosetHangersLoader.load(currentUserId);
|
||||
return closetHangers.some((h) => h.itemId === id && !h.owned);
|
||||
const closetHangers = await userItemClosetHangersLoader.load({
|
||||
userId: currentUserId,
|
||||
itemId: id,
|
||||
});
|
||||
return closetHangers.some((h) => !h.owned);
|
||||
},
|
||||
currentUserHasInLists: async (
|
||||
{ id },
|
||||
_,
|
||||
{ currentUserId, userClosetHangersLoader }
|
||||
{ currentUserId, userItemClosetHangersLoader }
|
||||
) => {
|
||||
if (currentUserId == null) return false;
|
||||
const closetHangers = await userClosetHangersLoader.load(currentUserId);
|
||||
const itemHangers = closetHangers.filter((h) => h.itemId === id);
|
||||
const listRefs = itemHangers.map((hanger) => {
|
||||
const closetHangers = await userItemClosetHangersLoader.load({
|
||||
userId: currentUserId,
|
||||
itemId: id,
|
||||
});
|
||||
const listRefs = closetHangers.map((hanger) => {
|
||||
if (hanger.listId) {
|
||||
return { id: hanger.listId };
|
||||
} else {
|
||||
|
|
Loading…
Reference in a new issue