gateway_request_pricing.go 1.9 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455
  1. package service
  2. import (
  3. "context"
  4. "time"
  5. "github.com/Wei-Shaw/sub2api/internal/pkg/ctxkey"
  6. "github.com/Wei-Shaw/sub2api/internal/pkg/timezone"
  7. )
  8. type gatewayTokenRequestPricingAtCtxKey struct{}
  9. type gatewayTokenRequestBillingGroupCtxKey struct{}
  10. // WithGatewayTokenRequestPricing marks a shared-gateway request as token billed
  11. // and freezes the downstream pricing instant for its whole lifetime. Media and
  12. // metadata-only handlers deliberately do not call this helper.
  13. func WithGatewayTokenRequestPricing(ctx context.Context) (context.Context, time.Time) {
  14. if ctx == nil {
  15. ctx = context.Background()
  16. }
  17. pricingAt := timezone.Now()
  18. ctx = context.WithValue(ctx, gatewayTokenRequestPricingAtCtxKey{}, pricingAt)
  19. // 调度过程中可能因 fallback/composite 路由覆盖 ctxkey.Group;计费 D 仍必须
  20. // 使用认证时刻的父分组,和最终 RecordUsage 的计费归属保持一致。
  21. if group, ok := ctx.Value(ctxkey.Group).(*Group); ok && IsGroupContextValid(group) {
  22. ctx = context.WithValue(ctx, gatewayTokenRequestBillingGroupCtxKey{}, group)
  23. }
  24. return ctx, pricingAt
  25. }
  26. func gatewayTokenRequestPricingAtFromContext(ctx context.Context) (time.Time, bool) {
  27. if ctx == nil {
  28. return time.Time{}, false
  29. }
  30. pricingAt, ok := ctx.Value(gatewayTokenRequestPricingAtCtxKey{}).(time.Time)
  31. return pricingAt, ok && !pricingAt.IsZero()
  32. }
  33. // GatewayTokenRequestPricingAtFromContext exposes the frozen instant to
  34. // handlers before they detach asynchronous usage-recording work.
  35. func GatewayTokenRequestPricingAtFromContext(ctx context.Context) time.Time {
  36. pricingAt, _ := gatewayTokenRequestPricingAtFromContext(ctx)
  37. return pricingAt
  38. }
  39. func gatewayTokenRequestBillingGroupFromContext(ctx context.Context) *Group {
  40. if ctx == nil {
  41. return nil
  42. }
  43. group, _ := ctx.Value(gatewayTokenRequestBillingGroupCtxKey{}).(*Group)
  44. if IsGroupContextValid(group) {
  45. return group
  46. }
  47. return nil
  48. }