aindrajaya / aindrajaya/node-proxy-server

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

Abierto
#1 0 comentarios 0 reacciones 1 asignado Reclamado por @aindrajaya Ver en GitHub
bug
Lenguaje dominante
TypeScript
Estrellas
0
Forks
0
Métricas de merge de PR
Sin PR fusionados en 30 d

Descripción

## 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();
}
}
```

Guía de contribución

No hay ninguna guía de contribución indexada para este repositorio

Evaluación

Este issue todavía no se ha evaluado.

Recibe los nuevos issues en tu correo

Un resumen breve de issues de GitHub para principiantes.