Commit 9b213115 authored by erio's avatar erio
Browse files

fix: address audit findings - cache sync, validation, consistency

- clearCreditsExhausted: sync Redis scheduler cache after DB update
- Image billing mode UI: write to per_request_price instead of image_output_price
- OpenAI RecordUsage: use BillingModelSourceRequested constant, add s.cfg nil guard
- Fix i18n key path: admin.channels.perRequestPriceRequired → admin.channels.form.perRequestPriceRequired
parent 55343473
...@@ -140,6 +140,10 @@ func (s *AntigravityGatewayService) clearCreditsExhausted(ctx context.Context, a ...@@ -140,6 +140,10 @@ func (s *AntigravityGatewayService) clearCreditsExhausted(ctx context.Context, a
}); err != nil { }); err != nil {
logger.LegacyPrintf("service.antigravity_gateway", "clear credits exhausted failed: account=%d err=%v", account.ID, err) logger.LegacyPrintf("service.antigravity_gateway", "clear credits exhausted failed: account=%d err=%v", account.ID, err)
} }
// 同步更新 Redis 调度快照,避免其他节点/请求延迟感知
if s.schedulerSnapshot != nil {
_ = s.schedulerSnapshot.UpdateAccountInCache(ctx, account)
}
} }
// classifyAntigravity429 将 Antigravity 的 429 响应归类为配额耗尽、限流或未知。 // classifyAntigravity429 将 Antigravity 的 429 响应归类为配额耗尽、限流或未知。
......
...@@ -4182,7 +4182,10 @@ func (s *OpenAIGatewayService) RecordUsage(ctx context.Context, input *OpenAIRec ...@@ -4182,7 +4182,10 @@ func (s *OpenAIGatewayService) RecordUsage(ctx context.Context, input *OpenAIRec
} }
// Get rate multiplier // Get rate multiplier
multiplier := s.cfg.Default.RateMultiplier multiplier := 1.0
if s.cfg != nil {
multiplier = s.cfg.Default.RateMultiplier
}
if apiKey.GroupID != nil && apiKey.Group != nil { if apiKey.GroupID != nil && apiKey.Group != nil {
resolver := s.userGroupRateResolver resolver := s.userGroupRateResolver
if resolver == nil { if resolver == nil {
...@@ -4200,7 +4203,7 @@ func (s *OpenAIGatewayService) RecordUsage(ctx context.Context, input *OpenAIRec ...@@ -4200,7 +4203,7 @@ func (s *OpenAIGatewayService) RecordUsage(ctx context.Context, input *OpenAIRec
if input.BillingModelSource == BillingModelSourceChannelMapped && input.ChannelMappedModel != "" { if input.BillingModelSource == BillingModelSourceChannelMapped && input.ChannelMappedModel != "" {
billingModel = input.ChannelMappedModel billingModel = input.ChannelMappedModel
} }
if input.BillingModelSource == "requested" && input.OriginalModel != "" { if input.BillingModelSource == BillingModelSourceRequested && input.OriginalModel != "" {
billingModel = input.OriginalModel billingModel = input.OriginalModel
} }
serviceTier := "" serviceTier := ""
......
...@@ -191,13 +191,13 @@ ...@@ -191,13 +191,13 @@
<!-- Image mode --> <!-- Image mode -->
<div v-else-if="entry.billing_mode === 'image'"> <div v-else-if="entry.billing_mode === 'image'">
<!-- Default image price --> <!-- Default image price (per-request, same as per_request mode) -->
<label class="mt-3 block text-xs font-medium text-gray-500 dark:text-gray-400"> <label class="mt-3 block text-xs font-medium text-gray-500 dark:text-gray-400">
{{ t('admin.channels.form.defaultImagePrice', '默认图片价格(未命中层级时使用)') }} {{ t('admin.channels.form.defaultImagePrice', '默认图片价格(未命中层级时使用)') }}
<span class="ml-1 font-normal text-gray-400">$</span> <span class="ml-1 font-normal text-gray-400">$</span>
</label> </label>
<div class="mt-1 w-48"> <div class="mt-1 w-48">
<input :value="entry.image_output_price" @input="emitField('image_output_price', ($event.target as HTMLInputElement).value)" <input :value="entry.per_request_price" @input="emitField('per_request_price', ($event.target as HTMLInputElement).value)"
type="number" step="any" min="0" class="input text-sm" :placeholder="t('admin.channels.form.pricePlaceholder', '默认')" /> type="number" step="any" min="0" class="input text-sm" :placeholder="t('admin.channels.form.pricePlaceholder', '默认')" />
</div> </div>
......
...@@ -916,7 +916,7 @@ async function handleSubmit() { ...@@ -916,7 +916,7 @@ async function handleSubmit() {
if ((entry.billing_mode === 'per_request' || entry.billing_mode === 'image') && if ((entry.billing_mode === 'per_request' || entry.billing_mode === 'image') &&
(entry.per_request_price == null || entry.per_request_price === '') && (entry.per_request_price == null || entry.per_request_price === '') &&
(!entry.intervals || entry.intervals.length === 0)) { (!entry.intervals || entry.intervals.length === 0)) {
appStore.showError(t('admin.channels.perRequestPriceRequired', '按次/图片计费模式必须设置默认价格或至少一个计费层级')) appStore.showError(t('admin.channels.form.perRequestPriceRequired', '按次/图片计费模式必须设置默认价格或至少一个计费层级'))
return return
} }
} }
......
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 to comment