94 lines
2.9 KiB
JavaScript
94 lines
2.9 KiB
JavaScript
// redisSingleton.mjs
|
|
// Conexión Singleton a Redis para Authentik (AK)
|
|
|
|
import { createClient } from 'redis';
|
|
|
|
class RedisAuthentik {
|
|
static instance = null;
|
|
|
|
constructor() {
|
|
if (RedisAuthentik.instance) {
|
|
return RedisAuthentik.instance;
|
|
}
|
|
|
|
const url = process.env.AK_REDIS_URL;
|
|
if (!url) {
|
|
throw new Error('Falta AK_REDIS_URL Ej: redis://:pass@host:6379/0');
|
|
}
|
|
if (!/^redis(s)?:\/\//i.test(url)) {
|
|
throw new Error('AK_REDIS_URL inválida: debe comenzar con "redis://" o "rediss://".');
|
|
}
|
|
|
|
this.url = url;
|
|
this.client = createClient({
|
|
url: this.url,
|
|
socket: { connectTimeout: 5000 },
|
|
});
|
|
|
|
this.client.on('connect', () => console.log(`[REDIS AK] Conectando a ${this.url}`));
|
|
this.client.on('ready', () => console.log('[REDIS AK] Conexión lista.'));
|
|
this.client.on('end', () => console.warn('[REDIS AK] Conexión cerrada.'));
|
|
this.client.on('reconnecting', () => console.warn('[REDIS AK] Reintentando conexión...'));
|
|
this.client.on('error', (err) => console.error('[REDIS AK] Error:', err?.message || err));
|
|
|
|
this._connectingPromise = null;
|
|
RedisAuthentik.instance = this;
|
|
}
|
|
|
|
async connect() {
|
|
if (this.client.isOpen) return this.client;
|
|
if (this._connectingPromise) return this._connectingPromise;
|
|
|
|
this._connectingPromise = this.client.connect()
|
|
.then(() => this.client)
|
|
.catch((err) => {
|
|
this._connectingPromise = null;
|
|
console.error('[REDIS AK] Falló la conexión inicial:', err?.message || err);
|
|
throw err;
|
|
});
|
|
|
|
return this._connectingPromise;
|
|
}
|
|
|
|
getClient() {
|
|
return this.client;
|
|
}
|
|
|
|
async release() {
|
|
try {
|
|
if (this.client?.isOpen) await this.client.quit();
|
|
} catch (e) {
|
|
console.warn('[REDIS AK] Error al cerrar:', e?.message || e);
|
|
} finally {
|
|
this._connectingPromise = null;
|
|
}
|
|
}
|
|
}
|
|
|
|
// Instancia única
|
|
const redisAuthentik = new RedisAuthentik();
|
|
|
|
// --------------------- Healthcheck ---------------------
|
|
async function verificarConexionRedisAuthentik() {
|
|
try {
|
|
console.log(`[REDIS AK] Comprobando accesibilidad a Redis en ${redisAuthentik.url} ...`);
|
|
await redisAuthentik.connect();
|
|
const client = redisAuthentik.getClient();
|
|
|
|
const pong = await client.ping();
|
|
const timeArr = await client.sendCommand(['TIME']);
|
|
const serverDate = new Date(Number(timeArr?.[0] || 0) * 1000);
|
|
|
|
await client.set('hc:authentik', String(Date.now()), { EX: 10 });
|
|
|
|
console.log(`[REDIS AK] Conexión OK. PING=${pong}. Hora Redis:`, serverDate.toISOString());
|
|
} catch (error) {
|
|
console.error('[REDIS AK] Error al conectar:', error?.message || error);
|
|
console.error('[REDIS AK] Revisar AK_REDIS_URL, credenciales, red y firewall.');
|
|
}
|
|
}
|
|
|
|
// Export al estilo de poolSingleton.mjs
|
|
export default { redisAuthentik, verificarConexionRedisAuthentik };
|
|
export { redisAuthentik, verificarConexionRedisAuthentik };
|