feat(redis): keep services running when Redis is unreachable
Add a lazy Redis client constructor and an in-memory fallback for the refresh-session store, plus tenant-api and ops-api bootstrap that warns and continues with the lazy client instead of failing. Refresh and blacklist operations now silently fall back to the in-memory store while Redis is down so existing sessions stay valid until it recovers. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -11,6 +11,19 @@ import (
|
||||
"github.com/stretchr/testify/require"
|
||||
)
|
||||
|
||||
func newFailingSessionRedisClient(t *testing.T) *goredis.Client {
|
||||
t.Helper()
|
||||
client := goredis.NewClient(&goredis.Options{
|
||||
Addr: "127.0.0.1:1",
|
||||
MaxRetries: 0,
|
||||
DialTimeout: 10 * time.Millisecond,
|
||||
ReadTimeout: 10 * time.Millisecond,
|
||||
WriteTimeout: 10 * time.Millisecond,
|
||||
})
|
||||
t.Cleanup(func() { _ = client.Close() })
|
||||
return client
|
||||
}
|
||||
|
||||
func TestSessionStoreRotateRefreshSuccess(t *testing.T) {
|
||||
mr := miniredis.RunT(t)
|
||||
client := goredis.NewClient(&goredis.Options{Addr: mr.Addr()})
|
||||
@@ -50,3 +63,25 @@ func TestSessionStoreRotateRefreshRejectsMismatch(t *testing.T) {
|
||||
_, getErr = store.GetRefresh(ctx, "new-jti")
|
||||
assert.Error(t, getErr)
|
||||
}
|
||||
|
||||
func TestSessionStoreUsesMemoryFallbackWhenRedisUnavailable(t *testing.T) {
|
||||
store := NewSessionStore(newFailingSessionRedisClient(t))
|
||||
ctx := context.Background()
|
||||
|
||||
require.NoError(t, store.SaveRefresh(ctx, "old-jti", "old-hash", time.Minute))
|
||||
value, err := store.GetRefresh(ctx, "old-jti")
|
||||
require.NoError(t, err)
|
||||
assert.Equal(t, "old-hash", value)
|
||||
|
||||
require.NoError(t, store.RotateRefresh(ctx, "old-jti", "old-hash", "new-jti", "new-hash", time.Minute))
|
||||
_, err = store.GetRefresh(ctx, "old-jti")
|
||||
assert.Error(t, err)
|
||||
value, err = store.GetRefresh(ctx, "new-jti")
|
||||
require.NoError(t, err)
|
||||
assert.Equal(t, "new-hash", value)
|
||||
|
||||
require.NoError(t, store.Blacklist(ctx, "access-jti", time.Minute))
|
||||
revoked, err := store.IsBlacklisted(ctx, "access-jti")
|
||||
require.NoError(t, err)
|
||||
assert.True(t, revoked)
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user