request_metadata.go 6.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216
  1. package service
  2. import (
  3. "context"
  4. "sync/atomic"
  5. "github.com/Wei-Shaw/sub2api/internal/pkg/ctxkey"
  6. )
  7. type requestMetadataContextKey struct{}
  8. var requestMetadataKey = requestMetadataContextKey{}
  9. type RequestMetadata struct {
  10. IsMaxTokensOneHaikuRequest *bool
  11. ThinkingEnabled *bool
  12. PrefetchedStickyAccountID *int64
  13. PrefetchedStickyGroupID *int64
  14. SingleAccountRetry *bool
  15. AccountSwitchCount *int
  16. }
  17. var (
  18. requestMetadataFallbackIsMaxTokensOneHaikuTotal atomic.Int64
  19. requestMetadataFallbackThinkingEnabledTotal atomic.Int64
  20. requestMetadataFallbackPrefetchedStickyAccount atomic.Int64
  21. requestMetadataFallbackPrefetchedStickyGroup atomic.Int64
  22. requestMetadataFallbackSingleAccountRetryTotal atomic.Int64
  23. requestMetadataFallbackAccountSwitchCountTotal atomic.Int64
  24. )
  25. func RequestMetadataFallbackStats() (isMaxTokensOneHaiku, thinkingEnabled, prefetchedStickyAccount, prefetchedStickyGroup, singleAccountRetry, accountSwitchCount int64) {
  26. return requestMetadataFallbackIsMaxTokensOneHaikuTotal.Load(),
  27. requestMetadataFallbackThinkingEnabledTotal.Load(),
  28. requestMetadataFallbackPrefetchedStickyAccount.Load(),
  29. requestMetadataFallbackPrefetchedStickyGroup.Load(),
  30. requestMetadataFallbackSingleAccountRetryTotal.Load(),
  31. requestMetadataFallbackAccountSwitchCountTotal.Load()
  32. }
  33. func metadataFromContext(ctx context.Context) *RequestMetadata {
  34. if ctx == nil {
  35. return nil
  36. }
  37. md, _ := ctx.Value(requestMetadataKey).(*RequestMetadata)
  38. return md
  39. }
  40. func updateRequestMetadata(
  41. ctx context.Context,
  42. bridgeOldKeys bool,
  43. update func(md *RequestMetadata),
  44. legacyBridge func(ctx context.Context) context.Context,
  45. ) context.Context {
  46. if ctx == nil {
  47. return nil
  48. }
  49. current := metadataFromContext(ctx)
  50. next := &RequestMetadata{}
  51. if current != nil {
  52. *next = *current
  53. }
  54. update(next)
  55. ctx = context.WithValue(ctx, requestMetadataKey, next)
  56. if bridgeOldKeys && legacyBridge != nil {
  57. ctx = legacyBridge(ctx)
  58. }
  59. return ctx
  60. }
  61. func WithIsMaxTokensOneHaikuRequest(ctx context.Context, value bool, bridgeOldKeys bool) context.Context {
  62. return updateRequestMetadata(ctx, bridgeOldKeys, func(md *RequestMetadata) {
  63. v := value
  64. md.IsMaxTokensOneHaikuRequest = &v
  65. }, func(base context.Context) context.Context {
  66. return context.WithValue(base, ctxkey.IsMaxTokensOneHaikuRequest, value)
  67. })
  68. }
  69. func WithThinkingEnabled(ctx context.Context, value bool, bridgeOldKeys bool) context.Context {
  70. return updateRequestMetadata(ctx, bridgeOldKeys, func(md *RequestMetadata) {
  71. v := value
  72. md.ThinkingEnabled = &v
  73. }, func(base context.Context) context.Context {
  74. return context.WithValue(base, ctxkey.ThinkingEnabled, value)
  75. })
  76. }
  77. func WithPrefetchedStickySession(ctx context.Context, accountID, groupID int64, bridgeOldKeys bool) context.Context {
  78. return updateRequestMetadata(ctx, bridgeOldKeys, func(md *RequestMetadata) {
  79. account := accountID
  80. group := groupID
  81. md.PrefetchedStickyAccountID = &account
  82. md.PrefetchedStickyGroupID = &group
  83. }, func(base context.Context) context.Context {
  84. bridged := context.WithValue(base, ctxkey.PrefetchedStickyAccountID, accountID)
  85. return context.WithValue(bridged, ctxkey.PrefetchedStickyGroupID, groupID)
  86. })
  87. }
  88. func WithSingleAccountRetry(ctx context.Context, value bool, bridgeOldKeys bool) context.Context {
  89. return updateRequestMetadata(ctx, bridgeOldKeys, func(md *RequestMetadata) {
  90. v := value
  91. md.SingleAccountRetry = &v
  92. }, func(base context.Context) context.Context {
  93. return context.WithValue(base, ctxkey.SingleAccountRetry, value)
  94. })
  95. }
  96. func WithAccountSwitchCount(ctx context.Context, value int, bridgeOldKeys bool) context.Context {
  97. return updateRequestMetadata(ctx, bridgeOldKeys, func(md *RequestMetadata) {
  98. v := value
  99. md.AccountSwitchCount = &v
  100. }, func(base context.Context) context.Context {
  101. return context.WithValue(base, ctxkey.AccountSwitchCount, value)
  102. })
  103. }
  104. func IsMaxTokensOneHaikuRequestFromContext(ctx context.Context) (bool, bool) {
  105. if md := metadataFromContext(ctx); md != nil && md.IsMaxTokensOneHaikuRequest != nil {
  106. return *md.IsMaxTokensOneHaikuRequest, true
  107. }
  108. if ctx == nil {
  109. return false, false
  110. }
  111. if value, ok := ctx.Value(ctxkey.IsMaxTokensOneHaikuRequest).(bool); ok {
  112. requestMetadataFallbackIsMaxTokensOneHaikuTotal.Add(1)
  113. return value, true
  114. }
  115. return false, false
  116. }
  117. func ThinkingEnabledFromContext(ctx context.Context) (bool, bool) {
  118. if md := metadataFromContext(ctx); md != nil && md.ThinkingEnabled != nil {
  119. return *md.ThinkingEnabled, true
  120. }
  121. if ctx == nil {
  122. return false, false
  123. }
  124. if value, ok := ctx.Value(ctxkey.ThinkingEnabled).(bool); ok {
  125. requestMetadataFallbackThinkingEnabledTotal.Add(1)
  126. return value, true
  127. }
  128. return false, false
  129. }
  130. func PrefetchedStickyGroupIDFromContext(ctx context.Context) (int64, bool) {
  131. if md := metadataFromContext(ctx); md != nil && md.PrefetchedStickyGroupID != nil {
  132. return *md.PrefetchedStickyGroupID, true
  133. }
  134. if ctx == nil {
  135. return 0, false
  136. }
  137. v := ctx.Value(ctxkey.PrefetchedStickyGroupID)
  138. switch t := v.(type) {
  139. case int64:
  140. requestMetadataFallbackPrefetchedStickyGroup.Add(1)
  141. return t, true
  142. case int:
  143. requestMetadataFallbackPrefetchedStickyGroup.Add(1)
  144. return int64(t), true
  145. }
  146. return 0, false
  147. }
  148. func PrefetchedStickyAccountIDFromContext(ctx context.Context) (int64, bool) {
  149. if md := metadataFromContext(ctx); md != nil && md.PrefetchedStickyAccountID != nil {
  150. return *md.PrefetchedStickyAccountID, true
  151. }
  152. if ctx == nil {
  153. return 0, false
  154. }
  155. v := ctx.Value(ctxkey.PrefetchedStickyAccountID)
  156. switch t := v.(type) {
  157. case int64:
  158. requestMetadataFallbackPrefetchedStickyAccount.Add(1)
  159. return t, true
  160. case int:
  161. requestMetadataFallbackPrefetchedStickyAccount.Add(1)
  162. return int64(t), true
  163. }
  164. return 0, false
  165. }
  166. func SingleAccountRetryFromContext(ctx context.Context) (bool, bool) {
  167. if md := metadataFromContext(ctx); md != nil && md.SingleAccountRetry != nil {
  168. return *md.SingleAccountRetry, true
  169. }
  170. if ctx == nil {
  171. return false, false
  172. }
  173. if value, ok := ctx.Value(ctxkey.SingleAccountRetry).(bool); ok {
  174. requestMetadataFallbackSingleAccountRetryTotal.Add(1)
  175. return value, true
  176. }
  177. return false, false
  178. }
  179. func AccountSwitchCountFromContext(ctx context.Context) (int, bool) {
  180. if md := metadataFromContext(ctx); md != nil && md.AccountSwitchCount != nil {
  181. return *md.AccountSwitchCount, true
  182. }
  183. if ctx == nil {
  184. return 0, false
  185. }
  186. v := ctx.Value(ctxkey.AccountSwitchCount)
  187. switch t := v.(type) {
  188. case int:
  189. requestMetadataFallbackAccountSwitchCountTotal.Add(1)
  190. return t, true
  191. case int64:
  192. requestMetadataFallbackAccountSwitchCountTotal.Add(1)
  193. return int(t), true
  194. }
  195. return 0, false
  196. }