From d2ac2bfdd8a583086eb9f33e50a4319ab81728ea Mon Sep 17 00:00:00 2001 From: "Torsten Schulz (local)" Date: Mon, 12 Jan 2026 11:46:16 +0100 Subject: [PATCH] Optimize gift retrieval in FalukantService by loading only necessary fields and implementing parallel data fetching. This change enhances performance and reduces data overhead during the gift and title of nobility retrieval process. --- backend/services/falukantService.js | 71 +++++++++++++++++++++-------- 1 file changed, 53 insertions(+), 18 deletions(-) diff --git a/backend/services/falukantService.js b/backend/services/falukantService.js index 585543e..0e7dcd3 100644 --- a/backend/services/falukantService.js +++ b/backend/services/falukantService.js @@ -3087,9 +3087,6 @@ class FalukantService extends BaseService { } timings.step7_possible_partners = Date.now() - step7Start; - const totalTime = Date.now() - startTime; - console.log(`[getFamily] Performance: ${totalTime}ms total`, timings); - return family; } catch (error) { console.error('[getFamily] Error:', error); @@ -3569,12 +3566,23 @@ class FalukantService extends BaseService { } async getGifts(hashedUserId) { - // 1) Mein User & Character - const user = await this.getFalukantUserByHashedId(hashedUserId); - const myChar = await FalukantCharacter.findOne({ where: { userId: user.id } }); + // 1) User & Character optimiert laden (nur benötigte Felder) + const user = await FalukantUser.findOne({ + include: [ + { model: User, as: 'user', attributes: ['hashedId'], where: { hashedId: hashedUserId } }, + { + model: FalukantCharacter, + as: 'character', + attributes: ['id', 'titleOfNobility'], + required: true + } + ] + }); + if (!user) throw new Error('User not found'); + const myChar = user.character; if (!myChar) throw new Error('Character not found'); - // 2) Beziehung finden und „anderen" Character bestimmen + // 2) Beziehung finden und „anderen" Character bestimmen (optimiert: nur benötigte Felder) const rel = await Relationship.findOne({ where: { [Op.or]: [ @@ -3583,8 +3591,32 @@ class FalukantService extends BaseService { ] }, include: [ - { model: FalukantCharacter, as: 'character1', include: [{ model: CharacterTrait, as: 'traits' }] }, - { model: FalukantCharacter, as: 'character2', include: [{ model: CharacterTrait, as: 'traits' }] } + { + model: FalukantCharacter, + as: 'character1', + attributes: ['id', 'moodId'], + include: [{ + model: CharacterTrait, + as: 'traits', + attributes: ['id'], + through: { attributes: [] }, + required: false + }], + required: false + }, + { + model: FalukantCharacter, + as: 'character2', + attributes: ['id', 'moodId'], + include: [{ + model: CharacterTrait, + as: 'traits', + attributes: ['id'], + through: { attributes: [] }, + required: false + }], + required: false + } ] }); @@ -3620,26 +3652,29 @@ class FalukantService extends BaseService { giftIncludes[0].where = { mood_id: relatedMoodId }; } if (rel && relatedTraitIds.length > 0) { - giftIncludes[1].where = { trait_id: relatedTraitIds }; + giftIncludes[1].where = { trait_id: { [Op.in]: relatedTraitIds } }; } - const gifts = await PromotionalGift.findAll({ - include: giftIncludes - }); + // 5) Parallel: Gifts und lowestTitleOfNobility laden + const [gifts, lowestTitleOfNobility] = await Promise.all([ + PromotionalGift.findAll({ + include: giftIncludes + }), + TitleOfNobility.findOne({ order: [['id', 'ASC']] }) + ]); - // 5) Rest wie gehabt: Kosten berechnen und zurückgeben - const lowestTitleOfNobility = await TitleOfNobility.findOne({ order: [['id', 'ASC']] }); - return Promise.all(gifts.map(async gift => ({ + // 6) Kosten berechnen (getGiftCost ist synchron, kein await nötig) + return gifts.map(gift => ({ id: gift.id, name: gift.name, - cost: await this.getGiftCost( + cost: this.getGiftCost( gift.value, myChar.titleOfNobility, lowestTitleOfNobility.id ), moodsAffects: gift.promotionalgiftmoods, // nur Einträge mit relatedMoodId charactersAffects: gift.characterTraits // nur Einträge mit relatedTraitIds - }))); + })); } async getChildren(hashedUserId) {