1
0
forked from baron/baron-sso

chore: consolidate local integration changes

This commit is contained in:
2026-06-09 21:03:05 +09:00
parent aa2848c3b6
commit 1341f07ef9
158 changed files with 10995 additions and 1490 deletions

View File

@@ -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
}