Spaces:
Runtime error
Runtime error
File size: 3,405 Bytes
46252cd b58ffca 46252cd b58ffca 46252cd b58ffca 46252cd b58ffca | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 | /**
* BullMQ Redis connection options for the WEBHOOK queue's Worker.
*
* The webhook PRODUCER (the Queue) is configured on the shared `BullModule.forRootAsync` connection
* with `enableOfflineQueue: false`, so `queue.add()` fails fast when Redis is unreachable and the
* dispatch path can fall back to direct delivery instead of buffering forever.
*
* The WORKER must NOT inherit that producer-only fast-fail. Its blocking/internal commands
* (moveToActive, lock renewal) need to tolerate a brief reconnect during a Redis blip/failover;
* BullMQ explicitly recommends leaving the offline queue enabled for Worker connections. Because
* @nestjs/bullmq otherwise builds the Worker from the same shared connection, the WebhookProcessor
* overrides its connection with these options — host/port/username/password/timeout identical to the producer
* (same env vars, same defaults as configuration.ts), but with the offline queue left at ioredis's
* default of `true` so a transient outage no longer throws "Stream isn't writeable" and stalls jobs.
*/
export interface WorkerConnectionOptions {
host: string;
port: number;
username?: string;
password?: string;
connectTimeout: number;
tls?: RedisOptions['tls'];
}
export function workerConnectionOptions(): WorkerConnectionOptions {
const connection = resolveRedisConnectionOptions();
return {
host: connection.host || 'localhost',
port: connection.port || 6379,
username: connection.username,
password: connection.password,
connectTimeout: connection.connectTimeout || 5000,
...(connection.tls ? { tls: connection.tls } : {}),
};
}
/** Default number of webhook deliveries the Worker processes in parallel. */
const DEFAULT_WEBHOOK_WORKER_CONCURRENCY = 10;
/**
* Webhook Worker concurrency. BullMQ defaults a Worker to 1, which serializes ALL webhook deliveries
* process-wide: one slow or timing-out receiver head-of-line-blocks every other session's webhooks
* until it finishes (up to WEBHOOK_TIMEOUT + retries). Running several in parallel decouples healthy
* receivers from a stuck one. Override via WEBHOOK_WORKER_CONCURRENCY; a non-positive/garbage value
* falls back to the default. (Read at module import like workerConnectionOptions above.)
*/
export function webhookWorkerConcurrency(): number {
const parsed = parseInt(process.env.WEBHOOK_WORKER_CONCURRENCY || '', 10);
return Number.isInteger(parsed) && parsed > 0 ? parsed : DEFAULT_WEBHOOK_WORKER_CONCURRENCY;
}
/** Default number of ingress events the Worker processes in parallel. */
const DEFAULT_INGRESS_WORKER_CONCURRENCY = 10;
/**
* Ingress Worker concurrency. Ordering within a conversation is now guaranteed by the
* per-conversation KeyedAsyncLock in the processor, not by a single-worker queue, so raising
* concurrency here parallelizes unrelated conversations instead of head-of-line-blocking every
* inbound event behind the slowest one. Override via INGRESS_WORKER_CONCURRENCY; a
* non-positive/garbage value falls back to the default.
*/
export function ingressWorkerConcurrency(): number {
const parsed = parseInt(process.env.INGRESS_WORKER_CONCURRENCY || '', 10);
return Number.isInteger(parsed) && parsed > 0 ? parsed : DEFAULT_INGRESS_WORKER_CONCURRENCY;
}
import type { RedisOptions } from 'ioredis';
import { resolveRedisConnectionOptions } from '../../config/managed-service-connections';
|