refactor: Remove Token management and integrate Redis for authentication
- Deleted the Token model and its repository, transitioning to a Redis-based token management system. - Updated the service layer to utilize Redis for token storage, enhancing performance and scalability. - Refactored the container to remove TokenRepository and integrate the new token service. - Cleaned up the Dockerfile and other files by removing unnecessary whitespace and comments. - Enhanced error handling and logging for Redis initialization and usage.
This commit is contained in:
184
pkg/database/cache_test.go
Normal file
184
pkg/database/cache_test.go
Normal file
@@ -0,0 +1,184 @@
|
||||
package database
|
||||
|
||||
import (
|
||||
"context"
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
pkgRedis "carrotskin/pkg/redis"
|
||||
|
||||
miniredis "github.com/alicebob/miniredis/v2"
|
||||
goRedis "github.com/redis/go-redis/v9"
|
||||
)
|
||||
|
||||
func newCacheWithMiniRedis(t *testing.T) (*CacheManager, func()) {
|
||||
t.Helper()
|
||||
|
||||
mr, err := miniredis.Run()
|
||||
if err != nil {
|
||||
t.Fatalf("failed to start miniredis: %v", err)
|
||||
}
|
||||
|
||||
rdb := goRedis.NewClient(&goRedis.Options{
|
||||
Addr: mr.Addr(),
|
||||
})
|
||||
client := &pkgRedis.Client{Client: rdb}
|
||||
|
||||
cache := NewCacheManager(client, CacheConfig{
|
||||
Prefix: "t:",
|
||||
Expiration: time.Minute,
|
||||
Enabled: true,
|
||||
Policy: CachePolicy{
|
||||
UserTTL: 2 * time.Minute,
|
||||
UserEmailTTL: 3 * time.Minute,
|
||||
ProfileTTL: 2 * time.Minute,
|
||||
ProfileListTTL: 90 * time.Second,
|
||||
TextureTTL: 2 * time.Minute,
|
||||
TextureListTTL: 45 * time.Second,
|
||||
},
|
||||
})
|
||||
|
||||
cleanup := func() {
|
||||
_ = rdb.Close()
|
||||
mr.Close()
|
||||
}
|
||||
return cache, cleanup
|
||||
}
|
||||
|
||||
func TestCacheManager_GetSet_TryGet(t *testing.T) {
|
||||
cache, cleanup := newCacheWithMiniRedis(t)
|
||||
defer cleanup()
|
||||
|
||||
ctx := context.Background()
|
||||
type User struct {
|
||||
ID int
|
||||
Name string
|
||||
}
|
||||
|
||||
u := User{ID: 1, Name: "alice"}
|
||||
if err := cache.Set(ctx, "user:1", u, 10*time.Second); err != nil {
|
||||
t.Fatalf("Set err: %v", err)
|
||||
}
|
||||
|
||||
var got User
|
||||
if err := cache.Get(ctx, "user:1", &got); err != nil {
|
||||
t.Fatalf("Get err: %v", err)
|
||||
}
|
||||
if got != u {
|
||||
t.Fatalf("unexpected value: %+v", got)
|
||||
}
|
||||
|
||||
var got2 User
|
||||
ok, err := cache.TryGet(ctx, "user:1", &got2)
|
||||
if err != nil || !ok {
|
||||
t.Fatalf("TryGet failed, ok=%v err=%v", ok, err)
|
||||
}
|
||||
if got2 != u {
|
||||
t.Fatalf("unexpected TryGet: %+v", got2)
|
||||
}
|
||||
}
|
||||
|
||||
func TestCacheManager_DeletePattern(t *testing.T) {
|
||||
cache, cleanup := newCacheWithMiniRedis(t)
|
||||
defer cleanup()
|
||||
ctx := context.Background()
|
||||
|
||||
_ = cache.Set(ctx, "user:1", "a", 0)
|
||||
_ = cache.Set(ctx, "user:2", "b", 0)
|
||||
_ = cache.Set(ctx, "profile:1", "c", 0)
|
||||
|
||||
// 删除 user:* 键
|
||||
if err := cache.DeletePattern(ctx, "user:*"); err != nil {
|
||||
t.Fatalf("DeletePattern err: %v", err)
|
||||
}
|
||||
|
||||
var v string
|
||||
ok, _ := cache.TryGet(ctx, "user:1", &v)
|
||||
if ok {
|
||||
t.Fatalf("expected user:1 deleted")
|
||||
}
|
||||
ok, _ = cache.TryGet(ctx, "user:2", &v)
|
||||
if ok {
|
||||
t.Fatalf("expected user:2 deleted")
|
||||
}
|
||||
ok, _ = cache.TryGet(ctx, "profile:1", &v)
|
||||
if !ok {
|
||||
t.Fatalf("expected profile:1 kept")
|
||||
}
|
||||
}
|
||||
|
||||
func TestCachedAndCachedList(t *testing.T) {
|
||||
cache, cleanup := newCacheWithMiniRedis(t)
|
||||
defer cleanup()
|
||||
ctx := context.Background()
|
||||
|
||||
callCount := 0
|
||||
result, err := Cached(ctx, cache, "key1", func() (*string, error) {
|
||||
callCount++
|
||||
val := "hello"
|
||||
return &val, nil
|
||||
}, cache.Policy.UserTTL)
|
||||
if err != nil || *result != "hello" || callCount != 1 {
|
||||
t.Fatalf("Cached first call failed")
|
||||
}
|
||||
// 等待缓存写入完成
|
||||
for i := 0; i < 10; i++ {
|
||||
var tmp string
|
||||
if ok, _ := cache.TryGet(ctx, "key1", &tmp); ok {
|
||||
break
|
||||
}
|
||||
time.Sleep(10 * time.Millisecond)
|
||||
}
|
||||
|
||||
// 第二次应命中缓存
|
||||
_, err = Cached(ctx, cache, "key1", func() (*string, error) {
|
||||
callCount++
|
||||
val := "world"
|
||||
return &val, nil
|
||||
}, cache.Policy.UserTTL)
|
||||
if err != nil || callCount != 1 {
|
||||
t.Fatalf("Cached should hit cache, callCount=%d err=%v", callCount, err)
|
||||
}
|
||||
|
||||
listCall := 0
|
||||
_, err = CachedList(ctx, cache, "list", func() ([]string, error) {
|
||||
listCall++
|
||||
return []string{"a", "b"}, nil
|
||||
}, cache.Policy.ProfileListTTL)
|
||||
if err != nil || listCall != 1 {
|
||||
t.Fatalf("CachedList first call failed")
|
||||
}
|
||||
for i := 0; i < 10; i++ {
|
||||
var tmp []string
|
||||
if ok, _ := cache.TryGet(ctx, "list", &tmp); ok {
|
||||
break
|
||||
}
|
||||
time.Sleep(10 * time.Millisecond)
|
||||
}
|
||||
_, err = CachedList(ctx, cache, "list", func() ([]string, error) {
|
||||
listCall++
|
||||
return []string{"c"}, nil
|
||||
}, cache.Policy.ProfileListTTL)
|
||||
if err != nil || listCall != 1 {
|
||||
t.Fatalf("CachedList should hit cache, calls=%d err=%v", listCall, err)
|
||||
}
|
||||
}
|
||||
|
||||
func TestIncrementWithExpire(t *testing.T) {
|
||||
cache, cleanup := newCacheWithMiniRedis(t)
|
||||
defer cleanup()
|
||||
ctx := context.Background()
|
||||
|
||||
val, err := cache.IncrementWithExpire(ctx, "counter", time.Second)
|
||||
if err != nil || val != 1 {
|
||||
t.Fatalf("first increment failed, val=%d err=%v", val, err)
|
||||
}
|
||||
val, err = cache.IncrementWithExpire(ctx, "counter", time.Second)
|
||||
if err != nil || val != 2 {
|
||||
t.Fatalf("second increment failed, val=%d err=%v", val, err)
|
||||
}
|
||||
ttl, err := cache.TTL(ctx, "counter")
|
||||
if err != nil || ttl <= 0 {
|
||||
t.Fatalf("TTL not set: ttl=%v err=%v", ttl, err)
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user