fix: 将活动改为跨服活动
This commit is contained in:
parent
eed6dd1b8f
commit
40774138d2
@ -4,13 +4,21 @@ import { ReqCanReceive, ResCanReceive } from '../../../shared/protocols/event/pa
|
|||||||
import { PublicShared } from "../../../shared/public/public";
|
import { PublicShared } from "../../../shared/public/public";
|
||||||
import { ActionLog } from "../../../public/actionLog/actionLog";
|
import { ActionLog } from "../../../public/actionLog/actionLog";
|
||||||
|
|
||||||
|
const hasGotKeyPrefix = 'payForDiamond:hasGot:'; // 已领取额度
|
||||||
|
const showOffListKeyPrefix = 'payForDiamond:ShowOff:'; // 需要炫耀的玩家列表。 其中需要包含信息:玩家区服, 玩家玩家名称, 领到的数量
|
||||||
|
|
||||||
export async function playerCanReceive(call: ApiCall) {
|
export async function playerCanReceive(call: ApiCall) {
|
||||||
const activityInfo = await HuoDongFun.getHdidInfo(call, call.req.activityId);
|
const activityId = call.req.activityId;
|
||||||
|
const activityInfo = await HuoDongFun.getHdidInfo(call, activityId);
|
||||||
if (!activityInfo) {
|
if (!activityInfo) {
|
||||||
return call.error('No such activity');
|
return call.error('No such activity');
|
||||||
}
|
}
|
||||||
const remaining = activityInfo.data['totalmoney'];
|
const hasReceivedKey = hasGotKeyPrefix + activityId;
|
||||||
const showOffList = activityInfo.data['showOffList'] || [];
|
const hasReceivedStr = await G.iorediscross.get(hasReceivedKey);
|
||||||
|
const hasReceived = hasReceivedStr? parseInt(hasReceivedStr) : 0;
|
||||||
|
const remaining = activityInfo.data['totalmoney'] - hasReceived;
|
||||||
|
const showOffResult = await G.iorediscross.lrange(showOffListKeyPrefix + activityId, 0, -1);
|
||||||
|
const showOffList = showOffResult.map(result => JSON.parse(result));
|
||||||
const zeroTime = PublicShared.getToDayZeroTime();
|
const zeroTime = PublicShared.getToDayZeroTime();
|
||||||
const vipScore = await ActionLog.getDayLog(call.uid, 'pay');
|
const vipScore = await ActionLog.getDayLog(call.uid, 'pay');
|
||||||
const price = activityInfo.data['price'];
|
const price = activityInfo.data['price'];
|
||||||
|
@ -2,7 +2,6 @@ import { ApiCall } from "tsrpc";
|
|||||||
import { ReqReceive, ResReceive } from '../../../shared/protocols/event/payForDiamond/PtlReceive';
|
import { ReqReceive, ResReceive } from '../../../shared/protocols/event/payForDiamond/PtlReceive';
|
||||||
import { playerCanReceive } from './ApiCanReceive';
|
import { playerCanReceive } from './ApiCanReceive';
|
||||||
import { PublicShared } from "../../../shared/public/public";
|
import { PublicShared } from "../../../shared/public/public";
|
||||||
import { ChatFun } from "../../../public/chat";
|
|
||||||
import { PlayerFun } from "../../../public/player";
|
import { PlayerFun } from "../../../public/player";
|
||||||
|
|
||||||
type diamondWeightGroup = {
|
type diamondWeightGroup = {
|
||||||
@ -10,6 +9,9 @@ type diamondWeightGroup = {
|
|||||||
numrange: [ min: number, max: number];
|
numrange: [ min: number, max: number];
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const hasGotKeyPrefix = 'payForDiamond:hasGot:'; // 已领取额度
|
||||||
|
const hasGotLockKey = "payForDiamond:lock"; // 更新锁, TTL 1s
|
||||||
|
const showOffListKeyPrefix = 'payForDiamond:ShowOff:'; // 需要炫耀的玩家列表。 其中需要包含信息:玩家区服, 玩家玩家名称, 领到的数量
|
||||||
/**
|
/**
|
||||||
* @param groups 各分组及其权重
|
* @param groups 各分组及其权重
|
||||||
*/
|
*/
|
||||||
@ -59,7 +61,7 @@ function calcDiamondGot(remaining: number, group: diamondWeightGroup, maxAmount:
|
|||||||
|
|
||||||
export default async function (call: ApiCall<ReqReceive, ResReceive>) {
|
export default async function (call: ApiCall<ReqReceive, ResReceive>) {
|
||||||
const canReceiveResult = await playerCanReceive(call);
|
const canReceiveResult = await playerCanReceive(call);
|
||||||
if (canReceiveResult) {
|
if (canReceiveResult) { // 该值不存在的情况已被函数直接返回 error, 无需再处理
|
||||||
if (!canReceiveResult.result) {
|
if (!canReceiveResult.result) {
|
||||||
return call.succ({
|
return call.succ({
|
||||||
amount: 0,
|
amount: 0,
|
||||||
@ -68,40 +70,52 @@ export default async function (call: ApiCall<ReqReceive, ResReceive>) {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
const activityData = canReceiveResult.activityInfo.data;
|
const activityData = canReceiveResult.activityInfo.data;
|
||||||
const remaining = activityData['totalmoney'];
|
// 更新 redis 领取记录之前先加锁, 防止多领
|
||||||
const { group, maxAmount } = randomWithWeight(activityData['groupConf']['base']['arr']);
|
const lockResult = await G.iorediscross.setnx(hasGotLockKey, 1);
|
||||||
const gotAmount = calcDiamondGot(remaining, group, maxAmount);
|
if (lockResult) {
|
||||||
// 减去余额
|
await G.iorediscross.expire(hasGotLockKey, 1); // 设置 ttl 避免死锁
|
||||||
const filter = {
|
const activityId = call.req.activityId;
|
||||||
hdid: call.req.activityId,
|
const hasReceivedKey = hasGotKeyPrefix + activityId;
|
||||||
$expr: { $gte: ['$data.totalmoney', gotAmount ]},
|
const hasReceivedStr = await G.iorediscross.get(hasReceivedKey);
|
||||||
};
|
const hasReceived = hasReceivedStr? parseInt(hasReceivedStr) : 0;
|
||||||
const updateDoc = {
|
const remaining = activityData['totalmoney'] - hasReceived;
|
||||||
$inc: { 'data.totalmoney': -1 * Math.abs(gotAmount) }
|
if (remaining <= 0) {
|
||||||
}
|
return call.succ({
|
||||||
const updateResult = await G.mongodb.collection('hdinfo').updateOne(filter, updateDoc);
|
amount: 0
|
||||||
// 更新成功
|
});
|
||||||
if (updateResult.modifiedCount) {
|
} else {
|
||||||
const showOff = gotAmount >= activityData['groupConf']['base']['loglimit'];
|
const { group, maxAmount } = randomWithWeight(activityData['groupConf']['base']['arr']);
|
||||||
await PlayerFun.sendPrize(call, [{ 'a': 'attr', 't': 'rmbmoney', 'n': gotAmount }]);
|
const gotAmount = calcDiamondGot(remaining, group, maxAmount);
|
||||||
// 请求返回
|
await G.iorediscross.incrby(hasReceivedKey, -1 * Math.abs(gotAmount)); // 添加已领取的额度
|
||||||
call.succ({
|
await G.iorediscross.del(); // 移除锁
|
||||||
amount: gotAmount,
|
await PlayerFun.sendPrize(call, [{ 'a': 'attr', 't': 'rmbmoney', 'n': gotAmount }]);
|
||||||
timesRemaining: 0,
|
const showOff = gotAmount >= activityData['groupConf']['base']['loglimit'];
|
||||||
showOff,
|
call.succ({ // 领取核心逻辑完成, 请求可以返回了
|
||||||
});
|
amount: gotAmount,
|
||||||
// 添加玩家领取记录
|
timesRemaining: 0,
|
||||||
const zeroTime = PublicShared.getToDayZeroTime();
|
showOff,
|
||||||
const setObj = {};
|
});
|
||||||
setObj[zeroTime] = gotAmount;
|
// 添加玩家领取记录
|
||||||
await G.mongodb.cEvent('payForDiamond').updateOne({ uid: call.uid, type: 'payForDiamond' }, {
|
const zeroTime = PublicShared.getToDayZeroTime();
|
||||||
$set: setObj
|
const setObj = {};
|
||||||
}, {upsert: true});
|
setObj[zeroTime] = gotAmount;
|
||||||
// 记录玩家日志. 仅保留最近 10 条
|
await G.mongodb.cEvent('payForDiamond').updateOne({ uid: call.uid, type: 'payForDiamond' }, {
|
||||||
if (showOff) {
|
$set: setObj
|
||||||
await G.mongodb.collection('hdinfo').updateOne({ hdid: call.req.activityId, }, { $push: { 'data.showOffList': { $each: [{ name: call.conn.gud.name, gotAmount }], $slice: -10 }}});
|
}, {upsert: true});
|
||||||
|
// 炫耀
|
||||||
|
if (showOff) {
|
||||||
|
const msg = JSON.stringify({
|
||||||
|
name: call.conn.gud.name, gotAmount, serverID: call.conn.gud.sid
|
||||||
|
});
|
||||||
|
const showOffListKey = showOffListKeyPrefix + activityId;
|
||||||
|
await G.iorediscross.lpush(showOffListKey, msg);
|
||||||
|
await G.ioredis.ltrim(showOffListKey, 0, 49); // 限制列表保存 50 条消息, 避免无限增长
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
} else {
|
||||||
|
return call.succ({
|
||||||
|
amount: 0
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -92,6 +92,8 @@ class _G {
|
|||||||
redis: redisJsonFun;
|
redis: redisJsonFun;
|
||||||
/**ioredis连接对象 */
|
/**ioredis连接对象 */
|
||||||
ioredis: Redis;
|
ioredis: Redis;
|
||||||
|
/** 跨服 ioredis 连接对象 */
|
||||||
|
iorediscross: Redis;
|
||||||
/**mongodb连接对象 */
|
/**mongodb连接对象 */
|
||||||
mongodb: _mongodb;
|
mongodb: _mongodb;
|
||||||
/**crossmongodb连接对象 */
|
/**crossmongodb连接对象 */
|
||||||
|
@ -16,4 +16,7 @@ export async function initIORedis() {
|
|||||||
G.ioredis = new Redis(G.argv.serverType == 'cross' ? G.config.crossRedisUrl : G.config.redisUrl,{
|
G.ioredis = new Redis(G.argv.serverType == 'cross' ? G.config.crossRedisUrl : G.config.redisUrl,{
|
||||||
keyPrefix: preKey,
|
keyPrefix: preKey,
|
||||||
});
|
});
|
||||||
}
|
G.iorediscross = new Redis(G.config.crossRedisUrl,{
|
||||||
|
keyPrefix: "cross_",
|
||||||
|
});
|
||||||
|
}
|
||||||
|
@ -4,6 +4,6 @@ export type ReqReceive = {
|
|||||||
|
|
||||||
export type ResReceive = {
|
export type ResReceive = {
|
||||||
amount: number,
|
amount: number,
|
||||||
timesRemaining: number;
|
timesRemaining?: number;
|
||||||
showOff: boolean;
|
showOff?: boolean;
|
||||||
};
|
};
|
||||||
|
@ -10188,14 +10188,16 @@ export const serviceProto: ServiceProto<ServiceType> = {
|
|||||||
"name": "timesRemaining",
|
"name": "timesRemaining",
|
||||||
"type": {
|
"type": {
|
||||||
"type": "Number"
|
"type": "Number"
|
||||||
}
|
},
|
||||||
|
"optional": true
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"id": 2,
|
"id": 2,
|
||||||
"name": "showOff",
|
"name": "showOff",
|
||||||
"type": {
|
"type": {
|
||||||
"type": "Boolean"
|
"type": "Boolean"
|
||||||
}
|
},
|
||||||
|
"optional": true
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
|
Loading…
Reference in New Issue
Block a user