aindrajaya / aindrajaya/node-proxy-server

Perkuat Redis reconnect strategy agar service auto-recover saat Redis restart

Aberta
#1 0 comentários 0 reações 1 responsável Reivindicada por @aindrajaya Ver no GitHub
bug
Linguagem predominante
TypeScript
Estrelas
0
Forks
0
Métricas de merge de PRs
Nenhum PR com merge em 30d

Descrição

## Ringkasan Masalah
Implementasi koneksi Redis saat ini belum cukup robust ketika Redis restart/intermiten. Akibatnya service berisiko gagal recover otomatis walaupun endpoint Redis valid.

## Konteks
- Redis berjalan di Docker dan dipublish ke host (`0.0.0.0:6379->6379/tcp`), sehingga `127.0.0.1:6379` valid.
- Masalah utama ada pada logic reconnect aplikasi, bukan pada alamat Redis.

## Temuan Audit
### 1) `src/db/redis.ts`
Konfigurasi saat ini hanya menggunakan:
- `lazyConnect: true`
- `enableReadyCheck: true`

Belum ada:
- `retryStrategy`
- `reconnectOnError`
- `maxRetriesPerRequest`
- event observability koneksi (`close`, `reconnecting`, `ready`, `end`)

### 2) `src/index.ts`
- `connectRedis()` dipanggil sekali saat startup.
- `connectRedis()` hanya memanggil `redisClient.connect()` jika `status === 'wait'`.
- Kondisi ini berpotensi tidak aman ketika status koneksi berubah ke state lain setelah Redis restart.

## Dampak
- Saat Redis sempat down/restart, proxy berpotensi error berkepanjangan atau tidak recover optimal.
- Risiko gangguan pada fitur yang bergantung pada Redis, seperti:
- token blocklist logout
- cache API key

## Usulan Perbaikan
1. Perkuat opsi koneksi ioredis di `src/db/redis.ts`:
- tambah `retryStrategy` (backoff dengan batas delay)
- tambah `reconnectOnError` (mis. tangani `READONLY`)
- set `maxRetriesPerRequest` sesuai kebutuhan service long-lived
2. Tambahkan event logging lifecycle Redis:
- `connect`, `ready`, `reconnecting`, `close`, `end`, `error`
3. Ubah `connectRedis()` agar tidak hanya memeriksa status `wait` (lebih defensif terhadap state non-ready lainnya).
4. (Opsional) Tambahkan health endpoint/check sederhana untuk observability dan restart PM2 hanya saat service benar-benar unhealthy (bukan restart setiap Redis restart).

## Kriteria Penerimaan
- [ ] Service otomatis mencoba reconnect saat Redis restart tanpa perlu restart PM2 manual.
- [ ] Setelah Redis kembali up, operasi Redis utama (blocklist token & cache API key) kembali normal.
- [ ] Log menunjukkan transisi state koneksi Redis secara jelas (`reconnecting`, `ready`, dll).
- [ ] Tidak ada loop crash aplikasi akibat error koneksi Redis sementara.

## Referensi Patch Awal (contoh)
```ts
import Redis from 'ioredis';
import { config } from '../config';

const MAX_RETRY_DELAY_MS = 5_000;

export const redisClient = new Redis(config.REDIS_URL, {
lazyConnect: true,
enableReadyCheck: true,
maxRetriesPerRequest: null,
retryStrategy(times) {
const delay = Math.min(times * 200, MAX_RETRY_DELAY_MS);
console.warn(`[Redis] Reconnecting attempt #${times}, delay=${delay}ms`);
return delay;
},
reconnectOnError(err) {
if (err.message.includes('READONLY')) return true;
return false;
},
});

redisClient.on('connect', () => console.log('[Redis] Connected'));
redisClient.on('ready', () => console.log('[Redis] Ready'));
redisClient.on('reconnecting', (ms) => console.warn(`[Redis] Reconnecting in ${ms}ms`));
redisClient.on('close', () => console.warn('[Redis] Connection closed'));
redisClient.on('end', () => console.error('[Redis] Connection ended'));
redisClient.on('error', (err) => console.error('[Redis] Error:', err));

export async function connectRedis(): Promise {
if (redisClient.status !== 'ready' && redisClient.status !== 'connect') {
await redisClient.connect();
}
}
```

Guia de contribuição

Nenhum guia de contribuição indexado para este repositório

Avaliação

Esta issue ainda não foi avaliada.

Receba novas issues na sua caixa de entrada

Um resumo curto de issues do GitHub para quem está começando.