-
Notifications
You must be signed in to change notification settings - Fork 70
Expand file tree
/
Copy pathusage.go
More file actions
62 lines (52 loc) · 1.46 KB
/
usage.go
File metadata and controls
62 lines (52 loc) · 1.46 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
package services
import (
"context"
"time"
"paperdebugger/internal/libs/cfg"
"paperdebugger/internal/libs/db"
"paperdebugger/internal/libs/logger"
"paperdebugger/internal/models"
"go.mongodb.org/mongo-driver/v2/bson"
"go.mongodb.org/mongo-driver/v2/mongo"
"go.mongodb.org/mongo-driver/v2/mongo/options"
)
type UsageService struct {
BaseService
usageCollection *mongo.Collection
}
func NewUsageService(db *db.DB, cfg *cfg.Cfg, logger *logger.Logger) *UsageService {
base := NewBaseService(db, cfg, logger)
return &UsageService{
BaseService: base,
usageCollection: base.db.Collection((models.Usage{}).CollectionName()),
}
}
// TrackUsage increments cost for a user/project/model/hour bucket.
// Uses upsert to create or update the usage record atomically.
func (s *UsageService) TrackUsage(ctx context.Context, userID bson.ObjectID, projectID string, modelSlug string, cost float64) error {
if cost == 0 {
return nil
}
now := time.Now()
hourBucket := models.TruncateToHour(now)
filter := bson.M{
"user_id": userID,
"project_id": projectID,
"model_slug": modelSlug,
"hour_bucket": bson.NewDateTimeFromTime(hourBucket),
}
update := bson.M{
"$inc": bson.M{
"cost": cost,
},
"$set": bson.M{
"updated_at": bson.NewDateTimeFromTime(now),
},
"$setOnInsert": bson.M{
"_id": bson.NewObjectID(),
},
}
opts := options.UpdateOne().SetUpsert(true)
_, err := s.usageCollection.UpdateOne(ctx, filter, update, opts)
return err
}