157 lines
4.9 KiB
JavaScript
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,
|
|
}
|