redis 排行榜分区
This commit is contained in:
@@ -55,7 +55,7 @@ mongoose.connect(mongoAddr, { useNewUrlParser: true, useUnifiedTopology: true },
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
redisService.initRank();
|
redisService.initAllRank();
|
||||||
/**
|
/**
|
||||||
* Init app for client.
|
* Init app for client.
|
||||||
*/
|
*/
|
||||||
|
|||||||
@@ -155,6 +155,7 @@ export class NormalBattleHandler {
|
|||||||
let roleId = session.get('roleId');
|
let roleId = session.get('roleId');
|
||||||
let roleName = session.get('roleName');
|
let roleName = session.get('roleName');
|
||||||
let sid = session.get('sid');
|
let sid = session.get('sid');
|
||||||
|
let serverId = session.get('serverId');
|
||||||
let warInfo = getWarById(battleId);
|
let warInfo = getWarById(battleId);
|
||||||
if(!warInfo) {
|
if(!warInfo) {
|
||||||
return resResult(STATUS.BATTLE_MISS_INFO);
|
return resResult(STATUS.BATTLE_MISS_INFO);
|
||||||
@@ -201,7 +202,7 @@ export class NormalBattleHandler {
|
|||||||
// 记录事件状态
|
// 记录事件状态
|
||||||
await setBattleStatus(this.app, session, roleId, battleId, isSuccess, battleCode);
|
await setBattleStatus(this.app, session, roleId, battleId, isSuccess, battleCode);
|
||||||
} else if (warInfo.warType == WAR_TYPE.TOWER) {
|
} else if (warInfo.warType == WAR_TYPE.TOWER) {
|
||||||
let towerEndResult = await towerBattleEnd(channelService, sid, roleId, battleCode, battleId, isSuccess, heroes);
|
let towerEndResult = await towerBattleEnd(channelService, sid, roleId, serverId, battleCode, battleId, isSuccess, heroes);
|
||||||
if(towerEndResult) {
|
if(towerEndResult) {
|
||||||
if(towerEndResult.status == -1) {
|
if(towerEndResult.status == -1) {
|
||||||
return towerEndResult.resResult;
|
return towerEndResult.resResult;
|
||||||
|
|||||||
@@ -11,7 +11,7 @@ import { decodeArrayStr, resResult, shouldRefresh, calculateNum, getRefTime, gen
|
|||||||
import { calcuHangUpReward, checkTaskConditions, checkHangUpSpdUpCnt, createCurTasks, treatTask, getRemainTime, getTasksReward, getTaskStatus, getDoingOrWaitingTasks } from '../../../services/battleService';
|
import { calcuHangUpReward, checkTaskConditions, checkHangUpSpdUpCnt, createCurTasks, treatTask, getRemainTime, getTasksReward, getTaskStatus, getDoingOrWaitingTasks } from '../../../services/battleService';
|
||||||
import { handleFixedReward, handleReward } from '../../../services/rewardService';
|
import { handleFixedReward, handleReward } from '../../../services/rewardService';
|
||||||
import { checkBattleHeroes } from '../../../services/normalBattleService';
|
import { checkBattleHeroes } from '../../../services/normalBattleService';
|
||||||
import { getRank, setRank } from '../../../services/redisService';
|
import { getRank, setRank, initRank, existsRank } from '../../../services/redisService';
|
||||||
|
|
||||||
export default function(app: Application) {
|
export default function(app: Application) {
|
||||||
return new TowerBattleHandler(app);
|
return new TowerBattleHandler(app);
|
||||||
@@ -27,13 +27,14 @@ export class TowerBattleHandler {
|
|||||||
*/
|
*/
|
||||||
async getStatus(msg: {}, session: BackendSession) {
|
async getStatus(msg: {}, session: BackendSession) {
|
||||||
let roleId = session.get('roleId');
|
let roleId = session.get('roleId');
|
||||||
|
let serverId = session.get('serverId');
|
||||||
let { towerLv } = await RoleModel.findByRoleId(roleId);
|
let { towerLv } = await RoleModel.findByRoleId(roleId);
|
||||||
if (!towerLv) {
|
if (!towerLv) {
|
||||||
towerLv = 1;
|
towerLv = 1;
|
||||||
let role = await RoleModel.towerLvUp(roleId);
|
let role = await RoleModel.towerLvUp(roleId);
|
||||||
// 更新redis
|
// 更新redis
|
||||||
let { roleName, towerUpTime, lv, vLv } = role;
|
let { roleName, towerUpTime, lv, vLv } = role;
|
||||||
await setRank(REDIS_KEY.TOWER_RANK, roleId, towerLv, towerUpTime.getTime(), {roleName, lv, vLv, guildName:"", head: "zhaoyun"});
|
await setRank(REDIS_KEY.TOWER_RANK, serverId, roleId, towerLv, towerUpTime.getTime(), {roleName, lv, vLv, guildName:"", head: "zhaoyun"});
|
||||||
|
|
||||||
}
|
}
|
||||||
let towerRec = await TowerRecordModel.getRecordByLv(roleId, towerLv);
|
let towerRec = await TowerRecordModel.getRecordByLv(roleId, towerLv);
|
||||||
@@ -105,7 +106,7 @@ export class TowerBattleHandler {
|
|||||||
const goods = await handleReward(roleId, roleName, timeReward);
|
const goods = await handleReward(roleId, roleName, timeReward);
|
||||||
await HangUpRecordModel.updateRec(roleId, roleName, endLv, endTime, needReceiveGoods);
|
await HangUpRecordModel.updateRec(roleId, roleName, endLv, endTime, needReceiveGoods);
|
||||||
|
|
||||||
return resResult(STATUS.SUCCESS, { endTime, hangUpPassTime: Math.floor((deltaTime%HANG_UP_CONSTS.MAX_TIME)/1000), ...goods });
|
return resResult(STATUS.SUCCESS, { endTime, hangUpPassTime: Math.floor((deltaTime%HANG_UP_CONSTS.UNIT_TIME)/1000), ...goods });
|
||||||
}
|
}
|
||||||
|
|
||||||
async hangUpSpeedUp(msg: {speedUpCnt: number}, session: BackendSession) {
|
async hangUpSpeedUp(msg: {speedUpCnt: number}, session: BackendSession) {
|
||||||
@@ -303,12 +304,15 @@ export class TowerBattleHandler {
|
|||||||
return resResult(STATUS.SUCCESS, { curTasks: treatTask(curTasks, curTime), goods, refRemainTime, nextCostGold: costGold });
|
return resResult(STATUS.SUCCESS, { curTasks: treatTask(curTasks, curTime), goods, refRemainTime, nextCostGold: costGold });
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
async getTowerRank(msg: {}, session: BackendSession) {
|
async getTowerRank(msg: {}, session: BackendSession) {
|
||||||
let roleId = session.get('roleId');
|
let roleId = session.get('roleId');
|
||||||
let roleName = session.get('roleName');
|
let roleName = session.get('roleName');
|
||||||
|
let serverId = session.get('serverId')
|
||||||
|
|
||||||
let {ranks, myRank} = await getRank(REDIS_KEY.TOWER_RANK, roleId);
|
const hasTowerRank = await existsRank(REDIS_KEY.TOWER_RANK, serverId);
|
||||||
|
if(!hasTowerRank) await initRank(serverId);
|
||||||
|
|
||||||
|
let {ranks, myRank} = await getRank(REDIS_KEY.TOWER_RANK, serverId, roleId);
|
||||||
if(!myRank) {
|
if(!myRank) {
|
||||||
let role = await RoleModel.findByRoleId(roleId);
|
let role = await RoleModel.findByRoleId(roleId);
|
||||||
let {towerLv, lv, vLv} = role;
|
let {towerLv, lv, vLv} = role;
|
||||||
|
|||||||
@@ -27,7 +27,6 @@ export class EntryHandler {
|
|||||||
* @param {Object} session current session object
|
* @param {Object} session current session object
|
||||||
*/
|
*/
|
||||||
async enter(msg: { token: string, serverId: number }, session: FrontendSession) {
|
async enter(msg: { token: string, serverId: number }, session: FrontendSession) {
|
||||||
|
|
||||||
let self = this;
|
let self = this;
|
||||||
let serverId = msg.serverId;
|
let serverId = msg.serverId;
|
||||||
let sessionService = self.app.get('sessionService');
|
let sessionService = self.app.get('sessionService');
|
||||||
@@ -53,10 +52,12 @@ export class EntryHandler {
|
|||||||
session.set('roleName', role.roleName);
|
session.set('roleName', role.roleName);
|
||||||
session.set('eventStatus', role.eventStatus);
|
session.set('eventStatus', role.eventStatus);
|
||||||
session.set('sid', self.app.get('serverId'));
|
session.set('sid', self.app.get('serverId'));
|
||||||
|
session.set('serverId', role.serverId);
|
||||||
session.push('sid', () => {});
|
session.push('sid', () => {});
|
||||||
session.push('roleId', () => {});
|
session.push('roleId', () => {});
|
||||||
session.push('roleName', () => {});
|
session.push('roleName', () => {});
|
||||||
session.push('eventStatus', () => {});
|
session.push('eventStatus', () => {});
|
||||||
|
session.push('serverId', () => {});
|
||||||
// session.push('rid', function (err) {
|
// session.push('rid', function (err) {
|
||||||
// if (err) {
|
// if (err) {
|
||||||
// console.error('set rid for session service failed! error is : %j', err.stack);
|
// console.error('set rid for session service failed! error is : %j', err.stack);
|
||||||
|
|||||||
@@ -47,7 +47,7 @@ export async function checkTowerWar(roleId: string, battleId: number, heroes: Ar
|
|||||||
}};
|
}};
|
||||||
}
|
}
|
||||||
|
|
||||||
export async function towerBattleEnd(channelService: ChannelService, sid: string, roleId: string, battleCode: string, battleId: number, succeed: boolean, heroes: Array<number>) {
|
export async function towerBattleEnd(channelService: ChannelService, sid: string, roleId: string, serverId: number, battleCode: string, battleId: number, succeed: boolean, heroes: Array<number>) {
|
||||||
if (succeed) {
|
if (succeed) {
|
||||||
let battleRec = await BattleRecordModel.getBattleRecordByCode(battleCode);
|
let battleRec = await BattleRecordModel.getBattleRecordByCode(battleCode);
|
||||||
if (battleRec.battleId != battleId) {
|
if (battleRec.battleId != battleId) {
|
||||||
@@ -73,7 +73,7 @@ export async function towerBattleEnd(channelService: ChannelService, sid: string
|
|||||||
let role = await RoleModel.towerLvUp(roleId);
|
let role = await RoleModel.towerLvUp(roleId);
|
||||||
// 更新redis
|
// 更新redis
|
||||||
let { roleName, towerLv, towerUpTime, lv, vLv } = role;
|
let { roleName, towerLv, towerUpTime, lv, vLv } = role;
|
||||||
await setRank(REDIS_KEY.TOWER_RANK, roleId, towerLv, towerUpTime.getTime(), {roleName, lv, vLv, guildName:"", head: "zhaoyun"});
|
await setRank(REDIS_KEY.TOWER_RANK, serverId, roleId, towerLv, towerUpTime.getTime(), {roleName, lv, vLv, guildName:"", head: "zhaoyun"});
|
||||||
|
|
||||||
const nextTowerInfo = getTowerDataByLv(towerLv + 1);
|
const nextTowerInfo = getTowerDataByLv(towerLv + 1);
|
||||||
if (nextTowerInfo) {
|
if (nextTowerInfo) {
|
||||||
|
|||||||
@@ -1,6 +1,8 @@
|
|||||||
import { RoleModel } from "../db/Role";
|
import { RoleModel } from "../db/Role";
|
||||||
import * as redis from 'redis';
|
import * as redis from 'redis';
|
||||||
import {REDIS_KEY} from '../consts/consts'
|
import {REDIS_KEY} from '../consts/consts'
|
||||||
|
import { GameModel } from "../db/Game";
|
||||||
|
import { exists } from "fs";
|
||||||
|
|
||||||
let redisArr = 'r-8vb4i2kgl91886fkxd.redis.zhangbei.rds.aliyuncs.com';
|
let redisArr = 'r-8vb4i2kgl91886fkxd.redis.zhangbei.rds.aliyuncs.com';
|
||||||
if(process.env.NODE_ENV == 'local') {
|
if(process.env.NODE_ENV == 'local') {
|
||||||
@@ -20,16 +22,38 @@ client.set('hello', 'redis', redis.print);
|
|||||||
/**
|
/**
|
||||||
* 在服务重新启动时,将信息存入redis
|
* 在服务重新启动时,将信息存入redis
|
||||||
*/
|
*/
|
||||||
export async function initRank() {
|
export async function initAllRank() {
|
||||||
await redisDel(REDIS_KEY.TOWER_RANK); // 清空天梯排行榜(ZSet)
|
const serverList = await GameModel.getAllServerList();
|
||||||
await redisDel(REDIS_KEY.USER_INFO); // 清空用户缓存信息
|
await redisDel(REDIS_KEY.USER_INFO);
|
||||||
let ranks = await RoleModel.getRank('tower', ['roleId', 'roleName', 'towerLv', 'lv', 'vLv']);
|
for(let {id} of serverList) {
|
||||||
|
await redisDel(getKeyName(REDIS_KEY.TOWER_RANK, id));
|
||||||
|
await initRank(id);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export async function initRank(serverId: number) {
|
||||||
|
console.log('*****', 'initRank')
|
||||||
|
await redisExpire(getKeyName(REDIS_KEY.TOWER_RANK, serverId), 30 * 24 * 60 * 60);
|
||||||
|
await redisExpire(REDIS_KEY.USER_INFO, 30 * 24 * 60 * 60);
|
||||||
|
|
||||||
|
let ranks = await RoleModel.getRank('tower', serverId, ['roleId', 'roleName', 'towerLv', 'lv', 'vLv']);
|
||||||
for(let {towerLv, roleId, roleName, lv, vLv, towerUpTime} of ranks) {
|
for(let {towerLv, roleId, roleName, lv, vLv, towerUpTime} of ranks) {
|
||||||
await redisZadd(REDIS_KEY.TOWER_RANK, encodeScoreWithTime(towerLv, towerUpTime?towerUpTime.getTime():0), roleId);
|
console.log(roleId);
|
||||||
|
await redisZadd(getKeyName(REDIS_KEY.TOWER_RANK, serverId), encodeScoreWithTime(towerLv, towerUpTime?towerUpTime.getTime():0), roleId);
|
||||||
await redisUserInfoAdd(roleId, {roleName, lv, vLv, guildName:"", head: "zhaoyun"});
|
await redisUserInfoAdd(roleId, {roleName, lv, vLv, guildName:"", head: "zhaoyun"});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 排行榜是否存在
|
||||||
|
export async function existsRank(key: string, serverId: number) {
|
||||||
|
const result = await redisExists(getKeyName(key, serverId));
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
export function getKeyName(key: string, serverId: number) {
|
||||||
|
return `${key}:${serverId.toString()}`;
|
||||||
|
}
|
||||||
|
|
||||||
// 更新玩家信息
|
// 更新玩家信息
|
||||||
export async function redisUserInfoUpdate(roleId: string, arr: Array<{field: string, value:(string|number)}>) {
|
export async function redisUserInfoUpdate(roleId: string, arr: Array<{field: string, value:(string|number)}>) {
|
||||||
let params = await redisHget(REDIS_KEY.USER_INFO, roleId);
|
let params = await redisHget(REDIS_KEY.USER_INFO, roleId);
|
||||||
@@ -49,12 +73,12 @@ export async function redisUserInfoAdd(roleId: string, params: {roleName: string
|
|||||||
}
|
}
|
||||||
|
|
||||||
// 更新排行榜
|
// 更新排行榜
|
||||||
export async function setRank(key: string, roleId: string, score: number, timestamp: number, params: {roleName: string, lv: number, vLv: number, guildName: string, head: string}) {
|
export async function setRank(key: string, serverId: number, roleId: string, score: number, timestamp: number, params: {roleName: string, lv: number, vLv: number, guildName: string, head: string}) {
|
||||||
// 更新分数
|
// 更新分数
|
||||||
const _score = encodeScoreWithTime(score, timestamp);
|
const _score = encodeScoreWithTime(score, timestamp);
|
||||||
await redisZadd(key, _score, roleId);
|
await redisZadd(getKeyName(key, serverId), _score, roleId);
|
||||||
// 移除100名以外
|
// 移除100名以外
|
||||||
await redisZremRangeByRank(key, 0, 100);
|
await redisZremRangeByRank(getKeyName(key, serverId), 100, 10000);
|
||||||
// 如果没有信息,更新玩家信息
|
// 如果没有信息,更新玩家信息
|
||||||
const hasCurUser = await redisHexists(REDIS_KEY.USER_INFO, roleId);
|
const hasCurUser = await redisHexists(REDIS_KEY.USER_INFO, roleId);
|
||||||
if(!hasCurUser) {
|
if(!hasCurUser) {
|
||||||
@@ -64,15 +88,15 @@ export async function setRank(key: string, roleId: string, score: number, timest
|
|||||||
}
|
}
|
||||||
|
|
||||||
// 获取排行榜
|
// 获取排行榜
|
||||||
export async function getRank(key: string, roleId: string) {
|
export async function getRank(key: string, serverId: number, roleId: string) {
|
||||||
let ranks = [], myRank = null;
|
let ranks = [], myRank = null;
|
||||||
const rankFromDb = await redisZrevrangeByScore(key, '+inf', '-inf', true, 100);
|
const rankFromDb = await redisZrevrangeByScore(getKeyName(key, serverId), '+inf', '-inf', true, 100);
|
||||||
for(let ii = 0; ii < rankFromDb.length; ii+=2) {
|
for(let ii = 0; ii < rankFromDb.length; ii+=2) {
|
||||||
const _roleId = rankFromDb[ii];
|
const _roleId = rankFromDb[ii];
|
||||||
const _score = decodeScoreWithTime(rankFromDb[ii + 1]);
|
const _score = decodeScoreWithTime(rankFromDb[ii + 1]);
|
||||||
const userInfo = await redisHget(REDIS_KEY.USER_INFO, _roleId);
|
const userInfo = await redisHget(REDIS_KEY.USER_INFO, _roleId);
|
||||||
const _userInfo = JSON.parse(userInfo);
|
const _userInfo = JSON.parse(userInfo);
|
||||||
const tmp = {..._userInfo, roleId: _roleId, num: _score, rank: ii%2+1}
|
const tmp = {..._userInfo, roleId: _roleId, num: _score, rank: Math.floor(ii/2)+1}
|
||||||
ranks.push(tmp);
|
ranks.push(tmp);
|
||||||
if(roleId == _roleId) myRank = tmp;
|
if(roleId == _roleId) myRank = tmp;
|
||||||
}
|
}
|
||||||
@@ -99,11 +123,21 @@ function decodeScoreWithTime(num: string): number {
|
|||||||
|
|
||||||
//// key
|
//// key
|
||||||
|
|
||||||
|
// key 是否存在。
|
||||||
|
export async function redisExists(key: string) {
|
||||||
|
return await createPromise('exists', [key]);
|
||||||
|
}
|
||||||
|
|
||||||
// 在 key 存在时删除 key。
|
// 在 key 存在时删除 key。
|
||||||
export async function redisDel(key: string) {
|
export async function redisDel(key: string) {
|
||||||
return await createPromise('del', [key]);
|
return await createPromise('del', [key]);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 设置过期时间
|
||||||
|
export async function redisExpire(key: string, seconds: number) {
|
||||||
|
return await createPromise('expire', [key, seconds]);
|
||||||
|
}
|
||||||
|
|
||||||
//// 有序集合
|
//// 有序集合
|
||||||
|
|
||||||
// 返回有序集中指定分数区间内的成员,分数从高到低排序
|
// 返回有序集中指定分数区间内的成员,分数从高到低排序
|
||||||
|
|||||||
@@ -55,6 +55,15 @@ export default class Game extends BaseModel {
|
|||||||
@prop({ required: true })
|
@prop({ required: true })
|
||||||
versionCode: number;
|
versionCode: number;
|
||||||
|
|
||||||
|
public static async getAllServerList() {
|
||||||
|
let game = await GameModel.findOne().lean();
|
||||||
|
if(game) {
|
||||||
|
return game.serverList;
|
||||||
|
} else {
|
||||||
|
return []
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
public static async getServerListByType(serverType: string) {
|
public static async getServerListByType(serverType: string) {
|
||||||
let game = await GameModel.findOne().lean();
|
let game = await GameModel.findOne().lean();
|
||||||
if (!game) {
|
if (!game) {
|
||||||
|
|||||||
@@ -339,13 +339,13 @@ export default class Role extends BaseModel {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// 获取排行榜
|
// 获取排行榜
|
||||||
public static async getRank(type: string, fields: Array<string>, page = 1, limit = 100, lean = true) {
|
public static async getRank(type: string, serverId: number, fields: Array<string>, page = 1, limit = 100, lean = true) {
|
||||||
let sortBy = {};
|
let sortBy = {};
|
||||||
if(type == 'tower') {
|
if(type == 'tower') {
|
||||||
sortBy['towerLv'] = -1;
|
sortBy['towerLv'] = -1;
|
||||||
sortBy['towerUpTime'] = 1;
|
sortBy['towerUpTime'] = 1;
|
||||||
}
|
}
|
||||||
const ranks = await RoleModel.find().select(fields.join(' ')).sort(sortBy).limit(limit).skip((page - 1) * limit).lean(lean);
|
const ranks = await RoleModel.find({serverId}).select(fields.join(' ')).sort(sortBy).limit(limit).skip((page - 1) * limit).lean(lean);
|
||||||
return ranks;
|
return ranks;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user