Skip to content

Commit c311666

Browse files
author
Jeff Yanta
committed
account: add cache store implementation
1 parent 615fc90 commit c311666

File tree

3 files changed

+117
-35
lines changed

3 files changed

+117
-35
lines changed

account/cache/store.go

Lines changed: 115 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,115 @@
1+
package cache
2+
3+
import (
4+
"bytes"
5+
"context"
6+
"errors"
7+
"time"
8+
9+
"github.com/ReneKroon/ttlcache"
10+
"google.golang.org/protobuf/proto"
11+
12+
commonpb "github.com/code-payments/flipchat-protobuf-api/generated/go/common/v1"
13+
14+
"github.com/code-payments/flipchat-server/account"
15+
)
16+
17+
type Cache struct {
18+
db account.Store
19+
pubkeyToUserCache *ttlcache.Cache
20+
registeredUserCache *ttlcache.Cache
21+
staffFlagCache *ttlcache.Cache
22+
}
23+
24+
func NewInCache(db account.Store) account.Store {
25+
return &Cache{
26+
db: db,
27+
pubkeyToUserCache: ttlcache.NewCache(),
28+
registeredUserCache: ttlcache.NewCache(),
29+
staffFlagCache: ttlcache.NewCache(),
30+
}
31+
}
32+
33+
func (c *Cache) Bind(ctx context.Context, userID *commonpb.UserId, pubKey *commonpb.PublicKey) (*commonpb.UserId, error) {
34+
return c.db.Bind(ctx, userID, pubKey)
35+
}
36+
37+
func (c *Cache) GetUserId(ctx context.Context, pubKey *commonpb.PublicKey) (*commonpb.UserId, error) {
38+
cached, ok := c.pubkeyToUserCache.Get(string(pubKey.Value))
39+
if !ok {
40+
userID, err := c.db.GetUserId(ctx, pubKey)
41+
if err == nil {
42+
cloned := proto.Clone(userID).(*commonpb.UserId)
43+
c.pubkeyToUserCache.Set(string(pubKey.Value), cloned)
44+
}
45+
return userID, err
46+
}
47+
cloned := proto.Clone(cached.(*commonpb.UserId)).(*commonpb.UserId)
48+
return cloned, nil
49+
}
50+
51+
func (c *Cache) GetPubKeys(ctx context.Context, userID *commonpb.UserId) ([]*commonpb.PublicKey, error) {
52+
return c.db.GetPubKeys(ctx, userID)
53+
}
54+
55+
func (c *Cache) RemoveKey(ctx context.Context, userID *commonpb.UserId, pubKey *commonpb.PublicKey) error {
56+
// Because we cache forever
57+
return errors.New("disabled for cache implementations")
58+
}
59+
60+
func (c *Cache) IsAuthorized(ctx context.Context, userID *commonpb.UserId, pubKey *commonpb.PublicKey) (bool, error) {
61+
linkedUserID, err := c.GetUserId(ctx, pubKey)
62+
if err != nil {
63+
return false, err
64+
}
65+
return bytes.Equal(linkedUserID.Value, userID.Value), nil
66+
}
67+
68+
func (c *Cache) IsStaff(ctx context.Context, userID *commonpb.UserId) (bool, error) {
69+
cached, ok := c.staffFlagCache.Get(string(userID.Value))
70+
if !ok {
71+
isStaff, err := c.db.IsStaff(ctx, userID)
72+
if err == nil {
73+
c.staffFlagCache.Set(string(userID.Value), isStaff)
74+
}
75+
return isStaff, err
76+
}
77+
return cached.(bool), nil
78+
}
79+
80+
func (c *Cache) IsRegistered(ctx context.Context, userID *commonpb.UserId) (bool, error) {
81+
cached, ok := c.registeredUserCache.Get(string(userID.Value))
82+
if !ok {
83+
isRegistered, err := c.db.IsRegistered(ctx, userID)
84+
if err == nil && isRegistered {
85+
// Only cache positive results
86+
c.registeredUserCache.Set(string(userID.Value), isRegistered)
87+
}
88+
return isRegistered, err
89+
}
90+
return cached.(bool), nil
91+
}
92+
93+
func (c *Cache) SetRegistrationFlag(ctx context.Context, userID *commonpb.UserId, isRegistered bool) error {
94+
return c.db.SetRegistrationFlag(ctx, userID, isRegistered)
95+
}
96+
97+
func (c *Cache) BatchSetNextAirdropTimestamp(ctx context.Context, ts time.Time, userIDs ...*commonpb.UserId) error {
98+
return c.db.BatchSetNextAirdropTimestamp(ctx, ts, userIDs...)
99+
}
100+
101+
func (c *Cache) GetNextAirdropTimestamp(ctx context.Context, userID *commonpb.UserId) (time.Time, error) {
102+
return c.db.GetNextAirdropTimestamp(ctx, userID)
103+
}
104+
105+
func (c *Cache) GetUsersToAirdrop(ctx context.Context, at time.Time) ([]*commonpb.UserId, error) {
106+
return c.db.GetUsersToAirdrop(ctx, at)
107+
}
108+
109+
func (c *Cache) ExtendAirdropEligibility(ctx context.Context, userID *commonpb.UserId, until time.Time) error {
110+
return c.db.ExtendAirdropEligibility(ctx, userID, until)
111+
}
112+
113+
func (c *Cache) GetAirdropEligibilityTimestamp(ctx context.Context, userID *commonpb.UserId) (time.Time, error) {
114+
return c.db.GetAirdropEligibilityTimestamp(ctx, userID)
115+
}

account/postgres/model.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -33,7 +33,7 @@ func dbBind(ctx context.Context, pool *pgxpool.Pool, userID *commonpb.UserId, pu
3333
return err
3434
}
3535

36-
putPubkeyQuery := `INSERT INTO ` + publicKeysTableName + ` (` + allPublicKeyFields + `) VALUES ($1, $2, NOW(), NOW()) ON CONFLICT ("key") DO UPDATE SET "userId" = $2 WHERE ` + publicKeysTableName + `."key" = $1`
36+
putPubkeyQuery := `INSERT INTO ` + publicKeysTableName + ` (` + allPublicKeyFields + `) VALUES ($1, $2, NOW(), NOW())`
3737
_, err = tx.Exec(ctx, putPubkeyQuery, pg.Encode(pubKey.Value, pg.Base58), pg.Encode(userID.Value))
3838
if err != nil {
3939
return err

logging/staff.go

Lines changed: 1 addition & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,6 @@ package logging
22

33
import (
44
"context"
5-
"sync"
65

76
"go.uber.org/zap"
87

@@ -12,21 +11,12 @@ import (
1211
"github.com/code-payments/flipchat-server/model"
1312
)
1413

15-
var (
16-
cachedStaffFlagMu sync.RWMutex
17-
cachedStaffFlag map[string]bool
18-
)
19-
20-
func init() {
21-
cachedStaffFlag = make(map[string]bool)
22-
}
23-
2414
type StaffLogger struct {
2515
log *zap.Logger
2616
}
2717

2818
func NewStaffLogger(ctx context.Context, log *zap.Logger, userID *commonpb.UserId, accounts account.Store) *StaffLogger {
29-
isStaff := isStaff(ctx, userID, accounts)
19+
isStaff, _ := accounts.IsStaff(ctx, userID)
3020
if !isStaff {
3121
return nil
3222
}
@@ -54,26 +44,3 @@ func (l *StaffLogger) With(fields ...zap.Field) *StaffLogger {
5444
l.log = l.log.With(fields...)
5545
return l
5646
}
57-
58-
func isStaff(ctx context.Context, userID *commonpb.UserId, accounts account.Store) bool {
59-
cacheKey := model.UserIDString(userID)
60-
61-
cachedStaffFlagMu.RLock()
62-
isStaff, ok := cachedStaffFlag[cacheKey]
63-
if ok {
64-
cachedStaffFlagMu.RUnlock()
65-
return isStaff
66-
}
67-
cachedStaffFlagMu.RUnlock()
68-
69-
isStaff, err := accounts.IsStaff(ctx, userID)
70-
if err != nil {
71-
return false
72-
}
73-
74-
cachedStaffFlagMu.Lock()
75-
cachedStaffFlag[cacheKey] = isStaff
76-
cachedStaffFlagMu.Unlock()
77-
78-
return isStaff
79-
}

0 commit comments

Comments
 (0)