catalog prices fix
This commit is contained in:
@ -3064,8 +3064,102 @@ export const resolvers = {
|
||||
}
|
||||
|
||||
console.log('✅ Получены товары каталога:', entities.list.length)
|
||||
console.log('🔍 Начинаем серверную фильтрацию по ценам...')
|
||||
|
||||
return entities
|
||||
// Глобальный кэш для результатов проверки цен (персистентный между запросами)
|
||||
if (!global.priceCache) {
|
||||
global.priceCache = new Map<string, { hasPrice: boolean, timestamp: number }>()
|
||||
}
|
||||
const priceCache = global.priceCache as Map<string, { hasPrice: boolean, timestamp: number }>
|
||||
const CACHE_TTL = 5 * 60 * 1000 // 5 минут
|
||||
|
||||
const getCachedPriceResult = (code: string, brand: string): boolean | null => {
|
||||
const key = `${code}_${brand}`
|
||||
const cached = priceCache.get(key)
|
||||
if (cached && (Date.now() - cached.timestamp) < CACHE_TTL) {
|
||||
return cached.hasPrice
|
||||
}
|
||||
return null
|
||||
}
|
||||
|
||||
const cachePriceResult = (code: string, brand: string, hasPrice: boolean): void => {
|
||||
const key = `${code}_${brand}`
|
||||
priceCache.set(key, { hasPrice, timestamp: Date.now() })
|
||||
}
|
||||
|
||||
// Фильтруем товары на сервере - проверяем наличие цен в AutoEuro
|
||||
const filteredEntities: any[] = []
|
||||
const batchSize = 20 // Увеличенный размер батча для скорости
|
||||
|
||||
for (let i = 0; i < entities.list.length; i += batchSize) {
|
||||
const batch = entities.list.slice(i, i + batchSize)
|
||||
|
||||
// Проверяем цены для каждого товара в батче параллельно
|
||||
const priceCheckPromises = batch.map(async (entity) => {
|
||||
try {
|
||||
// Сначала проверяем кэш
|
||||
const cachedResult = getCachedPriceResult(entity.code, entity.brand.name);
|
||||
if (cachedResult !== null) {
|
||||
if (cachedResult) {
|
||||
console.log(`💨 Кэш: товар ${entity.code} (${entity.brand.name}) имеет цену`);
|
||||
return entity;
|
||||
} else {
|
||||
console.log(`💨 Кэш: товар ${entity.code} (${entity.brand.name}) не имеет цены`);
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
const searchResult = await autoEuroService.searchItems({
|
||||
code: entity.code,
|
||||
brand: entity.brand.name,
|
||||
with_crosses: false,
|
||||
with_offers: true
|
||||
})
|
||||
|
||||
// Проверяем есть ли предложения с валидной ценой
|
||||
const hasValidPrice: boolean = Boolean(searchResult.success &&
|
||||
searchResult.data &&
|
||||
searchResult.data.length > 0 &&
|
||||
searchResult.data.some(offer =>
|
||||
offer.price &&
|
||||
parseFloat(offer.price.toString()) > 0
|
||||
))
|
||||
|
||||
// Кэшируем результат
|
||||
cachePriceResult(entity.code, entity.brand.name, hasValidPrice);
|
||||
|
||||
if (hasValidPrice) {
|
||||
console.log(`✅ Товар ${entity.code} (${entity.brand.name}) имеет цену`);
|
||||
return entity;
|
||||
} else {
|
||||
console.log(`❌ Товар ${entity.code} (${entity.brand.name}) не имеет цены`);
|
||||
return null;
|
||||
}
|
||||
} catch (error) {
|
||||
console.error(`❌ Ошибка проверки цены для ${entity.code}:`, error);
|
||||
return null // Исключаем товары с ошибками
|
||||
}
|
||||
})
|
||||
|
||||
// Ждем результаты для текущего батча
|
||||
const batchResults = await Promise.all(priceCheckPromises)
|
||||
|
||||
// Добавляем только товары с ценами
|
||||
filteredEntities.push(...batchResults.filter(entity => entity !== null))
|
||||
|
||||
// Убираем задержку между батчами для максимальной скорости
|
||||
// if (i + batchSize < entities.list.length) {
|
||||
// await new Promise(resolve => setTimeout(resolve, 50))
|
||||
// }
|
||||
}
|
||||
|
||||
console.log(`✅ Серверная фильтрация завершена. Товаров с ценами: ${filteredEntities.length} из ${entities.list.length}`)
|
||||
|
||||
// Возвращаем отфильтрованный результат
|
||||
return {
|
||||
...entities,
|
||||
list: filteredEntities
|
||||
}
|
||||
} catch (error) {
|
||||
console.error('❌ Ошибка в GraphQL resolver partsIndexCatalogEntities:', error)
|
||||
throw new Error('Не удалось получить товары каталога')
|
||||
|
@ -37,7 +37,7 @@ class PartsAPIService {
|
||||
private mediaApiKey: string;
|
||||
|
||||
constructor() {
|
||||
this.baseURL = 'https://api.partsapi.ru';
|
||||
this.baseURL = process.env.PARTSAPI_URL || 'https://api.partsapi.ru';
|
||||
|
||||
// Получаем ключи API из переменных окружения
|
||||
this.categoriesApiKey = process.env.PARTSAPI_CATEGORIES_KEY || '';
|
||||
|
@ -155,7 +155,7 @@ interface CacheEntry<T> {
|
||||
}
|
||||
|
||||
class PartsIndexService {
|
||||
private baseURL = 'https://api.parts-index.com/v1';
|
||||
private baseURL = process.env.PARTSAPI_URL+"/v1" || 'https://api.parts-index.com/v1';
|
||||
private apiKey = 'PI-E1C0ADB7-E4A8-4960-94A0-4D9C0A074DAE';
|
||||
|
||||
// Простой in-memory кэш
|
||||
|
Reference in New Issue
Block a user