HotTRDealsBackend/workers/hotDealList.worker.js
2026-02-07 22:42:02 +00:00

138 lines
4.3 KiB
JavaScript
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

const { Worker } = require("bullmq")
const Redis = require("ioredis")
const { getRedisConnectionOptions } = require("../services/redis/connection")
const HOT_DEAL_TTL_SECONDS = 12 * 60 * 60
const HOT_DEAL_LIMIT = 1000
const HOT_DEAL_WINDOW_DAYS = 3
const HOT_DAY_WINDOW_DAYS = 1
const HOT_WEEK_WINDOW_DAYS = 7
const HOT_MONTH_WINDOW_DAYS = 30
function createRedisClient() {
return new Redis(getRedisConnectionOptions())
}
function parseSearchResults(results = []) {
const ids = [];
// i=1'den başlıyoruz (results[0] toplam sayıdır), ikişer ikişer atlıyoruz
for (let i = 1; i < results.length; i += 2) {
const key = results[i]; // Örn: "deals:cache:20"
const value = results[i + 1]; // Örn: ["$", "[{\"id\":20,...}]"]
try {
// Dialect 3 formatında JSON her zaman bir array string'i olarak gelir: [0] = "$", [1] = "[{...}]"
// JSON.parse(value[1])[0] diyerek direkt objeye ulaşıyoruz.
const [deal] = JSON.parse(value[1]);
ids.push(Number(deal.id));
} catch {
// Eğer JSON'da bir sorun olursa, ID'yi key'den (deals:cache:20) güvenli bir şekilde çek
const idFromKey = key.split(":")[2];
if (idFromKey) ids.push(Number(idFromKey));
}
}
return ids;
}
async function buildHotDealListForRange({ windowDays, listKey, latestKey }) {
const redis = createRedisClient()
try {
const now = Date.now()
const windowMs = Math.floor(Number(windowDays) * 24 * 60 * 60 * 1000)
const cutoffMs = now - windowMs
console.log(`[hot-list] now=${new Date(now).toISOString()} cutoff=${new Date(cutoffMs).toISOString()}`)
/**
* SORGUNUN ANALİZİ:
* 1. @status:{ACTIVE} -> Veritabanında 'ACTIVE' (BÜYÜK HARF) olduğundan emin ol.
* 2. @createdAtTs:[${cutoffMs} +inf] -> Sayısal aralık.
*/
const query = `@status:{ACTIVE} @createdAtTs:[${cutoffMs} +inf]`
console.log(`🔍 Redis Query: FT.SEARCH idx:deals "${query}" SORTBY score DESC DIALECT 3`)
const results = await redis.call(
"FT.SEARCH",
"idx:deals",
query,
"SORTBY", "score", "DESC",
"LIMIT", "0", String(HOT_DEAL_LIMIT),
"DIALECT", "3",
"RETURN", "1", "$"
)
// Redis kaç tane döküman buldu?
const totalFound = results[0] || 0
console.log(`📊 Redis Toplam Bulunan: ${totalFound}`)
const dealIds = parseSearchResults(results)
const runId = String(now)
const payload = {
id: runId,
createdAt: new Date(now).toISOString(),
total: dealIds.length,
dealIds,
}
const key = `${listKey}:${runId}`
await redis.call("JSON.SET", key, "$", JSON.stringify(payload))
await redis.expire(key, HOT_DEAL_TTL_SECONDS)
await redis.set(latestKey, runId, "EX", HOT_DEAL_TTL_SECONDS)
return { id: runId, total: dealIds.length }
} catch (error) {
console.error("❌ buildHotDealList Hatası:", error.message)
throw error
} finally {
redis.disconnect()
}
}
async function handler() {
const results = {}
results.hot = await buildHotDealListForRange({
windowDays: HOT_DEAL_WINDOW_DAYS,
listKey: "deals:lists:hot",
latestKey: "deals:lists:hot:latest",
})
results.hotDay = await buildHotDealListForRange({
windowDays: HOT_DAY_WINDOW_DAYS,
listKey: "deals:lists:hot_day",
latestKey: "deals:lists:hot_day:latest",
})
results.hotWeek = await buildHotDealListForRange({
windowDays: HOT_WEEK_WINDOW_DAYS,
listKey: "deals:lists:hot_week",
latestKey: "deals:lists:hot_week:latest",
})
results.hotMonth = await buildHotDealListForRange({
windowDays: HOT_MONTH_WINDOW_DAYS,
listKey: "deals:lists:hot_month",
latestKey: "deals:lists:hot_month:latest",
})
return results
}
function startHotDealListWorker() {
const worker = new Worker("hotdeal-list", handler, {
connection: getRedisConnectionOptions(),
concurrency: 1,
})
worker.on("completed", (job) => {
console.log(
`✅ Hot lists done. hot=${job.returnvalue?.hot?.total ?? 0} day=${job.returnvalue?.hotDay?.total ?? 0} week=${job.returnvalue?.hotWeek?.total ?? 0} month=${job.returnvalue?.hotMonth?.total ?? 0}`
)
})
worker.on("failed", (job, err) => {
console.error(`❌ Hot Deal Worker Hatası!`, err.message)
})
return worker
}
module.exports = { startHotDealListWorker }