Files
sub2api/backend/internal/service/gateway_request_pricing.go
T
李建琦 6d655c9903
Release / update-version (push) Has been cancelled
Release / build-frontend (push) Has been cancelled
Release / release (push) Has been cancelled
Release / sync-version-file (push) Has been cancelled
CI / shell (push) Canceled after 0s
CI / test (push) Canceled after 0s
CI / frontend (push) Canceled after 0s
CI / golangci-lint (push) Canceled after 0s
Security Scan / backend-security (push) Canceled after 0s
Security Scan / frontend-security (push) Canceled after 0s
Sub2API v1.0 - AI API 网关(二开初始版本,基于上游 Wei-Shaw/sub2api)
2026-08-21 18:30:13 +08:00

56 lines
1.9 KiB
Go

package service
import (
"context"
"time"
"github.com/Wei-Shaw/sub2api/internal/pkg/ctxkey"
"github.com/Wei-Shaw/sub2api/internal/pkg/timezone"
)
type gatewayTokenRequestPricingAtCtxKey struct{}
type gatewayTokenRequestBillingGroupCtxKey struct{}
// WithGatewayTokenRequestPricing marks a shared-gateway request as token billed
// and freezes the downstream pricing instant for its whole lifetime. Media and
// metadata-only handlers deliberately do not call this helper.
func WithGatewayTokenRequestPricing(ctx context.Context) (context.Context, time.Time) {
if ctx == nil {
ctx = context.Background()
}
pricingAt := timezone.Now()
ctx = context.WithValue(ctx, gatewayTokenRequestPricingAtCtxKey{}, pricingAt)
// 调度过程中可能因 fallback/composite 路由覆盖 ctxkey.Group;计费 D 仍必须
// 使用认证时刻的父分组,和最终 RecordUsage 的计费归属保持一致。
if group, ok := ctx.Value(ctxkey.Group).(*Group); ok && IsGroupContextValid(group) {
ctx = context.WithValue(ctx, gatewayTokenRequestBillingGroupCtxKey{}, group)
}
return ctx, pricingAt
}
func gatewayTokenRequestPricingAtFromContext(ctx context.Context) (time.Time, bool) {
if ctx == nil {
return time.Time{}, false
}
pricingAt, ok := ctx.Value(gatewayTokenRequestPricingAtCtxKey{}).(time.Time)
return pricingAt, ok && !pricingAt.IsZero()
}
// GatewayTokenRequestPricingAtFromContext exposes the frozen instant to
// handlers before they detach asynchronous usage-recording work.
func GatewayTokenRequestPricingAtFromContext(ctx context.Context) time.Time {
pricingAt, _ := gatewayTokenRequestPricingAtFromContext(ctx)
return pricingAt
}
func gatewayTokenRequestBillingGroupFromContext(ctx context.Context) *Group {
if ctx == nil {
return nil
}
group, _ := ctx.Value(gatewayTokenRequestBillingGroupCtxKey{}).(*Group)
if IsGroupContextValid(group) {
return group
}
return nil
}