mirror of
https://github.com/labring/FastGPT.git
synced 2025-10-16 08:01:18 +00:00
Feat: Plan cache (#5052)
* add cache for team member,app,dataset (#5007) * add cache for team member,app,dataset * update for hook * update redis * update * perf: cache code * fix: i18n --------- Co-authored-by: gggaaallleee <91131304+gggaaallleee@users.noreply.github.com>
This commit is contained in:
@@ -10,6 +10,7 @@ weight: 787
|
|||||||
|
|
||||||
## 🚀 新增内容
|
## 🚀 新增内容
|
||||||
|
|
||||||
|
1. 套餐缓存,减少 MongoDB 查询次数。
|
||||||
|
|
||||||
## ⚙️ 优化
|
## ⚙️ 优化
|
||||||
|
|
||||||
|
@@ -6,7 +6,16 @@ const redisPrefix = 'cache:';
|
|||||||
const getCacheKey = (key: string) => `${redisPrefix}${key}`;
|
const getCacheKey = (key: string) => `${redisPrefix}${key}`;
|
||||||
|
|
||||||
export enum CacheKeyEnum {
|
export enum CacheKeyEnum {
|
||||||
team_vector_count = 'team_vector_count'
|
team_vector_count = 'team_vector_count',
|
||||||
|
team_point_surplus = 'team_point_surplus',
|
||||||
|
team_point_total = 'team_point_total'
|
||||||
|
}
|
||||||
|
|
||||||
|
// Seconds
|
||||||
|
export enum CacheKeyEnumTime {
|
||||||
|
team_vector_count = 30 * 60,
|
||||||
|
team_point_surplus = 1 * 60,
|
||||||
|
team_point_total = 1 * 60
|
||||||
}
|
}
|
||||||
|
|
||||||
export const setRedisCache = async (
|
export const setRedisCache = async (
|
||||||
@@ -17,7 +26,6 @@ export const setRedisCache = async (
|
|||||||
return await retryFn(async () => {
|
return await retryFn(async () => {
|
||||||
try {
|
try {
|
||||||
const redis = getGlobalRedisConnection();
|
const redis = getGlobalRedisConnection();
|
||||||
|
|
||||||
if (expireSeconds) {
|
if (expireSeconds) {
|
||||||
await redis.set(getCacheKey(key), data, 'EX', expireSeconds);
|
await redis.set(getCacheKey(key), data, 'EX', expireSeconds);
|
||||||
} else {
|
} else {
|
||||||
@@ -32,7 +40,19 @@ export const setRedisCache = async (
|
|||||||
|
|
||||||
export const getRedisCache = async (key: string) => {
|
export const getRedisCache = async (key: string) => {
|
||||||
const redis = getGlobalRedisConnection();
|
const redis = getGlobalRedisConnection();
|
||||||
return await retryFn(() => redis.get(getCacheKey(key)));
|
return retryFn(() => redis.get(getCacheKey(key)));
|
||||||
|
};
|
||||||
|
|
||||||
|
// Add value to cache
|
||||||
|
export const incrValueToCache = async (key: string, increment: number) => {
|
||||||
|
if (!increment || increment === 0) return;
|
||||||
|
const redis = getGlobalRedisConnection();
|
||||||
|
try {
|
||||||
|
const exists = await redis.exists(getCacheKey(key));
|
||||||
|
if (!exists) return;
|
||||||
|
|
||||||
|
await retryFn(() => redis.incrbyfloat(getCacheKey(key), increment));
|
||||||
|
} catch (error) {}
|
||||||
};
|
};
|
||||||
|
|
||||||
export const delRedisCache = async (key: string) => {
|
export const delRedisCache = async (key: string) => {
|
||||||
|
@@ -6,7 +6,14 @@ import { type DelDatasetVectorCtrlProps, type InsertVectorProps } from './contro
|
|||||||
import { type EmbeddingModelItemType } from '@fastgpt/global/core/ai/model.d';
|
import { type EmbeddingModelItemType } from '@fastgpt/global/core/ai/model.d';
|
||||||
import { MILVUS_ADDRESS, PG_ADDRESS, OCEANBASE_ADDRESS } from './constants';
|
import { MILVUS_ADDRESS, PG_ADDRESS, OCEANBASE_ADDRESS } from './constants';
|
||||||
import { MilvusCtrl } from './milvus';
|
import { MilvusCtrl } from './milvus';
|
||||||
import { setRedisCache, getRedisCache, delRedisCache, CacheKeyEnum } from '../redis/cache';
|
import {
|
||||||
|
setRedisCache,
|
||||||
|
getRedisCache,
|
||||||
|
delRedisCache,
|
||||||
|
incrValueToCache,
|
||||||
|
CacheKeyEnum,
|
||||||
|
CacheKeyEnumTime
|
||||||
|
} from '../redis/cache';
|
||||||
import { throttle } from 'lodash';
|
import { throttle } from 'lodash';
|
||||||
import { retryFn } from '@fastgpt/global/common/system/utils';
|
import { retryFn } from '@fastgpt/global/common/system/utils';
|
||||||
|
|
||||||
@@ -23,6 +30,7 @@ const onDelCache = throttle((teamId: string) => delRedisCache(getChcheKey(teamId
|
|||||||
leading: true,
|
leading: true,
|
||||||
trailing: true
|
trailing: true
|
||||||
});
|
});
|
||||||
|
const onIncrCache = (teamId: string) => incrValueToCache(getChcheKey(teamId), 1);
|
||||||
|
|
||||||
const Vector = getVectorObj();
|
const Vector = getVectorObj();
|
||||||
|
|
||||||
@@ -40,7 +48,7 @@ export const getVectorCountByTeamId = async (teamId: string) => {
|
|||||||
|
|
||||||
const count = await Vector.getVectorCountByTeamId(teamId);
|
const count = await Vector.getVectorCountByTeamId(teamId);
|
||||||
|
|
||||||
await setRedisCache(key, count, 30 * 60);
|
await setRedisCache(key, count, CacheKeyEnumTime.team_vector_count);
|
||||||
|
|
||||||
return count;
|
return count;
|
||||||
};
|
};
|
||||||
@@ -67,7 +75,7 @@ export const insertDatasetDataVector = async ({
|
|||||||
vector: vectors[0]
|
vector: vectors[0]
|
||||||
});
|
});
|
||||||
|
|
||||||
onDelCache(props.teamId);
|
onIncrCache(props.teamId);
|
||||||
|
|
||||||
return {
|
return {
|
||||||
tokens,
|
tokens,
|
||||||
|
@@ -1,4 +1,4 @@
|
|||||||
import { getTeamPlanStatus, getTeamStandPlan } from '../../support/wallet/sub/utils';
|
import { getTeamPlanStatus, getTeamStandPlan, getTeamPoints } from '../../support/wallet/sub/utils';
|
||||||
import { MongoApp } from '../../core/app/schema';
|
import { MongoApp } from '../../core/app/schema';
|
||||||
import { MongoDataset } from '../../core/dataset/schema';
|
import { MongoDataset } from '../../core/dataset/schema';
|
||||||
import { DatasetTypeEnum } from '@fastgpt/global/core/dataset/constants';
|
import { DatasetTypeEnum } from '@fastgpt/global/core/dataset/constants';
|
||||||
@@ -10,11 +10,9 @@ import { TeamMemberStatusEnum } from '@fastgpt/global/support/user/team/constant
|
|||||||
import { getVectorCountByTeamId } from '../../common/vectorDB/controller';
|
import { getVectorCountByTeamId } from '../../common/vectorDB/controller';
|
||||||
|
|
||||||
export const checkTeamAIPoints = async (teamId: string) => {
|
export const checkTeamAIPoints = async (teamId: string) => {
|
||||||
const { standardConstants, totalPoints, usedPoints } = await getTeamPlanStatus({
|
if (!global.subPlans?.standard) return;
|
||||||
teamId
|
|
||||||
});
|
|
||||||
|
|
||||||
if (!standardConstants) return;
|
const { totalPoints, usedPoints } = await getTeamPoints({ teamId });
|
||||||
|
|
||||||
if (usedPoints >= totalPoints) {
|
if (usedPoints >= totalPoints) {
|
||||||
return Promise.reject(TeamErrEnum.aiPointsNotEnough);
|
return Promise.reject(TeamErrEnum.aiPointsNotEnough);
|
||||||
|
@@ -13,6 +13,14 @@ import dayjs from 'dayjs';
|
|||||||
import { type ClientSession } from '../../../common/mongo';
|
import { type ClientSession } from '../../../common/mongo';
|
||||||
import { addMonths } from 'date-fns';
|
import { addMonths } from 'date-fns';
|
||||||
import { readFromSecondary } from '../../../common/mongo/utils';
|
import { readFromSecondary } from '../../../common/mongo/utils';
|
||||||
|
import {
|
||||||
|
setRedisCache,
|
||||||
|
getRedisCache,
|
||||||
|
delRedisCache,
|
||||||
|
CacheKeyEnum,
|
||||||
|
CacheKeyEnumTime,
|
||||||
|
incrValueToCache
|
||||||
|
} from '../../../common/redis/cache';
|
||||||
|
|
||||||
export const getStandardPlansConfig = () => {
|
export const getStandardPlansConfig = () => {
|
||||||
return global?.subPlans?.standard;
|
return global?.subPlans?.standard;
|
||||||
@@ -168,6 +176,8 @@ export const getTeamPlanStatus = async ({
|
|||||||
? standardPlans[standardPlan.currentSubLevel]
|
? standardPlans[standardPlan.currentSubLevel]
|
||||||
: undefined;
|
: undefined;
|
||||||
|
|
||||||
|
updateTeamPointsCache({ teamId, totalPoints, surplusPoints });
|
||||||
|
|
||||||
return {
|
return {
|
||||||
[SubTypeEnum.standard]: standardPlan,
|
[SubTypeEnum.standard]: standardPlan,
|
||||||
standardConstants: standardConstants
|
standardConstants: standardConstants
|
||||||
@@ -185,3 +195,59 @@ export const getTeamPlanStatus = async ({
|
|||||||
datasetMaxSize: totalDatasetSize
|
datasetMaxSize: totalDatasetSize
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
|
export const clearTeamPointsCache = async (teamId: string) => {
|
||||||
|
const surplusCacheKey = `${CacheKeyEnum.team_point_surplus}:${teamId}`;
|
||||||
|
const totalCacheKey = `${CacheKeyEnum.team_point_total}:${teamId}`;
|
||||||
|
|
||||||
|
await Promise.all([delRedisCache(surplusCacheKey), delRedisCache(totalCacheKey)]);
|
||||||
|
};
|
||||||
|
|
||||||
|
export const incrTeamPointsCache = async ({ teamId, value }: { teamId: string; value: number }) => {
|
||||||
|
const surplusCacheKey = `${CacheKeyEnum.team_point_surplus}:${teamId}`;
|
||||||
|
await incrValueToCache(surplusCacheKey, value);
|
||||||
|
};
|
||||||
|
export const updateTeamPointsCache = async ({
|
||||||
|
teamId,
|
||||||
|
totalPoints,
|
||||||
|
surplusPoints
|
||||||
|
}: {
|
||||||
|
teamId: string;
|
||||||
|
totalPoints: number;
|
||||||
|
surplusPoints: number;
|
||||||
|
}) => {
|
||||||
|
const surplusCacheKey = `${CacheKeyEnum.team_point_surplus}:${teamId}`;
|
||||||
|
const totalCacheKey = `${CacheKeyEnum.team_point_total}:${teamId}`;
|
||||||
|
|
||||||
|
await Promise.all([
|
||||||
|
setRedisCache(surplusCacheKey, surplusPoints, CacheKeyEnumTime.team_point_surplus),
|
||||||
|
setRedisCache(totalCacheKey, totalPoints, CacheKeyEnumTime.team_point_total)
|
||||||
|
]);
|
||||||
|
};
|
||||||
|
|
||||||
|
export const getTeamPoints = async ({ teamId }: { teamId: string }) => {
|
||||||
|
const surplusCacheKey = `${CacheKeyEnum.team_point_surplus}:${teamId}`;
|
||||||
|
const totalCacheKey = `${CacheKeyEnum.team_point_total}:${teamId}`;
|
||||||
|
|
||||||
|
const [surplusCacheStr, totalCacheStr] = await Promise.all([
|
||||||
|
getRedisCache(surplusCacheKey),
|
||||||
|
getRedisCache(totalCacheKey)
|
||||||
|
]);
|
||||||
|
|
||||||
|
if (surplusCacheStr && totalCacheStr) {
|
||||||
|
const totalPoints = Number(totalCacheStr);
|
||||||
|
const surplusPoints = Number(surplusCacheStr);
|
||||||
|
return {
|
||||||
|
totalPoints,
|
||||||
|
surplusPoints,
|
||||||
|
usedPoints: totalPoints - surplusPoints
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
const planStatus = await getTeamPlanStatus({ teamId });
|
||||||
|
return {
|
||||||
|
totalPoints: planStatus.totalPoints,
|
||||||
|
surplusPoints: planStatus.totalPoints - planStatus.usedPoints,
|
||||||
|
usedPoints: planStatus.usedPoints
|
||||||
|
};
|
||||||
|
};
|
||||||
|
@@ -121,12 +121,6 @@ const Test = ({ datasetId }: { datasetId: string }) => {
|
|||||||
};
|
};
|
||||||
pushDatasetTestItem(testItem);
|
pushDatasetTestItem(testItem);
|
||||||
setDatasetTestItem(testItem);
|
setDatasetTestItem(testItem);
|
||||||
},
|
|
||||||
onError(err) {
|
|
||||||
toast({
|
|
||||||
title: getErrText(err),
|
|
||||||
status: 'error'
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
|
Reference in New Issue
Block a user