52 lines
2.3 KiB
JavaScript
52 lines
2.3 KiB
JavaScript
const jwt = require('jsonwebtoken')
|
|
const UserModel = require('../models/UserModel')
|
|
const { getRedisClient } = require('../utils/redisClient')
|
|
const { markOnline } = require('../utils/presence')
|
|
|
|
// این میدلور روی *هر* درخواستِ احرازهویتشده اجرا میشه (app.use سراسری) — قبلاً
|
|
// یعنی هر درخواست یه findById+save کاملِ Mongo میزد، حتی برای کاربری که پشتِسرِهم
|
|
// صدها درخواست در دقیقه میفرسته. الان: وضعیتِ «آنلاینِ لحظهای» توی Redis با TTLِ
|
|
// کوتاه نگه داشته میشه (هر درخواست رفرش میشه، تقریباً رایگان — utils/presence.js)،
|
|
// و نوشتنِ last_online توی Mongo (برای «آخرین بازدید» که جاهای دیگهی اپ میخونن)
|
|
// throttle میشه به حداکثر یکبار در هر ۶۰ ثانیه برای هر کاربر
|
|
const MONGO_SYNC_TTL_SECONDS = 60
|
|
|
|
async function syncLastOnlineToMongo (userId) {
|
|
const user = await UserModel.findById(userId).select('ghost_mode account_status')
|
|
if (user && !user.ghost_mode && user.account_status !== 'deactivated') {
|
|
await UserModel.updateOne({ _id: userId }, { last_online: new Date() })
|
|
}
|
|
}
|
|
|
|
module.exports = async (req, res, next) => {
|
|
if (req.header && req.header('Authorization')) {
|
|
try {
|
|
const token = req.header('Authorization').split(' ')[1]
|
|
const decodedToken = jwt.verify(token, process.env.APP_SECRET)
|
|
const userId = String(decodedToken.id)
|
|
const redis = getRedisClient()
|
|
|
|
if (redis) {
|
|
await markOnline(userId)
|
|
|
|
const acquiredSyncLock = await redis.set(
|
|
`presence:sync:${userId}`,
|
|
'1',
|
|
{ NX: true, EX: MONGO_SYNC_TTL_SECONDS }
|
|
)
|
|
if (acquiredSyncLock) {
|
|
await syncLastOnlineToMongo(userId)
|
|
}
|
|
} else {
|
|
// Redis در دسترس نیست — همون رفتارِ قبلی، مستقیم Mongo (fallback امن، کندتر
|
|
// ولی درست) تا وقتی Redis دوباره وصل بشه
|
|
await syncLastOnlineToMongo(userId)
|
|
}
|
|
} catch (error) {
|
|
console.error('Error updating last online time:', error)
|
|
}
|
|
}
|
|
|
|
next()
|
|
}
|