import { GOOD_QUALITY, REDIS_RANK_TO_INFO, COM_BTL_QUALITY, GUILD_ACTIVITY_TYPE, GUILD_ACTIVITY_STATUS } from './../consts'; import { RoleModel, RoleType } from "../db/Role"; import * as Redis from 'redis'; import {REDIS_KEY} from '../consts' import { GameModel } from "../db/Game"; import { promisifyAll } from 'bluebird'; import { pinus } from 'pinus'; import { PvpDefenseModel } from '../db/PvpDefense'; import { SystemConfigModel } from '../db/SystemConfig'; import { GuildRankParam, GuildLeader, RankParam } from '../domain/rank'; import { GuildModel } from '../db/Guild'; import { comBtlRanges } from '../pubUtils/gamedata'; import { getNextHourPoint } from '../pubUtils/timeUtil'; import { gameData } from '../pubUtils/data'; /** * 在服务重新启动时,将信息存入redis */ export async function initAllRank() { const client: Redis.RedisClient = redisClient(); const serverList = await GameModel.getAllServerList(); await client.delAsync(REDIS_KEY.ONLINE_USERS); await client.delAsync(REDIS_KEY.USER_INFO); await client.delAsync(REDIS_KEY.GUILD_INFO); await client.delAsync(REDIS_KEY.PVP_RANK); for(let {id} of serverList) { await client.delAsync(getKeyName(REDIS_KEY.TOWER_RANK, id)); await client.delAsync(getKeyName(REDIS_KEY.GUILD_ACTIVE_RANK, id)); await initRank(id); } } /** * 分服内初始redis排行榜 * * @param serverId 服务器 */ export async function initRank(serverId: number) { // console.log('*****', 'initRank') const client: Redis.RedisClient = redisClient(); await setRankRedisFromDb(REDIS_KEY.TOWER_RANK, serverId); await setRankRedisFromDb(REDIS_KEY.GUILD_ACTIVE_RANK, serverId); await client.expireAsync(getKeyName(REDIS_KEY.TOWER_RANK, serverId), 30 * 24 * 60 * 60); await client.expireAsync(REDIS_KEY.PVP_RANK, 30 * 24 * 60 * 60); await client.expireAsync(REDIS_KEY.USER_INFO, 30 * 24 * 60 * 60); await client.expireAsync(REDIS_KEY.GUILD_INFO, 30 * 24 * 60 * 60); await client.expireAsync(getKeyName(REDIS_KEY.GUILD_ACTIVE_RANK, serverId), 30 * 24 * 60 * 60); } /** * 初始化某一个排行榜,如定时器内 * @param key redis内的key */ export async function initSingleRank(key: string) { const serverList = await GameModel.getAllServerList(); for(let {id} of serverList) { await initSingleRankWithServer(key, id); } } /** * 初始化某一服内的某一种排行榜 * @param key redis key */ export async function initSingleRankWithServer(key: string, serverId: number) { await redisClient().delAsync(getKeyName(key, serverId)); await setRankRedisFromDb(key, serverId); await redisClient().expireAsync(key, 30 * 24 * 60 * 60); } /** * 从数据库内获取排行榜存入redis * @param type 排行榜类型 * @param serverId 分服 */ async function setRankRedisFromDb(type: string, serverId: number) { if(type == REDIS_KEY.TOWER_RANK) { let ranks = await RoleModel.getRank('tower', serverId, ['roleId', 'roleName', 'towerLv', 'lv', 'vLv', 'head', 'frame', 'spine','title', 'updatedAt']); for(let {towerLv, roleId, roleName, lv, vLv, towerUpTime, head, frame, spine, title} of ranks) { // console.log(roleId); await redisClient().zaddAsync(getKeyName(REDIS_KEY.TOWER_RANK, serverId), encodeScoreWithTime(towerLv, towerUpTime?towerUpTime.getTime():0), roleId); let rankPram = new RankParam(roleName, lv, vLv, head, frame, spine, title); await redisUserInfoAdd(REDIS_KEY.USER_INFO, roleId, rankPram); } } else if (type == REDIS_KEY.GUILD_ACTIVE_RANK) { let ranks = await GuildModel.getRank(serverId); for(let { code, icon, name, lv, leader, activeWeekly = 0, activeUpdateTime = 0 } of ranks) { let _leader = leader; let { roleName, title, head, frame, spine, lv: leaderLv } = _leader; await redisClient().zaddAsync(getKeyName(REDIS_KEY.GUILD_ACTIVE_RANK, serverId), encodeScoreWithTime(activeWeekly, activeUpdateTime * 1000 ), code); let rankParam = new GuildRankParam(icon, name, lv, { roleName, title, head, frame, spine, lv: leaderLv }); await redisUserInfoAdd(REDIS_KEY.GUILD_INFO, code, rankParam); } } } // 排行榜是否存在 export async function existsRank(key: string, serverId: number) { const result = await redisClient().existsAsync(getKeyName(key, serverId)); return result; } /** * 获得redis key的名字 * @param key REDIS_KEY中配置的key * @param serverId 服务器id * @param plus 后面再加 */ function getKeyName(key: string, serverId?: number, plus: string = '') { let newKey = ''; if(serverId) { newKey = `${key}:${serverId}`; } else { newKey = key; } if(plus) { newKey += `:${plus}`; } return newKey; } // 更新玩家信息 export async function redisUserInfoUpdate(key: string, roleId: string, arr: Array<{field: string, value:(string|number|GuildLeader)}>) { let params = await redisClient().hgetAsync(key, roleId); if(params) { let obj = JSON.parse(params); for(let {field, value} of arr) { obj[field] = value; } return await redisClient().hsetAsync(key, roleId, JSON.stringify(obj)); } } // 添加玩家信息缓存 export async function redisUserInfoAdd(key: string, roleId: string, params: RankParam|GuildRankParam) { let value = JSON.stringify(params); return await redisClient().hsetAsync(key, roleId, value); } /** * 更新排行榜 * @param key 配置在REDIS_KEY中的key * @param serverId 区服id 如pvp这样跨服的,serverId传0 * @param myId 玩家roleId或军团code * @param score 得分 * @param timestamp 时间 13位时间戳 * @param params 玩家数据 * @param isAtom 是否是原子性的更新 * @param limit */ export async function setRank(key: string, serverId: number, myId: string, score: number, timestamp: number, params: RankParam|GuildRankParam, isAtom = false, limit = 100) { // 更新分数 let newScore = score; if(isAtom) { newScore = await updateRankAtom(key, serverId, myId, score, timestamp); } else { const _score = encodeScoreWithTime(score, timestamp); await redisClient().zaddAsync(getKeyName(key, serverId), _score, myId); // 移除100名以外 await redisClient().zremrangebyrankAsync(getKeyName(key, serverId), limit, 10000); } let infoKey = REDIS_RANK_TO_INFO.get(key)||REDIS_KEY.USER_INFO; // 如果没有信息,更新玩家信息 const hasCurUser = await redisClient().hexistsAsync(infoKey, myId); if(!hasCurUser) { await redisUserInfoAdd(infoKey, myId, params); } return parseInt(newScore.toString()); } export async function setRankWithoutUserInfo(key: string, serverId: number, myId: string, score: number, timestamp: number, isAtom = false, isInc = true, limit = 100) { // 更新分数 let newScore = score; if(isAtom) { newScore = await updateRankAtom(key, serverId, myId, score, timestamp, isInc); } else { const _score = encodeScoreWithTime(score, timestamp); await redisClient().zaddAsync(getKeyName(key, serverId), _score, myId); // 移除100名以外 await redisClient().zremrangebyrankAsync(getKeyName(key, serverId), limit, 10000); } return parseInt(newScore.toString()); } // 获取排行榜 export async function getRank(key: string, serverId: number, roleId: string, limit = 100) { let ranks = [], myRank = null; const rankFromDb = await redisClient().zrevrangebyscoreAsync(getKeyName(key, serverId), '+inf', '-inf', "WITHSCORES", "LIMIT", 0, limit); let _key = key.split(':')[0]; let infoKey = REDIS_RANK_TO_INFO.get(_key)||REDIS_KEY.USER_INFO; for(let ii = 0; ii < rankFromDb.length; ii+=2) { const _roleId = rankFromDb[ii]; const _score = decodeScoreWithTime(rankFromDb[ii + 1]); const info = await redisClient().hgetAsync(infoKey, _roleId); const _userInfo = JSON.parse(info); const tmp = {..._userInfo, num: _score, rank: Math.floor(ii/2)+1}; if(infoKey == REDIS_KEY.USER_INFO) { tmp["roleId"] = _roleId; } else if(infoKey == REDIS_KEY.GUILD_INFO) { tmp["code"] = _roleId; } ranks.push(tmp); if(roleId == _roleId) myRank = tmp; } return {ranks, myRank} } // 获取我的排名 export async function getMyRank(key: string, serverId: number, roleId: string) { let myRank = await redisClient().zrevrankAsync(getKeyName(key, serverId), roleId); return myRank + 1; } // 获取排名第几名的信息 export async function getFieldByRank(key: string, serverId: number, rank: number) { let myRank = await redisClient().zrevrangeAsync(getKeyName(key, serverId), rank - 1, rank - 1); return myRank; } // 有序排行综合时间和得分排序 function encodeScoreWithTime(score: number, timestamp: number): number { // value = score * Math.power(10, 14) + max_time - timestamp let timelen = 10; let pow = Math.pow(10, timelen + 1); return score * pow + pow - 1 - Math.floor(timestamp/1000) } function decodeScoreWithTime(num: string): number { let timelen = 10; let pow = Math.pow(10, timelen + 1); let _num = parseInt(num); return Math.floor(_num/pow); } // 从排行榜中移除 export async function removeFromRank(key: string, serverId: number, myId: string) { await redisClient().zremAsync(getKeyName(key, serverId), myId); return true; } /**************** 寻宝相关 start */ /** * @description 拼接匹配分组的 key * @param {number} quality 品质 * @param {number} lvRange 等级范围 */ function getComTeamKey(quality: number, lvRange: number) { return `${REDIS_KEY.COM_TEAM_SEARCH_PRE}:${quality}_${lvRange}`; } /** * @description 拼接匹配分组中 member 的值 * @param {string} roleId * @param {string} sid connector serverId * @returns */ function getComTeamValue(roleId: string, sid: string) { return `${roleId}:${sid}`; } /** * @description 把寻宝的玩家信息存入 redis * @export * @param {string} roleId * @param {string} sid * @param {Array} qualityArr * @param {number} lvRange * @returns */ export async function setTeamSearchReq(roleId: string, sid: string, qualityArr: Array, lvRange: number) { let cmds = []; qualityArr.forEach(quality => { if (quality) { cmds.push(['sadd', getComTeamKey(quality, lvRange), getComTeamValue(roleId, sid)]); } }); const multiClient = redisClient().multi(cmds) as Redis.Multi; const newMulti = promisifyAll(multiClient) as Redis.Multi; const res = await newMulti.execAsync(); console.log('setTeamSearchReq: ', res); return res; } /** * @description 从匹配队列中删除某个用户 * @export * @param {string} roleId * @param {string} sid * @param {Array} qualityArr * @param {number} lvRange */ export async function rmRoleFromQueue(roleId: string, sid: string, qualityArr: Array, lvRange: number) { let cmds = []; for (let q of qualityArr) { if (lvRange) { cmds.push(['srem', getComTeamKey(q, lvRange), getComTeamValue(roleId, sid)]); } else { for (let range of comBtlRanges()) { cmds.push(['srem', getComTeamKey(q, range), getComTeamValue(roleId, sid)]); } } }; const multiClient = redisClient().multi(cmds) as Redis.Multi; const newMulti = promisifyAll(multiClient) as Redis.Multi; await newMulti.execAsync(); } /** * @description 在寻宝匹配队列中随机两个玩家 * @export * @param {number} quality 队伍品质 * @param {number} lvRange 等级范围 * @returns */ export async function getTeamSearchByQuality(quality: number, lvRange: number) { // TODO: 操作不具有原子性 const userInfos = await redisClient().srandmemberAsync(getComTeamKey(quality, lvRange), 2); console.log('getTeamSearchByQuality: ' + userInfos); if (!userInfos || !userInfos.length) return null; let res = []; for (let userInfo of userInfos) { const decodeData = `${userInfo}`.split(':'); if (decodeData.length !== 2) return null; res.push({roleId: decodeData[0], sid: decodeData[1]}); } console.log('getTeamSearchByQuality res: ', res); return res; } /** * @description 检查玩家是否在某个队列中等待寻宝匹配 * @export * @param {string} roleId * @param {string} sid * @param {Array} qualityArr * @param {number} lvRange * @returns */ export async function checkRoleInQueue(roleId: string, sid: string, qualityArr: Array, lvRange: number) { for (let quality of qualityArr) { let res = await redisClient().sismemberAsync(getComTeamKey(quality, lvRange), `${roleId}:${sid}`); if (res) { return true; } }; return false; } /** * @description 清除所有的寻宝匹配队列 * @export */ export async function clearComBtlQueue() { for (let q of COM_BTL_QUALITY) { for (let lvRange of comBtlRanges()) { await redisClient().delAsync(getComTeamKey(q, lvRange)); } } } export function setRedis(key: string, data: string) { redisClient().setAsync(key, data); } export async function getRedis(key: string) { const str = await redisClient().getAsync(key); return str; } export async function delRedis(key: string) { await redisClient().delAsync(key); } export function redisSidKey(roleId: string) { return `login_roleId_${roleId}`; } export async function redisChannelServer(roomId: string) { const sid = await redisClient().hgetAsync(REDIS_KEY.CHANNEL_SERVERS, roomId); return sid; } export async function addRedisChannel(roomId: string, sid: string) { const result = await redisClient().hsetAsync(REDIS_KEY.CHANNEL_SERVERS, roomId, sid); return result; } export async function clearChannelServers() { const result = await redisClient().delAsync(REDIS_KEY.CHANNEL_SERVERS); return result; } /** * 玩家上线 * @param roleId role表id * @param userCode user表唯一字符串标识 * @param sid connector服的那个sid */ export async function roleLogin(roleId: string, userCode: string, sid: string, pkgName: string) { let param = { userCode, sid, pkgName }; return await redisClient().hsetAsync(REDIS_KEY.ONLINE_USERS, roleId, JSON.stringify(param)); } /** * 玩家下线 * @param roleId role表id */ export async function roleLeave(roleId: string) { let role = await getRoleOnlineInfo(roleId); await redisClient().hdelAsync(REDIS_KEY.ONLINE_USERS, roleId); return role; } /** * 判断玩家是否在线 * @param roleId role表id */ export async function isRoleOnline(roleId: string) { let result = await redisClient().hexistsAsync(REDIS_KEY.ONLINE_USERS, roleId); return !!result; } /** * 获得在线玩家userCode和sid * @param roleId */ export async function getRoleOnlineInfo(roleId: string) { let str = await redisClient().hgetAsync(REDIS_KEY.ONLINE_USERS, roleId); if(str) { try { let result = JSON.parse(str); return { isOnline: true, userCode: result.userCode, sid: result.sid, pkgName: result.pkgName } } catch(e) { return { isOnline: false } } } else { return { isOnline: false } } } /** * 获得所有在线的玩家 */ export async function getAllOnlineRoles() { const client: Redis.RedisClient = pinus.app.get('redis'); let allRoles = await redisClient().hgetallAsync(REDIS_KEY.ONLINE_USERS); let result = new Array<{roleId: string, userCode: string, sid: string, pkgName: string}>(); for(let roleId in allRoles) { try{ let param = JSON.parse(allRoles[roleId]); if(param) { result.push({ roleId, userCode: param.userCode, sid: param.sid, pkgName: param.pkgName }); } } catch(e) { continue; } } return result; } export async function resetPvpRanks() { await redisClient().delAsync(REDIS_KEY.PVP_RANK); let { seasonNum } = await SystemConfigModel.findSystemConfig(); console.log('execute season resetPvpRanks seasonNum = ' + seasonNum); let pvpRank = await PvpDefenseModel.getRank(seasonNum);//获得全服前1000名的排名,加入到redis中 for(let {roleId, role: _role, score, updatedAt } of pvpRank) { let role = _role; if (!role) { continue; } let { roleName, head, frame, spine, title, lv, vLv } = role; await redisClient().zaddAsync(getKeyName(REDIS_KEY.PVP_RANK), encodeScoreWithTime(score, updatedAt?updatedAt.getTime():0), roleId); const hasCurUser = await redisClient().hexistsAsync(REDIS_KEY.USER_INFO, roleId); if(!hasCurUser) { let rankPram = new RankParam(roleName, lv, vLv, head, frame, spine, title); await redisUserInfoAdd(REDIS_KEY.USER_INFO, roleId, rankPram); } } } // 排行榜是否存在 export async function smembersAsync(key: string) { const result = await redisClient().smembersAsync(key); return result; } export async function saddAsync(key: string, values: Array) { const result = await redisClient().saddAsync(key, values); return result; } export async function sismemberAsync(key: string, value: string) { const result = await redisClient().sismemberAsync(key, value); return result; } export async function delAsync(key:string) { await redisClient().delAsync(key); } export async function sremAsync(key:string, member:string) { await redisClient().sremAsync(key, member); } /**************** 寻宝相关 end */ /**************** 数据库表存入缓存 */ export async function readDataBase() { await setServerList(); } async function setServerList() { const serverList = await GameModel.getAllServerList(); await redisClient().delAsync(REDIS_KEY.DB_GAME); for(let { id, serverType, name } of serverList) { // console.log(roleId); await redisClient().hsetAsync(REDIS_KEY.DB_GAME, `${serverType}_${id}`, name); } } export async function getAllServers() { let servers = await redisClient().hgetallAsync(REDIS_KEY.DB_GAME); let serverlist = new Array(); for(let serverStr in servers) { let arr = serverStr.split('_'); let serverId = parseInt(arr[1]); if(!isNaN(serverId) && !serverlist.includes(serverId)) { serverlist.push(serverId); } } return serverlist; } export async function getServerName(serverType: string, serverId: number) { let name = await redisClient().hgetAsync(REDIS_KEY.DB_GAME, `${serverType}_${serverId}`); return name } function redisClient() { const client: Redis.RedisClient = pinus.app.get('redis'); return client; } /**************** 数据库表end */ /**************** 军团活动排行 */ /** * 更新排行榜(将得分和时间拆分开) * @param key 配置在REDIS_KEY中的key * @param serverId 区服id * @param field 玩家id/军团id * @param score 得分 * @param time 事件 */ async function updateRankAtom(key: string, serverId: number, field: string, score: number, timestamp: number, isInc = true) { let originKey = getKeyName(key, serverId); let timeKey = getKeyName(key, serverId, 'time'); let timelen = 10; let pow = Math.pow(10, timelen + 1); let newScore = 0; if(isInc) { newScore = await redisClient().zincrbyAsync(originKey, score, field); } else { newScore = await redisClient().zaddAsync(originKey, score, field); } await redisClient().zaddAsync(timeKey, pow - 1 - Math.floor(timestamp/1000), field); await redisClient().expireatAsync(originKey, getNextHourPoint(5)); await redisClient().expireatAsync(timeKey, getNextHourPoint(5)); return newScore; } async function generateUnionRank(key: string, serverId: number, timelen = 10) { let unionKey = getKeyName(key, serverId, 'union'); // 联合的key let existsKey = await redisClient().existsAsync(unionKey); if(!existsKey) { let originKey = getKeyName(key, serverId); let timeKey = getKeyName(key, serverId, 'time'); let pow = Math.pow(10, timelen + 1); await redisClient().zunionstoreAsync(unionKey, 2, originKey, timeKey, 'WEIGHTS', pow, 1); if(originKey.indexOf(REDIS_KEY.RACE_ACTIVITY) == -1) { await redisClient().expireAsync(unionKey, 10); // 10秒更新一次 } else { await redisClient().expireAsync(unionKey, 1); // 1秒更新一次 } } return unionKey; } /** * 使用updateRankAtom更新的排行榜,使用这个方法获取列表 * @param key 配置在REDIS_KEY中的key * @param serverId 区服id * @param roleId 自己的id */ export async function getUnionRank(key: string, serverId: number, roleId: string, timelen = 10, limit = 100) { let ranks = [], myRank = null; let unionKey = await generateUnionRank(key, serverId, timelen); const rankFromDb = await redisClient().zrevrangebyscoreAsync(unionKey, '+inf', '-inf', "WITHSCORES", "LIMIT", 0, limit); let _key = key.split(':')[0]; console.log(_key) let infoKey = REDIS_RANK_TO_INFO.get(_key)||REDIS_KEY.USER_INFO; for(let ii = 0; ii < rankFromDb.length; ii+=2) { const _roleId = rankFromDb[ii]; const _score = decodeScoreWithTime(rankFromDb[ii + 1]); const info = await redisClient().hgetAsync(infoKey, _roleId); const _userInfo = JSON.parse(info); const tmp = {..._userInfo, num: _score, rank: Math.floor(ii/2)+1}; if(infoKey == REDIS_KEY.USER_INFO) { tmp["roleId"] = _roleId; } else if(infoKey == REDIS_KEY.GUILD_INFO) { tmp["code"] = _roleId; } ranks.push(tmp); if(roleId == _roleId) myRank = tmp; } return {ranks, myRank} } /** * 获取(分两个zset的)排行的一段排名内的数据 * @param key 配置在REDIS_KEY中的key * @param serverId 区服id * @param startRank 开始排名 * @param endRank 结束排名 */ export async function getUnionRankRange(key: string, serverId: number, startRank: number, endRank: number) { let ranks = []; let unionKey = await generateUnionRank(key, serverId); const rankFromDb = await redisClient().zrevrangeAsync(unionKey, startRank - 1, endRank - 1, "WITHSCORES"); let _key = key.split(':')[0]; let infoKey = REDIS_RANK_TO_INFO.get(_key)||REDIS_KEY.USER_INFO; for(let ii = 0; ii < rankFromDb.length; ii+=2) { const _roleId = rankFromDb[ii]; const _score = decodeScoreWithTime(rankFromDb[ii + 1]); const info = await redisClient().hgetAsync(infoKey, _roleId); const _userInfo = JSON.parse(info); const tmp = {..._userInfo, num: _score, rank: Math.floor(ii/2)+1}; if(infoKey == REDIS_KEY.USER_INFO) { tmp["roleId"] = _roleId; } else if(infoKey == REDIS_KEY.GUILD_INFO) { tmp["code"] = _roleId; } ranks.push(tmp); } return ranks } // 获取我的排名 export async function getMyUnionRank(key: string, serverId: number, roleId: string) { let unionKey = await generateUnionRank(key, serverId); let myRank = await redisClient().zrevrankAsync(unionKey, roleId); return myRank + 1; } /** * 获取拼接得分的排行榜的某一个人的得分 * @param key REDIS_KEY中配置的 * @param serverId 分服 * @param field 查询的人 */ export async function getRankScore(key: string, serverId: number, field: string, needDecode = false) { let score = await redisClient().zscoreAsync(getKeyName(key, serverId), field); if(!score) score = 0; if(needDecode) { score = decodeScoreWithTime(score.toString()); } return parseInt(score.toString()); } export async function setUserGuildActivityRank(key: string, guildCode: string, serverId: number, roleId: string, score: number, time: number, userParam: RankParam) { let nkey = getGuildKeyName(key, guildCode); let oldScore = await getRankScore(nkey, serverId, roleId, true); let nScore = await setRank(nkey, serverId, roleId, oldScore + score, time, userParam); await redisClient().expireatAsync(getKeyName(nkey, serverId), getNextHourPoint(5)) return nScore } /** * 按军团名拼接key * @param key * @param guildCode 军团编号 */ export function getGuildKeyName(key: string, guildCode: string) { return `${key}:${guildCode}`; } export function getCityKeyName(key: string, cityId: number) { return `${key}:${cityId}`; } /** * debug接口使用,直接删除排行榜数据 * @param params serverId => guildCodes */ export async function delGuildActivityRank(aid: number, params: Map) { if(aid == GUILD_ACTIVITY_TYPE.GATE_ACTIVITY) { for(let [serverId, guildCodes] of params) { await redisClient().delAsync(getKeyName(REDIS_KEY.GATE_ACTIVITY, serverId)); await redisClient().delAsync(getKeyName(REDIS_KEY.GATE_ACTIVITY, serverId, 'time')); await redisClient().delAsync(getKeyName(REDIS_KEY.GATE_ACTIVITY, serverId, 'union')); for(let guildCode of guildCodes) { await redisClient().delAsync(getKeyName(getGuildKeyName(REDIS_KEY.USER_GATE_ACTIVITY, guildCode), serverId)); } } } else if (aid == GUILD_ACTIVITY_TYPE.CITY_ACTIVITY) { let dicCity = gameData.cityActivity; for(let [cityId] of dicCity) { for(let [serverId, guildCodes] of params) { await redisClient().delAsync(getKeyName(getCityKeyName(REDIS_KEY.CITY_ACTIVITY, cityId) , serverId)); await redisClient().delAsync(getKeyName(getCityKeyName(REDIS_KEY.CITY_ACTIVITY, cityId), serverId, 'time')); await redisClient().delAsync(getKeyName(getCityKeyName(REDIS_KEY.CITY_ACTIVITY, cityId), serverId, 'union')); for(let guildCode of guildCodes) { await redisClient().delAsync(getKeyName(getGuildKeyName(REDIS_KEY.USER_CITY_ACTIVITY, guildCode), serverId)); } } } } else if (aid == GUILD_ACTIVITY_TYPE.RACE_ACTIVITY) { for(let [serverId] of params) { await redisClient().delAsync(getKeyName(REDIS_KEY.RACE_ACTIVITY, serverId)); await redisClient().delAsync(getKeyName(REDIS_KEY.RACE_ACTIVITY, serverId, 'time')); await redisClient().delAsync(getKeyName(REDIS_KEY.RACE_ACTIVITY, serverId, 'union')); } } } /**************** 军团活动排行end */