egg-jianghu
Version:
egg-jianghu
90 lines (82 loc) • 3.14 kB
JavaScript
;
// 定时同步 userSession 中的 socketStatus 字段
const { duoxingSocketStatusEnum, tableEnum } = require('../constant/constant');
const dayjs = require('dayjs');
module.exports = app => {
return {
schedule: {
// immediate: true, // 应用启动后触发 // 刚起来时不需要做处理,因为连接都没过来
interval:
app.config.jiangHuConfig.syncSocketStatusRefreshInterval || "60s", // 推荐设置大于 socket 超时时间,否则可能导致状态不正确
type: "worker", // worker: 只有一个worker执行
disable: !app.config.jiangHuConfig.enableSyncSocketStatus,
},
async task(ctx) {
const startTime = new Date();
const { app } = ctx;
const { knex, logger } = app;
if (app.config.env !== "prod") {
return;
}
// 获取所有 socket
const allSockets = await ctx.app.socketIO.fetchSockets();
if (!allSockets || allSockets.length <= 0) {
return;
}
const onlineSocketIds = [];
const deviceIds = [];
allSockets.forEach((socket) => {
const socketId = socket.id;
if (!socketId.includes("::")) {
return;
}
const parts = socketId.split("::");
deviceIds.push(parts[0]);
onlineSocketIds.push(socketId);
});
logger.info("[syncSocketStatus.js] 获取所有在线 socketIds", {
onlineSocketIds,
length: onlineSocketIds.length,
useTime: `${new Date().getTime() - startTime.getTime()}/ms`,
});
// 获取对应的 user session
let userSessions = await knex(tableEnum._user_session)
.whereIn("deviceId", deviceIds)
.select();
// 获取数据库中在线的 user session
const onlineUserSessions = await knex(tableEnum._user_session)
.where("socketStatus", duoxingSocketStatusEnum.online)
.select();
userSessions = [...userSessions, ...onlineUserSessions];
// 判断并更新 user session 的 socketStatus
for (const userSession of userSessions) {
const realStatus = onlineSocketIds.includes(
`${userSession.deviceId}::${userSession.userId}`
)
? duoxingSocketStatusEnum.online
: duoxingSocketStatusEnum.offline;
if (userSession.socketStatus !== realStatus) {
logger.info(
"[syncSocketStatus.js] user session 在线状态异常,修复状态",
{
deviceId: userSession.deviceId,
userId: userSession.userId,
socketStatus: userSession.socketStatus,
realStatus,
}
);
const updateRes = await knex(tableEnum._user_session)
.andWhere("id", "=", userSession.id)
.update("socketStatus", realStatus);
if (updateRes) {
// TODO 同时通知他的好友「上下线消息」
}
console.log(updateRes);
}
}
logger.info("[syncSocketStatus.js] 任务执行结束", {
useTime: `${new Date().getTime() - startTime.getTime()}/ms`,
});
},
};
};