package cache import ( "context" "crypto/sha256" "encoding/hex" "encoding/json" "fmt" "time" "aiaa-notification-service/internal/adapter" "github.com/redis/go-redis/v9" ) func TokenHash(token string) string { sum := sha256.Sum256([]byte(token)) return hex.EncodeToString(sum[:]) } func safewChatsKey(hash string) string { return "safew:chats:" + hash } func safewOffsetKey(hash string) string { return "safew:offset:" + hash } func safewPollKey(hash string) string { return "safew:poll:" + hash } func (c *Cache) MergeSafewChats(ctx context.Context, token string, chats []adapter.SafewChat) error { if c == nil || c.rdb == nil { return fmt.Errorf("redis unavailable") } if len(chats) == 0 { return nil } hash := TokenHash(token) vals := make([]any, 0, len(chats)*2) for _, ch := range chats { b, err := json.Marshal(ch) if err != nil { return err } vals = append(vals, ch.ID, b) } return c.rdb.HSet(ctx, safewChatsKey(hash), vals...).Err() } func (c *Cache) ListSafewChats(ctx context.Context, token string) ([]adapter.SafewChat, error) { if c == nil || c.rdb == nil { return nil, fmt.Errorf("redis unavailable") } m, err := c.rdb.HGetAll(ctx, safewChatsKey(TokenHash(token))).Result() if err != nil { return nil, err } out := make([]adapter.SafewChat, 0, len(m)) for _, raw := range m { var ch adapter.SafewChat if err := json.Unmarshal([]byte(raw), &ch); err != nil { return nil, err } out = append(out, ch) } return out, nil } func (c *Cache) GetSafewOffset(ctx context.Context, token string) (int64, error) { if c == nil || c.rdb == nil { return 0, fmt.Errorf("redis unavailable") } n, err := c.rdb.Get(ctx, safewOffsetKey(TokenHash(token))).Int64() if err == redis.Nil { return 0, nil } return n, err } func (c *Cache) SetSafewOffset(ctx context.Context, token string, offset int64) error { if c == nil || c.rdb == nil { return fmt.Errorf("redis unavailable") } return c.rdb.Set(ctx, safewOffsetKey(TokenHash(token)), offset, 0).Err() } func (c *Cache) TrySafewPollLock(ctx context.Context, token string, ttl time.Duration) (bool, error) { if c == nil || c.rdb == nil { return false, fmt.Errorf("redis unavailable") } ok, err := c.rdb.SetNX(ctx, safewPollKey(TokenHash(token)), "1", ttl).Result() return ok, err } func (c *Cache) UnlockSafewPoll(ctx context.Context, token string) error { if c == nil || c.rdb == nil { return nil } return c.rdb.Del(ctx, safewPollKey(TokenHash(token))).Err() }