Commit c9ce1210 by tbphp

feat: 优化代码,去除多余注释和修改

parent b32ed556
This diff is collapsed. Click to expand it.
...@@ -19,25 +19,20 @@ const ( ...@@ -19,25 +19,20 @@ const (
ModelRequestRateLimitSuccessCountMark = "MRRLS" ModelRequestRateLimitSuccessCountMark = "MRRLS"
) )
// 检查Redis中的请求限制
func checkRedisRateLimit(ctx context.Context, rdb *redis.Client, key string, maxCount int, duration int64) (bool, error) { func checkRedisRateLimit(ctx context.Context, rdb *redis.Client, key string, maxCount int, duration int64) (bool, error) {
// 如果maxCount为0,表示不限制
if maxCount == 0 { if maxCount == 0 {
return true, nil return true, nil
} }
// 获取当前计数
length, err := rdb.LLen(ctx, key).Result() length, err := rdb.LLen(ctx, key).Result()
if err != nil { if err != nil {
return false, err return false, err
} }
// 如果未达到限制,允许请求
if length < int64(maxCount) { if length < int64(maxCount) {
return true, nil return true, nil
} }
// 检查时间窗口
oldTimeStr, _ := rdb.LIndex(ctx, key, -1).Result() oldTimeStr, _ := rdb.LIndex(ctx, key, -1).Result()
oldTime, err := time.Parse(timeFormat, oldTimeStr) oldTime, err := time.Parse(timeFormat, oldTimeStr)
if err != nil { if err != nil {
...@@ -49,7 +44,6 @@ func checkRedisRateLimit(ctx context.Context, rdb *redis.Client, key string, max ...@@ -49,7 +44,6 @@ func checkRedisRateLimit(ctx context.Context, rdb *redis.Client, key string, max
if err != nil { if err != nil {
return false, err return false, err
} }
// 如果在时间窗口内已达到限制,拒绝请求
subTime := nowTime.Sub(oldTime).Seconds() subTime := nowTime.Sub(oldTime).Seconds()
if int64(subTime) < duration { if int64(subTime) < duration {
rdb.Expire(ctx, key, time.Duration(setting.ModelRequestRateLimitDurationMinutes)*time.Minute) rdb.Expire(ctx, key, time.Duration(setting.ModelRequestRateLimitDurationMinutes)*time.Minute)
...@@ -59,9 +53,7 @@ func checkRedisRateLimit(ctx context.Context, rdb *redis.Client, key string, max ...@@ -59,9 +53,7 @@ func checkRedisRateLimit(ctx context.Context, rdb *redis.Client, key string, max
return true, nil return true, nil
} }
// 记录Redis请求
func recordRedisRequest(ctx context.Context, rdb *redis.Client, key string, maxCount int) { func recordRedisRequest(ctx context.Context, rdb *redis.Client, key string, maxCount int) {
// 如果maxCount为0,不记录请求
if maxCount == 0 { if maxCount == 0 {
return return
} }
...@@ -72,14 +64,12 @@ func recordRedisRequest(ctx context.Context, rdb *redis.Client, key string, maxC ...@@ -72,14 +64,12 @@ func recordRedisRequest(ctx context.Context, rdb *redis.Client, key string, maxC
rdb.Expire(ctx, key, time.Duration(setting.ModelRequestRateLimitDurationMinutes)*time.Minute) rdb.Expire(ctx, key, time.Duration(setting.ModelRequestRateLimitDurationMinutes)*time.Minute)
} }
// Redis限流处理器
func redisRateLimitHandler(duration int64, totalMaxCount, successMaxCount int) gin.HandlerFunc { func redisRateLimitHandler(duration int64, totalMaxCount, successMaxCount int) gin.HandlerFunc {
return func(c *gin.Context) { return func(c *gin.Context) {
userId := strconv.Itoa(c.GetInt("id")) userId := strconv.Itoa(c.GetInt("id"))
ctx := context.Background() ctx := context.Background()
rdb := common.RDB rdb := common.RDB
// 1. 检查成功请求数限制
successKey := fmt.Sprintf("rateLimit:%s:%s", ModelRequestRateLimitSuccessCountMark, userId) successKey := fmt.Sprintf("rateLimit:%s:%s", ModelRequestRateLimitSuccessCountMark, userId)
allowed, err := checkRedisRateLimit(ctx, rdb, successKey, successMaxCount, duration) allowed, err := checkRedisRateLimit(ctx, rdb, successKey, successMaxCount, duration)
if err != nil { if err != nil {
...@@ -92,9 +82,7 @@ func redisRateLimitHandler(duration int64, totalMaxCount, successMaxCount int) g ...@@ -92,9 +82,7 @@ func redisRateLimitHandler(duration int64, totalMaxCount, successMaxCount int) g
return return
} }
//2.检查总请求数限制并记录总请求(当totalMaxCount为0时会自动跳过,使用令牌桶限流器
totalKey := fmt.Sprintf("rateLimit:%s", userId) totalKey := fmt.Sprintf("rateLimit:%s", userId)
// 初始化
tb := limiter.New(ctx, rdb) tb := limiter.New(ctx, rdb)
allowed, err = tb.Allow( allowed, err = tb.Allow(
ctx, ctx,
...@@ -114,17 +102,14 @@ func redisRateLimitHandler(duration int64, totalMaxCount, successMaxCount int) g ...@@ -114,17 +102,14 @@ func redisRateLimitHandler(duration int64, totalMaxCount, successMaxCount int) g
abortWithOpenAiMessage(c, http.StatusTooManyRequests, fmt.Sprintf("您已达到总请求数限制:%d分钟内最多请求%d次,包括失败次数,请检查您的请求是否正确", setting.ModelRequestRateLimitDurationMinutes, totalMaxCount)) abortWithOpenAiMessage(c, http.StatusTooManyRequests, fmt.Sprintf("您已达到总请求数限制:%d分钟内最多请求%d次,包括失败次数,请检查您的请求是否正确", setting.ModelRequestRateLimitDurationMinutes, totalMaxCount))
} }
// 4. 处理请求
c.Next() c.Next()
// 5. 如果请求成功,记录成功请求
if c.Writer.Status() < 400 { if c.Writer.Status() < 400 {
recordRedisRequest(ctx, rdb, successKey, successMaxCount) recordRedisRequest(ctx, rdb, successKey, successMaxCount)
} }
} }
} }
// 内存限流处理器
func memoryRateLimitHandler(duration int64, totalMaxCount, successMaxCount int) gin.HandlerFunc { func memoryRateLimitHandler(duration int64, totalMaxCount, successMaxCount int) gin.HandlerFunc {
inMemoryRateLimiter.Init(time.Duration(setting.ModelRequestRateLimitDurationMinutes) * time.Minute) inMemoryRateLimiter.Init(time.Duration(setting.ModelRequestRateLimitDurationMinutes) * time.Minute)
...@@ -133,15 +118,12 @@ func memoryRateLimitHandler(duration int64, totalMaxCount, successMaxCount int) ...@@ -133,15 +118,12 @@ func memoryRateLimitHandler(duration int64, totalMaxCount, successMaxCount int)
totalKey := ModelRequestRateLimitCountMark + userId totalKey := ModelRequestRateLimitCountMark + userId
successKey := ModelRequestRateLimitSuccessCountMark + userId successKey := ModelRequestRateLimitSuccessCountMark + userId
// 1. 检查总请求数限制(当totalMaxCount为0时跳过)
if totalMaxCount > 0 && !inMemoryRateLimiter.Request(totalKey, totalMaxCount, duration) { if totalMaxCount > 0 && !inMemoryRateLimiter.Request(totalKey, totalMaxCount, duration) {
c.Status(http.StatusTooManyRequests) c.Status(http.StatusTooManyRequests)
c.Abort() c.Abort()
return return
} }
// 2. 检查成功请求数限制
// 使用一个临时key来检查限制,这样可以避免实际记录
checkKey := successKey + "_check" checkKey := successKey + "_check"
if !inMemoryRateLimiter.Request(checkKey, successMaxCount, duration) { if !inMemoryRateLimiter.Request(checkKey, successMaxCount, duration) {
c.Status(http.StatusTooManyRequests) c.Status(http.StatusTooManyRequests)
...@@ -149,54 +131,47 @@ func memoryRateLimitHandler(duration int64, totalMaxCount, successMaxCount int) ...@@ -149,54 +131,47 @@ func memoryRateLimitHandler(duration int64, totalMaxCount, successMaxCount int)
return return
} }
// 3. 处理请求
c.Next() c.Next()
// 4. 如果请求成功,记录到实际的成功请求计数中
if c.Writer.Status() < 400 { if c.Writer.Status() < 400 {
inMemoryRateLimiter.Request(successKey, successMaxCount, duration) inMemoryRateLimiter.Request(successKey, successMaxCount, duration)
} }
} }
} }
// ModelRequestRateLimit 模型请求限流中间件
func ModelRequestRateLimit() func(c *gin.Context) { func ModelRequestRateLimit() func(c *gin.Context) {
return func(c *gin.Context) { return func(c *gin.Context) {
// 在每个请求时检查是否启用限流
if !setting.ModelRequestRateLimitEnabled { if !setting.ModelRequestRateLimitEnabled {
c.Next() c.Next()
return return
} }
// 计算通用限流参数
duration := int64(setting.ModelRequestRateLimitDurationMinutes * 60) duration := int64(setting.ModelRequestRateLimitDurationMinutes * 60)
// 获取用户组
group := c.GetString("token_group") group := c.GetString("token_group")
if group == "" { if group == "" {
group = c.GetString("group") group = c.GetString("group")
} }
if group == "" { if group == "" {
group = "default" // 默认组 group = "default"
} }
// 尝试获取用户组特定的限制 finalTotalCount := setting.ModelRequestRateLimitCount
groupTotalCount, groupSuccessCount, found := setting.GetGroupRateLimit(group) finalSuccessCount := setting.ModelRequestRateLimitSuccessCount
foundGroupLimit := false
// 确定最终的限制值
finalTotalCount := setting.ModelRequestRateLimitCount // 默认使用全局总次数限制
finalSuccessCount := setting.ModelRequestRateLimitSuccessCount // 默认使用全局成功次数限制
groupTotalCount, groupSuccessCount, found := setting.GetGroupRateLimit(group)
if found { if found {
// 如果找到用户组特定限制,则使用它们
finalTotalCount = groupTotalCount finalTotalCount = groupTotalCount
finalSuccessCount = groupSuccessCount finalSuccessCount = groupSuccessCount
foundGroupLimit = true
common.LogWarn(c.Request.Context(), fmt.Sprintf("Using rate limit for group '%s': total=%d, success=%d", group, finalTotalCount, finalSuccessCount)) common.LogWarn(c.Request.Context(), fmt.Sprintf("Using rate limit for group '%s': total=%d, success=%d", group, finalTotalCount, finalSuccessCount))
} else { }
if !foundGroupLimit {
common.LogInfo(c.Request.Context(), fmt.Sprintf("No specific rate limit found for group '%s', using global limits: total=%d, success=%d", group, finalTotalCount, finalSuccessCount)) common.LogInfo(c.Request.Context(), fmt.Sprintf("No specific rate limit found for group '%s', using global limits: total=%d, success=%d", group, finalTotalCount, finalSuccessCount))
} }
// 根据存储类型选择并执行限流处理器,传入最终确定的限制值
if common.RedisEnabled { if common.RedisEnabled {
redisRateLimitHandler(duration, finalTotalCount, finalSuccessCount)(c) redisRateLimitHandler(duration, finalTotalCount, finalSuccessCount)(c)
} else { } else {
......
...@@ -94,11 +94,12 @@ func InitOptionMap() { ...@@ -94,11 +94,12 @@ func InitOptionMap() {
common.OptionMap["ModelRequestRateLimitCount"] = strconv.Itoa(setting.ModelRequestRateLimitCount) common.OptionMap["ModelRequestRateLimitCount"] = strconv.Itoa(setting.ModelRequestRateLimitCount)
common.OptionMap["ModelRequestRateLimitDurationMinutes"] = strconv.Itoa(setting.ModelRequestRateLimitDurationMinutes) common.OptionMap["ModelRequestRateLimitDurationMinutes"] = strconv.Itoa(setting.ModelRequestRateLimitDurationMinutes)
common.OptionMap["ModelRequestRateLimitSuccessCount"] = strconv.Itoa(setting.ModelRequestRateLimitSuccessCount) common.OptionMap["ModelRequestRateLimitSuccessCount"] = strconv.Itoa(setting.ModelRequestRateLimitSuccessCount)
jsonBytes, _ := json.Marshal(map[string][2]int{})
common.OptionMap["ModelRequestRateLimitGroup"] = string(jsonBytes)
common.OptionMap["ModelRatio"] = operation_setting.ModelRatio2JSONString() common.OptionMap["ModelRatio"] = operation_setting.ModelRatio2JSONString()
common.OptionMap["ModelPrice"] = operation_setting.ModelPrice2JSONString() common.OptionMap["ModelPrice"] = operation_setting.ModelPrice2JSONString()
common.OptionMap["CacheRatio"] = operation_setting.CacheRatio2JSONString() common.OptionMap["CacheRatio"] = operation_setting.CacheRatio2JSONString()
common.OptionMap["GroupRatio"] = setting.GroupRatio2JSONString() common.OptionMap["GroupRatio"] = setting.GroupRatio2JSONString()
common.OptionMap[setting.ModelRequestRateLimitGroupKey] = "{}" // 添加用户组速率限制默认值
common.OptionMap["UserUsableGroups"] = setting.UserUsableGroups2JSONString() common.OptionMap["UserUsableGroups"] = setting.UserUsableGroups2JSONString()
common.OptionMap["CompletionRatio"] = operation_setting.CompletionRatio2JSONString() common.OptionMap["CompletionRatio"] = operation_setting.CompletionRatio2JSONString()
common.OptionMap["TopUpLink"] = common.TopUpLink common.OptionMap["TopUpLink"] = common.TopUpLink
...@@ -153,47 +154,31 @@ func SyncOptions(frequency int) { ...@@ -153,47 +154,31 @@ func SyncOptions(frequency int) {
} }
func UpdateOption(key string, value string) error { func UpdateOption(key string, value string) error {
originalValue := value // 保存原始值以备后用 originalValue := value
// Validate and format specific keys before saving if key == "ModelRequestRateLimitGroup" {
if key == setting.ModelRequestRateLimitGroupKey {
var cfg map[string][2]int var cfg map[string][2]int
// Validate the JSON structure first using the original value
err := json.Unmarshal([]byte(originalValue), &cfg) err := json.Unmarshal([]byte(originalValue), &cfg)
if err != nil { if err != nil {
// 提供更具体的错误信息
return fmt.Errorf("无效的 JSON 格式 for %s: %w", key, err) return fmt.Errorf("无效的 JSON 格式 for %s: %w", key, err)
} }
// TODO: 可以添加更细致的结构验证,例如检查数组长度是否为2,值是否为非负数等。
// if !isValidModelRequestRateLimitGroupConfig(cfg) {
// return fmt.Errorf("无效的配置值 for %s", key)
// }
// If valid, format the JSON before saving
formattedValueBytes, marshalErr := json.MarshalIndent(cfg, "", " ") formattedValueBytes, marshalErr := json.MarshalIndent(cfg, "", " ")
if marshalErr != nil { if marshalErr != nil {
// This should ideally not happen if validation passed, but handle defensively
return fmt.Errorf("failed to marshal validated %s config: %w", key, marshalErr) return fmt.Errorf("failed to marshal validated %s config: %w", key, marshalErr)
} }
value = string(formattedValueBytes) // Use formatted JSON for saving and memory update value = string(formattedValueBytes)
} }
// Save to database
option := Option{ option := Option{
Key: key, Key: key,
} }
// https://gorm.io/docs/update.html#Save-All-Fields
DB.FirstOrCreate(&option, Option{Key: key}) DB.FirstOrCreate(&option, Option{Key: key})
option.Value = value option.Value = value
// Save is a combination function.
// If save value does not contain primary key, it will execute Create,
// otherwise it will execute Update (with all fields).
if err := DB.Save(&option).Error; err != nil { if err := DB.Save(&option).Error; err != nil {
return fmt.Errorf("保存选项 %s 到数据库失败: %w", key, err) // 添加错误上下文 return fmt.Errorf("保存选项 %s 到数据库失败: %w", key, err)
} }
// Update OptionMap in memory using the potentially formatted value
// updateOptionMap 会处理内存中 setting.ModelRequestRateLimitGroupConfig 的更新
return updateOptionMap(key, value) return updateOptionMap(key, value)
} }
...@@ -370,6 +355,8 @@ func updateOptionMap(key string, value string) (err error) { ...@@ -370,6 +355,8 @@ func updateOptionMap(key string, value string) (err error) {
setting.ModelRequestRateLimitDurationMinutes, _ = strconv.Atoi(value) setting.ModelRequestRateLimitDurationMinutes, _ = strconv.Atoi(value)
case "ModelRequestRateLimitSuccessCount": case "ModelRequestRateLimitSuccessCount":
setting.ModelRequestRateLimitSuccessCount, _ = strconv.Atoi(value) setting.ModelRequestRateLimitSuccessCount, _ = strconv.Atoi(value)
case "ModelRequestRateLimitGroup":
err = setting.UpdateModelRequestRateLimitGroup(value)
case "RetryTimes": case "RetryTimes":
common.RetryTimes, _ = strconv.Atoi(value) common.RetryTimes, _ = strconv.Atoi(value)
case "DataExportInterval": case "DataExportInterval":
...@@ -404,15 +391,6 @@ func updateOptionMap(key string, value string) (err error) { ...@@ -404,15 +391,6 @@ func updateOptionMap(key string, value string) (err error) {
operation_setting.AutomaticDisableKeywordsFromString(value) operation_setting.AutomaticDisableKeywordsFromString(value)
case "StreamCacheQueueLength": case "StreamCacheQueueLength":
setting.StreamCacheQueueLength, _ = strconv.Atoi(value) setting.StreamCacheQueueLength, _ = strconv.Atoi(value)
case setting.ModelRequestRateLimitGroupKey:
// Use the (potentially formatted) value passed from UpdateOption
// to update the actual configuration in memory.
// This is the single point where the memory state for this specific setting is updated.
err = setting.UpdateModelRequestRateLimitGroupConfig(value)
if err != nil {
// 添加错误上下文
err = fmt.Errorf("更新内存中的 %s 配置失败: %w", key, err)
}
} }
return err return err
} }
......
...@@ -11,24 +11,17 @@ var ModelRequestRateLimitEnabled = false ...@@ -11,24 +11,17 @@ var ModelRequestRateLimitEnabled = false
var ModelRequestRateLimitDurationMinutes = 1 var ModelRequestRateLimitDurationMinutes = 1
var ModelRequestRateLimitCount = 0 var ModelRequestRateLimitCount = 0
var ModelRequestRateLimitSuccessCount = 1000 var ModelRequestRateLimitSuccessCount = 1000
var ModelRequestRateLimitGroup map[string][2]int
// ModelRequestRateLimitGroupKey 定义了模型请求按组速率限制的配置键
const ModelRequestRateLimitGroupKey = "ModelRequestRateLimitGroup"
// ModelRequestRateLimitGroupConfig 存储按用户组解析后的速率限制配置
// map[groupName][2]int{totalCount, successCount}
var ModelRequestRateLimitGroupConfig map[string][2]int
var ModelRequestRateLimitGroupMutex sync.RWMutex var ModelRequestRateLimitGroupMutex sync.RWMutex
// UpdateModelRequestRateLimitGroupConfig 解析、校验并更新内存中的用户组速率限制配置 func UpdateModelRequestRateLimitGroup(jsonStr string) error {
func UpdateModelRequestRateLimitGroupConfig(jsonStr string) error {
ModelRequestRateLimitGroupMutex.Lock() ModelRequestRateLimitGroupMutex.Lock()
defer ModelRequestRateLimitGroupMutex.Unlock() defer ModelRequestRateLimitGroupMutex.Unlock()
var newConfig map[string][2]int var newConfig map[string][2]int
if jsonStr == "" || jsonStr == "{}" { if jsonStr == "" || jsonStr == "{}" {
// 如果配置为空或空JSON对象,则清空内存配置 ModelRequestRateLimitGroup = make(map[string][2]int)
ModelRequestRateLimitGroupConfig = make(map[string][2]int)
common.SysLog("Model request rate limit group config cleared") common.SysLog("Model request rate limit group config cleared")
return nil return nil
} }
...@@ -38,37 +31,19 @@ func UpdateModelRequestRateLimitGroupConfig(jsonStr string) error { ...@@ -38,37 +31,19 @@ func UpdateModelRequestRateLimitGroupConfig(jsonStr string) error {
return fmt.Errorf("failed to unmarshal ModelRequestRateLimitGroup config: %w", err) return fmt.Errorf("failed to unmarshal ModelRequestRateLimitGroup config: %w", err)
} }
// 校验配置值 ModelRequestRateLimitGroup = newConfig
for group, limits := range newConfig {
if len(limits) != 2 {
return fmt.Errorf("invalid config for group '%s': limits array length must be 2", group)
}
if limits[1] <= 0 { // successCount must be greater than 0
return fmt.Errorf("invalid config for group '%s': successCount (limits[1]) must be greater than 0", group)
}
if limits[0] < 0 { // totalCount can be 0 (no limit) or positive
return fmt.Errorf("invalid config for group '%s': totalCount (limits[0]) cannot be negative", group)
}
if limits[0] > 0 && limits[0] < limits[1] { // If totalCount is set, it must be >= successCount
return fmt.Errorf("invalid config for group '%s': totalCount (limits[0]) must be greater than or equal to successCount (limits[1]) when totalCount > 0", group)
}
}
ModelRequestRateLimitGroupConfig = newConfig
common.SysLog("Model request rate limit group config updated")
return nil return nil
} }
// GetGroupRateLimit 安全地获取指定用户组的速率限制值
func GetGroupRateLimit(group string) (totalCount, successCount int, found bool) { func GetGroupRateLimit(group string) (totalCount, successCount int, found bool) {
ModelRequestRateLimitGroupMutex.RLock() ModelRequestRateLimitGroupMutex.RLock()
defer ModelRequestRateLimitGroupMutex.RUnlock() defer ModelRequestRateLimitGroupMutex.RUnlock()
if ModelRequestRateLimitGroupConfig == nil { if ModelRequestRateLimitGroup == nil {
return 0, 0, false // 配置尚未初始化 return 0, 0, false
} }
limits, found := ModelRequestRateLimitGroupConfig[group] limits, found := ModelRequestRateLimitGroup[group]
if !found { if !found {
return 0, 0, false return 0, 0, false
} }
......
...@@ -13,7 +13,7 @@ const RateLimitSetting = () => { ...@@ -13,7 +13,7 @@ const RateLimitSetting = () => {
ModelRequestRateLimitCount: 0, ModelRequestRateLimitCount: 0,
ModelRequestRateLimitSuccessCount: 1000, ModelRequestRateLimitSuccessCount: 1000,
ModelRequestRateLimitDurationMinutes: 1, ModelRequestRateLimitDurationMinutes: 1,
ModelRequestRateLimitGroup: {}, ModelRequestRateLimitGroup: '{}',
}); });
let [loading, setLoading] = useState(false); let [loading, setLoading] = useState(false);
...@@ -24,13 +24,15 @@ const RateLimitSetting = () => { ...@@ -24,13 +24,15 @@ const RateLimitSetting = () => {
if (success) { if (success) {
let newInputs = {}; let newInputs = {};
data.forEach((item) => { data.forEach((item) => {
// 检查 key 是否在初始 inputs 中定义
if (Object.prototype.hasOwnProperty.call(inputs, item.key)) {
if (item.key.endsWith('Enabled')) { if (item.key.endsWith('Enabled')) {
newInputs[item.key] = item.value === 'true' ? true : false; newInputs[item.key] = item.value === 'true';
} else { } else {
newInputs[item.key] = item.value; newInputs[item.key] = item.value;
} }
}
}); });
setInputs(newInputs); setInputs(newInputs);
} else { } else {
showError(message); showError(message);
...@@ -40,7 +42,6 @@ const RateLimitSetting = () => { ...@@ -40,7 +42,6 @@ const RateLimitSetting = () => {
try { try {
setLoading(true); setLoading(true);
await getOptions(); await getOptions();
// showSuccess('刷新成功');
} catch (error) { } catch (error) {
showError('刷新失败'); showError('刷新失败');
} finally { } finally {
...@@ -55,13 +56,12 @@ const RateLimitSetting = () => { ...@@ -55,13 +56,12 @@ const RateLimitSetting = () => {
return ( return (
<> <>
<Spin spinning={loading} size='large'> <Spin spinning={loading} size='large'>
{/* AI请求速率限制 */}
<Card style={{ marginTop: '10px' }}> <Card style={{ marginTop: '10px' }}>
<RequestRateLimit options={inputs} refresh={onRefresh} /> <RequestRateLimit options={inputs} refresh={onRefresh} />
</Card> </Card>
</Spin> </Spin>
</> </>
); );
}; };
export default RateLimitSetting; export default RateLimitSetting;
...@@ -18,7 +18,7 @@ export default function RequestRateLimit(props) { ...@@ -18,7 +18,7 @@ export default function RequestRateLimit(props) {
ModelRequestRateLimitCount: -1, ModelRequestRateLimitCount: -1,
ModelRequestRateLimitSuccessCount: 1000, ModelRequestRateLimitSuccessCount: 1000,
ModelRequestRateLimitDurationMinutes: 1, ModelRequestRateLimitDurationMinutes: 1,
ModelRequestRateLimitGroup: '{}', // 添加新字段并设置默认值 ModelRequestRateLimitGroup: '{}',
}); });
const refForm = useRef(); const refForm = useRef();
const [inputsRow, setInputsRow] = useState(inputs); const [inputsRow, setInputsRow] = useState(inputs);
...@@ -33,13 +33,11 @@ export default function RequestRateLimit(props) { ...@@ -33,13 +33,11 @@ export default function RequestRateLimit(props) {
} else { } else {
value = inputs[item.key]; value = inputs[item.key];
} }
// 校验 ModelRequestRateLimitGroup 是否为有效的 JSON 对象字符串
if (item.key === 'ModelRequestRateLimitGroup') { if (item.key === 'ModelRequestRateLimitGroup') {
try { try {
JSON.parse(value); JSON.parse(value);
} catch (e) { } catch (e) {
showError(t('用户组速率限制配置不是有效的 JSON 格式!')); showError(t('用户组速率限制配置不是有效的 JSON 格式!'));
// 阻止请求发送
return Promise.reject('Invalid JSON format'); return Promise.reject('Invalid JSON format');
} }
} }
...@@ -49,11 +47,9 @@ export default function RequestRateLimit(props) { ...@@ -49,11 +47,9 @@ export default function RequestRateLimit(props) {
}); });
}); });
// 过滤掉无效的请求(例如,无效的 JSON)
const validRequests = requestQueue.filter(req => req !== null && req !== undefined && typeof req.then === 'function'); const validRequests = requestQueue.filter(req => req !== null && req !== undefined && typeof req.then === 'function');
if (validRequests.length === 0 && requestQueue.length > 0) { if (validRequests.length === 0 && requestQueue.length > 0) {
// 如果所有请求都被过滤掉了(因为 JSON 无效),则不继续执行
return; return;
} }
...@@ -68,11 +64,9 @@ export default function RequestRateLimit(props) { ...@@ -68,11 +64,9 @@ export default function RequestRateLimit(props) {
} }
showSuccess(t('保存成功')); showSuccess(t('保存成功'));
props.refresh(); props.refresh();
// 更新 inputsRow 以反映保存后的状态
setInputsRow(structuredClone(inputs)); setInputsRow(structuredClone(inputs));
}) })
.catch((error) => { .catch((error) => {
// 检查是否是由于无效 JSON 导致的错误
if (error !== 'Invalid JSON format') { if (error !== 'Invalid JSON format') {
showError(t('保存失败,请重试')); showError(t('保存失败,请重试'));
} }
...@@ -85,17 +79,16 @@ export default function RequestRateLimit(props) { ...@@ -85,17 +79,16 @@ export default function RequestRateLimit(props) {
useEffect(() => { useEffect(() => {
const currentInputs = {}; const currentInputs = {};
for (let key in props.options) { for (let key in props.options) {
if (Object.keys(inputs).includes(key)) { if (Object.prototype.hasOwnProperty.call(inputs, key)) { // 使用 hasOwnProperty 检查
currentInputs[key] = props.options[key]; currentInputs[key] = props.options[key];
} }
} }
setInputs(currentInputs); setInputs(currentInputs);
setInputsRow(structuredClone(currentInputs)); setInputsRow(structuredClone(currentInputs));
// 检查 refForm.current 是否存在
if (refForm.current) { if (refForm.current) {
refForm.current.setValues(currentInputs); refForm.current.setValues(currentInputs);
} }
}, [props.options]); // 依赖项保持不变,因为 inputs 状态的结构已固定 }, [props.options]);
return ( return (
<> <>
...@@ -175,16 +168,15 @@ export default function RequestRateLimit(props) { ...@@ -175,16 +168,15 @@ export default function RequestRateLimit(props) {
/> />
</Col> </Col>
</Row> </Row>
{/* 用户组速率限制配置项 */} <Row style={{ marginTop: 15 }}>
<Row>
<Col span={24}> <Col span={24}>
<Form.TextArea <Form.TextArea
label={t('用户组速率限制 (JSON)')} label={t('用户组速率限制 (JSON)')}
field={'ModelRequestRateLimitGroup'} field={'ModelRequestRateLimitGroup'}
placeholder={t( // 更新 placeholder placeholder={t(
'请输入 JSON 格式的用户组限制,例如:\n{\n "default": [200, 100],\n "vip": [1000, 500]\n}', '请输入 JSON 格式的用户组限制,例如:\n{\n "default": [200, 100],\n "vip": [1000, 500]\n}',
)} )}
extraText={ // 更新 extraText extraText={
<div> <div>
<p>{t('说明:')}</p> <p>{t('说明:')}</p>
<ul> <ul>
...@@ -203,7 +195,7 @@ export default function RequestRateLimit(props) { ...@@ -203,7 +195,7 @@ export default function RequestRateLimit(props) {
onChange={(value) => { onChange={(value) => {
setInputs({ setInputs({
...inputs, ...inputs,
ModelRequestRateLimitGroup: value, // 直接更新字符串值 ModelRequestRateLimitGroup: value,
}); });
}} }}
/> />
...@@ -219,4 +211,4 @@ export default function RequestRateLimit(props) { ...@@ -219,4 +211,4 @@ export default function RequestRateLimit(props) {
</Spin> </Spin>
</> </>
); );
} }
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or sign in to comment