94 lines
2.5 KiB
JavaScript
94 lines
2.5 KiB
JavaScript
/**
|
|
* BullMQ / ioredis connection for concierge queues.
|
|
* DigitalOcean Managed Redis (port 25061) requires TLS — use rediss:// or REDIS_TLS=true.
|
|
*/
|
|
function parseRedisUrl(raw) {
|
|
const url = String(raw || 'redis://127.0.0.1:6379').trim();
|
|
try {
|
|
return new URL(url);
|
|
} catch {
|
|
return null;
|
|
}
|
|
}
|
|
|
|
function shouldUseTls(parsed) {
|
|
if (!parsed) return false;
|
|
const force =
|
|
String(process.env.REDIS_TLS || '').trim().toLowerCase() === '1' ||
|
|
String(process.env.REDIS_TLS || '').trim().toLowerCase() === 'true';
|
|
if (force) return true;
|
|
if (parsed.protocol === 'rediss:') return true;
|
|
if (parsed.port === '25061') return true;
|
|
if (parsed.hostname && parsed.hostname.includes('ondigitalocean.com')) return true;
|
|
return false;
|
|
}
|
|
|
|
/**
|
|
* Options for BullMQ `connection` (ioredis). maxRetriesPerRequest must be null for workers.
|
|
* @returns {import('ioredis').RedisOptions}
|
|
*/
|
|
function getBullMQConnection() {
|
|
const raw = process.env.REDIS_URL || 'redis://127.0.0.1:6379';
|
|
const parsed = parseRedisUrl(raw);
|
|
|
|
const conn = {
|
|
maxRetriesPerRequest: null,
|
|
enableReadyCheck: true,
|
|
retryStrategy(times) {
|
|
return Math.min(times * 300, 8000);
|
|
},
|
|
};
|
|
|
|
if (!parsed) {
|
|
return { ...conn, host: '127.0.0.1', port: 6379 };
|
|
}
|
|
|
|
Object.assign(conn, {
|
|
host: parsed.hostname,
|
|
port: Number(parsed.port) || 6379,
|
|
username: parsed.username || undefined,
|
|
password: parsed.password ? decodeURIComponent(parsed.password) : undefined,
|
|
});
|
|
|
|
if (parsed.pathname && parsed.pathname.length > 1) {
|
|
const db = Number(parsed.pathname.slice(1));
|
|
if (!Number.isNaN(db)) conn.db = db;
|
|
}
|
|
|
|
if (shouldUseTls(parsed)) {
|
|
conn.tls = {};
|
|
if (!parsed.port) conn.port = 25061;
|
|
}
|
|
|
|
return conn;
|
|
}
|
|
|
|
/**
|
|
* Verify Redis is reachable at startup (workers).
|
|
*/
|
|
async function verifyRedisConnection() {
|
|
const Redis = require('ioredis');
|
|
const opts = getBullMQConnection();
|
|
const client = new Redis(opts);
|
|
|
|
try {
|
|
await client.ping();
|
|
const tlsNote = opts.tls ? ' (TLS)' : '';
|
|
console.log(`[redis] connected: ${opts.host}:${opts.port}${tlsNote}`);
|
|
} catch (err) {
|
|
const hint = opts.tls
|
|
? ''
|
|
: '\n Hint: DigitalOcean Managed Redis needs TLS. Set REDIS_TLS=true or use rediss:// in REDIS_URL.';
|
|
throw new Error(`Redis connection failed: ${err.message}${hint}`);
|
|
} finally {
|
|
client.disconnect();
|
|
}
|
|
}
|
|
|
|
module.exports = {
|
|
getBullMQConnection,
|
|
verifyRedisConnection,
|
|
shouldUseTls,
|
|
parseRedisUrl,
|
|
};
|