chore: initial public snapshot for github upload
This commit is contained in:
@@ -0,0 +1,110 @@
|
||||
package service
|
||||
|
||||
import (
|
||||
"context"
|
||||
"crypto/sha256"
|
||||
"encoding/hex"
|
||||
"errors"
|
||||
"fmt"
|
||||
"strings"
|
||||
)
|
||||
|
||||
var ErrUsageBillingRequestIDRequired = errors.New("usage billing request_id is required")
|
||||
var ErrUsageBillingRequestConflict = errors.New("usage billing request fingerprint conflict")
|
||||
|
||||
// UsageBillingCommand describes one billable request that must be applied at most once.
|
||||
type UsageBillingCommand struct {
|
||||
RequestID string
|
||||
APIKeyID int64
|
||||
RequestFingerprint string
|
||||
RequestPayloadHash string
|
||||
|
||||
UserID int64
|
||||
AccountID int64
|
||||
SubscriptionID *int64
|
||||
AccountType string
|
||||
Model string
|
||||
ServiceTier string
|
||||
ReasoningEffort string
|
||||
BillingType int8
|
||||
InputTokens int
|
||||
OutputTokens int
|
||||
CacheCreationTokens int
|
||||
CacheReadTokens int
|
||||
ImageCount int
|
||||
MediaType string
|
||||
|
||||
BalanceCost float64
|
||||
SubscriptionCost float64
|
||||
APIKeyQuotaCost float64
|
||||
APIKeyRateLimitCost float64
|
||||
AccountQuotaCost float64
|
||||
}
|
||||
|
||||
func (c *UsageBillingCommand) Normalize() {
|
||||
if c == nil {
|
||||
return
|
||||
}
|
||||
c.RequestID = strings.TrimSpace(c.RequestID)
|
||||
if strings.TrimSpace(c.RequestFingerprint) == "" {
|
||||
c.RequestFingerprint = buildUsageBillingFingerprint(c)
|
||||
}
|
||||
}
|
||||
|
||||
func buildUsageBillingFingerprint(c *UsageBillingCommand) string {
|
||||
if c == nil {
|
||||
return ""
|
||||
}
|
||||
raw := fmt.Sprintf(
|
||||
"%d|%d|%d|%s|%s|%s|%s|%d|%d|%d|%d|%d|%d|%s|%d|%0.10f|%0.10f|%0.10f|%0.10f|%0.10f",
|
||||
c.UserID,
|
||||
c.AccountID,
|
||||
c.APIKeyID,
|
||||
strings.TrimSpace(c.AccountType),
|
||||
strings.TrimSpace(c.Model),
|
||||
strings.TrimSpace(c.ServiceTier),
|
||||
strings.TrimSpace(c.ReasoningEffort),
|
||||
c.BillingType,
|
||||
c.InputTokens,
|
||||
c.OutputTokens,
|
||||
c.CacheCreationTokens,
|
||||
c.CacheReadTokens,
|
||||
c.ImageCount,
|
||||
strings.TrimSpace(c.MediaType),
|
||||
valueOrZero(c.SubscriptionID),
|
||||
c.BalanceCost,
|
||||
c.SubscriptionCost,
|
||||
c.APIKeyQuotaCost,
|
||||
c.APIKeyRateLimitCost,
|
||||
c.AccountQuotaCost,
|
||||
)
|
||||
if payloadHash := strings.TrimSpace(c.RequestPayloadHash); payloadHash != "" {
|
||||
raw += "|" + payloadHash
|
||||
}
|
||||
sum := sha256.Sum256([]byte(raw))
|
||||
return hex.EncodeToString(sum[:])
|
||||
}
|
||||
|
||||
func HashUsageRequestPayload(payload []byte) string {
|
||||
if len(payload) == 0 {
|
||||
return ""
|
||||
}
|
||||
sum := sha256.Sum256(payload)
|
||||
return hex.EncodeToString(sum[:])
|
||||
}
|
||||
|
||||
func valueOrZero(v *int64) int64 {
|
||||
if v == nil {
|
||||
return 0
|
||||
}
|
||||
return *v
|
||||
}
|
||||
|
||||
type UsageBillingApplyResult struct {
|
||||
Applied bool
|
||||
APIKeyQuotaExhausted bool
|
||||
}
|
||||
|
||||
type UsageBillingRepository interface {
|
||||
Apply(ctx context.Context, cmd *UsageBillingCommand) (*UsageBillingApplyResult, error)
|
||||
}
|
||||
Reference in New Issue
Block a user