1package carstore
2
3import (
4 "context"
5 "github.com/bluesky-social/indigo/models"
6 "go.opentelemetry.io/otel"
7 "sync"
8)
9
10type LastShardSource interface {
11 GetLastShard(context.Context, models.Uid) (*CarShard, error)
12}
13
14type lastShardCache struct {
15 source LastShardSource
16
17 lscLk sync.Mutex
18 lastShardCache map[models.Uid]*CarShard
19}
20
21func (lsc *lastShardCache) Init() {
22 lsc.lastShardCache = make(map[models.Uid]*CarShard)
23}
24
25func (lsc *lastShardCache) check(user models.Uid) *CarShard {
26 lsc.lscLk.Lock()
27 defer lsc.lscLk.Unlock()
28
29 ls, ok := lsc.lastShardCache[user]
30 if ok {
31 return ls
32 }
33
34 return nil
35}
36
37func (lsc *lastShardCache) remove(user models.Uid) {
38 lsc.lscLk.Lock()
39 defer lsc.lscLk.Unlock()
40
41 delete(lsc.lastShardCache, user)
42}
43
44func (lsc *lastShardCache) put(ls *CarShard) {
45 if ls == nil {
46 return
47 }
48 lsc.lscLk.Lock()
49 defer lsc.lscLk.Unlock()
50
51 lsc.lastShardCache[ls.Usr] = ls
52}
53
54func (lsc *lastShardCache) get(ctx context.Context, user models.Uid) (*CarShard, error) {
55 ctx, span := otel.Tracer("carstore").Start(ctx, "getLastShard")
56 defer span.End()
57
58 maybeLs := lsc.check(user)
59 if maybeLs != nil {
60 return maybeLs, nil
61 }
62
63 lastShard, err := lsc.source.GetLastShard(ctx, user)
64 if err != nil {
65 return nil, err
66 }
67
68 lsc.put(lastShard)
69 return lastShard, nil
70}