This commit is contained in:
aozhiwei 2023-07-25 19:16:57 +08:00
commit a5a3eb563c
4 changed files with 138 additions and 225 deletions

View File

@ -0,0 +1,8 @@
const utils = require('j7/utils');
const basewrap = require('./basewrap');
class GameRedis extends basewrap.BaseWrap {
}
module.exports = GameRedis;

View File

@ -84,7 +84,12 @@ function init() {
'', '',
'GameDb2006' 'GameDb2006'
); );
registerMetaClass(configDir + 'game_redis.json',
'',
'GameRedis'
);
registerMetaClass(configDir + 'rankSeason.json', registerMetaClass(configDir + 'rankSeason.json',
'', '',
'RankSeason' 'RankSeason'

View File

@ -1,7 +1,9 @@
const metaFactory = require('../metadata/factory');
const redis = require("redis") const redis = require("redis")
const REDIS_CONF = { const REDIS_CONF = {
port: 6379, port: metaFactory.getMetaByKey('GameRedis', '0')['port'],
host: '127.0.0.1' host: metaFactory.getMetaByKey('GameRedis', '0')['host'],
} }
class Redis { class Redis {

View File

@ -3,244 +3,142 @@ const utils = require('j7/utils');
const constant = require('../constant'); const constant = require('../constant');
const Redis = require('../services/redis'); const Redis = require('../services/redis');
/** const RANKING_KEY = 'game2006api:';
* redis@3.1.2 const LAST_IDX = 'userLastIdx';
*/
const RANKING_KEY = 'game2006api:' const BASE_SCORE = 2800;
const LAST_IDX = 'userLastIdx'
class Rankings { class Rankings {
async start() {
console.log('Rankings.start');
while (true) {
await this.doRanking();
// const sleepTime = 60*60*2
const sleepTime = 60*60*2
console.log('sleepTime:' + sleepTime, new Date(), sleepTime /60);
await utils.sleep(sleepTime * 1000);
}
async start() {
console.log('Rankings.start');
while (true) {
await this.doRanking();
const sleepTime = 60*60*2;
console.log('sleepTime:' + sleepTime, new Date(), sleepTime /60);
await utils.sleep(sleepTime * 1000);
} }
}
async doRanking() { async doRanking() {
//redis连接 try {
// Redis.connect() const {err, conn} = await app.getDbConn("GameDb20060");
try { if (err){
const {err, conn} = await app.getDbConn("GameDb20060"); throw err
if (err){ }
throw err if (await Redis.exists(RANKING_KEY + "account")){
} await Redis.del(RANKING_KEY + 'account')
if (await Redis.exists(RANKING_KEY + "account")){ await Redis.del(RANKING_KEY + 'ranking')
await Redis.del(RANKING_KEY + 'account') await this.calcRanking();
await Redis.del(RANKING_KEY + 'ranking') console.log("刷新rank榜单")
await this.calcRanking(); }else {
console.log("跟新rank榜单") await this.calcRanking();
}else { console.log("生成rank榜单")
await this.calcRanking(); }
console.log("生成rank榜单") } catch (err){
} console.log(err);
}catch (err){
console.log(err);
}
//关闭redis连接
// Redis.quit()
} }
}
//计算用户排行榜 //计算用户排行榜
async calcRanking() { async calcRanking() {
console.log("calc ranking..."); console.log("calc ranking...");
const {err, conn} = await app.getDbConn("GameDb20060"); const {err, conn} = await app.getDbConn("GameDb20060");
if (err) { if (err) {
throw err; throw err;
}
if (!err && conn) {
// 从user表中遍历所有用户每次取1000个用户逐步加入到排序表中
let sorted = [];
let lastIdx = 0;
while(lastIdx>=0) {
const result = await this.getRecords(conn, lastIdx, 1000);
lastIdx = result.lastIdx;
if (lastIdx != -1) {
this.recordsSort(sorted, result.records)
}
}
await this.pushResultToRedis(sorted);
// let rankList = await this.pushRankingResult(sorted);
// console.log(rankList);
//存储到redis中
// let listJson = JSON.stringify(rankList);
// Redis.set(RANKING_KEY + "rank",listJson);
console.log("calc ranking end");
}
} }
if (!err && conn) {
// 从user表中遍历所有用户每次取1000个用户逐步加入到排序表中
let sorted = [];
let lastIdx = 0;
while (lastIdx>=0) {
const result = await this.getRecords(conn, lastIdx, 1000);
lastIdx = result.lastIdx;
//增加排名列 if (lastIdx != -1) {
async pushResultToRedis(sorted) { this.recordsSort(sorted, result.records)
let rankingList = [];
await utils.serial(
sorted,
(value , index) =>{
value.ranking = index+1
Redis.hset(RANKING_KEY + "ranking",value.ranking,value.account_id)
Redis.hset(RANKING_KEY + "account",value.account_id,value.ranking)
}
)
}
//跟新用户榜单
async updateRankRecords(conn,data){
if (!data || data.length == 0){
return
} }
for (let item of data) { console.log(lastIdx, sorted);
const {err, row} = await conn.execQueryOne( }
'select idx,account_id,channel,convert(`name` using utf8) as name,head_id,head_frame,rank,history_best_rank,score,history_best_score,createtime, score_modifytime from t_user where account_id = ? and score_modifytime > ?', await this.pushResultToRedis(sorted);
[ console.log("calc ranking end");
item.account_id, }
item.score_modifytime, }
]
); //增加排名列
if (err){ async pushResultToRedis(sorted) {
throw err console.log(sorted);
} let rankingList = [];
if (row){ await utils.serial(
item.idx = row.idx sorted,
item.account_id = row.account_id (value , index) =>{
item.channel = row.channel value.ranking = index+1
item.name = row.name Redis.hset(RANKING_KEY + "ranking",value.ranking,value.account_id)
item.head_id = row.head_id Redis.hset(RANKING_KEY + "account",value.account_id,value.ranking)
item.head_frame = row.head_frame }
item.rank = row.rank )
item.history_best_rank = row.history_best_rank }
item.score = row.score
item.history_best_score = row.history_best_score //获取用户记录
item.score_modifytime = row.score_modifytime async getRecords(conn, lastIdx, limit) {
} const {err, rows} = await conn.execQuery(
'select idx,account_id,channel,convert(`name` using utf8) as name,head_id,head_frame,rank,history_best_rank,score,history_best_score,createtime, score_modifytime from t_user where idx > ? order by idx LIMIT ?',
[
lastIdx,
limit
]
);
if (err) {
throw err;
}
if (rows.length==0) {
return {
lastIdx: -1,
records: []
};
}
// Redis.set(LAST_IDX,rows[rows.length-1].idx)
return {
lastIdx: rows[rows.length-1].idx,
records: rows
};
}
//给记录按分数排序
recordsSort(sorted, records) {
// 根据分数加入到排序表中
for (let element of records) {
if (element.score>BASE_SCORE) {
if (sorted.length >= 10000){
if (element.score >= sorted[sorted.length - 1].score){
this._recordsSort(sorted,element);
sorted.pop();
}
} else {
this._recordsSort(sorted,element);
} }
let sorted = []; }
this.recordsSort(sorted,data)
let rankList = await this.pushRankingResult(sorted);
//更新redis中榜单
let newListJson = JSON.stringify(rankList);
Redis.set(RANKING_KEY + "rank",newListJson);
} }
}
//获取数据库中最后一个自增id _recordsSort(sorted,element){
async getDbLastIdx (conn){ sorted.push(element);
const {err, row} = await conn.execQueryOne( sorted.sort(function(a,b) {
"select max(idx) as last_idx from t_user" let r = b.score - a.score;
) if (r==0) {
if (err) { r = a.score_modifytime - b.score_modifytime;
throw err; }
} if (r==0) {
return row.last_idx; r = a.idx - b.idx;
} }
return r;
});
}
//追加新用户到榜单记录中
async pushNewUserRecords(conn,lastIdx,data){
while(lastIdx>=0) {
const result = await this.getRecords(conn, lastIdx, 1000);
lastIdx = result.lastIdx;
if (lastIdx != -1) {
this.recordsSort(data, result.records)
}
}
console.log("LAST_IDX : ",lastIdx)
let rankList = await this.pushRankingResult(data);
//存储到redis中
let listJson = JSON.stringify(rankList);
Redis.set(RANKING_KEY + "rank",listJson);
}
//获取用户记录
async getRecords(conn, lastIdx, limit) {
const {err, rows} = await conn.execQuery(
'select idx,account_id,channel,convert(`name` using utf8) as name,head_id,head_frame,rank,history_best_rank,score,history_best_score,createtime, score_modifytime from t_user where idx > ? order by idx LIMIT ?',
[
lastIdx,
limit
]
);
if (err) {
throw err;
}
if (rows.length==0) {
return {
lastIdx: -1,
records: []
};
}
// Redis.set(LAST_IDX,rows[rows.length-1].idx)
return {
lastIdx: rows[rows.length-1].idx,
records: rows
};
}
//给记录按分数排序
recordsSort(sorted, records) {
// 根据分数加入到排序表中
for (let element of records) {
if (element.score>2800) {
if (sorted.length >= 10000){
if (element.score >= sorted[sorted.length - 1].score){
sorted.pop()
this._recordsSort(sorted,element)
}
} else {
this._recordsSort(sorted,element)
}
}
}
// if (sorted.length>10000) {
// sorted.length = 10000;
// }
}
_recordsSort(sorted,element){
sorted.push(element);
sorted.sort(function(a,b) {
let r = b.score - a.score;
if (r==0) {
r = a.score_modifytime - b.score_modifytime;
}
if (r==0) {
r = a.idx - b.idx;
}
return r;
});
}
//增加排名列
async pushRankingResult(sorted) {
let rankingList = [];
await utils.serial(
sorted,
(value , index) =>{
value.ranking = index+1
rankingList.push(value)
}
)
return rankingList;
}
} }
function init() { function init() {
(new Rankings()).start(); (new Rankings()).start();
} }
exports.init = init; exports.init = init;