HotTRDealsBackend/services/vote.service.js
2026-02-09 21:47:55 +00:00

133 lines
4.1 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 { updateDealVoteInRedis } = require("./redis/dealVote.service");
const { queueVoteUpdate, queueDealUpdate, queueNotificationCreate } = require("./redis/dbSync.service");
const { updateDealInRedis, getDealFromRedis } = require("./redis/dealCache.service");
const { publishNotification } = require("./redis/notificationPubsub.service");
const { trackUserCategoryInterest, USER_INTEREST_ACTIONS } = require("./userInterest.service");
const voteDb = require("../db/vote.db")
async function voteDeal({ dealId, userId, voteType }) {
if (!dealId || !userId || voteType === undefined) {
const err = new Error("Eksik veri");
err.statusCode = 400;
throw err;
}
if (![ -1, 0, 1 ].includes(voteType)) {
const err = new Error("voteType -1, 0 veya 1 olmalı");
err.statusCode = 400;
throw err;
}
const deal = await getDealFromRedis(Number(dealId));
if (!deal || !["ACTIVE", "EXPIRED"].includes(deal.status)) {
const err = new Error("deal sadece ACTIVE veya EXPIRED iken oylanabilir");
err.statusCode = 400;
throw err;
}
const createdAt = new Date();
const redisResult = await updateDealVoteInRedis({
dealId,
userId,
voteType,
}).catch((err) => {
console.error("Redis vote update failed:", err?.message || err);
return { updated: false, delta: 0, score: null, maxNotifiedMilestone: 0, dealUserId: null };
});
queueVoteUpdate({
dealId,
userId,
voteType,
createdAt: createdAt.toISOString(),
}).catch((err) => console.error("DB sync vote queue failed:", err?.message || err));
const scoreVal = Number(redisResult?.score)
const maxNotified = Number(redisResult?.maxNotifiedMilestone ?? 0)
const ownerId = Number(redisResult?.dealUserId)
if (Number.isFinite(scoreVal) && Number.isInteger(ownerId) && ownerId > 0) {
const milestone = 100
if (scoreVal >= milestone && maxNotified < milestone) {
const updatedAt = new Date()
await updateDealInRedis(dealId, { maxNotifiedMilestone: milestone }, { updatedAt }).catch((err) =>
console.error("Redis deal milestone update failed:", err?.message || err)
)
queueDealUpdate({
dealId,
data: { maxNotifiedMilestone: milestone },
updatedAt: updatedAt.toISOString(),
}).catch((err) => console.error("DB sync deal milestone update failed:", err?.message || err))
queueNotificationCreate({
userId: ownerId,
message: "Fırsatın 100 beğeniyi geçti!",
type: "MILESTONE",
extras: {
dealId: Number(dealId),
milestone,
},
createdAt: updatedAt.toISOString(),
}).catch((err) => console.error("DB sync notification queue failed:", err?.message || err))
publishNotification({
userId: ownerId,
message: "Fırsatın 100 beğeniyi geçti!",
type: "MILESTONE",
extras: {
dealId: Number(dealId),
milestone,
},
createdAt: updatedAt.toISOString(),
}).catch((err) => console.error("Notification publish failed:", err?.message || err))
}
}
// Fallback: Redis yoksa mevcut DB'den approx hesapla
let delta = redisResult?.delta ?? 0;
let score = redisResult?.score ?? null;
if (score === null) {
const current = await getDealFromRedis(Number(dealId));
score = current ? Number(current?.score ?? 0) : null;
delta = 0;
}
if (Number(voteType) === 1) {
trackUserCategoryInterest({
userId,
categoryId: deal.categoryId,
action: USER_INTEREST_ACTIONS.DEAL_HOT_VOTE,
}).catch((err) => console.error("User interest track failed:", err?.message || err))
}
return {
dealId,
voteType,
delta,
score,
};
}
async function getVotes(dealId) {
const votes = await voteDb.findVotes(
{ dealId },
{
select: {
id: true,
dealId: true,
userId: true,
voteType: true,
createdAt: true,
lastVotedAt: true,
},
orderBy: { createdAt: "desc" },
}
)
return votes.map((vote) => ({
...vote,
createdAt: vote.createdAt.toISOString(),
lastVotedAt: vote.lastVotedAt.toISOString(),
}))
}
module.exports = { voteDeal, getVotes };