Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
22 commits
Select commit Hold shift + click to select a range
74c7ace
feat(redisclient): add cluster endpoint mode
KurodaKayn Jun 19, 2026
3771bd2
refactor(app): carry universal redis clients
KurodaKayn Jun 19, 2026
965c829
refactor(api): accept universal redis dependents
KurodaKayn Jun 19, 2026
789e7d3
refactor(browser-session): accept universal redis clients
KurodaKayn Jun 19, 2026
357f359
refactor(dashboard): accept universal redis clients
KurodaKayn Jun 19, 2026
fa92e47
refactor(platform-account): accept universal redis clients
KurodaKayn Jun 19, 2026
2b5ec0a
refactor(mediaasset): accept universal redis clients
KurodaKayn Jun 19, 2026
d365602
refactor(project): accept universal redis clients
KurodaKayn Jun 19, 2026
033675a
refactor(queue): accept universal redis clients
KurodaKayn Jun 19, 2026
9d70524
refactor(publish): accept universal redis clients
KurodaKayn Jun 19, 2026
eb8ecbe
refactor(stats): accept universal redis clients
KurodaKayn Jun 19, 2026
5365637
feat(browser-session): add cluster redis state client
KurodaKayn Jun 19, 2026
d5c72f6
feat(collab): add cluster redis client mode
KurodaKayn Jun 19, 2026
0ca9d25
test(redisclient): cover cluster client modes
KurodaKayn Jun 19, 2026
462c9d6
test(app): adapt redis role client assertion
KurodaKayn Jun 19, 2026
829c4c4
test(browser-session): cover cluster state config
KurodaKayn Jun 19, 2026
43e86ba
test(collab): cover cluster redis options
KurodaKayn Jun 19, 2026
2f0dce8
chore(env): validate cluster redis seed lists
KurodaKayn Jun 19, 2026
e0bf644
chore(env): refresh cluster redis examples
KurodaKayn Jun 19, 2026
4b017ed
docs(redis): document cluster client mode
KurodaKayn Jun 19, 2026
d45e1d4
fix(project): tag list cache scan pattern
KurodaKayn Jun 19, 2026
f2c34c7
test(project): cover tagged list scan pattern
KurodaKayn Jun 19, 2026
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions backend/cmd/api/server.go
Original file line number Diff line number Diff line change
Expand Up @@ -23,8 +23,8 @@ import (
type serverConfig struct {
runtimeConfig app.RuntimeConfig
jwtSigningKey []byte
redisClient *redis.Client
rateLimitRedis *redis.Client
redisClient redis.UniversalClient
rateLimitRedis redis.UniversalClient
mockLogin bool
ready *atomic.Bool
sqlDB *gorm.DB
Expand Down
2 changes: 1 addition & 1 deletion backend/internal/app/health.go
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ import (
"gorm.io/gorm"
)

func RegisterHealthRoutes(e *echo.Echo, ready *atomic.Bool, sqlDB *gorm.DB, redisClient *redis.Client) {
func RegisterHealthRoutes(e *echo.Echo, ready *atomic.Bool, sqlDB *gorm.DB, redisClient redis.UniversalClient) {
e.GET("/health", func(c echo.Context) error {
return c.JSON(http.StatusOK, map[string]string{"status": "healthy"})
})
Expand Down
2 changes: 1 addition & 1 deletion backend/internal/app/health_server.go
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ const defaultHTTPPort = "8080"

type HealthServerConfig struct {
Ready *atomic.Bool
RedisClient *redis.Client
RedisClient redis.UniversalClient
ObservabilitySuite *observability.Suite
DBRouter *db.Router
SQLDB *gorm.DB
Expand Down
14 changes: 7 additions & 7 deletions backend/internal/app/runtime.go
Original file line number Diff line number Diff line change
Expand Up @@ -42,11 +42,11 @@ type Runtime struct {
Config RuntimeConfig
JWTSigningKey []byte
MockLogin bool
RedisClient *redis.Client
RedisCoordination *redis.Client
RedisCache *redis.Client
RedisQueue *redis.Client
RedisSessionContinuity *redis.Client
RedisClient redis.UniversalClient
RedisCoordination redis.UniversalClient
RedisCache redis.UniversalClient
RedisQueue redis.UniversalClient
RedisSessionContinuity redis.UniversalClient
ObservabilitySuite *observability.Suite
DashboardService *dashboardsvc.DashboardService
CollabDocumentService *collabdoc.Service
Expand Down Expand Up @@ -214,14 +214,14 @@ func (r *Runtime) Close() error {
if r == nil {
return nil
}
clients := []*redis.Client{
clients := []redis.UniversalClient{
r.RedisClient,
r.RedisCoordination,
r.RedisCache,
r.RedisQueue,
r.RedisSessionContinuity,
}
seen := map[*redis.Client]struct{}{}
seen := map[redis.UniversalClient]struct{}{}
var firstErr error
for _, client := range clients {
if client == nil {
Expand Down
9 changes: 7 additions & 2 deletions backend/internal/app/runtime_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import (

"github.com/alicebob/miniredis/v2"
"github.com/glebarez/sqlite"
"github.com/redis/go-redis/v9"
"gorm.io/gorm"
)

Expand Down Expand Up @@ -90,8 +91,12 @@ func TestNewRuntimeBuildsRedisRoleClientsWhenConfigured(t *testing.T) {
if runtime.RedisClient == nil || runtime.RedisCoordination == nil || runtime.RedisCache == nil || runtime.RedisQueue == nil || runtime.RedisSessionContinuity == nil {
t.Fatal("expected all redis role clients to be wired")
}
if runtime.RedisCoordination.Options().DialTimeout.String() != "500ms" {
t.Fatalf("expected coordination client baseline, got %s", runtime.RedisCoordination.Options().DialTimeout)
coordinationClient, ok := runtime.RedisCoordination.(*redis.Client)
if !ok {
t.Fatalf("expected coordination client to be a direct redis client, got %T", runtime.RedisCoordination)
}
if coordinationClient.Options().DialTimeout.String() != "500ms" {
t.Fatalf("expected coordination client baseline, got %s", coordinationClient.Options().DialTimeout)
}
}

Expand Down
4 changes: 2 additions & 2 deletions backend/internal/handlers/auth.go
Original file line number Diff line number Diff line change
Expand Up @@ -26,13 +26,13 @@ import (

type AuthHandler struct {
db *gorm.DB
redis *redis.Client
redis redis.UniversalClient
email email.EmailService
jwtSigningKey []byte
usernameLoginEnabled bool
}

func NewAuthHandler(db *gorm.DB, redis *redis.Client, email email.EmailService, jwtSigningKey []byte) *AuthHandler {
func NewAuthHandler(db *gorm.DB, redis redis.UniversalClient, email email.EmailService, jwtSigningKey []byte) *AuthHandler {
return &AuthHandler{
db: db,
redis: redis,
Expand Down
12 changes: 6 additions & 6 deletions backend/internal/middleware/rate_limit.go
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@ var defaultRateLimitPolicyYAML []byte

type RateLimitConfig struct {
Enabled bool
RedisClient *redis.Client
RedisClient redis.UniversalClient
KeyPrefix string
FailOpen bool
guard *redisdegrade.Guard
Expand Down Expand Up @@ -111,15 +111,15 @@ local ttl = redis.call("PTTL", KEYS[1])
return { current, ttl }
`

func DefaultRateLimitConfig(client *redis.Client) RateLimitConfig {
func DefaultRateLimitConfig(client redis.UniversalClient) RateLimitConfig {
policy, err := rateLimitPolicyFromYAML(defaultRateLimitPolicyYAML)
if err != nil {
panic(err)
}
return rateLimitConfigFromPolicy(client, policy)
}

func rateLimitConfigFromPolicy(client *redis.Client, policy rateLimitPolicy) RateLimitConfig {
func rateLimitConfigFromPolicy(client redis.UniversalClient, policy rateLimitPolicy) RateLimitConfig {
return RateLimitConfig{
Enabled: client != nil,
RedisClient: client,
Expand Down Expand Up @@ -149,7 +149,7 @@ func rateLimitConfigFromPolicy(client *redis.Client, policy rateLimitPolicy) Rat
}
}

func RateLimitConfigFromEnv(client *redis.Client) (RateLimitConfig, error) {
func RateLimitConfigFromEnv(client redis.UniversalClient) (RateLimitConfig, error) {
policy, err := rateLimitPolicyFromYAML(defaultRateLimitPolicyYAML)
if err != nil {
return RateLimitConfig{}, err
Expand Down Expand Up @@ -342,7 +342,7 @@ func rateLimitCategory(method, route string) string {
}
}

func checkRateLimitBuckets(ctx context.Context, client *redis.Client, prefix string, guard *redisdegrade.Guard, buckets []rateLimitBucket) (rateLimitResult, error) {
func checkRateLimitBuckets(ctx context.Context, client redis.UniversalClient, prefix string, guard *redisdegrade.Guard, buckets []rateLimitBucket) (rateLimitResult, error) {
var selected rateLimitResult
for _, bucket := range buckets {
current, ttl, err := incrementRateLimitBucket(ctx, client, guard, rateLimitRedisKey(prefix, bucket), bucket.Window)
Expand Down Expand Up @@ -370,7 +370,7 @@ func checkRateLimitBuckets(ctx context.Context, client *redis.Client, prefix str
return selected, nil
}

func incrementRateLimitBucket(ctx context.Context, client *redis.Client, guard *redisdegrade.Guard, key string, window time.Duration) (int64, time.Duration, error) {
func incrementRateLimitBucket(ctx context.Context, client redis.UniversalClient, guard *redisdegrade.Guard, key string, window time.Duration) (int64, time.Duration, error) {
raw, err := redisdegrade.CallWork(guard, "rate_limit", func() (any, error) {
return client.Eval(ctx, redisRateLimitScript, []string{key}, window.Milliseconds()).Result()
})
Expand Down
4 changes: 2 additions & 2 deletions backend/internal/pkg/streamgate/streamgate.go
Original file line number Diff line number Diff line change
Expand Up @@ -75,7 +75,7 @@ func (l *Lease) Release(ctx context.Context) error {

type Limiter struct {
config Config
redis *redis.Client
redis redis.UniversalClient
memory *memoryStore
}

Expand All @@ -94,7 +94,7 @@ func (e *LimitError) Unwrap() error {
return ErrLimitExceeded
}

func New(redisClient *redis.Client, config Config) *Limiter {
func New(redisClient redis.UniversalClient, config Config) *Limiter {
config = normalizeConfig(config)
if !config.Enabled {
return nil
Expand Down
Loading
Loading