HotTRDealsBackend/services/redis/userCache.service.js
2026-02-04 06:39:10 +00:00

157 lines
4.9 KiB
JavaScript

const { getRedisClient } = require("./client")
const USER_KEY_PREFIX = "data:users:"
const USER_SAVED_SET_PREFIX = "data:users:saved:"
const USER_UNSAVED_SET_PREFIX = "data:users:unsaved:"
const DEFAULT_USER_TTL_SECONDS = 60 * 60
function createRedisClient() {
return getRedisClient()
}
function normalizeUserId(userId) {
const id = Number(userId)
return Number.isInteger(id) && id > 0 ? id : null
}
async function ensureUserCache(userId, { ttlSeconds = DEFAULT_USER_TTL_SECONDS } = {}) {
const id = normalizeUserId(userId)
if (!id) return false
const redis = createRedisClient()
const key = `${USER_KEY_PREFIX}${id}`
try {
const exists = await redis.exists(key)
if (!exists) {
await redis.call(
"JSON.SET",
key,
"$",
JSON.stringify({ id, savedDeals: [] })
)
}
if (ttlSeconds) {
await redis.expire(key, Number(ttlSeconds))
}
return true
} finally {}
}
async function getUserSavedIdsFromRedis(userId) {
const id = normalizeUserId(userId)
if (!id) return []
const redis = createRedisClient()
const key = `${USER_KEY_PREFIX}${id}`
const setKey = `${USER_SAVED_SET_PREFIX}${id}`
const unsavedKey = `${USER_UNSAVED_SET_PREFIX}${id}`
try {
const [raw, setIds, unsavedIds] = await Promise.all([
redis.call("JSON.GET", key, "$.savedDeals"),
redis.smembers(setKey),
redis.smembers(unsavedKey),
])
const fromJson = raw ? JSON.parse(raw) : []
const arr = Array.isArray(fromJson) ? (Array.isArray(fromJson[0]) ? fromJson[0] : fromJson) : []
const jsonIds = arr
.map((v) => Number(v))
.filter((v) => Number.isInteger(v) && v > 0)
const setList = (Array.isArray(setIds) ? setIds : [])
.map((v) => Number(v))
.filter((v) => Number.isInteger(v) && v > 0)
const unsavedList = (Array.isArray(unsavedIds) ? unsavedIds : [])
.map((v) => Number(v))
.filter((v) => Number.isInteger(v) && v > 0)
return {
jsonIds,
savedSet: new Set(setList),
unsavedSet: new Set(unsavedList),
}
} finally {}
}
async function setUserSavedDeals(userId, ids = [], { ttlSeconds = DEFAULT_USER_TTL_SECONDS } = {}) {
const uid = normalizeUserId(userId)
if (!uid) return false
const redis = createRedisClient()
const key = `${USER_KEY_PREFIX}${uid}`
try {
const list = Array.isArray(ids) ? ids : []
await redis.call("JSON.SET", key, "$.savedDeals", JSON.stringify(list))
if (ttlSeconds) {
await redis.expire(key, Number(ttlSeconds))
}
return true
} finally {}
}
async function addUserSavedDeal(userId, dealId, { ttlSeconds = DEFAULT_USER_TTL_SECONDS } = {}) {
const uid = normalizeUserId(userId)
const did = normalizeUserId(dealId)
if (!uid || !did) return false
const redis = createRedisClient()
const key = `${USER_KEY_PREFIX}${uid}`
const setKey = `${USER_SAVED_SET_PREFIX}${uid}`
const unsavedKey = `${USER_UNSAVED_SET_PREFIX}${uid}`
try {
await ensureUserCache(uid, { ttlSeconds })
const raw = await redis.call("JSON.GET", key, "$.savedDeals")
let list = []
if (raw) {
const parsed = JSON.parse(raw)
const arr = Array.isArray(parsed) ? parsed[0] : []
list = Array.isArray(arr) ? arr : []
}
const exists = Array.isArray(list)
? list.some((v) => Number(v) === did)
: false
if (!exists) {
list = [did, ...list]
await redis.call("JSON.SET", key, "$.savedDeals", JSON.stringify(list))
}
await redis.sadd(setKey, String(did))
await redis.srem(unsavedKey, String(did))
if (ttlSeconds) {
await redis.expire(setKey, Number(ttlSeconds))
await redis.expire(unsavedKey, Number(ttlSeconds))
await redis.expire(key, Number(ttlSeconds))
}
return true
} finally {}
}
async function removeUserSavedDeal(userId, dealId, { ttlSeconds = DEFAULT_USER_TTL_SECONDS } = {}) {
const uid = normalizeUserId(userId)
const did = normalizeUserId(dealId)
if (!uid || !did) return false
const redis = createRedisClient()
const key = `${USER_KEY_PREFIX}${uid}`
const setKey = `${USER_SAVED_SET_PREFIX}${uid}`
const unsavedKey = `${USER_UNSAVED_SET_PREFIX}${uid}`
try {
const raw = await redis.call("JSON.GET", key, "$.savedDeals")
if (raw) {
const parsed = JSON.parse(raw)
const arr = Array.isArray(parsed) ? parsed[0] : []
const list = Array.isArray(arr)
? arr.filter((v) => Number(v) !== did)
: []
await redis.call("JSON.SET", key, "$.savedDeals", JSON.stringify(list))
}
await redis.srem(setKey, String(did))
await redis.sadd(unsavedKey, String(did))
if (ttlSeconds) {
await redis.expire(setKey, Number(ttlSeconds))
await redis.expire(unsavedKey, Number(ttlSeconds))
await redis.expire(key, Number(ttlSeconds))
}
return true
} finally {}
}
module.exports = {
ensureUserCache,
getUserSavedIdsFromRedis,
setUserSavedDeals,
addUserSavedDeal,
removeUserSavedDeal,
}