/**
 * BullMQRunner — BullMQ v5 orchestration wrapper.
 *
 * Centralises queue/worker/flow creation with per-archetype defaults,
 * Dead-Letter Queue (DLQ) handling, and OTel alerting.
 *
 * Design constraints:
 * - R2-1: BullMQ parent-failed event unreliable in multi-queue flows.
 *         Every job MUST have `attempts`, `backoff`, `removeOnFail`,
 *         AND a DLQ receiving timeouts > N minutes + OTel alert on DLQ write.
 * - R2-2: BullMQ v5 + Redis + Postgres job log (no Temporal, no Inngest).
 *
 * Archetypes:
 * - cron          — scheduled background jobs (10min timeout, 3 attempts, exp 30s)
 * - event         — reactive to Citadel events / webhooks (2min, 5 attempts, exp 5s)
 * - interactive   — human-in-the-loop tasks (60min, 1 attempt, no backoff)
 * - orchestration — parent/child DAG coordinators (30min, 2 attempts, exp 60s)
 */
import { FlowProducer, type Job, type JobsOptions, Queue, Worker, type WorkerOptions } from "bullmq";
import IORedis from "ioredis";
export type QueueArchetype = "cron" | "event" | "interactive" | "orchestration";
interface ArchetypePolicy {
    /** Hard job timeout (ms). Jobs exceeding this → DLQ + alert. */
    timeoutMs: number;
    /** Max BullMQ attempts. */
    attempts: number;
    /** Backoff policy. `null` disables backoff entirely. */
    backoff: {
        type: "exponential" | "fixed";
        delay: number;
    } | null;
}
export interface BullMQRunnerConfig {
    /**
     * Redis connection URL. Example:
     *   redis://brain-prod-redis.brain-prod.svc.cluster.local:6379
     */
    redisUrl: string;
    /** Logical Redis DB index for isolation from Brain. Default 3. */
    redisDb?: number;
    /** DLQ queue name. Default "cc-dlq". */
    dlqName?: string;
    /** Default attempts if archetype policy is overridden. */
    defaultAttempts?: number;
    /** Default backoff if archetype policy is overridden. */
    defaultBackoff?: {
        type: "exponential" | "fixed";
        delay: number;
    };
    /** Global job timeout override (ms). Default uses archetype policy. */
    jobTimeoutMs?: number;
    /** Factory override for the Redis connection — lets tests inject a mock. */
    redisFactory?: (url: string, db: number) => IORedisLike;
}
/**
 * Minimal Redis surface exposed to BullMQ. Kept as a shared type so tests may
 * supply in-memory fakes without pulling `ioredis-mock` as a dep.
 */
export type IORedisLike = IORedis;
export interface DlqJobPayload {
    originalQueue: string;
    jobId: string | undefined;
    failureReason: string;
    attemptsMade: number;
    /** Best-effort capture of the job data at time of failure (may be undefined). */
    data?: unknown;
    /** ISO timestamp when the entry was moved to DLQ. */
    movedAt: string;
}
export declare class BullMQRunner {
    private readonly cfg;
    private readonly connection;
    private readonly sharedConnectionOpts;
    private readonly queues;
    private readonly queueArchetypes;
    private readonly queueEvents;
    private readonly workers;
    private _flow;
    private _dlq;
    private closed;
    constructor(config: BullMQRunnerConfig);
    /**
     * Create (or return cached) a named queue bound to an archetype.
     * Repeated calls with the same name return the cached queue; the archetype
     * is validated on re-use.
     */
    createQueue(name: string, archetype: QueueArchetype): Queue;
    /**
     * Create a worker bound to a queue. The processor receives BullMQ job;
     * workers inherit the queue's archetype for lock/stall durations.
     */
    createWorker<T = unknown, R = unknown>(queueName: string, processor: (job: Job<T, R>) => Promise<R>, opts?: Partial<WorkerOptions>): Worker<T, R>;
    /** Lazy accessor for the FlowProducer singleton. */
    flowProducer(): FlowProducer;
    /** Lazy accessor for the DLQ. */
    dlqQueue(): Queue<DlqJobPayload>;
    /**
     * Parent-failed reliability helper.
     *
     * Wraps FlowProducer.add() and polls the parent job's
     * `getDependencies({ failed: true })` to explicitly mark the parent failed
     * when any child fails — guaranteeing parent.on("failed") fires even when
     * BullMQ's native propagation is flaky.
     */
    runFlowReliable<Parent = unknown>(parent: {
        name: string;
        queueName: string;
        data?: Parent;
        opts?: JobsOptions;
    }, children: Array<{
        name: string;
        queueName: string;
        data?: unknown;
        opts?: JobsOptions;
    }>, waitOpts?: {
        pollIntervalMs?: number;
        maxWaitMs?: number;
    }): Promise<{
        parentStatus: "completed" | "failed";
        failedChildren: string[];
        parentJobId: string | undefined;
    }>;
    /**
     * Build a simple queue-backed retry helper that ProviderRouter can hand
     * to its retry chain.
     */
    queueRetryFn<T>(queueName: string): (payload: T) => Promise<string>;
    /** Close all resources. Idempotent. */
    close(): Promise<void>;
    private attachDlqListener;
    private moveToDlq;
}
/** Archetype policy accessor (read-only) — exposed for tests and docs. */
export declare function archetypePolicy(archetype: QueueArchetype): Readonly<ArchetypePolicy>;
/** Factory — preferred over direct instantiation for testability. */
export declare function createBullMQRunner(config: BullMQRunnerConfig): BullMQRunner;
export {};
//# sourceMappingURL=bullmq-runner.d.ts.map