Enhance FalukantService with character caching and optimized city retrieval: Introduce caching for cities with branch types to reduce database queries, and streamline character retrieval logic. Update product and knowledge fetching to improve performance and maintainability.
This commit is contained in:
@@ -4541,36 +4541,47 @@ class FalukantService extends BaseService {
|
|||||||
const priceByProduct = new Map(items.map(i => [i.productId, i.currentPrice]));
|
const priceByProduct = new Map(items.map(i => [i.productId, i.currentPrice]));
|
||||||
|
|
||||||
const user = await this.getFalukantUserByHashedId(hashedUserId);
|
const user = await this.getFalukantUserByHashedId(hashedUserId);
|
||||||
const character = await FalukantCharacter.findOne({ where: { userId: user.id } });
|
const character = user.character || await FalukantCharacter.findOne({ where: { userId: user.id }, attributes: ['id'] });
|
||||||
if (!character) {
|
if (!character) {
|
||||||
throw new Error(`No FalukantCharacter found for user with id ${user.id}`);
|
throw new Error(`No FalukantCharacter found for user with id ${user.id}`);
|
||||||
}
|
}
|
||||||
|
const characterId = character.id;
|
||||||
|
|
||||||
const [products, knowledges, cities, townWorths] = await Promise.all([
|
let citiesWithBranchType = FalukantService._citiesBatchCache?.get(user.id);
|
||||||
|
const now = Date.now();
|
||||||
|
if (citiesWithBranchType && citiesWithBranchType.expires > now) {
|
||||||
|
citiesWithBranchType = citiesWithBranchType.data;
|
||||||
|
} else {
|
||||||
|
const cityRows = await sequelize.query(
|
||||||
|
`SELECT r.id, r.name,
|
||||||
|
MAX(CASE WHEN bt.label_tr IN ('store','fullstack') THEN 2 WHEN bt.label_tr = 'production' THEN 1 ELSE 0 END) AS branch_type_sort
|
||||||
|
FROM falukant_data.region r
|
||||||
|
INNER JOIN falukant_type.region rt ON r.region_type_id = rt.id AND rt.label_tr = 'city'
|
||||||
|
LEFT JOIN falukant_data.branch b ON b.region_id = r.id AND b.falukant_user_id = :userId
|
||||||
|
LEFT JOIN falukant_type.branch bt ON b.branch_type_id = bt.id
|
||||||
|
GROUP BY r.id, r.name
|
||||||
|
ORDER BY r.id`,
|
||||||
|
{ replacements: { userId: user.id }, type: sequelize.QueryTypes.SELECT }
|
||||||
|
);
|
||||||
|
const branchTypeByCityId = new Map();
|
||||||
|
const cities = [];
|
||||||
|
for (const row of cityRows) {
|
||||||
|
cities.push({ id: row.id, name: row.name });
|
||||||
|
const sort = row.branch_type_sort ?? 0;
|
||||||
|
branchTypeByCityId.set(row.id, sort === 2 ? 'store' : sort === 1 ? 'production' : null);
|
||||||
|
}
|
||||||
|
citiesWithBranchType = { cities, branchTypeByCityId };
|
||||||
|
if (!FalukantService._citiesBatchCache) FalukantService._citiesBatchCache = new Map();
|
||||||
|
FalukantService._citiesBatchCache.set(user.id, { data: citiesWithBranchType, expires: now + 60000 });
|
||||||
|
}
|
||||||
|
const { cities, branchTypeByCityId } = citiesWithBranchType;
|
||||||
|
|
||||||
|
const [products, knowledges, townWorths] = await Promise.all([
|
||||||
ProductType.findAll({ where: { id: { [Op.in]: productIds } }, attributes: ['id', 'sellCost'] }),
|
ProductType.findAll({ where: { id: { [Op.in]: productIds } }, attributes: ['id', 'sellCost'] }),
|
||||||
Knowledge.findAll({
|
Knowledge.findAll({
|
||||||
where: { characterId: character.id, productId: { [Op.in]: productIds } },
|
where: { characterId: characterId, productId: { [Op.in]: productIds } },
|
||||||
attributes: ['productId', 'knowledge']
|
attributes: ['productId', 'knowledge']
|
||||||
}),
|
}),
|
||||||
RegionData.findAll({
|
|
||||||
attributes: ['id', 'name'],
|
|
||||||
include: [
|
|
||||||
{
|
|
||||||
model: RegionType,
|
|
||||||
as: 'regionType',
|
|
||||||
where: { labelTr: 'city' },
|
|
||||||
attributes: ['labelTr']
|
|
||||||
},
|
|
||||||
{
|
|
||||||
model: Branch,
|
|
||||||
as: 'branches',
|
|
||||||
where: { falukantUserId: user.id },
|
|
||||||
include: [{ model: BranchType, as: 'branchType', attributes: ['labelTr'] }],
|
|
||||||
attributes: ['branchTypeId'],
|
|
||||||
required: false
|
|
||||||
}
|
|
||||||
]
|
|
||||||
}),
|
|
||||||
TownProductWorth.findAll({
|
TownProductWorth.findAll({
|
||||||
where: { productId: { [Op.in]: productIds } },
|
where: { productId: { [Op.in]: productIds } },
|
||||||
attributes: ['productId', 'regionId', 'worthPercent']
|
attributes: ['productId', 'regionId', 'worthPercent']
|
||||||
@@ -4578,12 +4589,7 @@ class FalukantService extends BaseService {
|
|||||||
]);
|
]);
|
||||||
|
|
||||||
const knowledgeByProduct = new Map(knowledges.map(k => [k.productId, k.knowledge || 0]));
|
const knowledgeByProduct = new Map(knowledges.map(k => [k.productId, k.knowledge || 0]));
|
||||||
const worthByProductRegion = new Map();
|
const worthByProductRegion = new Map(townWorths.map(tw => [`${tw.productId}-${tw.regionId}`, tw.worthPercent]));
|
||||||
for (const tw of townWorths) {
|
|
||||||
const key = `${tw.productId}-${tw.regionId}`;
|
|
||||||
worthByProductRegion.set(key, tw.worthPercent);
|
|
||||||
}
|
|
||||||
const productById = new Map(products.map(p => [p.id, p]));
|
|
||||||
|
|
||||||
const PRICE_TOLERANCE = 0.01;
|
const PRICE_TOLERANCE = 0.01;
|
||||||
const out = {};
|
const out = {};
|
||||||
@@ -4604,18 +4610,11 @@ class FalukantService extends BaseService {
|
|||||||
const priceInCity = calcRegionalSellPriceSync(product, knowledgeFactor, worthPercent);
|
const priceInCity = calcRegionalSellPriceSync(product, knowledgeFactor, worthPercent);
|
||||||
if (priceInCity == null) continue;
|
if (priceInCity == null) continue;
|
||||||
if (priceInCity <= currentRegionalPrice - PRICE_TOLERANCE) continue;
|
if (priceInCity <= currentRegionalPrice - PRICE_TOLERANCE) continue;
|
||||||
|
|
||||||
let branchType = null;
|
|
||||||
if (city.branches && city.branches.length > 0) {
|
|
||||||
const branchTypes = city.branches.map(b => b.branchType?.labelTr).filter(Boolean);
|
|
||||||
if (branchTypes.includes('store') || branchTypes.includes('fullstack')) branchType = 'store';
|
|
||||||
else if (branchTypes.includes('production')) branchType = 'production';
|
|
||||||
}
|
|
||||||
results.push({
|
results.push({
|
||||||
regionId: city.id,
|
regionId: city.id,
|
||||||
regionName: city.name,
|
regionName: city.name,
|
||||||
price: priceInCity,
|
price: priceInCity,
|
||||||
branchType
|
branchType: branchTypeByCityId.get(city.id) ?? null
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
results.sort((a, b) => b.price - a.price);
|
results.sort((a, b) => b.price - a.price);
|
||||||
|
|||||||
Reference in New Issue
Block a user