Skip to content

Commit 229b016

Browse files
committed
[auth] add users cache
1 parent 9dfe593 commit 229b016

File tree

6 files changed

+489
-33
lines changed

6 files changed

+489
-33
lines changed

internal/sms-gateway/modules/auth/service.go

+26-2
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,16 @@
11
package auth
22

33
import (
4+
"crypto/sha256"
5+
"encoding/hex"
46
"fmt"
7+
"time"
58

69
"github.com/capcom6/sms-gateway/internal/sms-gateway/models"
710
"github.com/capcom6/sms-gateway/internal/sms-gateway/modules/devices"
811
"github.com/capcom6/sms-gateway/internal/sms-gateway/repositories"
912
"github.com/capcom6/sms-gateway/pkg/crypto"
13+
"github.com/capcom6/sms-gateway/pkg/types/cache"
1014
"github.com/jaevor/go-nanoid"
1115
"go.uber.org/fx"
1216
"go.uber.org/zap"
@@ -32,6 +36,8 @@ type Service struct {
3236
config Config
3337

3438
users *repositories.UsersRepository
39+
usersCache *cache.Cache[models.User]
40+
3541
devicesSvc *devices.Service
3642

3743
logger *zap.Logger
@@ -48,6 +54,8 @@ func New(params Params) *Service {
4854
devicesSvc: params.DevicesSvc,
4955
logger: params.Logger.Named("Service"),
5056
idgen: idgen,
57+
58+
usersCache: cache.New[models.User](cache.Config{TTL: 1 * time.Hour}),
5159
}
5260
}
5361

@@ -111,10 +119,26 @@ func (s *Service) AuthorizeDevice(token string) (models.Device, error) {
111119
}
112120

113121
func (s *Service) AuthorizeUser(username, password string) (models.User, error) {
114-
user, err := s.users.GetByLogin(username)
122+
hash := sha256.Sum256([]byte(username + password))
123+
cacheKey := hex.EncodeToString(hash[:])
124+
125+
user, err := s.usersCache.Get(cacheKey)
126+
if err == nil {
127+
return user, nil
128+
}
129+
130+
user, err = s.users.GetByLogin(username)
115131
if err != nil {
116132
return user, err
117133
}
118134

119-
return user, crypto.CompareBCryptHash(user.PasswordHash, password)
135+
if err := crypto.CompareBCryptHash(user.PasswordHash, password); err != nil {
136+
return models.User{}, err
137+
}
138+
139+
if err := s.usersCache.Set(cacheKey, user); err != nil {
140+
s.logger.Error("can't cache user", zap.Error(err))
141+
}
142+
143+
return user, nil
120144
}

internal/sms-gateway/modules/push/service.go

+5-2
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@ package push
22

33
import (
44
"context"
5+
"fmt"
56
"time"
67

78
"github.com/capcom6/sms-gateway/pkg/types/cache"
@@ -60,7 +61,7 @@ func New(params Params) *Service {
6061
return &Service{
6162
config: params.Config,
6263
client: params.Client,
63-
cache: cache.New[Event](),
64+
cache: cache.New[Event](cache.Config{}),
6465
enqueuedCounter: enqueuedCounter,
6566
logger: params.Logger,
6667
}
@@ -83,7 +84,9 @@ func (s *Service) Run(ctx context.Context) {
8384

8485
// Enqueue adds the data to the cache and immediately sends all messages if the debounce is 0.
8586
func (s *Service) Enqueue(token string, event *Event) error {
86-
s.cache.Set(token, *event)
87+
if err := s.cache.Set(token, *event); err != nil {
88+
return fmt.Errorf("can't add message to cache: %w", err)
89+
}
8790

8891
s.enqueuedCounter.WithLabelValues(string(event.Event)).Inc()
8992

pkg/types/cache/cache.go

+74-12
Original file line numberDiff line numberDiff line change
@@ -1,32 +1,94 @@
11
package cache
22

3-
import "sync"
3+
import (
4+
"sync"
5+
"time"
6+
)
7+
8+
type item[T any] struct {
9+
value T
10+
validUntil time.Time
11+
}
12+
13+
func (i *item[T]) isExpired(now time.Time) bool {
14+
return !i.validUntil.IsZero() && now.After(i.validUntil)
15+
}
416

517
type Cache[T any] struct {
6-
storage map[string]T
7-
mux sync.RWMutex
18+
items map[string]*item[T]
19+
ttl time.Duration
20+
empty T
21+
22+
mux sync.RWMutex
823
}
924

10-
func New[T any]() *Cache[T] {
25+
func New[T any](cfg Config) *Cache[T] {
1126
return &Cache[T]{
12-
storage: make(map[string]T),
27+
items: make(map[string]*item[T]),
28+
ttl: cfg.TTL,
1329
}
1430
}
1531

16-
func (c *Cache[T]) Set(key string, value T) {
32+
func (c *Cache[T]) Set(key string, value T) error {
33+
var validUntil time.Time
34+
if c.ttl > 0 {
35+
validUntil = time.Now().Add(c.ttl)
36+
}
37+
1738
c.mux.Lock()
18-
defer c.mux.Unlock()
39+
c.items[key] = &item[T]{
40+
value: value,
41+
validUntil: validUntil,
42+
}
43+
c.mux.Unlock()
1944

20-
c.storage[key] = value
45+
return nil
46+
}
47+
48+
func (c *Cache[T]) Get(key string) (T, error) {
49+
c.mux.RLock()
50+
item, ok := c.items[key]
51+
c.mux.RUnlock()
52+
53+
if !ok {
54+
return c.empty, ErrKeyNotFound
55+
}
56+
57+
if item.isExpired(time.Now()) {
58+
return c.empty, ErrKeyExpired
59+
}
60+
61+
return item.value, nil
2162
}
2263

2364
func (c *Cache[T]) Drain() map[string]T {
65+
t := time.Now()
66+
2467
c.mux.Lock()
25-
defer c.mux.Unlock()
68+
copy := c.items
69+
c.items = make(map[string]*item[T], len(copy))
70+
c.mux.Unlock()
71+
72+
items := make(map[string]T, len(copy))
73+
for key, item := range copy {
74+
if item.isExpired(t) {
75+
continue
76+
}
77+
items[key] = item.value
78+
}
79+
80+
return items
81+
}
2682

27-
storage := c.storage
83+
func (c *Cache[T]) Cleanup() {
84+
t := time.Now()
2885

29-
c.storage = make(map[string]T)
86+
c.mux.Lock()
87+
defer c.mux.Unlock()
3088

31-
return storage
89+
for key, item := range c.items {
90+
if item.isExpired(t) {
91+
delete(c.items, key)
92+
}
93+
}
3294
}

0 commit comments

Comments
 (0)