forked from baron/baron-sso
chore: consolidate local integration changes
This commit is contained in:
@@ -1,7 +1,9 @@
|
||||
package service
|
||||
|
||||
import (
|
||||
"baron-sso-backend/internal/domain"
|
||||
"context"
|
||||
"encoding/json"
|
||||
"os"
|
||||
"time"
|
||||
|
||||
@@ -14,6 +16,14 @@ type RedisService struct {
|
||||
Client *redis.Client
|
||||
}
|
||||
|
||||
type identityMirrorStateStore struct {
|
||||
Status string `json:"status"`
|
||||
LastRefreshedAt *time.Time `json:"lastRefreshedAt,omitempty"`
|
||||
LastError string `json:"lastError,omitempty"`
|
||||
ObservedCount int64 `json:"observedCount,omitempty"`
|
||||
UpdatedAt *time.Time `json:"updatedAt,omitempty"`
|
||||
}
|
||||
|
||||
// NewRedisService creates and returns a new RedisService
|
||||
func NewRedisService() (*RedisService, error) {
|
||||
redisAddr := os.Getenv("REDIS_ADDR")
|
||||
@@ -90,3 +100,139 @@ func (s *RedisService) Get(key string) (string, error) {
|
||||
func (s *RedisService) Delete(key string) error {
|
||||
return s.Client.Del(ctx, key).Err()
|
||||
}
|
||||
|
||||
func (s *RedisService) GetIdentityCacheStatus(ctx context.Context) (domain.IdentityCacheStatus, error) {
|
||||
if s == nil || s.Client == nil {
|
||||
return domain.IdentityCacheStatus{
|
||||
Status: "unavailable",
|
||||
RedisReady: false,
|
||||
LastError: "redis service unavailable",
|
||||
}, nil
|
||||
}
|
||||
|
||||
if err := s.Client.Ping(ctx).Err(); err != nil {
|
||||
return domain.IdentityCacheStatus{
|
||||
Status: "failed",
|
||||
RedisReady: false,
|
||||
LastError: err.Error(),
|
||||
}, nil
|
||||
}
|
||||
|
||||
keyCount, err := s.countIdentityCacheKeys(ctx)
|
||||
if err != nil {
|
||||
return domain.IdentityCacheStatus{
|
||||
Status: "failed",
|
||||
RedisReady: true,
|
||||
LastError: err.Error(),
|
||||
}, nil
|
||||
}
|
||||
|
||||
raw, err := s.Client.Get(ctx, "identity:mirror:state").Result()
|
||||
if err == redis.Nil {
|
||||
return domain.IdentityCacheStatus{
|
||||
Status: "empty",
|
||||
RedisReady: true,
|
||||
KeyCount: keyCount,
|
||||
}, nil
|
||||
}
|
||||
if err != nil {
|
||||
return domain.IdentityCacheStatus{
|
||||
Status: "failed",
|
||||
RedisReady: true,
|
||||
KeyCount: keyCount,
|
||||
LastError: err.Error(),
|
||||
}, nil
|
||||
}
|
||||
|
||||
var stored identityMirrorStateStore
|
||||
if err := json.Unmarshal([]byte(raw), &stored); err != nil {
|
||||
return domain.IdentityCacheStatus{
|
||||
Status: "failed",
|
||||
RedisReady: true,
|
||||
KeyCount: keyCount,
|
||||
LastError: err.Error(),
|
||||
}, nil
|
||||
}
|
||||
status := stored.Status
|
||||
if status == "" {
|
||||
status = "unknown"
|
||||
}
|
||||
return domain.IdentityCacheStatus{
|
||||
Status: status,
|
||||
RedisReady: true,
|
||||
ObservedCount: stored.ObservedCount,
|
||||
KeyCount: keyCount,
|
||||
LastRefreshedAt: stored.LastRefreshedAt,
|
||||
LastError: stored.LastError,
|
||||
UpdatedAt: stored.UpdatedAt,
|
||||
}, nil
|
||||
}
|
||||
|
||||
func (s *RedisService) FlushIdentityCache(ctx context.Context) (domain.IdentityCacheFlushResult, error) {
|
||||
if s == nil || s.Client == nil {
|
||||
return domain.IdentityCacheFlushResult{}, os.ErrInvalid
|
||||
}
|
||||
|
||||
keys, err := s.identityCacheKeys(ctx)
|
||||
if err != nil {
|
||||
return domain.IdentityCacheFlushResult{}, err
|
||||
}
|
||||
var deleted int64
|
||||
for len(keys) > 0 {
|
||||
chunkSize := len(keys)
|
||||
if chunkSize > 500 {
|
||||
chunkSize = 500
|
||||
}
|
||||
chunk := keys[:chunkSize]
|
||||
count, err := s.Client.Del(ctx, chunk...).Result()
|
||||
if err != nil {
|
||||
return domain.IdentityCacheFlushResult{}, err
|
||||
}
|
||||
deleted += count
|
||||
keys = keys[chunkSize:]
|
||||
}
|
||||
|
||||
return domain.IdentityCacheFlushResult{
|
||||
Status: "success",
|
||||
FlushedKeys: deleted,
|
||||
UpdatedAt: time.Now().UTC(),
|
||||
}, nil
|
||||
}
|
||||
|
||||
func (s *RedisService) countIdentityCacheKeys(ctx context.Context) (int64, error) {
|
||||
keys, err := s.identityCacheKeys(ctx)
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
return int64(len(keys)), nil
|
||||
}
|
||||
|
||||
func (s *RedisService) identityCacheKeys(ctx context.Context) ([]string, error) {
|
||||
seen := make(map[string]bool)
|
||||
patterns := []string{
|
||||
"identity:mirror:*",
|
||||
"identity:index:*",
|
||||
}
|
||||
for _, pattern := range patterns {
|
||||
var cursor uint64
|
||||
for {
|
||||
keys, next, err := s.Client.Scan(ctx, cursor, pattern, 250).Result()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
for _, key := range keys {
|
||||
seen[key] = true
|
||||
}
|
||||
cursor = next
|
||||
if cursor == 0 {
|
||||
break
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
keys := make([]string, 0, len(seen))
|
||||
for key := range seen {
|
||||
keys = append(keys, key)
|
||||
}
|
||||
return keys, nil
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user