mirror of
https://github.com/labring/FastGPT.git
synced 2025-12-25 20:02:47 +00:00
team qpm limit & plan tracks
This commit is contained in:
parent
3e0b853a88
commit
036c37855f
|
|
@ -10,5 +10,7 @@ export enum TrackEnum {
|
|||
readSystemAnnouncement = 'readSystemAnnouncement',
|
||||
clickOperationalAd = 'clickOperationalAd',
|
||||
closeOperationalAd = 'closeOperationalAd',
|
||||
teamChatQPM = 'teamChatQPM'
|
||||
teamChatQPM = 'teamChatQPM',
|
||||
subscriptionDeleted = 'subscriptionDeleted',
|
||||
freeAccountCleanup = 'freeAccountCleanup'
|
||||
}
|
||||
|
|
|
|||
|
|
@ -2,15 +2,19 @@
|
|||
import { getGlobalRedisConnection } from '../../common/redis';
|
||||
import { jsonRes } from '../../common/response';
|
||||
import type { NextApiResponse } from 'next';
|
||||
import {
|
||||
getCachedTeamQPMLimit,
|
||||
setCachedTeamQPMLimit,
|
||||
getTeamPlanStatus
|
||||
} from '../../support/wallet/sub/utils';
|
||||
import { SubTypeEnum } from '@fastgpt/global/support/wallet/sub/constants';
|
||||
|
||||
export enum LimitTypeEnum {
|
||||
chat = 'chat'
|
||||
}
|
||||
const limitMap = {
|
||||
[LimitTypeEnum.chat]: {
|
||||
seconds: 60,
|
||||
limit: Number(process.env.CHAT_MAX_QPM || 5000)
|
||||
}
|
||||
|
||||
const limitSecondsMap = {
|
||||
[LimitTypeEnum.chat]: 60
|
||||
};
|
||||
|
||||
type FrequencyLimitOption = {
|
||||
|
|
@ -19,8 +23,31 @@ type FrequencyLimitOption = {
|
|||
res: NextApiResponse;
|
||||
};
|
||||
|
||||
// Get team's dynamic QPM limit with caching
|
||||
export const getTeamQPMLimit = async (teamId: string): Promise<number> => {
|
||||
// 1. Try to get from cache first
|
||||
const cachedLimit = await getCachedTeamQPMLimit(teamId);
|
||||
if (cachedLimit !== null) {
|
||||
return cachedLimit;
|
||||
}
|
||||
|
||||
// 2. Cache miss, compute from database
|
||||
const teamPlanStatus = await getTeamPlanStatus({ teamId });
|
||||
const limit =
|
||||
teamPlanStatus[SubTypeEnum.standard]?.requestsPerMinute ??
|
||||
teamPlanStatus.standardConstants?.requestsPerMinute ??
|
||||
30;
|
||||
|
||||
// 3. Write to cache
|
||||
await setCachedTeamQPMLimit(teamId, limit);
|
||||
|
||||
return limit;
|
||||
};
|
||||
|
||||
export const teamFrequencyLimit = async ({ teamId, type, res }: FrequencyLimitOption) => {
|
||||
const { seconds, limit } = limitMap[type];
|
||||
const limit = await getTeamQPMLimit(teamId);
|
||||
const seconds = limitSecondsMap[type];
|
||||
|
||||
const redis = getGlobalRedisConnection();
|
||||
const key = `frequency:${type}:${teamId}`;
|
||||
|
||||
|
|
|
|||
|
|
@ -156,5 +156,38 @@ export const pushTrack = {
|
|||
teamId: data.teamId
|
||||
}
|
||||
});
|
||||
},
|
||||
subscriptionDeleted: (data: {
|
||||
teamId: string;
|
||||
subscriptionType: string;
|
||||
subLevel?: string;
|
||||
totalPoints: number;
|
||||
usedPoints: number;
|
||||
startTime: Date;
|
||||
expiredTime: Date;
|
||||
}) => {
|
||||
return createTrack({
|
||||
event: TrackEnum.subscriptionDeleted,
|
||||
data: {
|
||||
teamId: data.teamId,
|
||||
subscriptionType: data.subscriptionType,
|
||||
subLevel: data.subLevel,
|
||||
totalPoints: data.totalPoints,
|
||||
usedPoints: data.usedPoints,
|
||||
activeDays: Math.ceil(
|
||||
(new Date(data.expiredTime).getTime() - new Date(data.startTime).getTime()) /
|
||||
(1000 * 60 * 60 * 24)
|
||||
)
|
||||
}
|
||||
});
|
||||
},
|
||||
freeAccountCleanup: (data: { teamId: string; expiredTime: Date }) => {
|
||||
return createTrack({
|
||||
event: TrackEnum.freeAccountCleanup,
|
||||
data: {
|
||||
teamId: data.teamId,
|
||||
expiredTime: data.expiredTime
|
||||
}
|
||||
});
|
||||
}
|
||||
};
|
||||
|
|
|
|||
|
|
@ -8,14 +8,16 @@ const getCacheKey = (key: string) => `${redisPrefix}${key}`;
|
|||
export enum CacheKeyEnum {
|
||||
team_vector_count = 'team_vector_count',
|
||||
team_point_surplus = 'team_point_surplus',
|
||||
team_point_total = 'team_point_total'
|
||||
team_point_total = 'team_point_total',
|
||||
team_qpm_limit = 'team_qpm_limit'
|
||||
}
|
||||
|
||||
// Seconds
|
||||
export enum CacheKeyEnumTime {
|
||||
team_vector_count = 30 * 60,
|
||||
team_point_surplus = 1 * 60,
|
||||
team_point_total = 1 * 60
|
||||
team_point_total = 1 * 60,
|
||||
team_qpm_limit = 60 * 60
|
||||
}
|
||||
|
||||
export const setRedisCache = async (
|
||||
|
|
|
|||
|
|
@ -10,7 +10,9 @@ export enum TimerIdEnum {
|
|||
clearExpiredRawTextBuffer = 'clearExpiredRawTextBuffer',
|
||||
clearExpiredDatasetImage = 'clearExpiredDatasetImage',
|
||||
clearExpiredMinioFiles = 'clearExpiredMinioFiles',
|
||||
recordTeamQPM = 'recordTeamQPM'
|
||||
recordTeamQPM = 'recordTeamQPM',
|
||||
auditLogCleanup = 'auditLogCleanup',
|
||||
chatHistoryCleanup = 'chatHistoryCleanup'
|
||||
}
|
||||
|
||||
export enum LockNotificationEnum {
|
||||
|
|
|
|||
|
|
@ -278,3 +278,17 @@ export const getTeamPoints = async ({ teamId }: { teamId: string }) => {
|
|||
usedPoints: planStatus.usedPoints
|
||||
};
|
||||
};
|
||||
|
||||
export const getCachedTeamQPMLimit = async (teamId: string): Promise<number | null> => {
|
||||
const cacheKey = `${CacheKeyEnum.team_qpm_limit}:${teamId}`;
|
||||
const cached = await getRedisCache(cacheKey);
|
||||
return cached ? Number(cached) : null;
|
||||
};
|
||||
export const setCachedTeamQPMLimit = async (teamId: string, limit: number): Promise<void> => {
|
||||
const cacheKey = `${CacheKeyEnum.team_qpm_limit}:${teamId}`;
|
||||
await setRedisCache(cacheKey, limit.toString(), CacheKeyEnumTime.team_qpm_limit);
|
||||
};
|
||||
export const clearTeamQPMLimitCache = async (teamId: string): Promise<void> => {
|
||||
const cacheKey = `${CacheKeyEnum.team_qpm_limit}:${teamId}`;
|
||||
await delRedisCache(cacheKey);
|
||||
};
|
||||
|
|
|
|||
Loading…
Reference in New Issue