ravenflow 0.3.0 → 0.4.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/logger.ts","../src/app/queue-manager.ts","../src/processors/token-bucket-job.processor/constants.ts","../src/processors/constants.ts","../src/processors/simple-job.processor.ts","../src/types/job/common.ts","../src/types/job/simple.ts","../src/types/job/memory-etl.ts","../src/types/job/distributed-etl.ts","../src/types/job/stateful-etl.ts","../src/types/job/token-bucket.ts","../src/types/job/unions.ts","../src/types/config.ts","../src/rate-limiter.ts","../src/processors/memory-etl-job.processor.ts","../src/processors/sub-job.ts","../src/processors/etl-context.ts","../src/processors/distributed-etl-job.processor.ts","../src/mongo/connection.ts","../src/mongo/run.repo.ts","../src/mongo/token-bucket.repo.ts","../src/processors/stateful-etl-job.processor/constants.ts","../src/processors/stateful-etl-job.processor/heartbeat.ts","../src/processors/stateful-etl-job.processor/paginate.ts","../src/processors/stateful-etl-job.processor/process.ts","../src/processors/token-bucket-job.processor/compute-credit.ts","../src/processors/token-bucket-job.processor/index.ts","../src/app/job-registry.ts","../src/banner.ts","../src/app/worker-manager.ts","../src/app/scheduler.ts","../src/internal-jobs/stall-watcher/types.ts","../src/internal-jobs/stall-watcher/check-stalled-runs.ts","../src/internal-jobs/stall-watcher/resume-stalled-run.ts","../src/internal-jobs/stall-watcher/index.ts","../src/mongo/repositories/_base.ts","../src/mongo/repositories/workers.repo.ts","../src/mongo/repositories/_types.ts","../src/mongo/repositories/bucket-utils.ts","../src/mongo/mongo-error.ts","../src/mongo/repositories/types.ts","../src/mongo/repositories/job-stats.repo.ts","../src/monitoring/error-signature.ts","../src/monitoring/error-extraction.ts","../src/mongo/repositories/job-errors.repo.ts","../src/mongo/repositories/job-failures.repo.ts","../src/mongo/repositories/job-configs.repo.ts","../src/monitoring/worker-registry.ts","../src/monitoring/batch-writer.types.ts","../src/monitoring/batch-writer.ts","../src/monitoring/log-capture.ts","../src/monitoring/event-hooks.ts","../src/app/disabled-job.ts","../src/app/app.ts","../src/index.ts"],"names":["pino","Queue","QueueEvents","z","resolve","logger","MongoClient","ObjectId","collection","processJob","Worker","db","COLLECTION","createHash","os","crypto","MongoBulkWriteError","DelayedError"],"mappings":"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","file":"index.js","sourcesContent":["import pino from \"pino\";\n\nexport type Logger = pino.Logger;\n\nexport interface LoggerOptions {\n level?: \"trace\" | \"debug\" | \"info\" | \"warn\" | \"error\" | \"fatal\";\n pretty?: boolean;\n}\n\nlet logger: Logger | null = null;\n\nexport function initLogger(options: LoggerOptions = {}): Logger {\n if (logger) return logger;\n\n const isDev = process.env.NODE_ENV !== \"production\";\n const usePretty = options.pretty ?? isDev;\n\n logger = pino({\n level: options.level || (isDev ? \"debug\" : \"info\"),\n transport: usePretty\n ? {\n target: \"pino-pretty\",\n options: {\n colorize: true,\n translateTime: \"HH:MM:ss\",\n ignore: \"pid,hostname\",\n },\n }\n : undefined,\n });\n\n return logger;\n}\n\nexport function getLogger(): Logger {\n if (!logger) {\n throw new Error(\"[ravenflow] Logger not initialized. Call initLogger() first.\");\n }\n return logger;\n}\n","import { ConnectionOptions, DefaultJobOptions, Queue, QueueEvents } from \"bullmq\";\nimport { RavenflowConfig, JobConfig, RetentionConfig } from \"../types\";\n\nexport type QueueStore = Record<string, { queue: Queue; events: QueueEvents }>;\n\nfunction buildDefaultJobOptions(\n retention?: RetentionConfig,\n): DefaultJobOptions | undefined {\n if (!retention) return undefined;\n\n const opts: DefaultJobOptions = {};\n\n if (retention.completed !== undefined) {\n opts.removeOnComplete = { count: retention.completed };\n }\n if (retention.failed !== undefined) {\n opts.removeOnFail = { count: retention.failed };\n }\n\n return Object.keys(opts).length > 0 ? opts : undefined;\n}\n\nexport function initQueues(\n config: RavenflowConfig,\n connection: ConnectionOptions,\n retention?: RetentionConfig,\n): QueueStore {\n const queueNames = new Set<string>([config.defaultQueue]);\n for (const job of Object.values<JobConfig>(config.jobs)) {\n if (job.queue) queueNames.add(job.queue);\n }\n\n const defaultJobOptions = buildDefaultJobOptions(retention);\n\n const queues: QueueStore = {};\n for (const name of queueNames) {\n queues[name] = {\n queue: new Queue(name, { connection, defaultJobOptions }),\n events: new QueueEvents(name, { connection }),\n };\n }\n return queues;\n}\n\n// Generic-erasure internals: `params` width is resolved at the typed proxy boundary\n// (`JobProxy<T>.send`); here the dispatcher accepts the erased shape. Typed config-walker\n// deferred per Story 1.8 AC #15.\n/* eslint-disable @typescript-eslint/no-explicit-any */\nexport async function sendJob(\n jobName: string,\n params: any,\n queues: QueueStore,\n queueName: string,\n) {\n const queueData = queues[queueName];\n if (!queueData) {\n throw new Error(`Queue ${queueName} not found`);\n }\n return await queueData.queue.add(jobName, params);\n}\n\nexport async function sendJobAndWait(\n jobName: string,\n params: any,\n queues: QueueStore,\n queueName: string,\n) {\n const queueData = queues[queueName];\n if (!queueData) {\n throw new Error(`Queue ${queueName} not found`);\n }\n const job = await queueData.queue.add(jobName, params);\n return await job.waitUntilFinished(queueData.events);\n}\n/* eslint-enable @typescript-eslint/no-explicit-any */\n\nexport async function closeQueues(queues: QueueStore) {\n await Promise.all(\n Object.values(queues).map(({ queue, events }) =>\n Promise.all([queue.close(), events.close()]),\n ),\n );\n}\n","import type { TokenBucketInterval } from \"@/types\";\n\nexport const TOKEN_BUCKET_CONSUME_SUFFIX = \":consume\";\n\nexport const INTERVAL_MS: Record<TokenBucketInterval, number> = {\n second: 1_000,\n minute: 60_000,\n hour: 3_600_000,\n day: 86_400_000,\n week: 604_800_000,\n};\n","export const ETL_EXTRACT_SUFFIX = \":extract\";\nexport const ETL_TRANSFORM_SUFFIX = \":transform\";\nexport const ETL_LOAD_SUFFIX = \":load\";\nexport { TOKEN_BUCKET_CONSUME_SUFFIX } from \"./token-bucket-job.processor/constants\";\n","import { Job } from \"bullmq\";\nimport { SimpleJobConfig } from \"../types\";\n\nexport async function processSimpleJob<TData, TReturn>(\n job: Job,\n jobConfig: SimpleJobConfig<TData, TReturn>\n): Promise<TReturn> {\n return jobConfig.handler(job, job.data);\n}\n","import { z } from \"zod\";\n\n// ---------------------------------------------------------------------------\n// Job config base (shared across all job configs)\n// ---------------------------------------------------------------------------\n\nexport interface BaseJobConfig {\n queue?: string;\n cron?: string;\n attempts?: number;\n backoff?: { type: \"fixed\" | \"exponential\"; delay: number };\n}\n\n/** Job config with queue resolved (always has a queue name). */\nexport type ResolvedJobConfig<T extends BaseJobConfig> = T & { queue: string };\n\nexport const zRateLimitConfig = z.union([\n z.object({ perSecond: z.number().positive() }),\n z.object({ perMinute: z.number().positive() }),\n]);\n\nexport type RateLimitConfig = z.infer<typeof zRateLimitConfig>;\n\nexport interface MemoryEtlStepConfig {\n rateLimit?: RateLimitConfig;\n}\n\nexport interface StepConfig extends MemoryEtlStepConfig {\n attempts?: number;\n backoff?: { type: \"fixed\" | \"exponential\"; delay: number };\n queue?: string;\n}\n\nexport interface EtlExtractResult<TRaw, TCursor> {\n data: TRaw[];\n cursor: TCursor | null;\n hasMore: boolean;\n}\n\n// ---------------------------------------------------------------------------\n// Job entity base (shared across all DB-persisted jobs)\n// ---------------------------------------------------------------------------\n\nexport const zJobStatus = z.enum([\n \"pending\",\n \"in_progress\",\n \"completed\",\n \"failed\",\n \"stalled\",\n]);\nexport type JobStatus = z.infer<typeof zJobStatus>;\n\nexport const zBaseJob = z.object({\n _id: z.string(),\n type: z.string(),\n jobId: z.string(),\n jobName: z.string(),\n status: zJobStatus,\n params: z.unknown().nullable(),\n result: z.unknown().nullable(),\n error: z.string().nullable(),\n\n timestamps: z.object({\n createdAt: z.date(),\n updatedAt: z.date(),\n startedAt: z.date().nullable(),\n completedAt: z.date().nullable(),\n }),\n});\n\nexport type BaseJob = z.infer<typeof zBaseJob>;\n","import { z } from \"zod\";\nimport { Job } from \"bullmq\";\nimport { BaseJobConfig, zBaseJob } from \"./common\";\n\n// ---------------------------------------------------------------------------\n// Config\n// ---------------------------------------------------------------------------\n\nexport interface SimpleJobConfig<TData, TReturn> extends BaseJobConfig {\n type: \"simple\";\n handler: (job: Job, params: TData) => Promise<TReturn>;\n}\n\nexport function defineSimpleJob<TData, TReturn>(\n config: Omit<SimpleJobConfig<TData, TReturn>, \"type\">,\n): SimpleJobConfig<TData, TReturn> {\n return { ...config, type: \"simple\" };\n}\n\n// ---------------------------------------------------------------------------\n// Entity\n// ---------------------------------------------------------------------------\n\nexport const zSimpleJob = zBaseJob.extend({\n type: z.literal(\"simple\"),\n});\n\nexport type SimpleJob = z.infer<typeof zSimpleJob>;\n","import { z } from \"zod\";\nimport { BaseJobConfig, EtlExtractResult, MemoryEtlStepConfig, zBaseJob } from \"./common\";\n\n// ---------------------------------------------------------------------------\n// Config\n// ---------------------------------------------------------------------------\n\nexport interface MemoryEtlJobConfig<TRaw, TProcessed, TCursor = number>\n extends BaseJobConfig {\n type: \"memory-etl\";\n extract: (\n cursor: TCursor | null,\n ) => Promise<EtlExtractResult<TRaw, TCursor>>;\n transform: (data: TRaw) => Promise<TProcessed>;\n load: (data: TProcessed[]) => Promise<void>;\n steps?: {\n extract?: MemoryEtlStepConfig;\n transform?: MemoryEtlStepConfig;\n load?: MemoryEtlStepConfig;\n };\n}\n\n// ---------------------------------------------------------------------------\n// Entity\n// ---------------------------------------------------------------------------\n\nexport const zMemoryEtlJob = zBaseJob.extend({\n type: z.literal(\"memory-etl\"),\n\n progress: z.object({\n extractedCount: z.number().int().nonnegative(),\n transformedCount: z.number().int().nonnegative(),\n loadedCount: z.number().int().nonnegative(),\n }),\n});\n\nexport type MemoryEtlJob = z.infer<typeof zMemoryEtlJob>;\n\nexport function defineMemoryEtlJob<TRaw, TProcessed, TCursor = number>(\n config: Omit<MemoryEtlJobConfig<TRaw, TProcessed, TCursor>, \"type\">,\n): MemoryEtlJobConfig<TRaw, TProcessed, TCursor> {\n return { ...config, type: \"memory-etl\" };\n}\n","import { z } from \"zod\";\nimport { BaseJobConfig, EtlExtractResult, StepConfig, zBaseJob } from \"./common\";\n\n// ---------------------------------------------------------------------------\n// Config\n// ---------------------------------------------------------------------------\n\nexport interface DistributedEtlJobConfig<TRaw, TProcessed, TCursor = number>\n extends BaseJobConfig {\n type: \"distributed-etl\";\n extract: (cursor: TCursor | null) => Promise<EtlExtractResult<TRaw, TCursor>>;\n transform: (data: TRaw) => Promise<TProcessed>;\n load: (data: TProcessed[]) => Promise<void>;\n steps?: {\n extract?: StepConfig;\n transform?: StepConfig;\n load?: StepConfig;\n };\n}\n\n// ---------------------------------------------------------------------------\n// Entity\n// ---------------------------------------------------------------------------\n\nexport const zDistributedEtlJob = zBaseJob.extend({\n type: z.literal(\"distributed-etl\"),\n\n progress: z.object({\n extractedCount: z.number().int().nonnegative(),\n transformedCount: z.number().int().nonnegative(),\n loadedCount: z.number().int().nonnegative(),\n }),\n});\n\nexport type DistributedEtlJob = z.infer<typeof zDistributedEtlJob>;\n\nexport function defineDistributedEtlJob<TRaw, TProcessed, TCursor = number>(\n config: Omit<DistributedEtlJobConfig<TRaw, TProcessed, TCursor>, \"type\">,\n): DistributedEtlJobConfig<TRaw, TProcessed, TCursor> {\n return { ...config, type: \"distributed-etl\" };\n}\n","import { z } from \"zod\";\nimport { BaseJobConfig, EtlExtractResult, StepConfig, zBaseJob } from \"./common\";\n\n// ---------------------------------------------------------------------------\n// Config\n// ---------------------------------------------------------------------------\n\nexport interface StatefulEtlJobConfig<TRaw, TProcessed, TCursor = string>\n extends BaseJobConfig {\n type: \"stateful-etl\";\n\n extract: (\n cursor: TCursor | null,\n ) => Promise<EtlExtractResult<TRaw, TCursor>>;\n transform: (data: TRaw) => Promise<TProcessed>;\n load: (data: TProcessed[]) => Promise<void>;\n\n /**\n * When true, only one run of this job can be active at a time.\n * If a run is already pending or in_progress (with a live heartbeat), the new trigger is skipped.\n * Defaults to false — each trigger creates an independent run.\n */\n singletonRun?: boolean;\n stallTimeoutMs?: number;\n maxStallRetries?: number;\n steps?: {\n extract?: StepConfig;\n transform?: StepConfig;\n load?: StepConfig;\n };\n}\n\n// ---------------------------------------------------------------------------\n// Entity\n// ---------------------------------------------------------------------------\n\nexport const zStatefulEtlJob = zBaseJob.extend({\n type: z.literal(\"stateful-etl\"),\n\n stallTimeoutMs: z.number().int().positive(),\n maxStallRetries: z.number().int().nonnegative(),\n\n progress: z.object({\n transformedCount: z.number().int().nonnegative(),\n extractedCount: z.number().int().nonnegative(),\n loadedCount: z.number().int().nonnegative(),\n\n checkpoint: z.unknown().nullable(),\n lastHeartbeatAt: z.date().nullable(),\n stallRetries: z.number().int().nonnegative(),\n }),\n});\n\nexport type StatefulEtlJob = z.infer<typeof zStatefulEtlJob>;\n\nexport function defineStatefulEtlJob<TRaw, TProcessed, TCursor = string>(\n config: Omit<StatefulEtlJobConfig<TRaw, TProcessed, TCursor>, \"type\">,\n): StatefulEtlJobConfig<TRaw, TProcessed, TCursor> {\n return { ...config, type: \"stateful-etl\" };\n}\n","import { z } from \"zod\";\nimport { BaseJobConfig } from \"./common\";\n\n// ---------------------------------------------------------------------------\n// Config\n// ---------------------------------------------------------------------------\n\nexport type TokenBucketInterval = \"second\" | \"minute\" | \"hour\" | \"day\" | \"week\";\n\nexport interface TokenBucketJobConfig extends BaseJobConfig {\n type: \"token-bucket\";\n cron: string;\n\n rate?: {\n amount: number;\n interval: TokenBucketInterval;\n };\n\n getBudget?: () => Promise<number> | number;\n maxCarryOver?: number;\n consumeTimeout?: number;\n\n consume: (tokens: number) => Promise<number | void> | number | void;\n}\n\n// ---------------------------------------------------------------------------\n// State entity (persisted in MongoDB — one document per job)\n// ---------------------------------------------------------------------------\n\nexport const zTokenBucketState = z.object({\n _id: z.string(),\n accumulatedCredit: z.number(),\n lastTickAt: z.date(),\n});\n\nexport type TokenBucketState = z.infer<typeof zTokenBucketState>;\n\nexport function defineTokenBucketJob(\n config: Omit<TokenBucketJobConfig, \"type\">,\n): TokenBucketJobConfig {\n return { ...config, type: \"token-bucket\" };\n}\n","import { z } from \"zod\";\nimport { SimpleJobConfig, zSimpleJob } from \"./simple\";\nimport { MemoryEtlJobConfig, zMemoryEtlJob } from \"./memory-etl\";\nimport { DistributedEtlJobConfig, zDistributedEtlJob } from \"./distributed-etl\";\nimport { StatefulEtlJobConfig, zStatefulEtlJob } from \"./stateful-etl\";\nimport { TokenBucketJobConfig } from \"./token-bucket\";\n\n// ---------------------------------------------------------------------------\n// Config union (discriminated on `type`)\n// ---------------------------------------------------------------------------\n\nexport type JobConfig =\n // `any` in type-parameter position: `JobConfig` is the discriminated-union of all\n // job definitions regardless of their data/return generics. A typed config-walker\n // is deferred per Story 1.8 AC #14 — flagged in deferred-work.md.\n /* eslint-disable @typescript-eslint/no-explicit-any */\n | SimpleJobConfig<any, any>\n | MemoryEtlJobConfig<any, any, any>\n | DistributedEtlJobConfig<any, any, any>\n | StatefulEtlJobConfig<any, any, any>\n | TokenBucketJobConfig;\n/* eslint-enable @typescript-eslint/no-explicit-any */\n\n// ---------------------------------------------------------------------------\n// Entity union (discriminated on `type`)\n// ---------------------------------------------------------------------------\n\nexport const zRavenflowJob = z.discriminatedUnion(\"type\", [\n zSimpleJob,\n zMemoryEtlJob,\n zDistributedEtlJob,\n zStatefulEtlJob,\n]);\n\nexport type RavenflowJob = z.infer<typeof zRavenflowJob>;\n","import { JobConfig } from \"./job\";\n\nexport interface RetentionConfig {\n /** Number of completed jobs to keep per queue. Set to 0 to remove immediately. */\n completed?: number;\n /** Number of failed jobs to keep per queue. Set to 0 to remove immediately. */\n failed?: number;\n}\n\nexport interface RavenflowConfig<TJobs extends string = string> {\n defaultQueue: string;\n jobs: Record<TJobs, JobConfig>;\n}\n\nexport type JobNames<T extends RavenflowConfig> =\n T extends RavenflowConfig<infer TJobs> ? TJobs : never;\n\nexport function defineConfig<const T extends RavenflowConfig>(config: T): T {\n return config;\n}\n","import { type RateLimitConfig, zRateLimitConfig } from \"./types\";\n\nexport class RateLimiter {\n private slots = new Map<string, number>(); // key → nextAvailableAt\n\n /**\n * Block until a slot is available. Combines getDelay + wait in a loop.\n */\n public async waitForSlot(\n key: string,\n config: RateLimitConfig,\n ): Promise<void> {\n let delay = this.getDelay(key, config);\n while (delay > 0) {\n await this.wait(delay);\n delay = this.getDelay(key, config);\n }\n }\n\n /**\n * Check if a slot is available. Returns 0 if allowed (and consumes the slot),\n * or the number of ms to wait before retrying.\n *\n * Slots are evenly spaced: perSecond: 10 → one slot every 100ms.\n */\n public getDelay(key: string, config: RateLimitConfig): number {\n const intervalMs = resolve(config);\n const now = Date.now();\n const nextAvailableAt = this.slots.get(key);\n\n if (nextAvailableAt === undefined || now >= nextAvailableAt) {\n this.slots.set(key, now + intervalMs);\n return 0;\n }\n\n return nextAvailableAt - now;\n }\n\n /**\n * Wait for the given number of ms.\n */\n public wait(ms: number): Promise<void> {\n if (ms <= 0) return Promise.resolve();\n return new Promise((resolve) => setTimeout(resolve, ms));\n }\n}\n\nfunction resolve(config: RateLimitConfig): number {\n zRateLimitConfig.parse(config);\n if (\"perSecond\" in config) return 1_000 / config.perSecond;\n return 60_000 / config.perMinute;\n}\n","import { Job } from \"bullmq\";\nimport { MemoryEtlJobConfig } from \"@/types\";\nimport { getLogger } from \"@/logger\";\nimport { RateLimiter } from \"@/rate-limiter\";\n\nexport async function processMemoryEtlJob<TRaw, TProcessed, TCursor>(\n job: Job,\n config: MemoryEtlJobConfig<TRaw, TProcessed, TCursor>,\n) {\n const logger = getLogger();\n const jobName = job.name;\n const counts = { extractedCount: 0, transformedCount: 0, loadedCount: 0 };\n const limiter = config.steps ? new RateLimiter() : null;\n\n let cursor: TCursor | null = null;\n let hasMore = true;\n\n while (hasMore) {\n await applyRateLimit(limiter, jobName, \"extract\", config);\n\n const page = await config.extract(cursor);\n hasMore = page.hasMore;\n cursor = page.cursor;\n\n if (page.data.length === 0) continue;\n\n counts.extractedCount += page.data.length;\n\n const processed = await transformParallel(\n page.data,\n config.transform,\n limiter,\n jobName,\n config,\n );\n counts.transformedCount += processed.length;\n\n await applyRateLimit(limiter, jobName, \"load\", config);\n await config.load(processed);\n counts.loadedCount += processed.length;\n\n logger.debug({ jobName, ...counts }, \"[memory-etl] batch done\");\n }\n\n logger.info({ jobName, ...counts }, \"[memory-etl] completed\");\n return counts;\n}\n\nasync function transformParallel<TRaw, TProcessed, TCursor>(\n batch: TRaw[],\n transform: (item: TRaw) => Promise<TProcessed>,\n limiter: RateLimiter | null,\n jobName: string,\n config: MemoryEtlJobConfig<TRaw, TProcessed, TCursor>,\n): Promise<TProcessed[]> {\n const pending: Promise<TProcessed>[] = [];\n\n for (const item of batch) {\n await applyRateLimit(limiter, jobName, \"transform\", config);\n pending.push(transform(item));\n }\n\n return Promise.all(pending);\n}\n\ntype StepName = \"extract\" | \"transform\" | \"load\";\n\nasync function applyRateLimit<TRaw, TProcessed, TCursor>(\n limiter: RateLimiter | null,\n jobName: string,\n step: StepName,\n config: MemoryEtlJobConfig<TRaw, TProcessed, TCursor>,\n): Promise<void> {\n const rlConfig = config.steps?.[step]?.rateLimit;\n if (!limiter || !rlConfig) return;\n await limiter.waitForSlot(`ravenflow:rl:${jobName}:${step}`, rlConfig);\n}\n","import { Job, Queue, QueueEvents } from \"bullmq\";\n\nexport interface SubJobOptions {\n attempts?: number;\n backoff?: { type: \"fixed\" | \"exponential\"; delay: number };\n}\n\n/**\n * Dispatch a single sub-job and wait for its result.\n */\nexport async function dispatchSubJob<TData, TReturn>(\n queue: Queue,\n queueEvents: QueueEvents,\n name: string,\n data: TData,\n options?: SubJobOptions,\n): Promise<TReturn> {\n const job = await queue.add(name, data, {\n attempts: options?.attempts,\n backoff: options?.backoff,\n });\n\n return (await job.waitUntilFinished(queueEvents)) as TReturn;\n}\n\n/**\n * Dispatch multiple sub-jobs in parallel and wait for all results.\n */\nexport async function dispatchSubJobs<TData, TReturn>(\n queue: Queue,\n queueEvents: QueueEvents,\n name: string,\n items: TData[],\n options?: SubJobOptions,\n): Promise<TReturn[]> {\n const jobs = await queue.addBulk(\n items.map((data) => ({\n name,\n data,\n opts: {\n attempts: options?.attempts,\n backoff: options?.backoff,\n },\n })),\n );\n\n return Promise.all(\n jobs.map((job) => job.waitUntilFinished(queueEvents) as Promise<TReturn>),\n );\n}\n\n/**\n * Dispatch multiple sub-jobs without waiting. Returns the BullMQ Job instances\n * so the caller can track or ignore them.\n */\nexport async function dispatchSubJobsFireAndForget<TData>(\n queue: Queue,\n name: string,\n items: TData[],\n options?: SubJobOptions,\n): Promise<Job[]> {\n return queue.addBulk(\n items.map((data) => ({\n name,\n data,\n opts: {\n attempts: options?.attempts,\n backoff: options?.backoff,\n },\n })),\n );\n}\n","import { Queue, QueueEvents } from \"bullmq\";\nimport { StepConfig } from \"@/types\";\nimport { getLogger } from \"@/logger\";\nimport { RateLimiter } from \"@/rate-limiter\";\nimport { dispatchSubJob, SubJobOptions } from \"./sub-job\";\nimport { ETL_EXTRACT_SUFFIX, ETL_TRANSFORM_SUFFIX, ETL_LOAD_SUFFIX } from \"./constants\";\n\nexport type StepName = \"extract\" | \"transform\" | \"load\";\n\ninterface StepContext {\n queue: Queue;\n queueEvents: QueueEvents;\n options: SubJobOptions;\n}\n\nexport interface ProgressCounts {\n extractedCount: number;\n transformedCount: number;\n loadedCount: number;\n}\n\ninterface EtlConfig {\n queue: string;\n attempts?: number;\n backoff?: { type: \"fixed\" | \"exponential\"; delay: number };\n steps?: {\n extract?: StepConfig;\n transform?: StepConfig;\n load?: StepConfig;\n };\n}\n\nexport class EtlContext<TRaw, TProcessed> {\n readonly jobName: string;\n readonly counts: ProgressCounts;\n readonly logger: ReturnType<typeof getLogger>;\n\n private readonly steps: Record<StepName, StepContext>;\n private readonly limiter: RateLimiter | null;\n private readonly stepsConfig: EtlConfig[\"steps\"];\n\n constructor(\n jobName: string,\n config: EtlConfig,\n queues: Record<string, { queue: Queue; events: QueueEvents }>,\n initialCounts?: ProgressCounts,\n ) {\n this.jobName = jobName;\n this.logger = getLogger();\n this.stepsConfig = config.steps;\n this.limiter = config.steps ? new RateLimiter() : null;\n this.counts = initialCounts\n ? { ...initialCounts }\n : { extractedCount: 0, transformedCount: 0, loadedCount: 0 };\n\n const defaultQueue = queues[config.queue];\n this.steps = this.buildStepContexts(config, queues, defaultQueue);\n }\n\n // ---------------------------------------------------------------------------\n // Rate limiting\n // ---------------------------------------------------------------------------\n\n async applyRateLimit(step: StepName): Promise<void> {\n const config = this.stepsConfig?.[step]?.rateLimit;\n if (!this.limiter || !config) return;\n await this.limiter.waitForSlot(\n `ravenflow:rl:${this.jobName}:${step}`,\n config,\n );\n }\n\n // ---------------------------------------------------------------------------\n // Sub-job dispatch primitives\n // ---------------------------------------------------------------------------\n\n async dispatchExtract<TCursor>(\n cursor: TCursor | null,\n ): Promise<{\n data: TRaw[];\n cursor: TCursor | null;\n hasMore: boolean;\n }> {\n await this.applyRateLimit(\"extract\");\n const { queue, queueEvents, options } = this.steps.extract;\n\n return dispatchSubJob(\n queue,\n queueEvents,\n `${this.jobName}${ETL_EXTRACT_SUFFIX}`,\n { cursor },\n options,\n );\n }\n\n async dispatchTransform(item: TRaw): Promise<TProcessed> {\n const { queue, queueEvents, options } = this.steps.transform;\n\n return dispatchSubJob<TRaw, TProcessed>(\n queue,\n queueEvents,\n `${this.jobName}${ETL_TRANSFORM_SUFFIX}`,\n item,\n options,\n );\n }\n\n async transformParallel(rawItems: TRaw[]): Promise<TProcessed[]> {\n const pending: Promise<TProcessed>[] = [];\n\n for (const item of rawItems) {\n await this.applyRateLimit(\"transform\");\n pending.push(this.dispatchTransform(item));\n }\n\n return Promise.all(pending);\n }\n\n async dispatchLoad(processedItems: TProcessed[]): Promise<void> {\n await this.applyRateLimit(\"load\");\n const { queue, queueEvents, options } = this.steps.load;\n\n await dispatchSubJob(\n queue,\n queueEvents,\n `${this.jobName}${ETL_LOAD_SUFFIX}`,\n { data: processedItems, jobName: this.jobName },\n options,\n );\n }\n\n // ---------------------------------------------------------------------------\n // Step context setup\n // ---------------------------------------------------------------------------\n\n private buildStepContexts(\n config: EtlConfig,\n queues: Record<string, { queue: Queue; events: QueueEvents }>,\n defaultQueue: { queue: Queue; events: QueueEvents },\n ): Record<StepName, StepContext> {\n const resolve = (step: StepConfig | undefined): StepContext => {\n const q = step?.queue ? queues[step.queue] : defaultQueue;\n if (!q) throw new Error(`Queue \"${step?.queue}\" not found`);\n return {\n queue: q.queue,\n queueEvents: q.events,\n options: {\n attempts: step?.attempts ?? config.attempts,\n backoff: step?.backoff ?? config.backoff,\n },\n };\n };\n\n return {\n extract: resolve(config.steps?.extract),\n transform: resolve(config.steps?.transform),\n load: resolve(config.steps?.load),\n };\n }\n}\n","import { Job, Queue, QueueEvents } from \"bullmq\";\nimport { DistributedEtlJobConfig, EtlExtractResult, ResolvedJobConfig } from \"@/types\";\nimport { EtlContext } from \"./etl-context\";\n\nexport async function processDistributedEtlJob<TRaw, TProcessed, TCursor>(\n job: Job,\n config: ResolvedJobConfig<DistributedEtlJobConfig<TRaw, TProcessed, TCursor>>,\n queues: Record<string, { queue: Queue; events: QueueEvents }>,\n) {\n const ctx = new EtlContext<TRaw, TProcessed>(job.name, config, queues);\n\n let cursor: TCursor | null = null;\n let hasMore = true;\n\n while (hasMore) {\n const page: EtlExtractResult<TRaw, TCursor> = await ctx.dispatchExtract<TCursor>(cursor);\n hasMore = page.hasMore;\n cursor = page.cursor;\n\n if (page.data.length === 0) continue;\n\n ctx.counts.extractedCount += page.data.length;\n\n const processed = await ctx.transformParallel(page.data);\n ctx.counts.transformedCount += processed.length;\n\n await ctx.dispatchLoad(processed);\n ctx.counts.loadedCount += processed.length;\n\n ctx.logger.debug({ jobName: ctx.jobName, ...ctx.counts }, \"[distributed-etl] batch done\");\n }\n\n ctx.logger.info({ jobName: ctx.jobName, ...ctx.counts }, \"[distributed-etl] completed\");\n return ctx.counts;\n}\n","import { MongoClient, Db } from \"mongodb\";\n\nconst COLLECTION_PREFIX = \"ravenflow_\";\n\nlet client: MongoClient | null = null;\nlet db: Db | null = null;\n\nexport async function connectMongo(uri: string): Promise<Db> {\n if (db) return db;\n\n client = new MongoClient(uri);\n await client.connect();\n db = client.db();\n\n return db;\n}\n\nexport function getDb(): Db {\n if (!db) {\n throw new Error(\"[ravenflow] MongoDB not connected. Pass a mongo URI to createRavenflowApp().\");\n }\n return db;\n}\n\nexport function collectionName(name: string): string {\n return `${COLLECTION_PREFIX}${name}`;\n}\n\nexport async function closeMongo(): Promise<void> {\n if (client) {\n await client.close();\n client = null;\n db = null;\n }\n}\n","import { Collection, ObjectId } from \"mongodb\";\nimport { getDb, collectionName } from \"./connection\";\nimport type { StatefulEtlJob } from \"@/types\";\n\nconst RUNS_COLLECTION = \"runs\";\n\nfunction collection(): Collection<StatefulEtlJob> {\n return getDb().collection<StatefulEtlJob>(collectionName(RUNS_COLLECTION));\n}\n\nexport async function findActiveRun(jobName: string): Promise<StatefulEtlJob | null> {\n return await collection().findOne(\n { jobName, status: { $in: [\"pending\", \"in_progress\", \"stalled\"] } },\n { sort: { \"timestamps.createdAt\": -1 } },\n );\n}\n\nexport async function findById(runId: string): Promise<StatefulEtlJob | null> {\n return await collection().findOne({ _id: runId });\n}\n\nexport async function createRun(\n jobName: string,\n params: unknown,\n jobId: string,\n stallTimeoutMs: number,\n maxStallRetries: number,\n): Promise<string> {\n const now = new Date();\n const id = new ObjectId().toString();\n\n await collection().insertOne({\n _id: id,\n type: \"stateful-etl\",\n jobId,\n jobName,\n status: \"pending\",\n params: params ?? null,\n result: null,\n error: null,\n stallTimeoutMs,\n maxStallRetries,\n progress: {\n extractedCount: 0,\n transformedCount: 0,\n loadedCount: 0,\n checkpoint: null,\n lastHeartbeatAt: null,\n stallRetries: 0,\n },\n timestamps: {\n createdAt: now,\n updatedAt: now,\n startedAt: null,\n completedAt: null,\n },\n });\n\n return id;\n}\n\nexport async function markInProgress(runId: string): Promise<void> {\n const now = new Date();\n\n await collection().updateOne(\n { _id: runId },\n {\n $set: {\n status: \"in_progress\",\n \"timestamps.startedAt\": now,\n \"timestamps.updatedAt\": now,\n \"progress.lastHeartbeatAt\": now,\n },\n },\n );\n}\n\nexport async function updateHeartbeat(runId: string): Promise<void> {\n const now = new Date();\n\n await collection().updateOne(\n { _id: runId },\n {\n $set: {\n \"progress.lastHeartbeatAt\": now,\n \"timestamps.updatedAt\": now,\n },\n },\n );\n}\n\nexport async function updateCheckpoint(\n runId: string,\n checkpoint: unknown,\n counts: { extractedCount: number; transformedCount: number; loadedCount: number },\n): Promise<void> {\n await collection().updateOne(\n { _id: runId },\n {\n $set: {\n \"progress.checkpoint\": checkpoint,\n \"progress.extractedCount\": counts.extractedCount,\n \"progress.transformedCount\": counts.transformedCount,\n \"progress.loadedCount\": counts.loadedCount,\n \"timestamps.updatedAt\": new Date(),\n },\n },\n );\n}\n\nexport async function markCompleted(runId: string): Promise<void> {\n const now = new Date();\n\n await collection().updateOne(\n { _id: runId },\n {\n $set: {\n status: \"completed\",\n \"timestamps.completedAt\": now,\n \"timestamps.updatedAt\": now,\n \"progress.lastHeartbeatAt\": null,\n },\n },\n );\n}\n\nexport async function markFailed(runId: string, error: string): Promise<void> {\n const now = new Date();\n\n await collection().updateOne(\n { _id: runId },\n {\n $set: {\n status: \"failed\",\n error,\n \"timestamps.updatedAt\": now,\n \"progress.lastHeartbeatAt\": null,\n },\n },\n );\n}\n\nexport async function findStalled(stallTimeoutMs: number): Promise<StatefulEtlJob[]> {\n const threshold = new Date(Date.now() - stallTimeoutMs);\n\n return await collection()\n .find({\n status: \"in_progress\",\n \"progress.lastHeartbeatAt\": { $lt: threshold },\n })\n .toArray();\n}\n\nexport async function findStalledCandidates(): Promise<StatefulEtlJob[]> {\n const now = new Date();\n\n return await collection()\n .find({\n status: \"in_progress\",\n \"progress.lastHeartbeatAt\": { $ne: null },\n $expr: {\n $lt: [\n \"$progress.lastHeartbeatAt\",\n { $subtract: [now, \"$stallTimeoutMs\"] },\n ],\n },\n })\n .toArray();\n}\n\nexport async function claimStalledRun(runId: string): Promise<StatefulEtlJob | null> {\n const result = await collection().findOneAndUpdate(\n {\n _id: runId,\n status: \"in_progress\",\n },\n {\n $set: {\n status: \"stalled\",\n \"progress.lastHeartbeatAt\": null,\n \"timestamps.updatedAt\": new Date(),\n },\n $inc: {\n \"progress.stallRetries\": 1,\n },\n },\n { returnDocument: \"after\" },\n );\n\n return result ?? null;\n}\n\nexport async function markResuming(runId: string): Promise<void> {\n const now = new Date();\n\n await collection().updateOne(\n { _id: runId },\n {\n $set: {\n status: \"in_progress\",\n \"progress.lastHeartbeatAt\": now,\n \"timestamps.updatedAt\": now,\n },\n },\n );\n}\n","import { Collection } from \"mongodb\";\nimport { getDb, collectionName } from \"./connection\";\nimport type { TokenBucketState } from \"@/types\";\n\nconst COLLECTION = \"token_bucket_state\";\n\nfunction collection(): Collection<TokenBucketState> {\n return getDb().collection<TokenBucketState>(collectionName(COLLECTION));\n}\n\nexport async function getOrCreateState(\n jobName: string,\n now: Date,\n): Promise<TokenBucketState> {\n const result = await collection().findOneAndUpdate(\n { _id: jobName },\n {\n $setOnInsert: {\n _id: jobName,\n accumulatedCredit: 0,\n lastTickAt: now,\n },\n },\n { upsert: true, returnDocument: \"after\" },\n );\n\n return result!;\n}\n\nexport async function updateState(\n jobName: string,\n accumulatedCredit: number,\n lastTickAt: Date,\n): Promise<void> {\n await collection().updateOne(\n { _id: jobName },\n {\n $set: {\n accumulatedCredit,\n lastTickAt,\n },\n },\n );\n}\n\nexport async function ensureIndexes(): Promise<void> {\n // _id index is created automatically by MongoDB — nothing extra needed\n}\n","export { ETL_EXTRACT_SUFFIX, ETL_TRANSFORM_SUFFIX, ETL_LOAD_SUFFIX } from \"../constants\";\n\nexport const DEFAULT_STALL_TIMEOUT_MS = 300_000;\nexport const HEARTBEAT_INTERVAL_MS = 30_000;\nexport const DEFAULT_MAX_STALL_RETRIES = 3;\nexport const DEFAULT_WATCHER_INTERVAL_MS = 60_000;\n","import { getLogger } from \"@/logger\";\nimport { runRepo } from \"@/mongo\";\nimport { HEARTBEAT_INTERVAL_MS } from \"./constants\";\n\nexport function startHeartbeat(\n runId: string,\n): ReturnType<typeof setInterval> {\n const logger = getLogger();\n\n const timer = setInterval(async () => {\n try {\n await runRepo.updateHeartbeat(runId);\n } catch (err) {\n logger.warn(\n { runId, error: err },\n \"[stateful-etl] heartbeat update failed\",\n );\n }\n logger.debug({ runId }, \"[stateful-etl] heartbeat\");\n }, HEARTBEAT_INTERVAL_MS);\n\n timer.unref();\n return timer;\n}\n","import { Queue, QueueEvents } from \"bullmq\";\nimport { StatefulEtlJobConfig, ResolvedJobConfig } from \"@/types\";\nimport { runRepo } from \"@/mongo\";\nimport { EtlContext, type ProgressCounts } from \"../etl-context\";\n\nexport { type ProgressCounts };\n\nexport async function paginateAndProcess<TRaw, TProcessed, TCursor>(\n jobName: string,\n runId: string,\n jobConfig: ResolvedJobConfig<StatefulEtlJobConfig<TRaw, TProcessed, TCursor>>,\n queues: Record<string, { queue: Queue; events: QueueEvents }>,\n initialCursor: TCursor | null,\n initialCounts: ProgressCounts,\n): Promise<void> {\n const ctx = new EtlContext<TRaw, TProcessed>(\n jobName,\n jobConfig,\n queues,\n initialCounts,\n );\n\n let cursor = initialCursor;\n let hasMore = true;\n\n while (hasMore) {\n const page = await ctx.dispatchExtract<TCursor>(cursor);\n hasMore = page.hasMore;\n cursor = page.cursor;\n\n if (page.data.length === 0) continue;\n\n const processed = await ctx.transformParallel(page.data);\n await ctx.dispatchLoad(processed);\n\n ctx.counts.extractedCount += page.data.length;\n ctx.counts.transformedCount += processed.length;\n ctx.counts.loadedCount += processed.length;\n\n await runRepo.updateCheckpoint(runId, cursor, ctx.counts);\n ctx.logger.debug({ jobName, ...ctx.counts }, \"[stateful-etl] batch done\");\n }\n}\n","import { Job, Queue, QueueEvents } from \"bullmq\";\nimport { StatefulEtlJobConfig, ResolvedJobConfig } from \"@/types\";\nimport { runRepo } from \"@/mongo\";\nimport { getLogger } from \"@/logger\";\nimport { startHeartbeat } from \"./heartbeat\";\nimport { paginateAndProcess } from \"./paginate\";\nimport type { ProgressCounts } from \"./paginate\";\nimport { DEFAULT_STALL_TIMEOUT_MS, DEFAULT_MAX_STALL_RETRIES } from \"./constants\";\n\ninterface ResumeData {\n __ravenflow_resume: true;\n runId: string;\n checkpoint: unknown;\n counts: ProgressCounts;\n}\n\nfunction isResumeData(data: unknown): data is ResumeData {\n return (\n typeof data === \"object\" &&\n data !== null &&\n \"__ravenflow_resume\" in data &&\n (data as ResumeData).__ravenflow_resume === true\n );\n}\n\nexport async function processStatefulEtlJob<TRaw, TProcessed, TCursor>(\n job: Job,\n jobConfig: ResolvedJobConfig<StatefulEtlJobConfig<TRaw, TProcessed, TCursor>>,\n queues: Record<string, { queue: Queue; events: QueueEvents }>,\n): Promise<void> {\n const logger = getLogger();\n const jobName = job.name;\n\n if (isResumeData(job.data)) {\n return resumeRun(job.data, jobName, jobConfig, queues, logger);\n }\n\n return freshRun(job, jobName, jobConfig, queues, logger);\n}\n\nasync function resumeRun<TRaw, TProcessed, TCursor>(\n data: ResumeData,\n jobName: string,\n jobConfig: ResolvedJobConfig<StatefulEtlJobConfig<TRaw, TProcessed, TCursor>>,\n queues: Record<string, { queue: Queue; events: QueueEvents }>,\n logger: ReturnType<typeof getLogger>,\n): Promise<void> {\n const { runId, checkpoint, counts } = data;\n logger.info({ jobName, runId }, \"[stateful-etl] resuming stalled run\");\n\n await runRepo.markResuming(runId);\n const heartbeatTimer = startHeartbeat(runId);\n\n try {\n await paginateAndProcess(\n jobName,\n runId,\n jobConfig,\n queues,\n checkpoint as TCursor | null,\n counts,\n );\n\n await runRepo.markCompleted(runId);\n logger.info({ jobName, runId }, \"[stateful-etl] resumed run completed\");\n } catch (error) {\n const message = error instanceof Error ? error.message : String(error);\n await runRepo.markFailed(runId, message);\n logger.error({ jobName, runId, error: message }, \"[stateful-etl] resumed run failed\");\n throw error;\n } finally {\n clearInterval(heartbeatTimer);\n }\n}\n\nasync function freshRun<TRaw, TProcessed, TCursor>(\n job: Job,\n jobName: string,\n jobConfig: ResolvedJobConfig<StatefulEtlJobConfig<TRaw, TProcessed, TCursor>>,\n queues: Record<string, { queue: Queue; events: QueueEvents }>,\n logger: ReturnType<typeof getLogger>,\n): Promise<void> {\n const params = job.data ?? null;\n\n if (jobConfig.singletonRun) {\n await ensureNotAlreadyRunning(jobName);\n }\n\n const stallTimeoutMs = jobConfig.stallTimeoutMs ?? DEFAULT_STALL_TIMEOUT_MS;\n const maxStallRetries = jobConfig.maxStallRetries ?? DEFAULT_MAX_STALL_RETRIES;\n const runId = await runRepo.createRun(jobName, params, job.id!, stallTimeoutMs, maxStallRetries);\n await runRepo.markInProgress(runId);\n\n const heartbeatTimer = startHeartbeat(runId);\n\n try {\n await paginateAndProcess(\n jobName,\n runId,\n jobConfig,\n queues,\n null,\n { extractedCount: 0, transformedCount: 0, loadedCount: 0 },\n );\n\n await runRepo.markCompleted(runId);\n logger.info({ jobName }, \"[stateful-etl] run completed\");\n } catch (error) {\n const message = error instanceof Error ? error.message : String(error);\n await runRepo.markFailed(runId, message);\n logger.error({ jobName, error: message }, \"[stateful-etl] run failed\");\n throw error;\n } finally {\n clearInterval(heartbeatTimer);\n }\n}\n\nasync function ensureNotAlreadyRunning(jobName: string): Promise<void> {\n const activeRun = await runRepo.findActiveRun(jobName);\n if (activeRun) {\n throw new Error(\n `[stateful-etl] job \"${jobName}\" already has an active run (status: ${activeRun.status})`,\n );\n }\n}\n","import type { TokenBucketInterval } from \"@/types\";\nimport { INTERVAL_MS } from \"./constants\";\n\nexport interface ComputeCreditInput {\n now: Date;\n rate?: { amount: number; interval: TokenBucketInterval };\n lastTickAt: Date;\n accumulatedCredit: number;\n maxCarryOver: number;\n budget?: number;\n}\n\nexport interface ComputeCreditResult {\n tokens: number;\n newCredit: number;\n}\n\nexport function computeCredit(input: ComputeCreditInput): ComputeCreditResult {\n const { now, rate, lastTickAt, accumulatedCredit, maxCarryOver, budget } = input;\n\n const elapsedMs = Math.max(0, now.getTime() - lastTickAt.getTime());\n\n const tickCredit = rate\n ? (rate.amount * elapsedMs) / INTERVAL_MS[rate.interval]\n : 0;\n\n const totalCredit = accumulatedCredit + tickCredit;\n\n const cappedCredit = rate\n ? Math.min(totalCredit, tickCredit * (1 + maxCarryOver / 100))\n : totalCredit;\n\n const availableCredit =\n budget !== undefined ? Math.min(cappedCredit, budget) : cappedCredit;\n\n const tokens = Math.floor(availableCredit);\n const newCredit = cappedCredit - tokens;\n\n return { tokens, newCredit };\n}\n","import type { Job } from \"bullmq\";\nimport type { TokenBucketJobConfig, ResolvedJobConfig } from \"@/types\";\nimport type { QueueStore } from \"@/app/queue-manager\";\nimport { getLogger } from \"@/logger\";\nimport { tokenBucketRepo } from \"@/mongo\";\nimport { computeCredit } from \"./compute-credit\";\nimport { TOKEN_BUCKET_CONSUME_SUFFIX } from \"./constants\";\n\nexport { TOKEN_BUCKET_CONSUME_SUFFIX } from \"./constants\";\n\nexport async function processTokenBucketJob(\n job: Job,\n config: ResolvedJobConfig<TokenBucketJobConfig>,\n queues: QueueStore,\n): Promise<void> {\n const logger = getLogger();\n const tickStartedAt = new Date();\n\n const state = await tokenBucketRepo.getOrCreateState(job.name, tickStartedAt);\n\n const budget = config.getBudget ? await config.getBudget() : undefined;\n\n const { tokens, newCredit } = computeCredit({\n now: tickStartedAt,\n rate: config.rate,\n lastTickAt: state.lastTickAt,\n accumulatedCredit: state.accumulatedCredit,\n maxCarryOver: config.maxCarryOver ?? 100,\n budget,\n });\n\n if (tokens === 0) {\n await tokenBucketRepo.updateState(job.name, newCredit, tickStartedAt);\n logger.debug({ jobName: job.name, newCredit }, \"[token-bucket] zero tokens, skipping consume\");\n return;\n }\n\n try {\n const queueData = queues[config.queue];\n const consumeJob = await queueData.queue.add(\n `${job.name}${TOKEN_BUCKET_CONSUME_SUFFIX}`,\n tokens,\n );\n\n // BullMQ's `JobsOptions` has no `timeout` field; the consume-side wait TTL is the\n // second arg of `waitUntilFinished(events, ttl)` per bullmq@5.63.1\n // node_modules/bullmq/dist/esm/classes/job.d.ts:436.\n const result = await consumeJob.waitUntilFinished(queueData.events, config.consumeTimeout);\n\n const consumed = typeof result === \"number\" ? result : tokens;\n const finalCredit = newCredit + (tokens - consumed);\n\n await tokenBucketRepo.updateState(job.name, finalCredit, tickStartedAt);\n logger.info({ jobName: job.name, tokens, consumed, finalCredit }, \"[token-bucket] tick complete\");\n } catch (error) {\n logger.warn({ jobName: job.name, error: String(error) }, \"[token-bucket] consume failed, skipping state update\");\n }\n}\n","import { Job } from \"bullmq\";\nimport { RavenflowConfig, JobConfig, JobNames, JobsProxy } from \"../types\";\nimport {\n processSimpleJob,\n processMemoryEtlJob,\n processDistributedEtlJob,\n processStatefulEtlJob,\n processTokenBucketJob,\n ETL_EXTRACT_SUFFIX,\n ETL_TRANSFORM_SUFFIX,\n ETL_LOAD_SUFFIX,\n TOKEN_BUCKET_CONSUME_SUFFIX,\n} from \"../processors\";\nimport { QueueStore, sendJob, sendJobAndWait } from \"./queue-manager\";\n\nexport function initJobs<TConfig extends RavenflowConfig>(\n config: TConfig,\n queues: QueueStore\n): {\n jobsProxy: JobsProxy<TConfig[\"jobs\"]>;\n jobConfigs: Record<JobNames<TConfig>, JobConfig>;\n} {\n // Generic-erasure proxy: per-job TData/TReturn get resolved via `JobsProxy<TConfig[\"jobs\"]>`\n // at the public API; here we hold the runtime dispatcher as loose `any` and cast once below.\n // Typed config-walker deferred per Story 1.8 AC #15.\n /* eslint-disable @typescript-eslint/no-explicit-any */\n const jobsProxy: Record<string, { send: (params: any) => any; sendAndWait: (params: any) => any }> = {};\n const jobConfigs: Record<string, JobConfig> = {};\n\n for (const [jobName, jobConfig] of Object.entries(config.jobs)) {\n jobConfigs[jobName] = jobConfig;\n\n const resolvedQueue = jobConfig.queue ?? config.defaultQueue;\n\n jobsProxy[jobName] = {\n send: async (params: any) => {\n return sendJob(jobName, params, queues, resolvedQueue);\n },\n sendAndWait: async (params: any) => {\n return sendJobAndWait(jobName, params, queues, resolvedQueue);\n },\n };\n }\n /* eslint-enable @typescript-eslint/no-explicit-any */\n\n return {\n jobsProxy: jobsProxy as JobsProxy<TConfig[\"jobs\"]>,\n jobConfigs: jobConfigs as Record<JobNames<TConfig>, JobConfig>,\n };\n}\n\nconst ALL_SUFFIXES = [\n ETL_EXTRACT_SUFFIX,\n ETL_TRANSFORM_SUFFIX,\n ETL_LOAD_SUFFIX,\n TOKEN_BUCKET_CONSUME_SUFFIX,\n] as const;\n\nexport function resolveJobName(\n name: string,\n jobConfigs: Record<string, JobConfig>\n): { baseName: string; suffix: string | null } {\n for (const suffix of ALL_SUFFIXES) {\n if (!name.endsWith(suffix)) continue;\n\n const baseName = name.slice(0, -suffix.length);\n if (jobConfigs[baseName]) {\n return { baseName, suffix };\n }\n }\n return { baseName: name, suffix: null };\n}\n\nexport async function processJob<TConfig extends RavenflowConfig>(\n job: Job,\n jobConfigs: Record<JobNames<TConfig>, JobConfig>,\n queues: QueueStore,\n defaultQueue: string,\n) {\n const { baseName, suffix } = resolveJobName(job.name, jobConfigs as Record<string, JobConfig>);\n const jobConfig = getJobConfig(baseName, jobConfigs);\n const resolvedQueue = jobConfig.queue ?? defaultQueue;\n\n // -- Sub-job routing --\n if (suffix !== null) {\n if (jobConfig.type === \"distributed-etl\") {\n if (suffix === ETL_EXTRACT_SUFFIX) {\n return await jobConfig.extract(job.data.cursor);\n }\n if (suffix === ETL_TRANSFORM_SUFFIX) {\n return await jobConfig.transform(job.data);\n }\n if (suffix === ETL_LOAD_SUFFIX) {\n return await jobConfig.load(job.data.data);\n }\n }\n\n if (jobConfig.type === \"stateful-etl\") {\n if (suffix === ETL_EXTRACT_SUFFIX) {\n return await jobConfig.extract(job.data.cursor);\n }\n if (suffix === ETL_TRANSFORM_SUFFIX) {\n return await jobConfig.transform(job.data);\n }\n if (suffix === ETL_LOAD_SUFFIX) {\n return await jobConfig.load(job.data.data);\n }\n }\n\n if (jobConfig.type === \"token-bucket\") {\n if (suffix === TOKEN_BUCKET_CONSUME_SUFFIX) {\n return await jobConfig.consume(job.data);\n }\n }\n\n throw new Error(`Unexpected sub-job suffix \"${suffix}\" for ${baseName} (type: ${jobConfig.type})`);\n }\n\n // -- Top-level job routing --\n if (jobConfig.type === \"simple\") {\n return await processSimpleJob(job, jobConfig);\n }\n\n if (jobConfig.type === \"memory-etl\") {\n return await processMemoryEtlJob(job, jobConfig);\n }\n\n if (jobConfig.type === \"distributed-etl\") {\n return await processDistributedEtlJob(job, { ...jobConfig, queue: resolvedQueue }, queues);\n }\n\n if (jobConfig.type === \"stateful-etl\") {\n return await processStatefulEtlJob(job, { ...jobConfig, queue: resolvedQueue }, queues);\n }\n\n if (jobConfig.type === \"token-bucket\") {\n return await processTokenBucketJob(job, { ...jobConfig, queue: resolvedQueue }, queues);\n }\n\n throw new Error(`Unknown job type for: ${job.name}`);\n}\n\nfunction getJobConfig<TConfig extends RavenflowConfig>(\n jobName: string,\n jobConfigs: Record<JobNames<TConfig>, JobConfig>\n): JobConfig {\n const config = jobConfigs[jobName as JobNames<TConfig>];\n if (!config) throw new Error(`Job handler not found: ${jobName}`);\n return config;\n}\n","import { JobConfig } from \"./types\";\n\nconst RAVENFLOW_ASCII = `\n ██████╗ █████╗ ██╗ ██╗███████╗███╗ ██╗███████╗██╗ ██████╗ ██╗ ██╗\n ██╔══██╗██╔══██╗██║ ██║██╔════╝████╗ ██║██╔════╝██║ ██╔═══██╗██║ ██║\n ██████╔╝███████║██║ ██║█████╗ ██╔██╗ ██║█████╗ ██║ ██║ ██║██║ █╗ ██║\n ██╔══██╗██╔══██║╚██╗ ██╔╝██╔══╝ ██║╚██╗██║██╔══╝ ██║ ██║ ██║██║███╗██║\n ██║ ██║██║ ██║ ╚████╔╝ ███████╗██║ ╚████║██║ ███████╗╚██████╔╝╚███╔███╔╝\n ╚═╝ ╚═╝╚═╝ ╚═╝ ╚═══╝ ╚══════╝╚═╝ ╚═══╝╚═╝ ╚══════╝ ╚═════╝ ╚══╝╚══╝\n`;\n\nconst RAVENFLOW_ASCII_ART = ` :==++==-:::..\n :--:::.*%%%%###+====--:::::.\n ===--:+@@%%%##%##*==-=%%%###*##:\n :+===-*@@%%%######*#*#%@@%\n =++==*@@%%%#########@@@@%.\n -*+==@@@%%%######*%@@@@%*\n **+#@@%%%#######%@@@@%%*=\n =**@@%%%%#######@@@@%%%**\n **@@%%%%#%####@@@@@%%#**+\n +#@%%%%%%#%##%@@@@@%%#***-\n %%%%%%#%#%##@@@@@%%%*+***\n .@%%%%%#%%%#%@@@@%%%%+=++*:\n =%%%%%#%%%##@@@@@%%%%===++=\n #%%%%%%%%##@@@@@%%%%*-=====\n =%%%%%%%%%#@@@@@%%%%%::-===\n =%%%#%%%#%@@@@@@@%%%=.:::-:\n +******#%%%%%%%#*=: . .\n`;\n\ninterface BannerConfig {\n queueName: string;\n concurrency: number;\n redis: {\n host: string;\n port: number;\n db: number;\n };\n mongo?: string | null;\n jobs: Record<string, JobConfig>;\n}\n\nfunction censorUri(uri: string): string {\n try {\n const url = new URL(uri);\n if (url.password) url.password = \"***\";\n return url.toString();\n } catch {\n return uri;\n }\n}\n\nexport function printWorkerBanner(config: BannerConfig): void {\n const { queueName, concurrency, redis, mongo, jobs } = config;\n\n console.log(\"\\n\\n\" + RAVENFLOW_ASCII_ART);\n console.log(\"\\n\" + RAVENFLOW_ASCII);\n console.log(\"═\".repeat(85));\n\n console.log(\"\\n[Config]\");\n console.log(` -> queue: ${queueName}`);\n console.log(` -> concurrency: ${concurrency}`);\n console.log(` -> redis: ${redis.host}:${redis.port}/${redis.db}`);\n if (mongo) {\n console.log(` -> mongo: ${censorUri(mongo)}`);\n }\n\n console.log(\"\\n[Registered Jobs]\");\n\n const regularJobs: string[] = [];\n const cronJobs: { name: string; cron: string }[] = [];\n\n for (const [jobName, jobConfig] of Object.entries(jobs)) {\n if (jobConfig.cron) {\n cronJobs.push({ name: jobName, cron: jobConfig.cron });\n } else {\n regularJobs.push(jobName);\n }\n }\n\n if (regularJobs.length > 0) {\n regularJobs.forEach((jobName) => {\n console.log(` . ${jobName}`);\n });\n }\n\n if (cronJobs.length > 0) {\n cronJobs.forEach(({ name, cron }) => {\n console.log(` . ${name} (↻ ${cron})`);\n });\n }\n\n console.log(\"\\n\" + \"═\".repeat(85));\n console.log(\"Ready to process jobs...\\n\");\n}\n","import {\n ConnectionOptions,\n Worker,\n Job,\n type WorkerOptions,\n} from \"bullmq\";\nimport { getLogger } from \"../logger\";\nimport { printWorkerBanner } from \"../banner\";\nimport { JobConfig } from \"../types\";\n\n/**\n * Inlined minute-count constants. Mirrors BullMQ's `MetricsTime` enum\n * (bullmq@5.63.1) but severs the import edge so consumers of this constant\n * don't pull BullMQ into their bundle. Values are pure math (minutes in\n * the named window) and therefore stable across BullMQ versions. Lives\n * here instead of `index.ts` to avoid an import cycle\n * (`index.ts` → `./app/index` → `./app/app` → `worker-manager`).\n */\nexport const METRICS_TIME = {\n ONE_MINUTE: 1,\n FIVE_MINUTES: 5,\n FIFTEEN_MINUTES: 15,\n THIRTY_MINUTES: 30,\n ONE_HOUR: 60,\n ONE_DAY: 1_440,\n ONE_WEEK: 10_080,\n TWO_WEEKS: 20_160,\n ONE_MONTH: 80_640,\n} as const;\n\n/**\n * Default BullMQ metrics configuration applied to every ravenflow-managed\n * Worker. Enables the per-minute data-point collection read by the\n * ravenflow-dashboard Jobs-per-Second indicator (Epic 4 Story 4.2).\n *\n * Without this default, BullMQ's `collectMetrics` Lua function is a no-op on\n * every `moveToFinished` — `queue.getMetrics('completed')` would return\n * `{ meta: { count: 0 }, data: [] }` indefinitely for Ravenflow-managed\n * queues (silent false-negative under real throughput).\n *\n * `ONE_WEEK = 10_080` minutes ≈ 7 days of minute-resolution history at a\n * Redis footprint of ~10 KB/queue/week. Callers may override via the\n * `workerOpts.metrics` parameter on `createWorker` (e.g. to disable\n * collection or pick a shorter window).\n *\n * Frozen so the exported reference cannot be mutated by a caller (shared\n * default would otherwise bleed globally across `createWorker` calls).\n */\nexport const DEFAULT_WORKER_METRICS: NonNullable<WorkerOptions[\"metrics\"]> = Object.freeze({\n maxDataPoints: METRICS_TIME.ONE_WEEK,\n});\n\n/**\n * Pass-through WorkerOptions accepted by `createWorker`. Excludes the three\n * fields ravenflow controls in-situ (`connection`, `autorun`, `concurrency`)\n * so callers cannot override them accidentally. Any other BullMQ option\n * (metrics, stalledInterval, lockDuration, ...) is forwarded to `new Worker`.\n */\nexport type RavenflowWorkerOpts = Omit<\n WorkerOptions,\n \"connection\" | \"autorun\" | \"concurrency\"\n>;\n\nexport function createWorker(\n queueName: string,\n connection: ConnectionOptions,\n concurrency: number,\n // eslint-disable-next-line @typescript-eslint/no-explicit-any -- processJob return width is resolved per job config; typed config-walker deferred per Story 1.8 AC #15\n processJob: (job: Job, token?: string) => Promise<any>,\n workerOpts?: RavenflowWorkerOpts,\n): Worker {\n const worker = new Worker(queueName, processJob, {\n ...workerOpts,\n connection,\n autorun: false,\n concurrency,\n metrics: workerOpts?.metrics ?? DEFAULT_WORKER_METRICS,\n });\n return worker;\n}\n\nexport function setupWorkerEvents(\n worker: Worker,\n queueName: string,\n): void {\n const logger = getLogger();\n worker.on(\"active\", (job) => {\n logger.info(`[${queueName}] ${job.name} - active`);\n });\n\n worker.on(\"completed\", (job) => {\n logger.info(`[${queueName}] ${job.name} - completed`);\n });\n\n worker.on(\"failed\", (job, error) => {\n logger.error(`[${queueName}] ${job?.name} - failed: ${error.message}`);\n });\n}\n\nexport function printBanner(\n queueName: string,\n concurrency: number,\n connection: ConnectionOptions,\n jobConfigs: Record<string, JobConfig>,\n mongoUri?: string | null,\n): void {\n const redisInfo = {\n host:\n typeof connection === \"object\" && \"host\" in connection\n ? (connection.host as string)\n : \"localhost\",\n port:\n typeof connection === \"object\" && \"port\" in connection\n ? (connection.port as number)\n : 6379,\n db:\n typeof connection === \"object\" && \"db\" in connection\n ? (connection.db as number)\n : 0,\n };\n\n printWorkerBanner({\n queueName,\n concurrency,\n redis: redisInfo,\n mongo: mongoUri,\n jobs: jobConfigs,\n });\n}\n\nexport async function closeWorkers(workers: Worker[]): Promise<void> {\n await Promise.all(workers.map((w) => w.close()));\n}\n","import { Queue } from \"bullmq\";\nimport { JobConfig } from \"../types\";\nimport { getLogger } from \"../logger\";\n\nexport async function syncJobSchedulers(\n queue: Queue,\n jobConfigs: Record<string, JobConfig>,\n): Promise<void> {\n const logger = getLogger();\n logger.info(\"[Scheduled Jobs]\");\n\n const jobConfigsWithCron: Record<string, JobConfig> = {};\n for (const jobName in jobConfigs) {\n if (jobConfigs[jobName].cron) {\n jobConfigsWithCron[jobName] = jobConfigs[jobName];\n }\n }\n\n const registeredJobSchedulers = await queue.getJobSchedulers();\n const existingSchedulerKeys = new Set(registeredJobSchedulers.map((s) => s.key));\n\n const removed: string[] = [];\n for (const jobScheduler of registeredJobSchedulers) {\n if (!jobConfigsWithCron[jobScheduler.key]) {\n removed.push(jobScheduler.key);\n await queue.removeJobScheduler(jobScheduler.key);\n }\n }\n\n const newJobs: string[] = [];\n const updated: string[] = [];\n\n for (const jobName in jobConfigsWithCron) {\n const jobConfig = jobConfigsWithCron[jobName];\n if (!jobConfig?.cron) continue;\n\n if (existingSchedulerKeys.has(jobName)) {\n updated.push(jobName);\n } else {\n newJobs.push(jobName);\n }\n\n await queue.upsertJobScheduler(jobName, { pattern: jobConfig.cron });\n }\n\n for (const name of newJobs) {\n logger.info(` + ${name} → ${jobConfigsWithCron[name].cron}`);\n }\n for (const name of updated) {\n logger.info(` ↻ ${name} → ${jobConfigsWithCron[name].cron}`);\n }\n for (const name of removed) {\n logger.info(` - ${name}`);\n }\n if (newJobs.length === 0 && updated.length === 0 && removed.length === 0) {\n logger.info(\" (no scheduled jobs)\");\n }\n}\n","import type { StatefulEtlJobConfig } from \"../../types\";\n\nexport const STALL_CHECK = \"__stall_check\";\nexport const STALL_RESUME = \"__stall_resume\";\n\nexport interface StatefulEtlEntry {\n // eslint-disable-next-line @typescript-eslint/no-explicit-any -- generic erasure at runtime; typed config-walker deferred per Story 1.8 AC #15\n config: StatefulEtlJobConfig<any, any, any>;\n queue: string;\n}\n\nexport interface StallResumePayload {\n runId: string;\n jobName: string;\n queueName: string;\n maxStallRetries: number;\n stallRetries: number;\n checkpoint: unknown;\n extractedCount: number;\n transformedCount: number;\n loadedCount: number;\n}\n","import { Queue } from \"bullmq\";\nimport { getLogger } from \"../../logger\";\nimport { runRepo } from \"../../mongo\";\nimport type { StatefulEtlEntry, StallResumePayload } from \"./types\";\nimport { STALL_RESUME } from \"./types\";\n\n/**\n * Step 1 — Scan MongoDB for stalled runs, verify against Redis,\n * atomically claim them, and dispatch resume sub-jobs.\n */\nexport async function checkStalledRuns(\n statefulEtlConfigs: Map<string, StatefulEtlEntry>,\n userQueues: Record<string, { queue: Queue }>,\n workerQueue: Queue,\n): Promise<void> {\n const logger = getLogger();\n const candidates = await runRepo.findStalledCandidates();\n\n for (const candidate of candidates) {\n const entry = statefulEtlConfigs.get(candidate.jobName);\n if (!entry) {\n logger.warn(\n { runId: candidate._id, jobName: candidate.jobName },\n \"[stall-watcher] unknown job, marking failed\",\n );\n await runRepo.markFailed(\n candidate._id,\n \"Job config not found during stall recovery\",\n );\n continue;\n }\n\n const queueData = userQueues[entry.queue];\n if (!queueData) {\n logger.error(\n { queueName: entry.queue, runId: candidate._id },\n \"[stall-watcher] queue not found\",\n );\n await runRepo.markFailed(\n candidate._id,\n `Queue \"${entry.queue}\" not found during stall recovery`,\n );\n continue;\n }\n\n if (await isJobActiveInRedis(queueData.queue, candidate.jobId)) {\n logger.debug(\n { runId: candidate._id, jobId: candidate.jobId },\n \"[stall-watcher] job still active in Redis, skipping\",\n );\n continue;\n }\n\n const claimed = await runRepo.claimStalledRun(candidate._id);\n if (!claimed) continue;\n\n await workerQueue.add(STALL_RESUME, {\n runId: claimed._id,\n jobName: claimed.jobName,\n queueName: entry.queue,\n maxStallRetries: claimed.maxStallRetries,\n stallRetries: claimed.progress.stallRetries,\n checkpoint: claimed.progress.checkpoint,\n extractedCount: claimed.progress.extractedCount,\n transformedCount: claimed.progress.transformedCount,\n loadedCount: claimed.progress.loadedCount,\n } satisfies StallResumePayload);\n }\n}\n\nasync function isJobActiveInRedis(\n queue: Queue,\n jobId: string,\n): Promise<boolean> {\n try {\n const state = await queue.getJobState(jobId);\n return state === \"active\";\n } catch {\n return false;\n }\n}\n","import { Queue } from \"bullmq\";\nimport { getLogger } from \"../../logger\";\nimport { runRepo } from \"../../mongo\";\nimport type { StallResumePayload } from \"./types\";\n\n/**\n * Step 2 — Handle a single stalled run: re-enqueue on the user's\n * queue with resume data, or mark failed if retries exhausted.\n */\nexport async function resumeStalledRun(\n data: StallResumePayload,\n userQueues: Record<string, { queue: Queue }>,\n): Promise<void> {\n const logger = getLogger();\n\n if (data.stallRetries > data.maxStallRetries) {\n logger.warn(\n {\n runId: data.runId,\n jobName: data.jobName,\n stallRetries: data.stallRetries,\n },\n \"[stall-watcher] max stall retries exceeded, marking failed\",\n );\n await runRepo.markFailed(\n data.runId,\n `Stall recovery exhausted after ${data.stallRetries} retries`,\n );\n return;\n }\n\n const queueData = userQueues[data.queueName];\n if (!queueData) {\n logger.error(\n { queueName: data.queueName, runId: data.runId },\n \"[stall-watcher] queue not found for resume\",\n );\n await runRepo.markFailed(\n data.runId,\n `Queue \"${data.queueName}\" not found`,\n );\n return;\n }\n\n logger.info(\n {\n runId: data.runId,\n jobName: data.jobName,\n stallRetries: data.stallRetries,\n checkpoint: data.checkpoint,\n },\n \"[stall-watcher] re-enqueuing stalled run\",\n );\n\n await queueData.queue.add(data.jobName, {\n __ravenflow_resume: true,\n runId: data.runId,\n checkpoint: data.checkpoint,\n counts: {\n extractedCount: data.extractedCount,\n transformedCount: data.transformedCount,\n loadedCount: data.loadedCount,\n },\n });\n}\n","import { Job, Queue } from \"bullmq\";\nimport { getLogger } from \"../../logger\";\nimport type { JobConfig, StatefulEtlJobConfig } from \"../../types\";\nimport { STALL_CHECK, STALL_RESUME } from \"./types\";\nimport type { StatefulEtlEntry, StallResumePayload } from \"./types\";\nimport { checkStalledRuns } from \"./check-stalled-runs\";\nimport { resumeStalledRun } from \"./resume-stalled-run\";\n\nexport class StallWatcher {\n private readonly workerQueue: Queue;\n private readonly statefulEtlConfigs: Map<string, StatefulEtlEntry>;\n private readonly userQueues: Record<string, { queue: Queue }>;\n\n constructor(\n jobConfigs: Record<string, JobConfig>,\n userQueues: Record<string, { queue: Queue }>,\n defaultQueue: string,\n workerQueue: Queue,\n ) {\n this.userQueues = userQueues;\n this.workerQueue = workerQueue;\n\n this.statefulEtlConfigs = new Map();\n for (const [jobName, config] of Object.entries(jobConfigs)) {\n if (config.type === \"stateful-etl\") {\n this.statefulEtlConfigs.set(jobName, {\n // eslint-disable-next-line @typescript-eslint/no-explicit-any -- generic erasure at runtime; typed config-walker deferred per Story 1.8 AC #15\n config: config as StatefulEtlJobConfig<any, any, any>,\n queue: config.queue ?? defaultQueue,\n });\n }\n }\n }\n\n canProcess(jobName: string): boolean {\n return jobName === STALL_CHECK || jobName === STALL_RESUME;\n }\n\n async start(): Promise<void> {\n if (this.statefulEtlConfigs.size === 0) return;\n\n const logger = getLogger();\n logger.info(\n { jobs: [...this.statefulEtlConfigs.keys()] },\n \"[stall-watcher] starting\",\n );\n\n await this.workerQueue.upsertJobScheduler(STALL_CHECK, {\n pattern: \"* * * * *\",\n });\n }\n\n async stop(): Promise<void> {\n await this.workerQueue.removeJobScheduler(STALL_CHECK);\n }\n\n async process(job: Job): Promise<void> {\n switch (job.name) {\n case STALL_CHECK:\n return checkStalledRuns(\n this.statefulEtlConfigs,\n this.userQueues,\n this.workerQueue,\n );\n case STALL_RESUME:\n return resumeStalledRun(\n job.data as StallResumePayload,\n this.userQueues,\n );\n }\n }\n}\n","import type { Collection, Db, Document } from \"mongodb\";\nimport { collectionName } from \"../connection\";\nimport type { IndexDescriptor } from \"./types\";\n\nexport abstract class Repository<T extends Document> {\n public readonly collection: Collection<T>;\n\n constructor(db: Db, rawCollectionName: string) {\n this.collection = db.collection<T>(collectionName(rawCollectionName));\n }\n\n protected abstract indexes(): IndexDescriptor[];\n\n async init(): Promise<void> {\n for (const idx of this.indexes()) {\n await this.collection.createIndex(idx.keys, idx.options);\n }\n }\n}\n","import type { Db, Filter } from \"mongodb\";\nimport { Repository } from \"./_base\";\nimport type { UpdateSpec } from \"./_types\";\nimport { getLogger } from \"../../logger\";\nimport {\n IndexDescriptor,\n RegisterWorkerInput,\n UpsertWorkerQueueInput,\n WorkerDoc,\n WorkerQueueEntry,\n} from \"./types\";\n\nconst COLLECTION = \"workers\";\n\nexport class WorkersRepo extends Repository<WorkerDoc> {\n constructor(db: Db) {\n super(db, COLLECTION);\n }\n\n protected indexes(): IndexDescriptor[] {\n return [\n {\n keys: { workerId: 1 },\n options: { unique: true, name: \"workerId_unique\" },\n },\n {\n keys: { lastHeartbeatAt: 1 },\n options: { name: \"lastHeartbeatAt_asc\" },\n },\n ];\n }\n\n async registerWorker(input: RegisterWorkerInput): Promise<void> {\n this.validateRegisterInput(input);\n const filter: Filter<WorkerDoc> = { workerId: input.workerId };\n const update: UpdateSpec<WorkerDoc> = {\n $currentDate: {\n lastHeartbeatAt: true,\n updatedAt: true,\n },\n $setOnInsert: {\n workerId: input.workerId,\n hostname: input.hostname,\n pid: input.pid,\n queues: input.queues,\n startedAt: input.startedAt,\n createdAt: new Date(),\n },\n };\n await this.collection.updateOne(filter, update, { upsert: true });\n }\n\n async updateHeartbeat(workerId: string): Promise<void> {\n if (typeof workerId !== \"string\" || workerId.length === 0) {\n throw new Error(\"WorkersRepo.updateHeartbeat: workerId must be a non-empty string\");\n }\n const filter: Filter<WorkerDoc> = { workerId };\n const update: UpdateSpec<WorkerDoc> = {\n $currentDate: { lastHeartbeatAt: true, updatedAt: true },\n };\n const result = await this.collection.updateOne(filter, update);\n if (result.matchedCount === 0) {\n getLogger().warn(\n { workerId },\n \"[workers-repo] heartbeat on missing worker record — ignoring\",\n );\n }\n }\n\n /**\n * Appends or replaces a queue entry on the worker's record.\n *\n * Single-writer invariant: this method is NOT atomic under concurrent writers to the\n * SAME `workerId`. WorkerRegistry is a process-local singleton, and `workerId` is\n * unique per process by contract (default: `<hostname>:<pid>:<uuid>`). Sharing a\n * stable `workerId` across processes violates AC #6 and will race last-writer-wins.\n */\n async addQueue(input: UpsertWorkerQueueInput): Promise<void> {\n if (typeof input.workerId !== \"string\" || input.workerId.length === 0) {\n throw new Error(\"WorkersRepo.addQueue: workerId must be a non-empty string\");\n }\n this.validateQueueEntry(input.queue, \"WorkersRepo.addQueue\");\n\n const existingFilter: Filter<WorkerDoc> = { workerId: input.workerId };\n const existing = await this.collection.findOne(existingFilter);\n\n if (existing === null) {\n throw new Error(\n `WorkersRepo.addQueue: worker not found for workerId=${input.workerId}`,\n );\n }\n\n const existingQueues = existing.queues ?? [];\n const matchIndex = existingQueues.findIndex((q) => q.name === input.queue.name);\n const newQueues: WorkerQueueEntry[] =\n matchIndex === -1\n ? [...existingQueues, input.queue]\n : existingQueues.map((q, i) => (i === matchIndex ? input.queue : q));\n\n const update: UpdateSpec<WorkerDoc> = {\n $set: { queues: newQueues },\n $currentDate: { updatedAt: true },\n };\n await this.collection.updateOne(existingFilter, update);\n }\n\n async deregisterWorker(workerId: string): Promise<void> {\n if (typeof workerId !== \"string\" || workerId.length === 0) {\n throw new Error(\"WorkersRepo.deregisterWorker: workerId must be a non-empty string\");\n }\n const filter: Filter<WorkerDoc> = { workerId };\n await this.collection.deleteOne(filter);\n }\n\n async findAlive(maxHeartbeatAgeMs: number): Promise<WorkerDoc[]> {\n this.validateMaxHeartbeatAgeMs(maxHeartbeatAgeMs, \"WorkersRepo.findAlive\");\n const threshold = new Date(Date.now() - maxHeartbeatAgeMs);\n const filter: Filter<WorkerDoc> = { lastHeartbeatAt: { $gte: threshold } };\n return await this.collection\n .find(filter)\n .sort({ lastHeartbeatAt: -1 })\n .toArray();\n }\n\n async cleanupStale(maxHeartbeatAgeMs: number): Promise<number> {\n this.validateMaxHeartbeatAgeMs(maxHeartbeatAgeMs, \"WorkersRepo.cleanupStale\");\n const threshold = new Date(Date.now() - maxHeartbeatAgeMs);\n const filter: Filter<WorkerDoc> = { lastHeartbeatAt: { $lt: threshold } };\n const result = await this.collection.deleteMany(filter);\n return result.deletedCount ?? 0;\n }\n\n private validateRegisterInput(input: RegisterWorkerInput): void {\n if (typeof input.workerId !== \"string\" || input.workerId.length === 0) {\n throw new Error(\"WorkersRepo.registerWorker: workerId must be a non-empty string\");\n }\n if (typeof input.hostname !== \"string\" || input.hostname.length === 0) {\n throw new Error(\"WorkersRepo.registerWorker: hostname must be a non-empty string\");\n }\n if (!Number.isInteger(input.pid) || input.pid < 0) {\n throw new Error(\"WorkersRepo.registerWorker: pid must be a non-negative integer\");\n }\n if (!Array.isArray(input.queues) || input.queues.length === 0) {\n throw new Error(\"WorkersRepo.registerWorker: queues must be a non-empty array\");\n }\n for (const q of input.queues) {\n this.validateQueueEntry(q, \"WorkersRepo.registerWorker\");\n }\n if (!(input.startedAt instanceof Date) || Number.isNaN(input.startedAt.getTime())) {\n throw new Error(\"WorkersRepo.registerWorker: startedAt must be a valid Date\");\n }\n }\n\n private validateQueueEntry(q: WorkerQueueEntry, ctx: string): void {\n if (q === null || typeof q !== \"object\") {\n throw new Error(`${ctx}: queue entry must be an object`);\n }\n if (typeof q.name !== \"string\" || q.name.length === 0) {\n throw new Error(`${ctx}: queue.name must be a non-empty string`);\n }\n if (!Number.isInteger(q.concurrency) || q.concurrency <= 0) {\n throw new Error(`${ctx}: queue.concurrency must be a positive integer`);\n }\n }\n\n private validateMaxHeartbeatAgeMs(value: number, ctx: string): void {\n const MAX_AGE_MS = 30 * 24 * 60 * 60 * 1000;\n if (!Number.isInteger(value) || value <= 0 || value > MAX_AGE_MS) {\n throw new Error(\n `${ctx}: maxHeartbeatAgeMs must be a positive integer <= ${MAX_AGE_MS}`,\n );\n }\n }\n}\n","import type {\n AnyBulkWriteOperation,\n Document,\n Filter,\n OptionalUnlessRequiredId,\n UpdateFilter,\n} from \"mongodb\";\n\n/**\n * Call-site alias for the driver's `UpdateFilter<T>`. Declaring an update literal\n * with `const update: UpdateSpec<T> = { ... }` widens the literal against the\n * full driver type (not the narrower shape TS infers from the literal), so\n * partial `$setOnInsert` / `$set` documents assign without a post-hoc cast.\n *\n * Type-identical to `UpdateFilter<T>` — readability alias at the declaration\n * site, not a type relaxation.\n */\nexport type UpdateSpec<T extends Document> = UpdateFilter<T>;\n\n/** The shape `insertOne` expects. Re-export for call-site annotations. */\nexport type InsertSpec<T extends Document> = OptionalUnlessRequiredId<T>;\n\nexport interface BulkUpdateOp<T extends Document> {\n updateOne: {\n filter: Filter<T>;\n update: UpdateSpec<T>;\n upsert?: boolean;\n };\n}\n\nexport interface BulkInsertOp<T extends Document> {\n insertOne: {\n document: InsertSpec<T>;\n };\n}\n\n/**\n * Widen a `BulkUpdateOp<T>` to the driver's `AnyBulkWriteOperation<T>` union.\n * Single cast point for the widening — callers use this helper and never\n * write the cast themselves.\n */\nexport function asBulkUpdateOp<T extends Document>(\n op: BulkUpdateOp<T>,\n): AnyBulkWriteOperation<T> {\n return op as AnyBulkWriteOperation<T>;\n}\n\nexport function asBulkInsertOp<T extends Document>(\n op: BulkInsertOp<T>,\n): AnyBulkWriteOperation<T> {\n return op as AnyBulkWriteOperation<T>;\n}\n","import type { BucketGranularity } from \"./types\";\n\nexport function computeBucketStart(\n ts: Date,\n granularity: BucketGranularity,\n): Date {\n const result = new Date(ts);\n if (granularity === \"hour\") {\n result.setUTCMinutes(0, 0, 0);\n } else {\n result.setUTCHours(0, 0, 0, 0);\n }\n return result;\n}\n","export const MONGO_DUPLICATE_KEY_CODE = 11000;\n\nexport function isDuplicateKeyError(err: unknown): boolean {\n if (typeof err !== \"object\" || err === null) return false;\n return (err as { code?: unknown }).code === MONGO_DUPLICATE_KEY_CODE;\n}\n","import type { CreateIndexesOptions, IndexSpecification } from \"mongodb\";\n\nexport interface IndexDescriptor {\n keys: IndexSpecification;\n options?: CreateIndexesOptions;\n}\n\nexport type BucketGranularity = \"hour\" | \"day\";\n\nexport interface IncrementStatsInput {\n success: boolean;\n durationMs?: number;\n}\n\nexport interface JobStatsDoc {\n jobType: string;\n bucketStart: Date;\n granularity: BucketGranularity;\n count: number;\n success: number;\n failed: number;\n totalDurationMs: number;\n createdAt: Date;\n updatedAt: Date;\n}\n\n/** NFR3 default: 90-day TTL for `job_stats`. Hardcoded for this story; configurable in a later story. */\nexport const JOB_STATS_TTL_SECONDS = 90 * 24 * 60 * 60;\n\nexport interface JobErrorDoc {\n signature: string;\n jobType: string;\n message: string;\n stack: string;\n count: number;\n firstSeenAt: Date;\n lastSeenAt: Date;\n createdAt: Date;\n updatedAt: Date;\n /** Normalized `Error.cause` chain beyond the top-level error. OMITTED when empty. */\n causeChain?: Array<{ message: string; name: string }>;\n}\n\nexport interface RecordOccurrenceInput {\n jobType: string;\n error: unknown;\n}\n\nexport interface TopErrorsOptions {\n limit: number;\n jobType?: string;\n /**\n * When set, restricts results to errors whose `lastSeenAt >= since`.\n * Dashboard health views pass the range start (e.g. 7 days ago, UTC midnight)\n * so \"top errors\" matches the displayed range; omitting returns all errors\n * back to the collection's 90-day TTL boundary.\n */\n since?: Date;\n}\n\nexport const JOB_ERRORS_MESSAGE_MAX_CHARS = 2000;\nexport const JOB_ERRORS_STACK_MAX_CHARS = 8000;\nexport const JOB_ERRORS_MAX_TOP_LIMIT = 1000;\n\nexport interface JobFailureDoc {\n jobId: string;\n jobType: string;\n input: string;\n errorMessage: string;\n errorStack: string;\n logs: string;\n failedAt: Date;\n createdAt: Date;\n /** Normalized `Error.cause` chain beyond the top-level error. OMITTED when empty. */\n causeChain?: Array<{ message: string; name: string }>;\n}\n\nexport interface RecordFailureInput {\n jobId: string;\n jobType: string;\n input: unknown;\n error: unknown;\n failedAt: Date;\n logs?: string;\n}\n\nexport interface ListFailuresOptions {\n jobType?: string;\n // `null` is accepted alongside `undefined` — callers crossing JSON boundaries routinely\n // serialize unset optional dates as `null`. The repo normalizes both to \"no filter applied\".\n fromDate?: Date | null;\n toDate?: Date | null;\n skip?: number;\n limit?: number;\n}\n\nexport const JOB_FAILURES_INPUT_MAX_CHARS = 100_000;\nexport const JOB_FAILURES_MESSAGE_MAX_CHARS = 2000;\nexport const JOB_FAILURES_STACK_MAX_CHARS = 8000;\nexport const JOB_FAILURES_LOGS_MAX_CHARS = 500_000;\nexport const JOB_FAILURES_MAX_LIST_LIMIT = 1000;\n\n/** NFR3 default: 7-day TTL for `job_failures`. Hardcoded for this story; configurable in a later story. */\nexport const JOB_FAILURES_TTL_SECONDS = 7 * 24 * 60 * 60;\n\nexport interface WorkerQueueEntry {\n name: string;\n concurrency: number;\n}\n\nexport interface WorkerDoc {\n workerId: string;\n hostname: string;\n pid: number;\n queues: WorkerQueueEntry[];\n startedAt: Date;\n lastHeartbeatAt: Date;\n createdAt: Date;\n updatedAt: Date;\n}\n\nexport interface RegisterWorkerInput {\n workerId: string;\n hostname: string;\n pid: number;\n queues: WorkerQueueEntry[];\n startedAt: Date;\n}\n\nexport interface UpsertWorkerQueueInput {\n workerId: string;\n queue: WorkerQueueEntry;\n}\n\nexport const WORKERS_DEFAULT_HEARTBEAT_INTERVAL_MS = 30_000;\nexport const WORKERS_MIN_HEARTBEAT_INTERVAL_MS = 1_000;\n\n/**\n * Read shape for the `job_configs` collection — what `JobConfigsRepo.getConfig`\n * returns (with persistence timestamps stripped, or synthesized for absent records).\n *\n * Distinct from `JobConfig` (in `src/types/job/unions.ts`), which is the discriminated\n * union of job-definition types (simple / memory-etl / distributed-etl / etc.) used\n * at app-registration time. `JobConfigEntry` is the runtime persistence shape for\n * dashboard-managed per-job-type settings (enabled flag + free-form metadata).\n */\nexport interface JobConfigEntry {\n jobType: string;\n enabled: boolean;\n metadata: Record<string, unknown>;\n}\n\n/**\n * Persisted shape for the `job_configs` collection — the read shape plus\n * MongoDB-managed timestamps. Returned by `JobConfigsRepo.listAll` (every row\n * there is, by definition, persisted, so the timestamps are always real).\n */\nexport interface JobConfigDoc extends JobConfigEntry {\n createdAt: Date;\n updatedAt: Date;\n}\n\nexport const JOB_CONFIGS_DEFAULT_ENABLED = true;\n","import type { AnyBulkWriteOperation, Db, Filter } from \"mongodb\";\nimport { Repository } from \"./_base\";\nimport { asBulkUpdateOp, type UpdateSpec } from \"./_types\";\nimport { computeBucketStart } from \"./bucket-utils\";\nimport { isDuplicateKeyError } from \"../mongo-error\";\nimport { getLogger } from \"../../logger\";\nimport {\n IndexDescriptor,\n JobStatsDoc,\n BucketGranularity,\n IncrementStatsInput,\n JOB_STATS_TTL_SECONDS,\n} from \"./types\";\n\nconst COLLECTION = \"job_stats\";\n\nconst GRANULARITIES: readonly BucketGranularity[] = [\"hour\", \"day\"];\n\nexport const MAX_GET_STATS_RESULTS = 10_000;\n\nexport class JobStatsRepo extends Repository<JobStatsDoc> {\n constructor(db: Db) {\n super(db, COLLECTION);\n }\n\n protected indexes(): IndexDescriptor[] {\n return [\n {\n keys: { jobType: 1, bucketStart: 1, granularity: 1 },\n options: { unique: true, name: \"jobType_bucketStart_granularity_unique\" },\n },\n // NOTE (TTL migration): MongoDB's `createIndex` is a no-op when an index with the same\n // key spec already exists — even if `expireAfterSeconds` differs. Changing\n // `JOB_STATS_TTL_SECONDS` will NOT propagate to a running deployment; apply a `collMod`\n // (or drop-and-recreate this index) manually at deploy time.\n {\n keys: { bucketStart: 1 },\n options: {\n expireAfterSeconds: JOB_STATS_TTL_SECONDS,\n name: \"bucketStart_ttl\",\n },\n },\n ];\n }\n\n /**\n * Builds the bulk write operations for a stats increment WITHOUT executing them.\n * Returns TWO ops — one for the hour bucket, one for the day bucket — matching\n * `incrementStats`'s direct-call shape bit-for-bit. Intended to be pushed through\n * a `BatchWriter` by the event-hooks layer (Story 1.7). Throws synchronously on\n * invalid `durationMs`; otherwise no side effects.\n *\n * NOTE: `now` is captured at builder invocation time, NOT at BatchWriter flush\n * time — `createdAt`, `updatedAt`, and `bucketStart` all reflect the event's\n * wall-clock, not the flush wall-clock. Aggregations are therefore correctly\n * attributed to the hour/day the event occurred, even if the batch flush is\n * delayed by the buffer timer.\n */\n toIncrementStatsOps(\n jobType: string,\n input: IncrementStatsInput,\n ): AnyBulkWriteOperation<JobStatsDoc>[] {\n this.validateDurationMs(input.durationMs, \"toIncrementStatsOps\");\n const now = new Date();\n return GRANULARITIES.map((g) => this.buildBucketOp(jobType, g, now, input));\n }\n\n async incrementStats(\n jobType: string,\n input: IncrementStatsInput,\n ): Promise<void> {\n this.validateDurationMs(input.durationMs, \"incrementStats\");\n\n const now = new Date();\n const results = await Promise.allSettled(\n GRANULARITIES.map((g) => this.upsertBucket(jobType, g, now, input)),\n );\n\n const failures = results\n .map((r, i) => ({ result: r, granularity: GRANULARITIES[i] }))\n .filter((x): x is { result: PromiseRejectedResult; granularity: BucketGranularity } =>\n x.result.status === \"rejected\",\n );\n\n if (failures.length === 0) return;\n\n const logger = getLogger();\n for (const { result, granularity } of failures) {\n logger.error(\n { jobType, granularity, err: result.reason },\n \"JobStatsRepo.incrementStats: bucket upsert failed\",\n );\n }\n\n if (failures.length === results.length) {\n throw failures[0].result.reason;\n }\n }\n\n async getStats(\n jobType: string,\n fromDate: Date,\n toDate: Date,\n granularity: BucketGranularity,\n ): Promise<JobStatsDoc[]> {\n if (fromDate > toDate) {\n throw new Error(\n `JobStatsRepo.getStats: fromDate (${fromDate.toISOString()}) must be <= toDate (${toDate.toISOString()})`,\n );\n }\n\n const filter: Filter<JobStatsDoc> = {\n jobType,\n granularity,\n bucketStart: { $gte: fromDate, $lte: toDate },\n };\n\n return await this.collection\n .find(filter)\n .sort({ bucketStart: 1 })\n .limit(MAX_GET_STATS_RESULTS)\n .toArray();\n }\n\n /**\n * Fetches every stats document in the given range + granularity, across ALL\n * jobTypes. Intended for dashboard views that need a cross-jobType overview\n * (e.g., \"7-day health per job type\") without a prior enumeration step.\n *\n * Result order: `bucketStart` ascending, then `jobType` ascending. Caller is\n * responsible for grouping by jobType client-side if desired.\n *\n * Applies the same `MAX_GET_STATS_RESULTS` cap as `getStats` — a single query\n * across all jobTypes × buckets × granularity is bounded, but the cap keeps\n * the method safe under accidental wide-range queries.\n */\n async getStatsAllJobTypes(\n fromDate: Date,\n toDate: Date,\n granularity: BucketGranularity,\n ): Promise<JobStatsDoc[]> {\n if (fromDate > toDate) {\n throw new Error(\n `JobStatsRepo.getStatsAllJobTypes: fromDate (${fromDate.toISOString()}) must be <= toDate (${toDate.toISOString()})`,\n );\n }\n\n const filter: Filter<JobStatsDoc> = {\n granularity,\n bucketStart: { $gte: fromDate, $lte: toDate },\n };\n\n return await this.collection\n .find(filter)\n .sort({ bucketStart: 1, jobType: 1 })\n .limit(MAX_GET_STATS_RESULTS)\n .toArray();\n }\n\n private async upsertBucket(\n jobType: string,\n granularity: BucketGranularity,\n now: Date,\n input: IncrementStatsInput,\n ): Promise<void> {\n const { filter, update } = this.buildBucketPayload(jobType, granularity, now, input);\n\n try {\n await this.collection.updateOne(filter, update, { upsert: true });\n } catch (err) {\n // E11000 can occur on upsert when two writers both miss the doc and race to insert.\n // Retry once: the doc now exists, so the second attempt hits the $inc path.\n if (isDuplicateKeyError(err)) {\n await this.collection.updateOne(filter, update, { upsert: true });\n return;\n }\n throw err;\n }\n }\n\n private buildBucketOp(\n jobType: string,\n granularity: BucketGranularity,\n now: Date,\n input: IncrementStatsInput,\n ): AnyBulkWriteOperation<JobStatsDoc> {\n const { filter, update } = this.buildBucketPayload(jobType, granularity, now, input);\n return asBulkUpdateOp<JobStatsDoc>({\n updateOne: { filter, update, upsert: true },\n });\n }\n\n private buildBucketPayload(\n jobType: string,\n granularity: BucketGranularity,\n now: Date,\n input: IncrementStatsInput,\n ): { filter: Filter<JobStatsDoc>; update: UpdateSpec<JobStatsDoc> } {\n const bucketStart = computeBucketStart(now, granularity);\n\n const filter: Filter<JobStatsDoc> = { jobType, bucketStart, granularity };\n const update: UpdateSpec<JobStatsDoc> = {\n $inc: {\n count: 1,\n success: input.success ? 1 : 0,\n failed: input.success ? 0 : 1,\n totalDurationMs: input.durationMs ?? 0,\n },\n $setOnInsert: {\n jobType,\n bucketStart,\n granularity,\n createdAt: now,\n },\n $set: {\n updatedAt: now,\n },\n };\n\n return { filter, update };\n }\n\n private validateDurationMs(\n durationMs: number | undefined,\n methodName: string,\n ): void {\n if (durationMs === undefined) return;\n if (!Number.isFinite(durationMs) || durationMs < 0) {\n throw new Error(\n `JobStatsRepo.${methodName}: durationMs must be a finite non-negative number (got ${durationMs})`,\n );\n }\n }\n}\n","import { createHash } from \"node:crypto\";\n\nexport const SIGNATURE_LENGTH = 16;\nexport const STACK_TOP_FRAMES = 5;\n\nconst ISO_TIMESTAMP_REGEX = /\\d{4}-\\d{2}-\\d{2}T\\d{2}:\\d{2}:\\d{2}(?:\\.\\d+)?Z?/g;\nconst UUID_REGEX = /\\b[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}\\b/gi;\nconst HEX_ADDRESS_REGEX = /\\b0x[0-9a-f]+\\b/gi;\nconst LONG_DIGIT_RUN_REGEX = /\\b\\d{5,}\\b/g;\n\nconst STACK_FRAME_PREFIX = \" at \";\nconst STACK_LINE_COL_SUFFIX_REGEX = /:\\d+:\\d+(\\)?)$/;\n\nfunction normalizeMessage(msg: string): string {\n return msg\n .replace(ISO_TIMESTAMP_REGEX, \"<ts>\")\n .replace(UUID_REGEX, \"<uuid>\")\n .replace(HEX_ADDRESS_REGEX, \"<hex>\")\n .replace(LONG_DIGIT_RUN_REGEX, \"<n>\");\n}\n\nfunction normalizeStack(stack: string): string {\n const frames: string[] = [];\n for (const rawLine of stack.split(\"\\n\")) {\n if (!rawLine.startsWith(STACK_FRAME_PREFIX)) continue;\n const slashed = rawLine.replace(/\\\\/g, \"/\");\n const stripped = slashed.replace(STACK_LINE_COL_SUFFIX_REGEX, \"$1\");\n frames.push(stripped);\n if (frames.length === STACK_TOP_FRAMES) break;\n }\n return frames.join(\"\\n\");\n}\n\nexport function errorSignature(err: unknown): string {\n let combined: string;\n if (err instanceof Error) {\n const name = err.name ?? \"Error\";\n const message = normalizeMessage(err.message ?? \"\");\n const stack = err.stack ? normalizeStack(err.stack) : \"\";\n combined = `${name}\\n${message}\\n${stack}`;\n } else {\n combined = normalizeMessage(String(err));\n }\n return createHash(\"sha256\").update(combined).digest(\"hex\").slice(0, SIGNATURE_LENGTH);\n}\n","import { getLogger } from \"../logger\";\n\nexport interface CauseChainEntry {\n message: string;\n name: string;\n}\n\nexport interface ExtractedError {\n /** Top-level message + \"\\nCaused by: \" + inner.message chain, truncated after joining. */\n message: string;\n /** Top-level stack trace only, truncated. Inner stacks are omitted to bound payload. */\n stack: string;\n /** Normalized chain beyond the top level. Empty array when the top Error has no `cause`. */\n causeChain: CauseChainEntry[];\n}\n\nexport interface ExtractMessageAndStackOptions {\n messageMaxChars: number;\n stackMaxChars: number;\n /** Depth cap to guard against cycles and pathological nesting. Default 5. */\n maxCauseDepth?: number;\n}\n\nconst DEFAULT_MAX_CAUSE_DEPTH = 5;\nconst NAME_MAX_CHARS = 64;\nconst CHAIN_SEPARATOR = \"\\nCaused by: \";\n\nfunction truncate(value: string, max: number): string {\n return value.length <= max ? value : value.slice(0, max);\n}\n\nfunction safeGet<T>(getter: () => T, fallback: T): T {\n try {\n return getter();\n } catch {\n return fallback;\n }\n}\n\nfunction isErrorLike(value: unknown): value is { message: unknown; name?: unknown } {\n if (typeof value !== \"object\" || value === null) return false;\n return safeGet(() => \"message\" in value, false);\n}\n\nfunction normalizeEntry(value: unknown, messageMaxChars: number): CauseChainEntry {\n const entryMax = Math.max(1, Math.floor(messageMaxChars / 2));\n if (isErrorLike(value)) {\n const rawMessage = safeGet<unknown>(() => (value as { message: unknown }).message, undefined);\n const rawName = safeGet<unknown>(() => (value as { name?: unknown }).name, undefined);\n const message = truncate(\n typeof rawMessage === \"string\" ? rawMessage : safeGet(() => String(rawMessage), \"\"),\n entryMax,\n );\n const name = truncate(typeof rawName === \"string\" ? rawName : \"Error\", NAME_MAX_CHARS);\n return { message, name };\n }\n return {\n message: truncate(safeGet(() => String(value), \"\"), entryMax),\n name: \"NonError\",\n };\n}\n\nfunction walkCauseChain(\n top: { cause?: unknown },\n maxDepth: number,\n messageMaxChars: number,\n): { chain: CauseChainEntry[]; truncated: boolean } {\n const chain: CauseChainEntry[] = [];\n const seen = new WeakSet<object>();\n if (typeof top === \"object\" && top !== null) seen.add(top);\n\n let current: unknown = safeGet<unknown>(() => top.cause, undefined);\n let truncated = false;\n\n while (current !== undefined && current !== null) {\n if (chain.length >= maxDepth) {\n truncated = true;\n break;\n }\n if (typeof current === \"object\" && current !== null) {\n if (seen.has(current)) {\n truncated = true;\n break;\n }\n seen.add(current);\n }\n\n chain.push(normalizeEntry(current, messageMaxChars));\n\n const hasCause =\n typeof current === \"object\" &&\n current !== null &&\n safeGet(() => \"cause\" in (current as object), false);\n if (hasCause) {\n current = safeGet(() => (current as { cause?: unknown }).cause, undefined);\n } else {\n break;\n }\n }\n\n return { chain, truncated };\n}\n\nexport function extractMessageAndStack(\n err: unknown,\n options: ExtractMessageAndStackOptions,\n): ExtractedError {\n const { messageMaxChars, stackMaxChars } = options;\n const rawMaxDepth = options.maxCauseDepth ?? DEFAULT_MAX_CAUSE_DEPTH;\n const maxCauseDepth = Number.isFinite(rawMaxDepth) && rawMaxDepth >= 1\n ? Math.floor(rawMaxDepth)\n : DEFAULT_MAX_CAUSE_DEPTH;\n\n if (!(err instanceof Error)) {\n return {\n message: truncate(safeGet(() => String(err), \"\"), messageMaxChars),\n stack: \"\",\n causeChain: [],\n };\n }\n\n const topMessage = safeGet<string>(() => {\n const m = err.message;\n return typeof m === \"string\" ? m : String(m ?? \"\");\n }, \"\");\n const topStack = safeGet<string>(() => {\n const s = err.stack;\n return typeof s === \"string\" ? s : String(s ?? \"\");\n }, \"\");\n\n const { chain, truncated } = walkCauseChain(\n err as { cause?: unknown },\n maxCauseDepth,\n messageMaxChars,\n );\n\n if (truncated) {\n getLogger().warn(\n { topMessage: truncate(topMessage, 120) },\n \"extractMessageAndStack: maxCauseDepth reached, truncating cause chain.\",\n );\n }\n\n let joinedMessage = topMessage;\n for (const entry of chain) {\n joinedMessage += `${CHAIN_SEPARATOR}${entry.message}`;\n }\n\n return {\n message: truncate(joinedMessage, messageMaxChars),\n stack: truncate(topStack, stackMaxChars),\n causeChain: chain,\n };\n}\n","import type { AnyBulkWriteOperation, Db, Filter } from \"mongodb\";\nimport { Repository } from \"./_base\";\nimport { asBulkUpdateOp, type UpdateSpec } from \"./_types\";\nimport { errorSignature } from \"../../monitoring/error-signature\";\nimport { extractMessageAndStack } from \"../../monitoring/error-extraction\";\nimport { isDuplicateKeyError } from \"../mongo-error\";\nimport {\n IndexDescriptor,\n JobErrorDoc,\n RecordOccurrenceInput,\n TopErrorsOptions,\n JOB_ERRORS_MESSAGE_MAX_CHARS,\n JOB_ERRORS_STACK_MAX_CHARS,\n JOB_ERRORS_MAX_TOP_LIMIT,\n} from \"./types\";\n\nconst COLLECTION = \"job_errors\";\n\nexport class JobErrorsRepo extends Repository<JobErrorDoc> {\n constructor(db: Db) {\n super(db, COLLECTION);\n }\n\n protected indexes(): IndexDescriptor[] {\n return [\n {\n keys: { signature: 1 },\n options: { unique: true, name: \"signature_unique\" },\n },\n {\n keys: { lastSeenAt: -1 },\n options: { name: \"lastSeenAt_desc\" },\n },\n {\n keys: { jobType: 1, count: -1 },\n options: { name: \"jobType_count_desc\" },\n },\n {\n keys: { count: -1 },\n options: { name: \"count_desc\" },\n },\n ];\n }\n\n /**\n * Records one occurrence of an error, deduplicated by its stable signature.\n *\n * Invariant: `jobType` is set **only on insert** (`$setOnInsert`). Once a signature\n * is first observed under jobType A, subsequent occurrences under jobType B do NOT\n * overwrite the stored value. The signature is the identity of the error; a signature\n * appearing across multiple job types indicates shared infrastructure failure (e.g.\n * ECONNRESET from the shared DB) and is worth surfacing on the first-observed job.\n */\n async recordOccurrence(input: RecordOccurrenceInput): Promise<void> {\n const { filter, update } = this.buildRecordOccurrencePayload(input);\n\n try {\n await this.collection.updateOne(filter, update, { upsert: true });\n } catch (err) {\n if (isDuplicateKeyError(err)) {\n await this.collection.updateOne(filter, update, { upsert: true });\n return;\n }\n throw err;\n }\n }\n\n /**\n * Builds the bulk write operation for `recordOccurrence` WITHOUT executing it.\n * Returns a single upsert op matching the direct-call shape bit-for-bit.\n *\n * NOTE: `now` is captured at builder invocation time, NOT at BatchWriter flush\n * time — firstSeenAt / lastSeenAt reflect the event's wall-clock, not the\n * flush wall-clock. This preserves the semantic that these timestamps track\n * the error's occurrence, not the observability pipeline's delay.\n */\n toRecordOccurrenceOp(input: RecordOccurrenceInput): AnyBulkWriteOperation<JobErrorDoc> {\n const { filter, update } = this.buildRecordOccurrencePayload(input);\n return asBulkUpdateOp<JobErrorDoc>({\n updateOne: { filter, update, upsert: true },\n });\n }\n\n private buildRecordOccurrencePayload(\n input: RecordOccurrenceInput,\n ): { filter: Filter<JobErrorDoc>; update: UpdateSpec<JobErrorDoc> } {\n const signature = errorSignature(input.error);\n const { message, stack, causeChain } = extractMessageAndStack(input.error, {\n messageMaxChars: JOB_ERRORS_MESSAGE_MAX_CHARS,\n stackMaxChars: JOB_ERRORS_STACK_MAX_CHARS,\n });\n const now = new Date();\n\n const filter: Filter<JobErrorDoc> = { signature };\n const update: UpdateSpec<JobErrorDoc> = {\n $inc: { count: 1 },\n $setOnInsert: {\n signature,\n jobType: input.jobType,\n message,\n stack,\n firstSeenAt: now,\n createdAt: now,\n ...(causeChain.length > 0 ? { causeChain } : {}),\n },\n $set: {\n lastSeenAt: now,\n updatedAt: now,\n },\n };\n\n return { filter, update };\n }\n\n async topErrors(options: TopErrorsOptions): Promise<JobErrorDoc[]> {\n if (!(options.limit > 0) || options.limit > JOB_ERRORS_MAX_TOP_LIMIT) {\n throw new Error(\n `JobErrorsRepo.topErrors: limit must be in (0, ${JOB_ERRORS_MAX_TOP_LIMIT}]`,\n );\n }\n\n const filter: Filter<JobErrorDoc> = {\n ...(options.jobType !== undefined ? { jobType: options.jobType } : {}),\n ...(options.since !== undefined ? { lastSeenAt: { $gte: options.since } } : {}),\n };\n\n return await this.collection\n .find(filter)\n .sort({ count: -1 })\n .limit(options.limit)\n .toArray();\n }\n\n}\n","import type { AnyBulkWriteOperation, Db, Filter } from \"mongodb\";\nimport { Repository } from \"./_base\";\nimport { asBulkInsertOp, type BulkInsertOp } from \"./_types\";\nimport { extractMessageAndStack } from \"../../monitoring/error-extraction\";\nimport {\n IndexDescriptor,\n JobFailureDoc,\n RecordFailureInput,\n ListFailuresOptions,\n JOB_FAILURES_INPUT_MAX_CHARS,\n JOB_FAILURES_MESSAGE_MAX_CHARS,\n JOB_FAILURES_STACK_MAX_CHARS,\n JOB_FAILURES_LOGS_MAX_CHARS,\n JOB_FAILURES_MAX_LIST_LIMIT,\n JOB_FAILURES_TTL_SECONDS,\n} from \"./types\";\n\nconst COLLECTION = \"job_failures\";\n\nconst DEFAULT_LIST_LIMIT = 50;\n\nexport class JobFailuresRepo extends Repository<JobFailureDoc> {\n constructor(db: Db) {\n super(db, COLLECTION);\n }\n\n protected indexes(): IndexDescriptor[] {\n return [\n {\n keys: { jobId: 1, failedAt: -1 },\n options: { name: \"jobId_failedAt_desc\" },\n },\n {\n keys: { jobType: 1, failedAt: -1 },\n options: { name: \"jobType_failedAt_desc\" },\n },\n // NOTE (TTL migration): MongoDB's `createIndex` is a no-op when an index with the same\n // key spec already exists — even if `expireAfterSeconds` differs. Changing\n // `JOB_FAILURES_TTL_SECONDS` will NOT propagate to a running deployment; apply a `collMod`\n // (or drop-and-recreate this index) manually at deploy time.\n {\n keys: { failedAt: 1 },\n options: {\n expireAfterSeconds: JOB_FAILURES_TTL_SECONDS,\n name: \"failedAt_ttl\",\n },\n },\n ];\n }\n\n async recordFailure(input: RecordFailureInput): Promise<void> {\n const doc = this.buildFailureDoc(input);\n await this.collection.insertOne(doc);\n }\n\n /**\n * Builds the bulk write operation for `recordFailure` WITHOUT executing it.\n * Returns a single insertOne op matching the direct-call document shape\n * bit-for-bit. Intended for the event-hooks layer (Story 1.7) to push through\n * a `BatchWriter`. Throws synchronously on invalid input using the same error\n * messages as `recordFailure`.\n */\n toRecordFailureOp(input: RecordFailureInput): AnyBulkWriteOperation<JobFailureDoc> {\n const doc = this.buildFailureDoc(input);\n const op: BulkInsertOp<JobFailureDoc> = { insertOne: { document: doc } };\n return asBulkInsertOp<JobFailureDoc>(op);\n }\n\n private buildFailureDoc(input: RecordFailureInput): JobFailureDoc {\n this.validateFailureInput(input);\n\n const serializedInput = this.serializeInputValue(input.input).slice(\n 0,\n JOB_FAILURES_INPUT_MAX_CHARS,\n );\n const { message, stack, causeChain } = extractMessageAndStack(input.error, {\n messageMaxChars: JOB_FAILURES_MESSAGE_MAX_CHARS,\n stackMaxChars: JOB_FAILURES_STACK_MAX_CHARS,\n });\n const logs = this.capLogs(input.logs);\n\n const doc: JobFailureDoc = {\n jobId: input.jobId,\n jobType: input.jobType,\n input: serializedInput,\n errorMessage: message,\n errorStack: stack,\n logs,\n failedAt: input.failedAt,\n createdAt: new Date(),\n };\n if (causeChain.length > 0) {\n doc.causeChain = causeChain;\n }\n return doc;\n }\n\n private validateFailureInput(input: RecordFailureInput): void {\n if (typeof input.jobId !== \"string\" || input.jobId.length === 0) {\n throw new Error(\"JobFailuresRepo.recordFailure: jobId must be a non-empty string\");\n }\n if (typeof input.jobType !== \"string\" || input.jobType.length === 0) {\n throw new Error(\"JobFailuresRepo.recordFailure: jobType must be a non-empty string\");\n }\n if (!(input.failedAt instanceof Date) || Number.isNaN(input.failedAt.getTime())) {\n throw new Error(\"JobFailuresRepo.recordFailure: failedAt must be a valid Date\");\n }\n }\n\n async listFailures(\n options: ListFailuresOptions,\n ): Promise<{ items: JobFailureDoc[]; total: number }> {\n if (options.limit !== undefined) {\n if (\n !Number.isInteger(options.limit) ||\n options.limit <= 0 ||\n options.limit > JOB_FAILURES_MAX_LIST_LIMIT\n ) {\n throw new Error(\n `JobFailuresRepo.listFailures: limit must be an integer in (0, ${JOB_FAILURES_MAX_LIST_LIMIT}]`,\n );\n }\n }\n if (options.skip !== undefined) {\n if (!Number.isInteger(options.skip) || options.skip < 0) {\n throw new Error(\n \"JobFailuresRepo.listFailures: skip must be a non-negative integer\",\n );\n }\n }\n\n // Normalize null → undefined; callers crossing JSON boundaries routinely send null for unset fields.\n const fromDate = options.fromDate ?? undefined;\n const toDate = options.toDate ?? undefined;\n if (fromDate !== undefined && (!(fromDate instanceof Date) || Number.isNaN(fromDate.getTime()))) {\n throw new Error(\"JobFailuresRepo.listFailures: fromDate must be a valid Date\");\n }\n if (toDate !== undefined && (!(toDate instanceof Date) || Number.isNaN(toDate.getTime()))) {\n throw new Error(\"JobFailuresRepo.listFailures: toDate must be a valid Date\");\n }\n if (fromDate !== undefined && toDate !== undefined && fromDate.getTime() > toDate.getTime()) {\n throw new Error(\"JobFailuresRepo.listFailures: fromDate must be <= toDate\");\n }\n\n const skip = options.skip ?? 0;\n const limit = options.limit ?? DEFAULT_LIST_LIMIT;\n\n const filter: Filter<JobFailureDoc> = {};\n if (options.jobType !== undefined) {\n filter.jobType = options.jobType;\n }\n if (fromDate !== undefined || toDate !== undefined) {\n const range: { $gte?: Date; $lte?: Date } = {};\n if (fromDate !== undefined) range.$gte = fromDate;\n if (toDate !== undefined) range.$lte = toDate;\n filter.failedAt = range;\n }\n\n const [items, total] = await Promise.all([\n this.collection\n .find(filter)\n .sort({ failedAt: -1 })\n .skip(skip)\n .limit(limit)\n .toArray(),\n this.collection.countDocuments(filter),\n ]);\n\n return { items, total };\n }\n\n async getFailure(jobId: string): Promise<JobFailureDoc | null> {\n if (typeof jobId !== \"string\" || jobId.length === 0) {\n throw new Error(\"JobFailuresRepo.getFailure: jobId must be a non-empty string\");\n }\n const filter: Filter<JobFailureDoc> = { jobId };\n return await this.collection.findOne(filter, { sort: { failedAt: -1 } });\n }\n\n private serializeInputValue(input: unknown): string {\n if (input === undefined) return \"undefined\";\n try {\n // Custom replacer preserves Map and Set (JSON.stringify otherwise serializes both as \"{}\").\n // Symbols are still silently dropped per ECMA-262 — that behavior is intentional.\n const result = JSON.stringify(input, (_key, value) => {\n if (value instanceof Map) return { __type: \"Map\", entries: Array.from(value.entries()) };\n if (value instanceof Set) return { __type: \"Set\", values: Array.from(value.values()) };\n return value;\n });\n // JSON.stringify can return undefined for e.g. functions or raw symbols passed as root value.\n if (result === undefined) return \"undefined\";\n return result;\n } catch (err) {\n const msg = err instanceof Error ? err.message : String(err);\n return `[input serialization failed: ${msg}]`;\n }\n }\n\n private capLogs(logs: string | undefined): string {\n if (logs === undefined) return \"\";\n if (logs.length <= JOB_FAILURES_LOGS_MAX_CHARS) return logs;\n\n const originalLen = logs.length;\n let tailLen = JOB_FAILURES_LOGS_MAX_CHARS;\n let marker = \"\";\n for (let i = 0; i < 3; i++) {\n marker = `[truncated — showing last ${tailLen} of ${originalLen} chars]\\n`;\n if (marker.length >= JOB_FAILURES_LOGS_MAX_CHARS) {\n return marker.slice(0, JOB_FAILURES_LOGS_MAX_CHARS);\n }\n tailLen = JOB_FAILURES_LOGS_MAX_CHARS - marker.length;\n }\n return marker + logs.slice(-tailLen);\n }\n}\n","import type { Db, Filter, AnyBulkWriteOperation } from \"mongodb\";\nimport { Repository } from \"./_base\";\nimport { asBulkUpdateOp, type UpdateSpec } from \"./_types\";\nimport {\n IndexDescriptor,\n JobConfigEntry,\n JobConfigDoc,\n JOB_CONFIGS_DEFAULT_ENABLED,\n} from \"./types\";\nimport type { JobConfig } from \"../../types\";\n\nconst COLLECTION = \"job_configs\";\n\nexport class JobConfigsRepo extends Repository<JobConfigDoc> {\n constructor(db: Db) {\n super(db, COLLECTION);\n }\n\n protected indexes(): IndexDescriptor[] {\n return [\n {\n keys: { jobType: 1 },\n options: { unique: true, name: \"jobType_unique\" },\n },\n ];\n }\n\n async getConfig(jobType: string): Promise<JobConfigEntry> {\n this.validateJobType(jobType, \"JobConfigsRepo.getConfig\");\n const filter: Filter<JobConfigDoc> = { jobType };\n const doc = await this.collection.findOne(filter);\n\n if (!doc) {\n return {\n jobType,\n enabled: JOB_CONFIGS_DEFAULT_ENABLED,\n metadata: {},\n };\n }\n\n return {\n jobType: doc.jobType,\n enabled: doc.enabled,\n metadata: doc.metadata,\n };\n }\n\n async setEnabled(jobType: string, enabled: boolean): Promise<void> {\n this.validateJobType(jobType, \"JobConfigsRepo.setEnabled\");\n if (typeof enabled !== \"boolean\") {\n throw new Error(\"JobConfigsRepo.setEnabled: enabled must be a boolean\");\n }\n\n const filter: Filter<JobConfigDoc> = { jobType };\n const update: UpdateSpec<JobConfigDoc> = {\n $set: { enabled },\n $setOnInsert: {\n jobType,\n metadata: {},\n createdAt: new Date(),\n },\n $currentDate: { updatedAt: true },\n };\n const result = await this.collection.updateOne(filter, update, { upsert: true });\n\n if (result.matchedCount === 0 && (result.upsertedCount ?? 0) === 0) {\n throw new Error(\n `JobConfigsRepo.setEnabled: updateOne acknowledged no write for jobType=${jobType}`,\n );\n }\n }\n\n async listAll(): Promise<JobConfigDoc[]> {\n return await this.collection\n .find({})\n .sort({ jobType: 1 })\n .toArray();\n }\n\n async isEnabled(jobType: string): Promise<boolean> {\n this.validateJobType(jobType, \"JobConfigsRepo.isEnabled\");\n const filter: Filter<JobConfigDoc> = { jobType };\n const doc = await this.collection.findOne(filter, {\n projection: { enabled: 1, _id: 0 },\n });\n\n if (!doc) {\n return JOB_CONFIGS_DEFAULT_ENABLED;\n }\n return doc.enabled;\n }\n\n /**\n * Idempotent bulk upsert of every registered jobType + its metadata\n * projection (Story 5.1 D5.1-a). Called once per `RavenflowApp` instance\n * inside `initializeMonitoring()`.\n *\n * Semantics:\n * - `$setOnInsert { enabled: true, createdAt }` — the enabled flag is\n * set to the default ONLY on initial insert. An operator-toggled\n * `enabled: false` is NEVER overwritten by a subsequent boot.\n * - `$set { metadata }` — metadata is always refreshed from code config\n * (code is source of truth for non-user-writable fields).\n * - `$currentDate { updatedAt }` — timestamp bumps every call.\n *\n * Metadata projection (narrow + stable — see D5.1-h):\n * - `type`: jobConfig.type (always present in the discriminated union).\n * - `queue`: jobConfig.queue ?? null (null = inherits defaultQueue).\n * - `cron`: jobConfig.cron if present (token-bucket only today), else null.\n *\n * Additional type-specific fields (token-bucket's `rate`, distributed-etl's\n * `steps`) are NOT extracted — BSON can't serialize the function references\n * they contain, and the dashboard surface consumes only `type`/`queue`/`cron`\n * in V1. Future stories can widen this projection without a schema change.\n *\n * Failure mode: `bulkWrite` is the only I/O. Empty input short-circuits\n * because the driver rejects empty ops arrays.\n */\n async ensureEntries(\n jobs: Record<string, JobConfig>,\n ): Promise<void> {\n // Null / non-object input — return instead of throwing Object.entries(null)\n // TypeError (Story 5.1 code review P7). Preserves the \"non-fatal at boot\"\n // contract the caller (app.ts::initializeMonitoring) relies on.\n if (jobs === null || typeof jobs !== \"object\") return;\n\n const entries = Object.entries(jobs);\n if (entries.length === 0) return;\n\n // Validate-first pass (Story 5.1 code review P8). A bad jobType throws\n // BEFORE any bulk op is constructed so the error is localized and no\n // partial state is built up.\n for (const [jobType] of entries) {\n this.validateJobType(jobType, \"JobConfigsRepo.ensureEntries\");\n }\n\n const ops: Array<AnyBulkWriteOperation<JobConfigDoc>> = entries.map(\n ([jobType, cfg]) => {\n const cron =\n \"cron\" in cfg && typeof cfg.cron === \"string\" && cfg.cron.length > 0\n ? cfg.cron\n : null;\n const metadata: Record<string, unknown> = {\n type: cfg.type,\n queue: cfg.queue ?? null,\n cron,\n };\n const update: UpdateSpec<JobConfigDoc> = {\n $setOnInsert: {\n jobType,\n enabled: JOB_CONFIGS_DEFAULT_ENABLED,\n createdAt: new Date(),\n },\n $set: { metadata },\n $currentDate: { updatedAt: true },\n };\n return asBulkUpdateOp<JobConfigDoc>({\n updateOne: {\n filter: { jobType } as Filter<JobConfigDoc>,\n update,\n upsert: true,\n },\n });\n },\n );\n\n await this.collection.bulkWrite(ops, { ordered: false });\n }\n\n private validateJobType(jobType: string, ctx: string): void {\n if (typeof jobType !== \"string\" || jobType.length === 0) {\n throw new Error(`${ctx}: jobType must be a non-empty string`);\n }\n // Reject Mongo-reserved prefix/operator characters — `$` begins a\n // Mongo operator, `.` is a path separator. A jobType containing\n // either one could cross the filter/update-document boundary and\n // rewrite an unintended field (Story 5.1 code review P9).\n if (jobType.includes(\".\") || jobType.includes(\"$\")) {\n throw new Error(\n `${ctx}: jobType cannot contain '.' or '$' (Mongo-reserved characters)`,\n );\n }\n }\n}\n","import * as os from \"node:os\";\nimport * as crypto from \"node:crypto\";\nimport type { WorkersRepo } from \"../mongo/repositories/workers.repo\";\nimport type { WorkerQueueEntry } from \"../mongo/repositories/types\";\nimport {\n WORKERS_DEFAULT_HEARTBEAT_INTERVAL_MS,\n WORKERS_MIN_HEARTBEAT_INTERVAL_MS,\n} from \"../mongo/repositories/types\";\nimport { getLogger } from \"../logger\";\n\nexport interface WorkerRegistryOptions {\n heartbeatIntervalMs?: number;\n /** @internal Injected for testability; real callers should rely on the default. */\n hostnameProvider?: () => string;\n /** @internal Injected for testability; real callers should rely on the default. */\n pidProvider?: () => number;\n /** @internal Injected for testability; real callers should rely on the default. */\n workerIdProvider?: () => string;\n /** @internal Injected for testability; real callers should rely on the default. */\n clock?: () => Date;\n}\n\nexport class WorkerRegistry {\n private readonly repo: WorkersRepo;\n private readonly heartbeatIntervalMs: number;\n private readonly hostname: string;\n private readonly pid: number;\n private readonly _workerId: string;\n private readonly startedAt: Date;\n private readonly clock: () => Date;\n private timer: ReturnType<typeof setInterval> | null = null;\n private started = false;\n private registered = false;\n\n constructor(repo: WorkersRepo, options: WorkerRegistryOptions = {}) {\n WorkerRegistry.validateHeartbeatInterval(options.heartbeatIntervalMs);\n\n this.repo = repo;\n this.heartbeatIntervalMs =\n options.heartbeatIntervalMs ?? WORKERS_DEFAULT_HEARTBEAT_INTERVAL_MS;\n\n this.hostname = options.hostnameProvider ? options.hostnameProvider() : os.hostname();\n this.pid = options.pidProvider ? options.pidProvider() : process.pid;\n this._workerId = options.workerIdProvider\n ? options.workerIdProvider()\n : `${this.hostname}:${this.pid}:${crypto.randomUUID()}`;\n this.clock = options.clock ?? (() => new Date());\n this.startedAt = this.clock();\n }\n\n get workerId(): string {\n return this._workerId;\n }\n\n async registerQueue(queue: WorkerQueueEntry): Promise<void> {\n WorkerRegistry.validateQueueEntry(queue);\n\n if (!this.registered) {\n await this.repo.registerWorker({\n workerId: this._workerId,\n hostname: this.hostname,\n pid: this.pid,\n queues: [queue],\n startedAt: this.startedAt,\n });\n this.registered = true;\n return;\n }\n\n await this.repo.addQueue({\n workerId: this._workerId,\n queue,\n });\n }\n\n async start(): Promise<void> {\n if (this.started) return;\n if (!this.registered) {\n throw new Error(\n \"WorkerRegistry.start: call registerQueue at least once before start\",\n );\n }\n\n this.timer = setInterval(() => {\n void this.doHeartbeat();\n }, this.heartbeatIntervalMs);\n this.timer.unref();\n this.started = true;\n }\n\n async stop(): Promise<void> {\n if (this.timer !== null) {\n clearInterval(this.timer);\n this.timer = null;\n }\n this.started = false;\n\n if (!this.registered) return;\n\n try {\n await this.repo.deregisterWorker(this._workerId);\n } catch (err) {\n getLogger().warn(\n { err, workerId: this._workerId },\n \"[worker-registry] deregister failed on stop\",\n );\n }\n this.registered = false;\n }\n\n private async doHeartbeat(): Promise<void> {\n try {\n await this.repo.updateHeartbeat(this._workerId);\n } catch (err) {\n getLogger().warn(\n { err, workerId: this._workerId },\n \"[worker-registry] heartbeat failed — will retry next tick\",\n );\n }\n }\n\n private static validateHeartbeatInterval(value: number | undefined | null): void {\n if (value == null) return;\n const MAX_HEARTBEAT_INTERVAL_MS = 24 * 60 * 60 * 1000;\n if (\n !Number.isInteger(value) ||\n value < WORKERS_MIN_HEARTBEAT_INTERVAL_MS ||\n value > MAX_HEARTBEAT_INTERVAL_MS\n ) {\n throw new Error(\n `[ravenflow] WorkerRegistry heartbeatIntervalMs must be an integer in [${WORKERS_MIN_HEARTBEAT_INTERVAL_MS}, ${MAX_HEARTBEAT_INTERVAL_MS}], got ${value}`,\n );\n }\n }\n\n private static validateQueueEntry(q: WorkerQueueEntry): void {\n if (q === null || typeof q !== \"object\") {\n throw new Error(\"WorkerRegistry.registerQueue: queue must be an object\");\n }\n if (typeof q.name !== \"string\" || q.name.length === 0) {\n throw new Error(\n \"WorkerRegistry.registerQueue: queue.name must be a non-empty string\",\n );\n }\n if (!Number.isInteger(q.concurrency) || q.concurrency <= 0) {\n throw new Error(\n \"WorkerRegistry.registerQueue: queue.concurrency must be a positive integer\",\n );\n }\n }\n}\n","export const DEFAULT_FLUSH_INTERVAL_MS = 30_000;\nexport const MIN_BUFFER_SIZE = 1000;\nexport const MAX_BUFFER_SIZE = 5000;\n\n/** Multiplier over `maxBufferSize` that caps memory growth under sustained flush failures. */\nexport const HARD_CAP_MULTIPLIER = 10;\n\n/** Backoff delays (ms) between drain retry attempts when the final flush fails. */\nexport const DRAIN_RETRY_BACKOFFS_MS = [0, 1000, 2000, 4000] as const;\n\nexport interface BatchWriterConfig {\n /** Max ops buffered before a size-triggered flush. Must be in [1000, 5000]. */\n maxBufferSize: number;\n /** Interval between time-triggered flushes in ms. Default 30000. Also used as `maxTimeMS` on bulkWrite. */\n flushIntervalMs?: number;\n}\n","import {\n MongoBulkWriteError,\n type AnyBulkWriteOperation,\n type Collection,\n type Document,\n} from \"mongodb\";\nimport { getLogger } from \"../logger\";\nimport {\n BatchWriterConfig,\n DEFAULT_FLUSH_INTERVAL_MS,\n DRAIN_RETRY_BACKOFFS_MS,\n HARD_CAP_MULTIPLIER,\n MAX_BUFFER_SIZE,\n MIN_BUFFER_SIZE,\n} from \"./batch-writer.types\";\n\nexport class BatchWriter<T extends Document = Document> {\n private readonly collection: Collection<T>;\n private readonly maxBufferSize: number;\n private readonly hardCapSize: number;\n private readonly flushIntervalMs: number;\n private buffer: AnyBulkWriteOperation<T>[] = [];\n private timer: ReturnType<typeof setInterval> | null = null;\n private flushing: Promise<void> | null = null;\n private drained = false;\n\n constructor(collection: Collection<T>, config: BatchWriterConfig) {\n this.validateConfig(config);\n\n this.collection = collection;\n this.maxBufferSize = config.maxBufferSize;\n this.hardCapSize = config.maxBufferSize * HARD_CAP_MULTIPLIER;\n this.flushIntervalMs = config.flushIntervalMs ?? DEFAULT_FLUSH_INTERVAL_MS;\n\n this.startTimer();\n }\n\n push(operation: AnyBulkWriteOperation<T>): void {\n if (this.drained) {\n getLogger().warn(\n \"[batch-writer] push called after drain — operation ignored\",\n );\n return;\n }\n\n this.buffer.push(operation);\n this.enforceHardCap();\n\n if (this.buffer.length >= this.maxBufferSize) {\n this.resetTimer();\n void this.flush();\n }\n }\n\n async drain(): Promise<void> {\n this.drained = true;\n this.stopTimer();\n\n if (this.flushing) await this.flushing;\n\n for (const backoffMs of DRAIN_RETRY_BACKOFFS_MS) {\n if (this.buffer.length === 0) return;\n if (backoffMs > 0) {\n await new Promise<void>((resolve) => setTimeout(resolve, backoffMs));\n }\n await this.flush();\n }\n\n if (this.buffer.length > 0) {\n getLogger().error(\n { unflushed: this.buffer.length },\n \"[batch-writer] drain exhausted retries — operations lost\",\n );\n }\n }\n\n private async flush(): Promise<void> {\n if (this.flushing) return this.flushing;\n if (this.buffer.length === 0) return;\n\n this.flushing = this.doFlush();\n try {\n await this.flushing;\n } finally {\n this.flushing = null;\n }\n }\n\n private async doFlush(): Promise<void> {\n while (this.buffer.length > 0) {\n const snapshot = this.buffer;\n this.buffer = [];\n\n try {\n await this.collection.bulkWrite(snapshot, {\n ordered: false,\n maxTimeMS: this.flushIntervalMs,\n });\n } catch (err: unknown) {\n // mongodb driver types `writeErrors` as `OneOrMore<WriteError>` —\n // runtime narrowing to `Array` is required before reading `.length`.\n // Fix surfaced by Story 3.2 code review D8: re-exporting the cap\n // constants requires a clean DTS build, which this narrowing unblocks\n // (the pre-existing TS2339 was in the \"4 preserved errors\" cohort).\n if (\n err instanceof MongoBulkWriteError &&\n Array.isArray(err.writeErrors) &&\n err.writeErrors.length > 0\n ) {\n getLogger().warn(\n {\n failed: err.writeErrors.length,\n total: snapshot.length,\n },\n \"[batch-writer] bulkWrite partial failure — dropping failed ops (likely persistent errors)\",\n );\n continue;\n }\n\n this.buffer = [...snapshot, ...this.buffer];\n this.enforceHardCap();\n getLogger().warn(\n { err, count: snapshot.length },\n \"[batch-writer] flush failed — will retry on next tick or threshold\",\n );\n return;\n }\n }\n }\n\n private enforceHardCap(): void {\n if (this.buffer.length <= this.hardCapSize) return;\n const dropCount = this.buffer.length - this.hardCapSize;\n this.buffer.splice(0, dropCount);\n getLogger().warn(\n { dropCount, hardCapSize: this.hardCapSize },\n \"[batch-writer] hard cap exceeded — dropped oldest operations\",\n );\n }\n\n private startTimer(): void {\n this.timer = setInterval(() => {\n void this.flush();\n }, this.flushIntervalMs);\n this.timer.unref();\n }\n\n private stopTimer(): void {\n if (this.timer) {\n clearInterval(this.timer);\n this.timer = null;\n }\n }\n\n private resetTimer(): void {\n this.stopTimer();\n this.startTimer();\n }\n\n private validateConfig(config: BatchWriterConfig): void {\n if (\n !Number.isInteger(config.maxBufferSize) ||\n config.maxBufferSize < MIN_BUFFER_SIZE ||\n config.maxBufferSize > MAX_BUFFER_SIZE\n ) {\n throw new Error(\n `[ravenflow] BatchWriter maxBufferSize must be an integer in [${MIN_BUFFER_SIZE}, ${MAX_BUFFER_SIZE}], got ${config.maxBufferSize}`,\n );\n }\n\n if (config.flushIntervalMs !== undefined) {\n if (\n !Number.isInteger(config.flushIntervalMs) ||\n config.flushIntervalMs <= 0\n ) {\n throw new Error(\n `[ravenflow] BatchWriter flushIntervalMs must be a positive integer, got ${config.flushIntervalMs}`,\n );\n }\n }\n }\n}\n","import type { Queue } from \"bullmq\";\nimport { getLogger } from \"../logger\";\n\nexport async function captureJobLogs(\n queue: Queue,\n jobId: string,\n maxChars: number,\n): Promise<string> {\n if (typeof jobId !== \"string\" || jobId.length === 0) {\n throw new Error(\"captureJobLogs: jobId must be a non-empty string\");\n }\n if (!Number.isInteger(maxChars) || maxChars <= 0) {\n throw new Error(\n `captureJobLogs: maxChars must be a positive integer, got ${maxChars}`,\n );\n }\n\n let logs: string[];\n try {\n const result = await queue.getJobLogs(jobId, 0, -1, true);\n logs = result.logs;\n } catch (err) {\n getLogger().warn(\n { err, jobId },\n \"[log-capture] failed to fetch job logs — returning empty string\",\n );\n return \"\";\n }\n\n const joined = logs.join(\"\\n\");\n if (joined.length <= maxChars) return joined;\n\n const originalLen = joined.length;\n let tailLen = maxChars;\n let marker = \"\";\n for (let i = 0; i < 3; i++) {\n marker = `[truncated — showing last ${tailLen} of ${originalLen} chars]\\n`;\n if (marker.length >= maxChars) {\n return marker.slice(0, maxChars);\n }\n tailLen = maxChars - marker.length;\n }\n return marker + joined.slice(-tailLen);\n}\n","import type { Job, Queue, Worker } from \"bullmq\";\nimport { resolveJobName } from \"../app/job-registry\";\nimport type { JobConfig } from \"../types\";\nimport type { BatchWriter } from \"./batch-writer\";\nimport type { JobStatsRepo } from \"../mongo/repositories/job-stats.repo\";\nimport type { JobErrorsRepo } from \"../mongo/repositories/job-errors.repo\";\nimport type { JobFailuresRepo } from \"../mongo/repositories/job-failures.repo\";\nimport type {\n JobStatsDoc,\n JobErrorDoc,\n JobFailureDoc,\n} from \"../mongo/repositories/types\";\nimport { JOB_FAILURES_LOGS_MAX_CHARS } from \"../mongo/repositories/types\";\nimport { captureJobLogs } from \"./log-capture\";\nimport { getLogger } from \"../logger\";\n\nexport interface EventHooksOptions {\n queue: Queue;\n jobConfigs: Record<string, JobConfig>;\n jobStatsRepo: JobStatsRepo;\n jobErrorsRepo: JobErrorsRepo;\n jobFailuresRepo: JobFailuresRepo;\n jobStatsBatchWriter: BatchWriter<JobStatsDoc>;\n jobErrorsBatchWriter: BatchWriter<JobErrorDoc>;\n jobFailuresBatchWriter: BatchWriter<JobFailureDoc>;\n logsMaxChars?: number;\n}\n\nexport function attachEventHooks(worker: Worker, options: EventHooksOptions): void {\n worker.on(\"completed\", (job) => {\n void handleCompleted(job, options);\n });\n worker.on(\"failed\", (job, error) => {\n void handleFailed(job, error, options);\n });\n}\n\nasync function handleCompleted(job: Job, options: EventHooksOptions): Promise<void> {\n try {\n const jobType = resolveTopLevelJobType(job, options.jobConfigs);\n if (jobType === null) return;\n\n const durationMs = computeDurationMs(job);\n const ops = options.jobStatsRepo.toIncrementStatsOps(jobType, {\n success: true,\n durationMs,\n });\n for (const op of ops) {\n options.jobStatsBatchWriter.push(op);\n }\n } catch (err) {\n getLogger().warn(\n { err, jobId: job?.id, path: \"stats\" },\n \"[event-hooks] completed handler failed\",\n );\n }\n}\n\nasync function handleFailed(\n job: Job | undefined,\n error: Error,\n options: EventHooksOptions,\n): Promise<void> {\n if (job === undefined) {\n getLogger().warn(\n { message: error?.message },\n \"[event-hooks] failed event fired without a job — skipping\",\n );\n return;\n }\n if (job.id === undefined || job.id === null) {\n getLogger().warn(\n { jobName: job.name },\n \"[event-hooks] failed event fired without a job.id — skipping\",\n );\n return;\n }\n\n try {\n const jobType = resolveTopLevelJobType(job, options.jobConfigs);\n if (jobType === null) return;\n\n const durationMs = computeDurationMs(job);\n const failedAt =\n typeof job.finishedOn === \"number\" && Number.isFinite(job.finishedOn)\n ? new Date(job.finishedOn)\n : new Date();\n const jobId = String(job.id);\n const logsMaxChars = options.logsMaxChars ?? JOB_FAILURES_LOGS_MAX_CHARS;\n\n try {\n const ops = options.jobStatsRepo.toIncrementStatsOps(jobType, {\n success: false,\n durationMs,\n });\n for (const op of ops) {\n options.jobStatsBatchWriter.push(op);\n }\n } catch (err) {\n getLogger().warn(\n { err, jobId, path: \"stats\" },\n \"[event-hooks] failed handler: stats write failed\",\n );\n }\n\n try {\n const op = options.jobErrorsRepo.toRecordOccurrenceOp({\n jobType,\n error,\n });\n options.jobErrorsBatchWriter.push(op);\n } catch (err) {\n getLogger().warn(\n { err, jobId, path: \"errors\" },\n \"[event-hooks] failed handler: errors write failed\",\n );\n }\n\n let logs = \"\";\n try {\n logs = await captureJobLogs(options.queue, jobId, logsMaxChars);\n } catch (err) {\n getLogger().warn(\n { err, jobId, path: \"failures\" },\n \"[event-hooks] failed handler: log capture failed — recording failure with empty logs\",\n );\n }\n\n try {\n const op = options.jobFailuresRepo.toRecordFailureOp({\n jobId,\n jobType,\n input: job.data,\n error,\n failedAt,\n logs,\n });\n options.jobFailuresBatchWriter.push(op);\n } catch (err) {\n getLogger().warn(\n { err, jobId, path: \"failures\" },\n \"[event-hooks] failed handler: failures write failed\",\n );\n }\n } catch (err) {\n getLogger().warn(\n { err, jobId: job.id, path: \"unknown\" },\n \"[event-hooks] failed handler failed\",\n );\n }\n}\n\nfunction computeDurationMs(job: Job): number | undefined {\n const processedOn = job.processedOn;\n const finishedOn = job.finishedOn;\n if (typeof processedOn !== \"number\" || !Number.isFinite(processedOn)) return undefined;\n if (typeof finishedOn !== \"number\" || !Number.isFinite(finishedOn)) return undefined;\n const delta = finishedOn - processedOn;\n if (delta < 0) return undefined;\n return delta;\n}\n\nfunction resolveTopLevelJobType(\n job: Job,\n jobConfigs: Record<string, JobConfig>,\n): string | null {\n const { baseName, suffix } = resolveJobName(job.name, jobConfigs);\n if (suffix !== null) return null;\n if (!Object.prototype.hasOwnProperty.call(jobConfigs, baseName)) {\n getLogger().debug(\n { jobName: job.name, jobId: job.id },\n \"[event-hooks] skipping event for unknown jobType\",\n );\n return null;\n }\n return baseName;\n}\n","import { DelayedError, type Job } from \"bullmq\";\nimport type { JobConfig } from \"../types\";\nimport type { JobConfigsRepo } from \"../mongo/repositories/job-configs.repo\";\nimport { getLogger } from \"../logger\";\nimport { resolveJobName } from \"./job-registry\";\n\n/**\n * Delay (ms) applied to jobs whose jobType is `enabled: false`. After this\n * window BullMQ returns the job to the `waiting` set and a worker picks it\n * up again; the gate re-evaluates. When the jobType re-enables the next\n * attempt passes the check and dispatches normally.\n *\n * 60 seconds strikes the balance between \"pause takes effect quickly\" and\n * \"don't hammer Redis / Mongo with redefer churn\" (D5.1-b).\n */\nexport const DISABLED_JOB_DEFER_DELAY_MS = 60_000;\n\n/**\n * Non-fatal wrapper around `JobConfigsRepo.ensureEntries` called during\n * `RavenflowApp.initializeMonitoring`. A rejection (Mongo disconnect at\n * boot, write-concern downgrade, collection flip) is logged + swallowed;\n * the app continues without its `job_configs` bootstrap. The worker-side\n * `isEnabled` gate still works because `JobConfigsRepo.isEnabled` returns\n * `JOB_CONFIGS_DEFAULT_ENABLED=true` on missing docs — jobs enqueued\n * during this degraded state run as though uninitialized, which is the\n * pre-Story-5.1 behavior.\n *\n * Story 5.1 code review D5-P-a — extracted so the P11 live-reachable\n * degraded path is regression-anchored by a unit test rather than only\n * by visible-code inspection inside `initializeMonitoring`.\n */\nexport async function safeEnsureEntriesAtBoot(\n jobConfigsRepo: JobConfigsRepo,\n jobs: Record<string, JobConfig>,\n): Promise<void> {\n try {\n await jobConfigsRepo.ensureEntries(jobs);\n } catch (err) {\n getLogger().error(\n { err },\n \"[app] job_configs ensureEntries failed at boot — dashboard may show a stale job-type list\",\n );\n }\n}\n\n/**\n * Worker-side defer gate for disabled jobTypes (Story 5.1 D5.1-b).\n *\n * When the jobType's `enabled` flag is `false` in `job_configs`, this\n * helper moves the job to `delayed` with a +60s timestamp, increments\n * the cumulative `disabledDeferCount` on `job.progress`, and throws\n * `DelayedError` — the BullMQ-canonical signal for \"I moved this job to\n * delayed, don't mark completed/failed\" (verified against\n * node_modules/bullmq/dist/esm/classes/errors/delayed-error.d.ts:9\n * bullmq@5.63.1).\n *\n * When the jobType is enabled (or no row exists — default is `true`),\n * this is a no-op and the caller proceeds to normal dispatch.\n *\n * The `token` argument is the processor lambda's 2nd BullMQ argument\n * (verified against node_modules/bullmq/dist/esm/classes/job.d.ts:444\n * bullmq@5.63.1 — moveToDelayed(timestamp, token?) — passing undefined\n * is accepted but may fail under lock contention with renewLock).\n */\nexport async function deferIfDisabled(\n job: Job,\n jobConfigs: Record<string, JobConfig>,\n jobConfigsRepo: JobConfigsRepo,\n token: string | undefined,\n): Promise<void> {\n // Defensive input guards (Story 5.1 code review P2/P3). A lambda called\n // with malformed shape falls through to default dispatch rather than\n // crashing the worker — mirrors the null-guard pattern used throughout\n // app.ts for optional-infra surfaces.\n if (typeof job.name !== \"string\" || job.name.length === 0) return;\n if (jobConfigs === null || typeof jobConfigs !== \"object\") return;\n\n // BullMQ passes `token` as the 2nd processor argument in real dispatch;\n // undefined indicates a test rig or library misuse. Warn but proceed —\n // moveToDelayed may fail under lock contention without the token (P6).\n if (token === undefined) {\n getLogger().warn(\n { jobId: job.id, jobName: job.name },\n \"[app] deferIfDisabled invoked with undefined token — moveToDelayed may fail under lock contention\",\n );\n }\n\n const { baseName } = resolveJobName(job.name, jobConfigs);\n // resolveJobName can return empty when `job.name` matches only a suffix\n // pattern with no registered base — skip the gate + warn rather than\n // feeding \"\" to validateJobType which throws non-empty-string (P4).\n if (!baseName) {\n getLogger().warn(\n { jobId: job.id, jobName: job.name },\n \"[app] deferIfDisabled: resolveJobName returned empty baseName — skipping gate\",\n );\n return;\n }\n\n // Propagate isEnabled rejection — the spec (line 255) explicitly locks\n // \"disabled-check failure = job failure\" as the intentional choice.\n // Fail-open would silently run disabled jobs during a persistent Mongo\n // outage; BullMQ attempt-erosion on a transient blip is the accepted\n // trade. Job goes to failed + surfaces in /failures if persistent.\n const enabled = await jobConfigsRepo.isEnabled(baseName);\n if (enabled) return;\n\n // Cumulative counter — not reset on redefer. Structured progress (per\n // D5.1-i) preserves room for future observability fields without a\n // worker-side migration. BullMQ types `job.progress` as\n // `number | string | object` (verified against job.d.ts) so we narrow\n // defensively at the boundary (safe runtime shape check, not an\n // escape-hatch cast per P2).\n const prev = job.progress;\n const prevCount =\n typeof prev === \"object\" && prev !== null && !Array.isArray(prev)\n ? (prev as { disabledDeferCount?: unknown }).disabledDeferCount\n : undefined;\n const nextCount =\n typeof prevCount === \"number\" && Number.isFinite(prevCount) ? prevCount + 1 : 1;\n\n // moveToDelayed FIRST (Story 5.1 code review P1) — the counter never\n // bumps for a defer that didn't actually happen. If moveToDelayed\n // rejects (Redis blip, lock lost), the caller's worker sees a non-\n // DelayedError and the job goes to failed with eroded attempts — a\n // real infra failure, not a regression of the counter's semantics.\n // verified against node_modules/bullmq/dist/esm/classes/job.d.ts:444\n // (bullmq@5.63.1) — moveToDelayed(timestamp, token?).\n await job.moveToDelayed(Date.now() + DISABLED_JOB_DEFER_DELAY_MS, token);\n // Counter write is best-effort — updateProgress after a successful\n // moveToDelayed must not unwind the defer. Log the slip and continue.\n try {\n await job.updateProgress({ disabledDeferCount: nextCount });\n } catch (err) {\n getLogger().warn(\n { err, jobType: baseName, jobId: job.id },\n \"[app] deferIfDisabled: updateProgress failed post-defer — counter may lag by one\",\n );\n }\n\n getLogger().info(\n { jobType: baseName, jobId: job.id, disabledDeferCount: nextCount },\n \"[app] job deferred: disabled\",\n );\n\n // verified against node_modules/bullmq/dist/esm/classes/errors/delayed-error.d.ts:9\n // (bullmq@5.63.1) — DelayedError signals 'I moved this job to delayed,\n // don't mark completed/failed'.\n throw new DelayedError();\n}\n","import { ConnectionOptions as RedisConnectionOptions, Worker } from \"bullmq\";\nimport {\n RavenflowConfig,\n RetentionConfig,\n JobConfig,\n JobNames,\n JobsProxy,\n} from \"../types\";\nimport { initLogger, getLogger, LoggerOptions } from \"../logger\";\nimport { initQueues, closeQueues, QueueStore } from \"./queue-manager\";\nimport { initJobs, processJob } from \"./job-registry\";\nimport {\n createWorker,\n setupWorkerEvents,\n printBanner,\n closeWorkers,\n} from \"./worker-manager\";\nimport { syncJobSchedulers } from \"./scheduler\";\nimport { connectMongo, closeMongo, getDb, tokenBucketRepo } from \"../mongo\";\nimport { StallWatcher } from \"../internal-jobs\";\nimport { WorkersRepo } from \"../mongo/repositories/workers.repo\";\nimport { JobStatsRepo } from \"../mongo/repositories/job-stats.repo\";\nimport { JobErrorsRepo } from \"../mongo/repositories/job-errors.repo\";\nimport { JobFailuresRepo } from \"../mongo/repositories/job-failures.repo\";\nimport { JobConfigsRepo } from \"../mongo/repositories/job-configs.repo\";\nimport type {\n JobStatsDoc,\n JobErrorDoc,\n JobFailureDoc,\n} from \"../mongo/repositories/types\";\nimport { WorkerRegistry } from \"../monitoring/worker-registry\";\nimport { BatchWriter } from \"../monitoring/batch-writer\";\nimport type { BatchWriterConfig } from \"../monitoring/batch-writer.types\";\nimport { MIN_BUFFER_SIZE } from \"../monitoring/batch-writer.types\";\nimport { attachEventHooks } from \"../monitoring/event-hooks\";\nimport { deferIfDisabled, safeEnsureEntriesAtBoot } from \"./disabled-job\";\n\nexport interface MongoConnectionObject {\n host: string;\n port?: number;\n username?: string;\n password?: string;\n database?: string;\n}\n\nexport interface RavenflowAppOptions {\n redis: RedisConnectionOptions;\n mongo?: string | MongoConnectionObject;\n retention?: RetentionConfig;\n logger?: LoggerOptions;\n monitoring?: {\n enabled?: boolean;\n heartbeatIntervalMs?: number;\n batchWriter?: {\n maxBufferSize?: number;\n flushIntervalMs?: number;\n };\n };\n}\n\nconst DEFAULT_MONITORING_BATCH_BUFFER = MIN_BUFFER_SIZE;\n\nconst MONGO_REQUIRED_TYPES = new Set([\"stateful-etl\", \"token-bucket\"]);\n\nfunction resolveMongoUri(\n mongo: RavenflowAppOptions[\"mongo\"],\n): string | null {\n if (!mongo) return null;\n if (typeof mongo === \"string\") return mongo;\n\n const { host, port = 27017, username, password, database } = mongo;\n const auth = username && password ? `${encodeURIComponent(username)}:${encodeURIComponent(password)}@` : \"\";\n const db = database ? `/${database}` : \"\";\n return `mongodb://${auth}${host}:${port}${db}`;\n}\n\nfunction validateConfig(\n config: RavenflowConfig,\n mongoUri: string | null,\n): void {\n const errors: string[] = [];\n\n for (const [jobName, jobConfig] of Object.entries(config.jobs)) {\n const jc = jobConfig as JobConfig;\n\n // Mongo required for stateful-etl and token-bucket\n if (MONGO_REQUIRED_TYPES.has(jc.type) && !mongoUri) {\n errors.push(\n `\"${jobName}\" (${jc.type}) requires a mongo connection. Pass { mongo: \"mongodb://...\" } to createRavenflowApp().`,\n );\n }\n\n // Token-bucket requires cron\n if (jc.type === \"token-bucket\" && !jc.cron?.trim()) {\n errors.push(`\"${jobName}\" (token-bucket) requires a cron schedule.`);\n }\n\n // Token-bucket requires at least rate or getBudget\n if (jc.type === \"token-bucket\" && !jc.rate && !jc.getBudget) {\n errors.push(\n `\"${jobName}\" (token-bucket) requires at least one of \"rate\" or \"getBudget\".`,\n );\n }\n\n // Token-bucket rate validation\n if (jc.type === \"token-bucket\" && jc.rate) {\n const validIntervals = new Set([\"second\", \"minute\", \"hour\", \"day\", \"week\"]);\n if (!validIntervals.has(jc.rate.interval)) {\n errors.push(\n `\"${jobName}\" (token-bucket) has invalid rate interval \"${jc.rate.interval}\". Must be one of: second, minute, hour, day, week.`,\n );\n }\n if (jc.rate.amount <= 0) {\n errors.push(\n `\"${jobName}\" (token-bucket) rate.amount must be a positive number.`,\n );\n }\n }\n\n // Token-bucket optional numeric field validation\n if (jc.type === \"token-bucket\") {\n if (jc.maxCarryOver !== undefined && jc.maxCarryOver < 0) {\n errors.push(\n `\"${jobName}\" (token-bucket) maxCarryOver must be >= 0.`,\n );\n }\n if (jc.consumeTimeout !== undefined && jc.consumeTimeout <= 0) {\n errors.push(\n `\"${jobName}\" (token-bucket) consumeTimeout must be a positive number.`,\n );\n }\n }\n\n // Step queue references must exist in config\n if (\"steps\" in jc && jc.steps) {\n // eslint-disable-next-line @typescript-eslint/no-explicit-any -- generic-erasure cast for free-form step map; typed config-walker deferred per Story 1.8 AC #14\n for (const [stepName, stepConfig] of Object.entries(jc.steps as Record<string, any>)) {\n if (stepConfig?.queue && stepConfig.queue !== config.defaultQueue) {\n const knownQueues = new Set<string>([config.defaultQueue]);\n for (const j of Object.values(config.jobs)) {\n if ((j as JobConfig).queue) knownQueues.add((j as JobConfig).queue!);\n }\n if (!knownQueues.has(stepConfig.queue)) {\n errors.push(\n `\"${jobName}\" step \"${stepName}\" references queue \"${stepConfig.queue}\" which is not declared by any job or as defaultQueue.`,\n );\n }\n }\n }\n }\n }\n\n if (errors.length > 0) {\n throw new Error(\n `[ravenflow] Config validation failed:\\n - ${errors.join(\"\\n - \")}`,\n );\n }\n}\n\nexport class RavenflowApp<TConfig extends RavenflowConfig = RavenflowConfig> {\n protected redisConnection: RedisConnectionOptions;\n protected defaultConcurrency: number = 5;\n protected config: TConfig;\n protected mongoUri: string | null;\n\n public jobs: JobsProxy<TConfig[\"jobs\"]>;\n protected jobConfigs: Record<JobNames<TConfig>, JobConfig>;\n protected queues: QueueStore;\n protected workers: Worker[] = [];\n protected stallWatcher: StallWatcher | null = null;\n protected workersRepo: WorkersRepo | null = null;\n protected workerRegistry: WorkerRegistry | null = null;\n protected jobStatsRepo: JobStatsRepo | null = null;\n protected jobErrorsRepo: JobErrorsRepo | null = null;\n protected jobFailuresRepo: JobFailuresRepo | null = null;\n protected jobConfigsRepo: JobConfigsRepo | null = null;\n protected jobStatsBatchWriter: BatchWriter<JobStatsDoc> | null = null;\n protected jobErrorsBatchWriter: BatchWriter<JobErrorDoc> | null = null;\n protected jobFailuresBatchWriter: BatchWriter<JobFailureDoc> | null = null;\n protected monitoringInitPromise: Promise<void> | null = null;\n protected readonly monitoringOptions: {\n enabled: boolean;\n heartbeatIntervalMs: number | undefined;\n batchWriter: BatchWriterConfig;\n };\n\n constructor(config: TConfig, options: RavenflowAppOptions) {\n this.redisConnection = options.redis;\n this.config = config;\n this.mongoUri = resolveMongoUri(options.mongo);\n\n initLogger(options.logger);\n\n validateConfig(config, this.mongoUri);\n\n this.queues = initQueues(config, options.redis, options.retention);\n\n const { jobsProxy, jobConfigs } = initJobs(config, this.queues);\n this.jobs = jobsProxy;\n this.jobConfigs = jobConfigs;\n\n this.monitoringOptions = {\n enabled:\n this.mongoUri !== null && options.monitoring?.enabled !== false,\n heartbeatIntervalMs: options.monitoring?.heartbeatIntervalMs,\n batchWriter: {\n maxBufferSize:\n options.monitoring?.batchWriter?.maxBufferSize ??\n DEFAULT_MONITORING_BATCH_BUFFER,\n flushIntervalMs: options.monitoring?.batchWriter?.flushIntervalMs,\n },\n };\n\n if (options.monitoring?.enabled === true && this.mongoUri === null) {\n getLogger().warn(\n {},\n \"[ravenflow] monitoring.enabled=true was requested but no mongo connection is configured — monitoring is disabled\",\n );\n }\n }\n\n public async startWorker(\n queueName: string,\n options?: { concurrency?: number },\n ) {\n if (this.mongoUri) {\n await connectMongo(this.mongoUri);\n await tokenBucketRepo.ensureIndexes();\n }\n\n const queueData = this.queues[queueName];\n if (!queueData) {\n throw new Error(`Queue ${queueName} not found in config.`);\n }\n\n const concurrency = options?.concurrency ?? this.defaultConcurrency;\n\n if (this.mongoUri && this.monitoringOptions.enabled) {\n if (!this.workerRegistry) {\n if (!this.monitoringInitPromise) {\n this.monitoringInitPromise = this.initializeMonitoring(queueName, concurrency);\n }\n try {\n await this.monitoringInitPromise;\n } catch {\n // Errors already logged inside initializeMonitoring.\n }\n }\n\n if (this.workerRegistry) {\n try {\n await this.workerRegistry.registerQueue({ name: queueName, concurrency });\n } catch (err) {\n getLogger().error(\n { err },\n \"[app] worker registry registerQueue failed — will retry on next startWorker call\",\n );\n }\n }\n }\n\n printBanner(\n queueName,\n concurrency,\n this.redisConnection,\n this.jobConfigs,\n this.mongoUri,\n );\n\n await syncJobSchedulers(queueData.queue, this.jobConfigs);\n\n const hasStatefulEtl = Object.values(this.jobConfigs).some(\n (c) => (c as JobConfig).type === \"stateful-etl\",\n );\n\n if (hasStatefulEtl && !this.stallWatcher) {\n this.stallWatcher = new StallWatcher(\n this.jobConfigs,\n this.queues,\n this.config.defaultQueue,\n queueData.queue,\n );\n }\n\n const worker = createWorker(\n queueName,\n this.redisConnection,\n concurrency,\n async (job, token) => {\n // D5.1-b — disabled-jobType defer gate (Story 5.1). When a jobType's\n // `enabled` flag is false, deferIfDisabled calls moveToDelayed(+60s)\n // and throws DelayedError so BullMQ requeues the job without\n // counting it against `attempts`. Skipped entirely when monitoring\n // is off (no jobConfigsRepo → pre-5.1 behavior, backward compat).\n // Snapshot the repo ref locally (Story 5.1 code review P11) so a\n // concurrent `close()` nulling `this.jobConfigsRepo` between the\n // check and the call cannot cause a null-deref.\n const configsRepo = this.jobConfigsRepo;\n if (configsRepo) {\n await deferIfDisabled(\n job,\n this.jobConfigs as Record<string, JobConfig>,\n configsRepo,\n token,\n );\n }\n if (this.stallWatcher?.canProcess(job.name)) {\n return this.stallWatcher.process(job);\n }\n return processJob(job, this.jobConfigs, this.queues, this.config.defaultQueue);\n },\n );\n setupWorkerEvents(worker, queueName);\n this.workers.push(worker);\n worker.run();\n\n if (\n this.monitoringOptions.enabled &&\n this.jobStatsRepo &&\n this.jobErrorsRepo &&\n this.jobFailuresRepo &&\n this.jobStatsBatchWriter &&\n this.jobErrorsBatchWriter &&\n this.jobFailuresBatchWriter\n ) {\n attachEventHooks(worker, {\n queue: queueData.queue,\n jobConfigs: this.jobConfigs as Record<string, JobConfig>,\n jobStatsRepo: this.jobStatsRepo,\n jobErrorsRepo: this.jobErrorsRepo,\n jobFailuresRepo: this.jobFailuresRepo,\n jobStatsBatchWriter: this.jobStatsBatchWriter,\n jobErrorsBatchWriter: this.jobErrorsBatchWriter,\n jobFailuresBatchWriter: this.jobFailuresBatchWriter,\n });\n }\n\n if (this.stallWatcher) {\n await this.stallWatcher.start();\n }\n }\n\n protected async initializeMonitoring(\n queueName: string,\n concurrency: number,\n ): Promise<void> {\n let registry: WorkerRegistry | null = null;\n let statsBatchWriter: BatchWriter<JobStatsDoc> | null = null;\n let errorsBatchWriter: BatchWriter<JobErrorDoc> | null = null;\n let failuresBatchWriter: BatchWriter<JobFailureDoc> | null = null;\n try {\n const db = getDb();\n const workersRepo = new WorkersRepo(db);\n const statsRepo = new JobStatsRepo(db);\n const errorsRepo = new JobErrorsRepo(db);\n const failuresRepo = new JobFailuresRepo(db);\n const configsRepo = new JobConfigsRepo(db);\n await Promise.all([\n workersRepo.init(),\n statsRepo.init(),\n errorsRepo.init(),\n failuresRepo.init(),\n configsRepo.init(),\n ]);\n\n // D5.1-a — idempotent upsert of registered job types + metadata.\n // Non-fatal per P11 audit: a transient Mongo blip here leaves the\n // dashboard with a stale list but the worker-side isEnabled gate\n // still works (falls back to default=true on missing docs), and\n // the next boot retries. Extracted into `safeEnsureEntriesAtBoot`\n // so the degraded path is regression-anchored by a unit test\n // (Story 5.1 code review D5-P-a).\n await safeEnsureEntriesAtBoot(\n configsRepo,\n this.config.jobs as Record<string, JobConfig>,\n );\n\n registry = new WorkerRegistry(workersRepo, {\n heartbeatIntervalMs: this.monitoringOptions.heartbeatIntervalMs,\n });\n await registry.registerQueue({ name: queueName, concurrency });\n await registry.start();\n\n statsBatchWriter = new BatchWriter<JobStatsDoc>(\n statsRepo.collection,\n this.monitoringOptions.batchWriter,\n );\n errorsBatchWriter = new BatchWriter<JobErrorDoc>(\n errorsRepo.collection,\n this.monitoringOptions.batchWriter,\n );\n failuresBatchWriter = new BatchWriter<JobFailureDoc>(\n failuresRepo.collection,\n this.monitoringOptions.batchWriter,\n );\n\n this.workersRepo = workersRepo;\n this.workerRegistry = registry;\n this.jobStatsRepo = statsRepo;\n this.jobErrorsRepo = errorsRepo;\n this.jobFailuresRepo = failuresRepo;\n this.jobConfigsRepo = configsRepo;\n this.jobStatsBatchWriter = statsBatchWriter;\n this.jobErrorsBatchWriter = errorsBatchWriter;\n this.jobFailuresBatchWriter = failuresBatchWriter;\n } catch (err) {\n getLogger().error(\n { err },\n \"[app] monitoring setup failed — continuing without observability writes\",\n );\n if (registry) {\n await registry.stop().catch(() => {});\n }\n const drainables = [statsBatchWriter, errorsBatchWriter, failuresBatchWriter].filter(\n // eslint-disable-next-line @typescript-eslint/no-explicit-any -- heterogeneous BatchWriter union; typed narrowing deferred per Story 1.8 AC #14\n (bw): bw is BatchWriter<any> => bw !== null,\n );\n if (drainables.length > 0) {\n await Promise.allSettled(drainables.map((bw) => bw.drain()));\n }\n this.workerRegistry = null;\n this.workersRepo = null;\n this.jobStatsRepo = null;\n this.jobErrorsRepo = null;\n this.jobFailuresRepo = null;\n this.jobConfigsRepo = null;\n this.jobStatsBatchWriter = null;\n this.jobErrorsBatchWriter = null;\n this.jobFailuresBatchWriter = null;\n } finally {\n this.monitoringInitPromise = null;\n }\n }\n\n public async close(): Promise<void> {\n const logger = getLogger();\n logger.info(\"Shutting down...\");\n\n if (this.stallWatcher) {\n await this.stallWatcher.stop();\n this.stallWatcher = null;\n }\n\n if (this.workerRegistry) {\n await this.workerRegistry.stop();\n this.workerRegistry = null;\n this.workersRepo = null;\n }\n\n await closeWorkers(this.workers);\n\n const drainables = [\n this.jobStatsBatchWriter,\n this.jobErrorsBatchWriter,\n this.jobFailuresBatchWriter,\n // eslint-disable-next-line @typescript-eslint/no-explicit-any -- heterogeneous BatchWriter union; typed narrowing deferred per Story 1.8 AC #14\n ].filter((bw): bw is BatchWriter<any> => bw !== null);\n if (drainables.length > 0) {\n await Promise.allSettled(drainables.map((bw) => bw.drain()));\n }\n this.jobStatsBatchWriter = null;\n this.jobErrorsBatchWriter = null;\n this.jobFailuresBatchWriter = null;\n this.jobStatsRepo = null;\n this.jobErrorsRepo = null;\n this.jobFailuresRepo = null;\n this.jobConfigsRepo = null;\n\n await closeQueues(this.queues);\n await closeMongo();\n logger.info(\"Shutdown complete.\");\n }\n}\n","import { RavenflowConfig } from \"./types\";\nimport { RavenflowApp, RavenflowAppOptions } from \"./app/index\";\n\nexport { RavenflowApp } from \"./app/index\";\nexport type { RavenflowAppOptions, MongoConnectionObject } from \"./app/index\";\nexport { initLogger, getLogger } from \"./logger\";\n\nexport type {\n // Config\n JobConfig,\n RavenflowConfig,\n RetentionConfig,\n\n // Job configs\n SimpleJobConfig,\n MemoryEtlJobConfig,\n DistributedEtlJobConfig,\n StatefulEtlJobConfig,\n TokenBucketJobConfig,\n TokenBucketInterval,\n\n // Step & rate limit configs\n StepConfig,\n MemoryEtlStepConfig,\n RateLimitConfig,\n\n // ETL types\n EtlExtractResult,\n EtlResult,\n\n // Job status\n JobStatus,\n} from \"./types\";\n\nexport {\n defineConfig,\n defineSimpleJob,\n defineMemoryEtlJob,\n defineDistributedEtlJob,\n defineStatefulEtlJob,\n defineTokenBucketJob,\n} from \"./types\";\n\nexport type { Logger, LoggerOptions } from \"./logger\";\n\nexport { BatchWriter } from \"./monitoring\";\nexport type { BatchWriterConfig } from \"./monitoring\";\nexport { errorSignature } from \"./monitoring\";\nexport { captureJobLogs } from \"./monitoring\";\nexport { WorkerRegistry } from \"./monitoring\";\nexport type { WorkerRegistryOptions } from \"./monitoring\";\nexport { attachEventHooks } from \"./monitoring\";\nexport type { EventHooksOptions } from \"./monitoring\";\n\nexport { DEFAULT_WORKER_METRICS, METRICS_TIME } from \"./app/worker-manager\";\nexport { DISABLED_JOB_DEFER_DELAY_MS, deferIfDisabled } from \"./app/disabled-job\";\n\nexport {\n JobStatsRepo,\n JobErrorsRepo,\n JobFailuresRepo,\n WorkersRepo,\n JobConfigsRepo,\n Repository,\n computeBucketStart,\n JOB_FAILURES_INPUT_MAX_CHARS,\n JOB_FAILURES_MESSAGE_MAX_CHARS,\n JOB_FAILURES_STACK_MAX_CHARS,\n JOB_FAILURES_LOGS_MAX_CHARS,\n} from \"./mongo/repositories\";\nexport type {\n IndexDescriptor,\n BucketGranularity,\n IncrementStatsInput,\n JobStatsDoc,\n JobErrorDoc,\n RecordOccurrenceInput,\n TopErrorsOptions,\n JobFailureDoc,\n RecordFailureInput,\n ListFailuresOptions,\n WorkerDoc,\n WorkerQueueEntry,\n RegisterWorkerInput,\n UpsertWorkerQueueInput,\n JobConfigEntry,\n JobConfigDoc,\n} from \"./mongo/repositories\";\n\nexport function createRavenflowApp<TConfig extends RavenflowConfig>(\n config: TConfig,\n options: RavenflowAppOptions,\n): RavenflowApp<TConfig> {\n return new RavenflowApp(config, options);\n}\n"]}
1
+ {"version":3,"sources":["../src/job/definition.ts","../src/job/any-job.ts","../src/job/continuation.ts","../src/job/deduplication-id.ts","../src/job/policies.ts","../src/config/validate-config/schemas/primitives.ts","../src/config/validate-config/schemas/pace.schema.ts","../src/spools/governor.ts","../src/config/validate-config/schemas/trigger.schema.ts","../src/config/validate-config/schemas/job.schema.ts","../src/config/constants.ts","../src/config/validate-config/schemas/config.schema.ts","../src/config/validate-config/shape-errors.ts","../src/config/validate-config/declared-jobs.ts","../src/config/validate-config/shared-spool-errors.ts","../src/config/validate-config/spool-pace-errors.ts","../src/config/validate-config/index.ts","../src/logger.ts","../src/mongo/connection.ts","../src/queues/declared-queues.ts","../src/queues/open-queues.ts","../src/queues/close-queues.ts","../src/queues/build-job-options.ts","../src/queues/link-id.ts","../src/control-plane/control-key.ts","../src/control-plane/cache/control-cache.ts","../src/control-plane/control-plane.ts","../src/control-plane/redis-connection.ts","../src/control-plane/channel/control-channel.ts","../src/control-plane/levers.ts","../src/control-plane/store/live-controls.ts","../src/control-plane/store/rehydrate-controls.ts","../src/control-plane/store/control-store.ts","../src/control-plane/store/control-hash.ts","../src/control-plane/store/control-mirror.ts","../src/control-plane/init-control-plane.ts","../src/spools/backlog.ts","../src/spools/spool-job-id.ts","../src/spools/item-runs.ts","../src/client/job-proxy/build-backlog.ts","../src/client/job-proxy/controls.ts","../src/client/job-proxy/deduplication.ts","../src/client/job-proxy/send.ts","../src/client/job-proxy/spool-ingest.ts","../src/client/job-proxy/init-job-proxies.ts","../src/client/ravenflow-client.ts","../src/client/create-ravenflow-client.ts","../src/describe-error.ts","../src/worker/banner.ts","../src/worker/control-plane-reader.ts","../src/worker/log-bullmq-errors.ts","../src/worker/mongodb-deadline-on-close.ts","../src/worker/job-results-recorder/batch-writer.ts","../src/worker/job-results-recorder/job-results-collection.ts","../src/worker/job-router/execution-gate.ts","../src/worker/job-router/pace-gate.ts","../src/worker/job-router/execution-signal.ts","../src/worker/job-router/job-logger.ts","../src/worker/job-router/link-deduplication.ts","../src/worker/job-router/next-link.ts","../src/worker/job-router/run-link.ts","../src/worker/job-router/progress-marks.ts","../src/worker/job-router/trigger-gate.ts","../src/worker/job-router/route-by-name.ts","../src/worker/job-results-recorder/job-result-limits.ts","../src/worker/job-results-recorder/error-extraction.ts","../src/worker/job-results-recorder/storable-value.ts","../src/worker/job-results-recorder/job-result.ts","../src/worker/job-results-recorder/log-capture.ts","../src/worker/job-results-recorder/job-results-listener.ts","../src/worker/job-results-recorder/job-results-recorder.ts","../src/worker/internal-jobs/job-results-aggregator/aggregated-results-collection.ts","../src/worker/internal-jobs/job-results-aggregator/aggregate-job-results.ts","../src/worker/internal-jobs/job-results-aggregator/job-results-aggregator.ts","../src/worker/internal-jobs/spool-feeder/feed-spool.ts","../src/worker/internal-jobs/spool-feeder/item-removals.ts","../src/worker/internal-jobs/spool-feeder/stage.ts","../src/worker/internal-jobs/spool-feeder/ticks.ts","../src/worker/internal-jobs/spool-feeder/spool-feeder.ts","../src/worker/open-worker.ts","../src/worker/schedulers.ts","../src/worker/served-queue.ts","../src/worker/serving.ts","../src/worker/withdrawal/mongo-watch.ts","../src/worker/withdrawal/withdraw.ts","../src/worker/ravenflow-worker.ts","../src/worker/create-ravenflow-worker.ts","../src/config/ravenflow-config.ts"],"names":["z","isObject","pino","MongoClient","Queue","Redis","stored","ObjectId","Job","isRedisInstance","release","MongoBulkWriteError","DelayedError","Worker","format","inspect","BSON","SECONDS_PER_HOUR","secondsOf","TICKS_KEPT","scheduleTicks","ONE_TICK_AT_A_TIME","MetricsTime"],"mappings":"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","file":"index.js","sourcesContent":["import type { Continuation } from \"./continuation\";\nimport type { JobContext } from \"./context\";\nimport type { BackoffPolicy, DeduplicatePolicy, PacePolicy } from \"./policies\";\nimport type { CronTrigger, SpoolTriggerDeclaration } from \"./trigger\";\nimport type { CronTriggerFor, TriggerFor } from \"./trigger-for\";\n\nexport interface JobDefinition<TPayload, TResult> {\n queue?: string;\n attempts?: number;\n backoff?: BackoffPolicy;\n trigger?: TriggerFor<TPayload>;\n deduplicate?: DeduplicatePolicy<TPayload>;\n pace?: PacePolicy;\n handler: JobHandler<TPayload, TResult>;\n}\n\nexport type JobHandler<TPayload, TResult> = (\n ctx: JobContext<TPayload>,\n) => Promise<TResult | Continuation<TPayload>>;\n\nexport type SpoolFedJob<TPayload, TResult> = JobDefinition<TPayload, TResult> & {\n trigger: SpoolTriggerDeclaration;\n pace: PacePolicy;\n};\n\nexport type ClockFedJob<TPayload, TResult> = JobDefinition<TPayload, TResult> & {\n trigger: CronTrigger;\n};\n\nexport function defineJob<TPayload, TResult>(\n definition: JobDefinitionWith<SpoolTriggerDeclaration, TPayload, TResult> & { pace: PacePolicy },\n): SpoolFedJob<TPayload, TResult>;\nexport function defineJob<TPayload, TResult>(\n definition: JobDefinitionWith<CronTriggerFor<TPayload>, TPayload, TResult>,\n): ClockFedJob<TPayload, TResult>;\nexport function defineJob<TPayload, TResult>(\n definition: UnspooledJobDefinition<TPayload, TResult>,\n): JobDefinition<TPayload, TResult>;\nexport function defineJob<TPayload, TResult>(\n definition: JobDefinition<TPayload, TResult>,\n): JobDefinition<TPayload, TResult> {\n return { ...definition };\n}\n\ntype JobDefinitionWith<TTrigger, TPayload, TResult> = Omit<\n JobDefinition<TPayload, TResult>,\n \"trigger\"\n> & { trigger: TTrigger };\n\ntype UnspooledJobDefinition<TPayload, TResult> = Omit<\n JobDefinition<TPayload, TResult>,\n \"trigger\"\n> & { trigger?: CronTriggerFor<TPayload> };\n","import type { JobContext } from \"./context\";\nimport type { BackoffPolicy, DeduplicatePolicy, PacePolicy } from \"./policies\";\nimport type { DeclaredTrigger, SpoolTrigger } from \"./trigger\";\n\nexport interface AnyJob {\n queue?: string;\n attempts?: number;\n backoff?: BackoffPolicy;\n trigger?: DeclaredTrigger;\n deduplicate?: DeduplicatePolicy<never>;\n pace?: PacePolicy;\n handler: (ctx: JobContext<never>) => Promise<unknown>;\n}\n\nexport interface AnySpoolFedJob extends AnyJob {\n trigger: DeclaredTrigger & { spool: SpoolTrigger };\n pace: PacePolicy;\n}\n\nexport function isSpoolFed(job: AnyJob): job is AnySpoolFedJob {\n return job.trigger?.spool !== undefined && job.pace !== undefined;\n}\n","const CONTINUATION = Symbol.for(\"ravenflow.continuation\");\n\nexport interface Continuation<TPayload> {\n readonly [CONTINUATION]: true;\n readonly params: TPayload;\n readonly delayMs?: number;\n readonly deduplicationId?: string;\n}\n\nexport interface ContinueOptions {\n delayMs?: number;\n deduplicationId?: string;\n}\n\nexport function continueWith<TPayload>(\n params: TPayload,\n options?: ContinueOptions,\n): Continuation<TPayload> {\n return {\n [CONTINUATION]: true,\n params,\n delayMs: options?.delayMs,\n deduplicationId: options?.deduplicationId,\n };\n}\n\nexport function isContinuation(value: unknown): value is Continuation<unknown> {\n return (\n isObject(value) && CONTINUATION in value && value[CONTINUATION] === true\n );\n}\n\nfunction isObject(value: unknown): value is object {\n return typeof value === \"object\" && value !== null;\n}\n","export function namespacedDeduplicationId(\n jobName: string,\n deduplicationId: string,\n): string {\n return `${namespaceOf(jobName)}:${deduplicationId}`;\n}\n\nexport function deduplicationIdOf(\n jobName: string,\n namespacedId: string,\n): string {\n return namespacedId.slice(namespaceOf(jobName).length + 1);\n}\n\nfunction namespaceOf(jobName: string): string {\n return encodeURIComponent(jobName);\n}\n","export const MS_PER_PACE_UNIT = {\n perSecond: 1_000,\n perMinute: 60_000,\n perHour: 3_600_000,\n} as const;\n\nexport type PaceUnit = keyof typeof MS_PER_PACE_UNIT;\n\nexport const FASTEST_PACE_SPACING_MS = 1;\n\nexport const SLOWEST_PACE_SPACING_MS = 86_400_000;\n\nexport interface BackoffPolicy {\n type: \"fixed\" | \"exponential\";\n delayMs: number;\n jitter?: number;\n}\n\nexport type DeduplicatePolicy<TPayload> = true | ((params: TPayload) => string);\n\nexport type PacePolicy =\n | { perSecond: number; perMinute?: never; perHour?: never }\n | { perMinute: number; perSecond?: never; perHour?: never }\n | { perHour: number; perSecond?: never; perMinute?: never };\n\nexport function spacingMsOf(pace: PacePolicy): number {\n const { unit, releases } = releasesPerUnitOf(pace);\n return MS_PER_PACE_UNIT[unit] / releases;\n}\n\nexport function releasesWithin(ms: number, pace: PacePolicy): number {\n const { unit, releases } = releasesPerUnitOf(pace);\n return (ms * releases) / MS_PER_PACE_UNIT[unit];\n}\n\nfunction releasesPerUnitOf(pace: PacePolicy): {\n unit: PaceUnit;\n releases: number;\n} {\n if (pace.perSecond !== undefined) {\n return { unit: \"perSecond\", releases: pace.perSecond };\n }\n if (pace.perMinute !== undefined) {\n return { unit: \"perMinute\", releases: pace.perMinute };\n }\n return { unit: \"perHour\", releases: pace.perHour };\n}\n","import { z } from \"zod\";\n\nexport const wholeNumber = (min: number, error: string) =>\n z.number({ error }).int({ error }).min(min, { error });\n\nexport const numberBetween = (min: number, max: number, error: string) =>\n z.number({ error }).min(min, { error }).max(max, { error });\n\nexport const aFunction = z.custom<(...args: never[]) => unknown>(\n (value) => typeof value === \"function\",\n { error: \"must be a function.\" },\n);\n","import { z } from \"zod\";\nimport { FASTEST_PACE_SPACING_MS, MS_PER_PACE_UNIT, SLOWEST_PACE_SPACING_MS, type PaceUnit } from \"@/job\";\nimport { numberBetween } from \"./primitives\";\n\nconst ONE_UNIT = \"must declare exactly one of perSecond, perMinute or perHour.\";\n\nconst UNIT_NAMES: Record<PaceUnit, string> = { perSecond: \"second\", perMinute: \"minute\", perHour: \"hour\" };\n\nexport const paceSchema = z\n .strictObject({\n perSecond: releasesPer(\"perSecond\").optional(),\n perMinute: releasesPer(\"perMinute\").optional(),\n perHour: releasesPer(\"perHour\").optional(),\n })\n .refine(declaresOneUnit, { error: ONE_UNIT });\n\nfunction releasesPer(unit: PaceUnit) {\n const msPerUnit = MS_PER_PACE_UNIT[unit];\n const fastest = msPerUnit / FASTEST_PACE_SPACING_MS;\n return numberBetween(msPerUnit / SLOWEST_PACE_SPACING_MS, fastest, outOfRange(UNIT_NAMES[unit], fastest));\n}\n\nfunction outOfRange(unit: string, fastest: number): string {\n return `must be a number of releases per ${unit}, from one a day to ${fastest} — so 0.5 is one every two ${unit}s. Faster than one a millisecond cannot be spaced by Redis; slower than one a day is a pause, and there is a verb for that.`;\n}\n\nfunction declaresOneUnit(pace: Partial<Record<PaceUnit, number>>): boolean {\n const rates = [pace.perSecond, pace.perMinute, pace.perHour];\n return rates.filter((rate) => rate !== undefined).length === 1;\n}\n","import { releasesWithin, type PacePolicy, type SpoolTrigger } from \"@/job\";\n\nexport const DEFAULT_TICK_MS = 30_000;\n\nconst A_CLAIM_HOLDS_FOR_TICKS = 10;\n\nexport function tickMsOf(spool: SpoolTrigger): number {\n return spool.tickMs ?? DEFAULT_TICK_MS;\n}\n\nexport function claimHoldMsOf(spool: SpoolTrigger): number {\n return A_CLAIM_HOLDS_FOR_TICKS * tickMsOf(spool);\n}\n\nexport function inFlightCeilingOf(\n spool: SpoolTrigger,\n pace: PacePolicy,\n): number {\n return Math.ceil(releasesWithin(tickMsOf(spool), pace));\n}\n\nexport function roomUnderTheCeiling(\n spool: SpoolTrigger,\n pace: PacePolicy,\n inFlight: number,\n): number {\n return inFlightCeilingOf(spool, pace) - inFlight;\n}\n\nexport async function mayPull(spool: SpoolTrigger): Promise<boolean> {\n return (await spool.canPull?.()) ?? true;\n}\n","import { z } from \"zod\";\nimport { DEFAULT_TICK_MS } from \"@/spools/governor\";\nimport { aFunction, wholeNumber } from \"./primitives\";\n\nconst NO_NAME = \"must name the spool, whose backlog is rav:spool-backlog:<name>.\";\nconst COLON_IN_NAME =\n 'must not contain \":\" — it would break the job id of each item (spool:<name>:<_id>). Rename the spool.';\nconst NOT_A_TICK = `must be a whole number of milliseconds, one or more. Omit it to tick every ${DEFAULT_TICK_MS / 1_000} seconds.`;\nconst NOT_AN_EXPIRY = \"must be a whole number of milliseconds, one or more. Omit it to keep an item until it is released.\";\n\nexport const spoolNameSchema = z\n .string({ error: NO_NAME })\n .trim()\n .min(1, { error: NO_NAME })\n .refine((name) => !name.includes(\":\"), { error: COLON_IN_NAME });\n\nconst spoolSchema = z.strictObject({\n name: spoolNameSchema,\n tickMs: wholeNumber(1, NOT_A_TICK).optional(),\n canPull: aFunction.optional(),\n expireUnclaimedAfterMs: wholeNumber(1, NOT_AN_EXPIRY).optional(),\n});\n\nexport const triggerSchema = z.strictObject({\n cron: z.string({ error: \"must be a cron expression.\" }).optional(),\n spool: spoolSchema.optional(),\n});\n","import { z } from \"zod\";\nimport { paceSchema } from \"./pace.schema\";\nimport { aFunction, numberBetween } from \"./primitives\";\nimport { triggerSchema } from \"./trigger.schema\";\n\nconst NOT_A_JITTER =\n \"must be a number between 0 and 1: the share of its delay a retry may be brought forward by, so 0.2 retries between 80% and 100% of it.\";\nconst NOT_A_DEDUPLICATION =\n \"must be true or a function of the payload: true lets one run of the job be in flight at a time, a function one per id it returns. Omit it to deduplicate nothing.\";\n\nconst backoffSchema = z.strictObject({\n type: z.enum([\"fixed\", \"exponential\"], { error: \"must be 'fixed' or 'exponential'.\" }),\n delayMs: z.number({ error: \"must be a number of milliseconds.\" }),\n jitter: numberBetween(0, 1, NOT_A_JITTER).optional(),\n});\n\nconst deduplicateSchema = z.union([z.literal(true), aFunction], { error: NOT_A_DEDUPLICATION });\n\nexport const jobSchema = z.strictObject({\n queue: z.string({ error: \"must be a queue name.\" }).optional(),\n attempts: z.number({ error: \"must be a number.\" }).optional(),\n backoff: backoffSchema.optional(),\n trigger: triggerSchema.optional(),\n deduplicate: deduplicateSchema.optional(),\n pace: paceSchema.optional(),\n handler: aFunction,\n});\n","export const DEFAULT_COMPLETED_COUNT_RETENTION = 1000;\nexport const DEFAULT_FAILED_COUNT_RETENTION = 1000;\nexport const DEFAULT_JOB_RESULTS_RETENTION_HOURS = 14 * 24;\nexport const DEFAULT_AGGREGATED_RESULTS_RETENTION_HOURS = 90 * 24;\nexport const DEFAULT_GRACE_PERIOD_MS = 30_000;\n","import { z } from \"zod\";\nimport { jobSchema } from \"./job.schema\";\nimport {\n DEFAULT_AGGREGATED_RESULTS_RETENTION_HOURS,\n DEFAULT_JOB_RESULTS_RETENTION_HOURS,\n} from \"../../constants\";\nimport { wholeNumber } from \"./primitives\";\n\nconst NOT_A_QUEUE = \"must be a queue name.\";\nconst NOT_A_JOB_COUNT = \"must be a whole number of jobs, zero or more. Omit it to use the default.\";\nconst NOT_A_LEVEL = \"must be one of trace, debug, info, warn, error, fatal.\";\nconst NOT_JOB_RESULTS_HOURS = notWholeHours(\"job results\", DEFAULT_JOB_RESULTS_RETENTION_HOURS);\nconst NOT_AGGREGATED_RESULTS_HOURS = notWholeHours(\"aggregated results\", DEFAULT_AGGREGATED_RESULTS_RETENTION_HOURS);\n\nconst loggerSchema = z.strictObject({\n level: z.enum([\"trace\", \"debug\", \"info\", \"warn\", \"error\", \"fatal\"], { error: NOT_A_LEVEL }).optional(),\n pretty: z.boolean({ error: \"must be true or false.\" }).optional(),\n});\n\nconst queuesRetentionSchema = z.strictObject({\n completedCount: wholeNumber(0, NOT_A_JOB_COUNT).optional(),\n failedCount: wholeNumber(0, NOT_A_JOB_COUNT).optional(),\n});\n\nexport const configSchema = z.strictObject({\n defaultQueue: z.string({ error: NOT_A_QUEUE }).min(1, { error: NOT_A_QUEUE }),\n jobs: z.record(z.string(), jobSchema, { error: \"must map each job's name to its declaration.\" }),\n logger: loggerSchema.optional(),\n queuesRetention: queuesRetentionSchema.optional(),\n jobResultsRetentionHours: wholeNumber(1, NOT_JOB_RESULTS_HOURS).optional(),\n aggregatedResultsRetentionHours: wholeNumber(1, NOT_AGGREGATED_RESULTS_HOURS).optional(),\n});\n\nfunction notWholeHours(kept: string, defaultHours: number): string {\n return `must be a whole number of hours, one or more. Omit it to keep ${kept} ${defaultHours / 24} days.`;\n}\n","import type { z } from \"zod\";\nimport type { RavenflowConfig } from \"../ravenflow-config\";\nimport { configSchema } from \"./schemas\";\n\nexport function shapeErrors(config: RavenflowConfig): string[] {\n const parsed = configSchema.safeParse(config);\n return parsed.success ? [] : parsed.error.issues.flatMap(describeIssue);\n}\n\nfunction describeIssue(issue: z.core.$ZodIssue): string[] {\n const path = issue.path.map(String);\n const inJob = path[0] === \"jobs\" && path.length > 1;\n const subject = inJob ? `\"${path[1]}\"` : \"config\";\n const field = inJob ? path.slice(2) : path;\n\n if (issue.code === \"unrecognized_keys\") {\n return issue.keys.map((key) => unknownKey(subject, [...field, key]));\n }\n return [[subject, field.join(\".\"), issue.message].filter(Boolean).join(\" \")];\n}\n\nfunction unknownKey(subject: string, field: string[]): string {\n return `${subject} ${field.join(\".\")} is not a key Ravenflow reads — check its spelling.`;\n}\n","import type { AnyJob } from \"@/job\";\nimport type { RavenflowConfig } from \"../ravenflow-config\";\n\nexport function declaredJobs(config: RavenflowConfig): Array<[string, AnyJob]> {\n const jobs: unknown = config.jobs;\n if (!isObject(jobs)) return [];\n return Object.entries(jobs as Record<string, AnyJob>).filter(([, job]) => isObject(job));\n}\n\nfunction isObject(value: unknown): value is object {\n return value !== null && typeof value === \"object\";\n}\n","import type { RavenflowConfig } from \"../ravenflow-config\";\nimport { declaredJobs } from \"./declared-jobs\";\nimport { spoolNameSchema } from \"./schemas\";\n\nexport function sharedSpoolErrors(config: RavenflowConfig): string[] {\n const ownerBySpool = new Map<string, string>();\n const errors: string[] = [];\n\n for (const [name, spoolName] of spoolNameOfEachJob(config)) {\n const owner = ownerBySpool.get(spoolName);\n if (owner !== undefined) {\n errors.push(sharedSpool(name, owner, spoolName));\n continue;\n }\n ownerBySpool.set(spoolName, name);\n }\n return errors;\n}\n\nfunction spoolNameOfEachJob(config: RavenflowConfig): Array<[string, string]> {\n return declaredJobs(config).flatMap(([name, job]): Array<[string, string]> => {\n const parsed = spoolNameSchema.safeParse(job.trigger?.spool?.name);\n return parsed.success ? [[name, parsed.data]] : [];\n });\n}\n\nfunction sharedSpool(name: string, owner: string, spoolName: string): string {\n return `\"${name}\" and \"${owner}\" are both fed by the spool \"${spoolName}\". Two jobs over one backlog would claim each other's items.`;\n}\n","import type { AnyJob } from \"@/job\";\nimport type { RavenflowConfig } from \"../ravenflow-config\";\nimport { declaredJobs } from \"./declared-jobs\";\n\nexport function spoolPaceErrors(config: RavenflowConfig): string[] {\n return declaredJobs(config)\n .filter(([, job]) => isSpoolFedWithoutAPace(job))\n .map(([name]) => `\"${name}\" pace is required: a spool drains at its job's pace.`);\n}\n\nfunction isSpoolFedWithoutAPace(job: AnyJob): boolean {\n return job.trigger?.spool !== undefined && job.pace === undefined;\n}\n","import type { RavenflowConfig } from \"../ravenflow-config\";\nimport { shapeErrors } from \"./shape-errors\";\nimport { sharedSpoolErrors } from \"./shared-spool-errors\";\nimport { spoolPaceErrors } from \"./spool-pace-errors\";\n\nexport function validateConfig(config: RavenflowConfig): void {\n throwIfAny([\n ...shapeErrors(config),\n ...spoolPaceErrors(config),\n ...sharedSpoolErrors(config),\n ]);\n}\n\nfunction throwIfAny(errors: string[]): void {\n if (errors.length === 0) return;\n throw new Error(`[ravenflow] Config validation failed:\\n - ${errors.join(\"\\n - \")}`);\n}\n","import pino from \"pino\";\n\nexport type Logger = pino.Logger;\n\nexport interface LoggerOptions {\n level?: \"trace\" | \"debug\" | \"info\" | \"warn\" | \"error\" | \"fatal\";\n pretty?: boolean;\n}\n\nexport function createLogger(options: LoggerOptions = {}): Logger {\n const isDev = process.env.NODE_ENV !== \"production\";\n const usePretty = options.pretty ?? isDev;\n\n return pino({\n level: options.level ?? (isDev ? \"debug\" : \"info\"),\n transport: usePretty\n ? {\n target: \"pino-pretty\",\n options: {\n colorize: true,\n translateTime: \"HH:MM:ss\",\n ignore: \"pid,hostname,job\",\n messageFormat: \"{if job}({job}) {end}{msg}\",\n },\n }\n : undefined,\n });\n}\n","import { MongoClient, type Db } from \"mongodb\";\n\nexport class MongoConnection {\n private client: MongoClient | null = null;\n private database: Db | null = null;\n private connecting: Promise<Db> | null = null;\n\n constructor(private readonly uri: string) {}\n\n async connect(): Promise<Db> {\n if (this.database) return this.database;\n this.connecting ??= this.openTheDatabase().catch((error: unknown) =>\n this.forgetTheAttempt(error),\n );\n return this.connecting;\n }\n\n async close(): Promise<void> {\n const closing = this.client;\n this.client = null;\n this.database = null;\n this.connecting = null;\n await closing?.close();\n }\n\n private async openTheDatabase(): Promise<Db> {\n const opened = new MongoClient(this.uri);\n await opened.connect();\n this.client = opened;\n this.database = opened.db();\n return this.database;\n }\n\n private forgetTheAttempt(error: unknown): never {\n this.connecting = null;\n throw error;\n }\n}\n","import type { RavenflowConfig } from \"@/config/ravenflow-config\";\nimport type { AnyJob } from \"@/job\";\n\nexport function declaredQueueNames(config: RavenflowConfig): string[] {\n const queueOfEachJob = Object.values(config.jobs).map((job) =>\n queueOf(job, config),\n );\n return [...new Set([config.defaultQueue, ...queueOfEachJob])];\n}\n\nexport function jobsDeclaredOn(\n queue: string,\n config: RavenflowConfig,\n): Record<string, AnyJob> {\n return Object.fromEntries(\n Object.entries(config.jobs).filter(\n ([, job]) => queueOf(job, config) === queue,\n ),\n );\n}\n\nfunction queueOf(job: AnyJob, config: RavenflowConfig): string {\n return job.queue ?? config.defaultQueue;\n}\n","import { Queue, type ConnectionOptions, type DefaultJobOptions } from \"bullmq\";\nimport type {\n RavenflowConfig,\n QueuesRetentionConfig,\n} from \"@/config/ravenflow-config\";\n\nimport {\n DEFAULT_COMPLETED_COUNT_RETENTION,\n DEFAULT_FAILED_COUNT_RETENTION,\n} from \"@/config/constants\";\n\nimport { declaredQueueNames } from \"./declared-queues\";\n\nexport type QueuesByName = Record<string, Queue>;\n\nexport interface QueueSettings {\n connection: ConnectionOptions;\n retention?: QueuesRetentionConfig;\n}\n\nexport function openQueues(\n config: RavenflowConfig,\n connection: ConnectionOptions,\n): QueuesByName {\n const settings = { connection, retention: config.queuesRetention };\n return Object.fromEntries(\n declaredQueueNames(config).map((name): [string, Queue] => [\n name,\n openQueue(name, settings),\n ]),\n );\n}\n\nexport function openQueue(name: string, settings: QueueSettings): Queue {\n return new Queue(name, {\n connection: settings.connection,\n defaultJobOptions: defaultJobOptionsFor(settings.retention),\n });\n}\n\nfunction defaultJobOptionsFor(\n retention: QueuesRetentionConfig = {},\n): DefaultJobOptions {\n return {\n removeOnComplete: {\n count: retention.completedCount ?? DEFAULT_COMPLETED_COUNT_RETENTION,\n },\n removeOnFail: {\n count: retention.failedCount ?? DEFAULT_FAILED_COUNT_RETENTION,\n },\n };\n}\n","import type { QueuesByName } from \"./open-queues\";\n\nexport async function closeQueues(queues: QueuesByName): Promise<void> {\n await Promise.all(Object.values(queues).map((queue) => queue.close()));\n}\n","import type { BackoffOptions, JobsOptions } from \"bullmq\";\nimport type { AnyJob, BackoffPolicy } from \"@/job\";\n\nexport function buildJobOptions(\n job: Pick<AnyJob, \"attempts\" | \"backoff\">,\n): JobsOptions {\n const options: JobsOptions = {};\n if (job.attempts !== undefined) options.attempts = job.attempts;\n if (job.backoff !== undefined) options.backoff = backoffOptions(job.backoff);\n\n return options;\n}\n\nfunction backoffOptions(backoff: BackoffPolicy): BackoffOptions {\n return {\n type: backoff.type,\n delay: backoff.delayMs,\n jitter: backoff.jitter,\n };\n}\n","const LINK_SEPARATOR = \".\";\n\nconst A_NUMBERED_LINK = /^(.+)\\.([1-9]\\d*)$/;\n\nexport interface LinkOfARun {\n runId: string;\n link: number;\n}\n\nexport function nextLinkIdOf(linkId: string): string {\n const { runId, link } = linkOfItsRun(linkId);\n return linkIdOf({ runId, link: link + 1 });\n}\n\nexport function linkIdOf({ runId, link }: LinkOfARun): string {\n if (link === 0) return runId;\n return `${asACustomJobId(runId)}${LINK_SEPARATOR}${link}`;\n}\n\nexport function linkOfItsRun(linkId: string): LinkOfARun {\n const numbered = A_NUMBERED_LINK.exec(linkId);\n if (numbered === null) return { runId: linkId, link: 0 };\n return { runId: numbered[1], link: Number(numbered[2]) };\n}\n\nfunction asACustomJobId(runId: string): string {\n if (holdsColonsBullmqRefuses(runId)) return encodeURIComponent(runId);\n return runId;\n}\n\nfunction holdsColonsBullmqRefuses(id: string): boolean {\n const parts = id.split(\":\").length;\n return parts !== 1 && parts !== 3;\n}\n","const JOB_PREFIX = \"job:\";\n\nexport type ControlKey = `job:${string}`;\n\nexport const CONTROL_KEY_MAX_LENGTH = 512;\n\nexport function controlKey(jobName: string): ControlKey {\n return `${JOB_PREFIX}${jobName}`;\n}\n\nexport function isControlKey(raw: unknown): raw is ControlKey {\n if (typeof raw !== \"string\" || raw.length > CONTROL_KEY_MAX_LENGTH) return false;\n return raw.startsWith(JOB_PREFIX) && raw.length > JOB_PREFIX.length;\n}\n\nexport function jobNameOf(key: ControlKey): string {\n return key.slice(JOB_PREFIX.length);\n}\n\nexport function validateControlName(name: string, caller: string): void {\n if (typeof name !== \"string\" || name.trim().length === 0) {\n throw new Error(`${caller}: name must be a non-empty string`);\n }\n\n if (name.includes(\".\") || name.includes(\"$\")) {\n throw new Error(\n `${caller}: name cannot contain '.' or '$' (Mongo-reserved characters)`,\n );\n }\n}\n","import type { Logger } from \"@/logger\";\n\nimport { controlKey, type ControlKey } from \"../control-key\";\nimport type { JobControls } from \"../levers\";\nimport type { ControlReads } from \"../types\";\n\nexport const CONTROL_CACHE_TTL_MS = 15_000;\n\nexport interface InvalidationSource {\n subscribe(onInvalidate: (key: ControlKey) => void): Promise<void>;\n}\n\nexport class ControlCache implements ControlReads {\n private readonly entries = new Map<\n ControlKey,\n {\n controls: JobControls;\n expiresAt: number;\n }\n >();\n private readonly inFlight = new Map<ControlKey, Promise<JobControls>>();\n private subscription: Promise<void> | null = null;\n\n constructor(\n private readonly parts: {\n source: ControlReads;\n invalidations: InvalidationSource;\n logger: Logger;\n },\n ) {}\n\n async read(jobName: string): Promise<JobControls> {\n const key = controlKey(jobName);\n const cached = this.entries.get(key);\n if (cached !== undefined && cached.expiresAt > Date.now()) {\n return cached.controls;\n }\n\n this.subscribeOnce();\n\n const reading = this.inFlight.get(key);\n if (reading !== undefined) return await reading;\n\n return await this.startRead(key, jobName);\n }\n\n invalidate(key: ControlKey): void {\n this.entries.delete(key);\n this.inFlight.delete(key);\n }\n\n clear(): void {\n this.entries.clear();\n this.inFlight.clear();\n }\n\n private startRead(key: ControlKey, jobName: string): Promise<JobControls> {\n const reading: Promise<JobControls> = this.parts.source.read(jobName).then(\n (controls) => {\n if (this.inFlight.get(key) === reading) this.keep(key, controls);\n return controls;\n },\n (err: unknown) => {\n if (this.inFlight.get(key) === reading) this.inFlight.delete(key);\n throw err;\n },\n );\n\n this.inFlight.set(key, reading);\n return reading;\n }\n\n private keep(key: ControlKey, controls: JobControls): void {\n this.entries.set(key, {\n controls,\n expiresAt: Date.now() + CONTROL_CACHE_TTL_MS,\n });\n this.inFlight.delete(key);\n }\n\n private subscribeOnce(): void {\n if (this.subscription) return;\n\n this.subscription = this.parts.invalidations\n .subscribe((key) => this.invalidate(key))\n .catch((err: unknown) => {\n this.parts.logger.warn(\n { err },\n \"[control] invalidation subscribe failed — changes arrive on the cache TTL instead\",\n );\n });\n }\n}\n","import type { Logger } from \"@/logger\";\n\nimport { ControlCache } from \"./cache\";\nimport type { ControlChannel } from \"./channel\";\nimport { controlKey } from \"./control-key\";\nimport type { JobControls } from \"./levers\";\nimport type { ControlStore } from \"./store\";\nimport type { JobControlPlane } from \"./types\";\n\nexport class ControlPlane implements JobControlPlane {\n private readonly cache: ControlCache;\n\n constructor(\n private readonly parts: {\n store: ControlStore;\n channel: ControlChannel;\n logger: Logger;\n },\n ) {\n this.cache = new ControlCache({\n source: parts.store,\n invalidations: parts.channel,\n logger: parts.logger,\n });\n }\n\n async read(jobName: string): Promise<JobControls> {\n return await this.cache.read(jobName);\n }\n\n async write(jobName: string, patch: Partial<JobControls>): Promise<void> {\n await this.parts.store.write(jobName, patch);\n this.cache.invalidate(controlKey(jobName));\n }\n\n async rehydrate(): Promise<void> {\n try {\n await this.parts.store.rehydrate();\n this.cache.clear();\n } catch (err) {\n this.parts.logger.error(\n { err },\n \"[control] rehydration failed — controls set before this boot may read as unset until they are written again\",\n );\n }\n }\n\n async close(): Promise<void> {\n await this.closeQuietly(\n () => this.parts.store.close(),\n \"[control] control store close failed\",\n );\n await this.closeQuietly(\n () => this.parts.channel.close(),\n \"[control] control channel close failed\",\n );\n }\n\n private async closeQuietly(\n close: () => Promise<void>,\n failure: string,\n ): Promise<void> {\n try {\n await close();\n } catch (err) {\n this.parts.logger.warn({ err }, failure);\n }\n }\n}\n","import { Redis, type Cluster } from \"ioredis\";\nimport type {\n ConnectionOptions,\n RedisOptions as BullMQRedisOptions,\n} from \"bullmq\";\nimport type { Logger } from \"@/logger\";\n\nexport type RavenflowConnection = Redis | Cluster;\n\nexport type ConnectionRole = \"publisher\" | \"subscriber\" | \"store\";\n\nexport function openRavenflowConnection(\n connection: ConnectionOptions,\n role: ConnectionRole,\n logger: Logger,\n): RavenflowConnection {\n const opened = duplicateOrBuild(connection);\n opened.on(\"error\", (err: Error) => {\n logger.warn(\n { err, role },\n \"[ravenflow] redis connection error — ioredis reconnects, a command in flight fails\",\n );\n });\n return opened;\n}\n\nfunction duplicateOrBuild(connection: ConnectionOptions): RavenflowConnection {\n const candidate = connection as Partial<Redis>;\n if (typeof candidate.duplicate === \"function\") {\n return (connection as Redis).duplicate();\n }\n\n const { url, ...rest } = connection as BullMQRedisOptions;\n return url ? new Redis(url, rest) : new Redis(rest);\n}\n","import type { ConnectionOptions } from \"bullmq\";\nimport type { Logger } from \"@/logger\";\nimport {\n openRavenflowConnection,\n type RavenflowConnection,\n} from \"../redis-connection\";\n\nimport { isControlKey, type ControlKey } from \"../control-key\";\n\nexport const CONTROL_INVALIDATION_CHANNEL = \"rav:controls:invalidate\";\n\nexport interface ControlPublisher {\n publish(key: ControlKey): Promise<void>;\n}\n\nexport class ControlChannel implements ControlPublisher {\n private publisher: RavenflowConnection | null = null;\n private subscriber: RavenflowConnection | null = null;\n\n constructor(\n private readonly connection: ConnectionOptions,\n private readonly logger: Logger,\n ) {}\n\n async publish(key: ControlKey): Promise<void> {\n this.publisher ??= this.open(\"publisher\");\n await this.publisher.publish(CONTROL_INVALIDATION_CHANNEL, key);\n }\n\n async subscribe(onInvalidate: (key: ControlKey) => void): Promise<void> {\n if (this.subscriber) {\n throw new Error(\"[ravenflow] ControlChannel is already subscribed\");\n }\n\n const subscriber = this.open(\"subscriber\");\n this.subscriber = subscriber;\n subscriber.on(\"message\", (channel: string, message: string) => {\n if (channel === CONTROL_INVALIDATION_CHANNEL) {\n this.deliver(message, onInvalidate);\n }\n });\n\n try {\n await this.listenOn(subscriber);\n } catch (err) {\n if (this.subscriber === subscriber) this.subscriber = null;\n throw err;\n }\n }\n\n async close(): Promise<void> {\n const open = [this.publisher, this.subscriber].filter(\n (connection) => connection !== null,\n );\n this.publisher = null;\n this.subscriber = null;\n\n await Promise.all(open.map(leave));\n }\n\n private deliver(\n message: string,\n onInvalidate: (key: ControlKey) => void,\n ): void {\n if (!isControlKey(message)) {\n this.logger.warn(\n { channel: CONTROL_INVALIDATION_CHANNEL, length: message.length },\n \"[control] invalidation message is not a control key — ignored\",\n );\n return;\n }\n\n onInvalidate(message);\n }\n\n private async listenOn(subscriber: RavenflowConnection): Promise<void> {\n try {\n await subscriber.subscribe(CONTROL_INVALIDATION_CHANNEL);\n } catch (err) {\n subscriber.disconnect();\n throw err;\n }\n }\n\n private open(role: \"publisher\" | \"subscriber\"): RavenflowConnection {\n return openRavenflowConnection(this.connection, role, this.logger);\n }\n}\n\nasync function leave(connection: RavenflowConnection): Promise<void> {\n try {\n await connection.quit();\n } catch {\n connection.disconnect();\n }\n}\n","import type { Logger } from \"@/logger\";\n\nimport type { ControlKey } from \"./control-key\";\n\nexport const LEVERS = [\"executionPaused\", \"triggerPaused\", \"ingestPaused\"] as const;\n\nexport type Lever = (typeof LEVERS)[number];\n\nexport type JobControls = Record<Lever, boolean>;\n\nexport const JOB_CONTROLS_OPEN: JobControls = {\n executionPaused: false,\n triggerPaused: false,\n ingestPaused: false,\n};\n\nexport function decodeLever(\n raw: string | undefined,\n key: ControlKey,\n logger: Logger,\n): boolean | undefined {\n if (raw === undefined) return undefined;\n\n let stored: unknown;\n try {\n stored = JSON.parse(raw);\n } catch (err) {\n logger.warn(\n { err, key },\n \"[control] stored control is not readable — treating it as unset\",\n );\n return undefined;\n }\n\n if (typeof stored === \"boolean\") return stored;\n\n logger.warn(\n { key, type: typeof stored },\n \"[control] stored control is not a boolean — treating it as unset\",\n );\n return undefined;\n}\n","import type { Logger } from \"@/logger\";\n\nimport { controlKey } from \"../control-key\";\nimport { decodeLever, JOB_CONTROLS_OPEN, type JobControls } from \"../levers\";\nimport type { StoredLever } from \"./control-hash\";\n\nexport type LiveControls = Map<string, JobControls>;\n\nexport function liveControls(\n stored: StoredLever[],\n logger: Logger,\n): LiveControls {\n const live: LiveControls = new Map();\n\n for (const held of stored) {\n const pulled = decodeLever(held.value, controlKey(held.jobName), logger);\n if (pulled === undefined) continue;\n\n const controls = live.get(held.jobName) ?? { ...JOB_CONTROLS_OPEN };\n controls[held.lever] = pulled;\n live.set(held.jobName, controls);\n }\n\n return live;\n}\n","import type { Logger } from \"@/logger\";\n\nimport { controlKey } from \"../control-key\";\nimport { LEVERS } from \"../levers\";\nimport type { ControlHash, LeverEntry } from \"./control-hash\";\nimport type { ControlMirror, MirroredControls } from \"./control-mirror\";\n\nexport const CONTROL_REHYDRATE_MAX_ENTRIES = 10_000;\n\nexport interface RehydrationParts {\n hash: ControlHash;\n mirror: ControlMirror;\n logger: Logger;\n}\n\nexport interface RehydrationReport {\n restored: number;\n alreadyLive: number;\n truncated: boolean;\n}\n\nexport async function rehydrateControls(\n parts: RehydrationParts,\n): Promise<RehydrationReport> {\n const levers = (await parts.mirror.listAll()).flatMap(pulledLevers);\n const report = await restoreMissing(parts.hash, levers);\n\n if (report.truncated) reportTruncation(parts.logger, levers.length);\n\n return report;\n}\n\nfunction pulledLevers(mirrored: MirroredControls): LeverEntry[] {\n const key = controlKey(mirrored._id);\n\n return LEVERS.filter((lever) => mirrored[lever] === true).map(\n (lever): LeverEntry => ({ key, lever, value: JSON.stringify(true) }),\n );\n}\n\nasync function restoreMissing(\n hash: ControlHash,\n levers: LeverEntry[],\n): Promise<RehydrationReport> {\n let restored = 0;\n let alreadyLive = 0;\n\n for (const lever of levers.slice(0, CONTROL_REHYDRATE_MAX_ENTRIES)) {\n if (await hash.writeIfAbsent(lever)) restored++;\n else alreadyLive++;\n }\n\n return {\n restored,\n alreadyLive,\n truncated: levers.length > CONTROL_REHYDRATE_MAX_ENTRIES,\n };\n}\n\nfunction reportTruncation(logger: Logger, held: number): void {\n logger.error(\n {\n fields: held,\n cap: CONTROL_REHYDRATE_MAX_ENTRIES,\n skipped: held - CONTROL_REHYDRATE_MAX_ENTRIES,\n },\n \"[control] the mirror holds more controls than rehydration will restore — the controls past the cap read as open until they are set again\",\n );\n}\n","import type { Logger } from \"@/logger\";\n\nimport type { ControlPublisher } from \"../channel\";\nimport {\n controlKey,\n validateControlName,\n type ControlKey,\n} from \"../control-key\";\nimport { decodeLever, LEVERS, type JobControls } from \"../levers\";\nimport type { JobControlPlane } from \"../types\";\nimport type { ControlHash } from \"./control-hash\";\nimport type { ControlMirror } from \"./control-mirror\";\nimport { liveControls, type LiveControls } from \"./live-controls\";\nimport {\n rehydrateControls,\n type RehydrationReport,\n} from \"./rehydrate-controls\";\n\nexport interface ControlStoreParts {\n hash: ControlHash;\n publisher: ControlPublisher;\n mirror: ControlMirror;\n logger: Logger;\n}\n\nexport class ControlStore implements JobControlPlane {\n constructor(private readonly parts: ControlStoreParts) {}\n\n async read(jobName: string): Promise<JobControls> {\n const key = controlKey(jobName);\n const stored = await this.parts.hash.readLevers(key);\n\n return {\n executionPaused: this.isPulled(stored.get(\"executionPaused\"), key),\n triggerPaused: this.isPulled(stored.get(\"triggerPaused\"), key),\n ingestPaused: this.isPulled(stored.get(\"ingestPaused\"), key),\n };\n }\n\n async write(jobName: string, patch: Partial<JobControls>): Promise<void> {\n validateControlName(jobName, \"ControlStore.write\");\n refuseNonBooleanLevers(patch);\n const key = controlKey(jobName);\n\n await this.writeLevers(key, patch);\n await this.announce(key);\n await this.writeMirror(jobName, patch);\n }\n\n async readAll(): Promise<LiveControls> {\n return liveControls(\n await this.parts.hash.readEveryLever(),\n this.parts.logger,\n );\n }\n\n async rehydrate(): Promise<RehydrationReport> {\n return await rehydrateControls({\n hash: this.parts.hash,\n mirror: this.parts.mirror,\n logger: this.parts.logger,\n });\n }\n\n async close(): Promise<void> {\n await this.parts.hash.close();\n }\n\n private isPulled(raw: string | undefined, key: ControlKey): boolean {\n return decodeLever(raw, key, this.parts.logger) ?? false;\n }\n\n private async writeLevers(\n key: ControlKey,\n patch: Partial<JobControls>,\n ): Promise<void> {\n for (const lever of LEVERS) {\n const pulled = patch[lever];\n if (pulled === undefined) continue;\n\n await this.parts.hash.write({\n key,\n lever,\n value: JSON.stringify(pulled),\n });\n }\n }\n\n private async announce(key: ControlKey): Promise<void> {\n try {\n await this.parts.publisher.publish(key);\n } catch (err) {\n this.parts.logger.warn(\n { err, key },\n \"[control] invalidation publish failed — workers pick this up on the cache TTL instead\",\n );\n }\n }\n\n private async writeMirror(\n jobName: string,\n patch: Partial<JobControls>,\n ): Promise<void> {\n try {\n await this.parts.mirror.mirrorJobControls(jobName, patch);\n } catch (err) {\n this.parts.logger.error(\n { err, jobName, patch },\n \"[control] mirror write failed — the change is live but will not survive a Redis flush until the next successful write\",\n );\n }\n }\n}\n\nfunction refuseNonBooleanLevers(patch: Partial<JobControls>): void {\n for (const lever of LEVERS) {\n const pulled = patch[lever];\n if (pulled === undefined || typeof pulled === \"boolean\") continue;\n\n throw new Error(`ControlStore.write: ${lever} must be a boolean`);\n }\n}\n","import type { ConnectionOptions } from \"bullmq\";\nimport type { Logger } from \"@/logger\";\nimport { openRavenflowConnection } from \"../redis-connection\";\n\nimport { isControlKey, jobNameOf, type ControlKey } from \"../control-key\";\nimport { LEVERS, type Lever } from \"../levers\";\n\nexport const CONTROL_HASH_KEY = \"rav:controls\";\n\nexport interface LeverEntry {\n key: ControlKey;\n lever: Lever;\n value: string;\n}\n\nexport interface StoredLever {\n jobName: string;\n lever: Lever;\n value: string;\n}\n\ninterface HashConnection {\n hgetall(key: string): Promise<Record<string, string>>;\n hmget(key: string, ...fields: string[]): Promise<Array<string | null>>;\n hset(key: string, field: string, value: string): Promise<number>;\n hsetnx(key: string, field: string, value: string): Promise<number>;\n quit(): Promise<unknown>;\n disconnect(): void;\n}\n\nexport class ControlHash {\n private connection: HashConnection | null = null;\n\n constructor(\n private readonly options: ConnectionOptions,\n private readonly logger: Logger,\n ) {}\n\n async readLevers(key: ControlKey): Promise<Map<Lever, string>> {\n const stored = await this.redis.hmget(\n CONTROL_HASH_KEY,\n ...LEVERS.map((lever) => controlField(key, lever)),\n );\n\n const pulled = new Map<Lever, string>();\n LEVERS.forEach((lever, index) => {\n const raw = stored[index];\n if (raw !== null && raw !== undefined) pulled.set(lever, raw);\n });\n return pulled;\n }\n\n async readEveryLever(): Promise<StoredLever[]> {\n return storedLevers(await this.redis.hgetall(CONTROL_HASH_KEY));\n }\n\n async write(entry: LeverEntry): Promise<void> {\n await this.redis.hset(\n CONTROL_HASH_KEY,\n controlField(entry.key, entry.lever),\n entry.value,\n );\n }\n\n async writeIfAbsent(entry: LeverEntry): Promise<boolean> {\n const written = await this.redis.hsetnx(\n CONTROL_HASH_KEY,\n controlField(entry.key, entry.lever),\n entry.value,\n );\n return written === 1;\n }\n\n async close(): Promise<void> {\n const open = this.connection;\n this.connection = null;\n if (!open) return;\n\n try {\n await open.quit();\n } catch {\n open.disconnect();\n }\n }\n\n private get redis(): HashConnection {\n this.connection ??= openRavenflowConnection(\n this.options,\n \"store\",\n this.logger,\n ) as HashConnection;\n return this.connection;\n }\n}\n\nexport function controlField(key: ControlKey, lever: Lever): string {\n return `${key}#${lever}`;\n}\n\nfunction storedLevers(fields: Record<string, string>): StoredLever[] {\n return Object.entries(fields).flatMap(([field, value]): StoredLever[] => {\n const held = leverOf(field);\n return held === undefined ? [] : [{ ...held, value }];\n });\n}\n\nfunction leverOf(field: string): { jobName: string; lever: Lever } | undefined {\n for (const lever of LEVERS) {\n const suffix = `#${lever}`;\n if (!field.endsWith(suffix)) continue;\n\n const key = field.slice(0, -suffix.length);\n if (isControlKey(key)) return { jobName: jobNameOf(key), lever };\n }\n return undefined;\n}\n","import type { Collection } from \"mongodb\";\nimport type { MongoConnection } from \"@/mongo/connection\";\n\nimport type { JobControls } from \"../levers\";\n\nconst CONTROL_MIRROR_COLLECTION = \"rav:job-controls\";\n\nexport interface MirroredControls extends Partial<JobControls> {\n _id: string;\n updatedAt: Date;\n}\n\nexport interface ControlMirror {\n mirrorJobControls(\n jobName: string,\n patch: Partial<JobControls>,\n ): Promise<void>;\n listAll(): Promise<MirroredControls[]>;\n}\n\nexport function controlMirror(connection: MongoConnection): ControlMirror {\n const mirrorCollection = async (): Promise<Collection<MirroredControls>> => {\n const db = await connection.connect();\n return db.collection<MirroredControls>(CONTROL_MIRROR_COLLECTION);\n };\n\n return {\n mirrorJobControls: async (jobName, patch) => {\n const collection = await mirrorCollection();\n await collection.updateOne(\n { _id: jobName },\n { $set: { ...patch, updatedAt: new Date() } },\n { upsert: true },\n );\n },\n listAll: async () => (await mirrorCollection()).find().toArray(),\n };\n}\n","import type { ConnectionOptions as RedisConnectionOptions } from \"bullmq\";\nimport type { Logger } from \"@/logger\";\nimport type { MongoConnection } from \"@/mongo/connection\";\n\nimport { ControlPlane } from \"./control-plane\";\nimport { ControlChannel } from \"./channel\";\nimport { ControlHash, ControlStore, controlMirror } from \"./store\";\n\nexport function initControlPlane(runtime: {\n redis: RedisConnectionOptions;\n mongo: MongoConnection;\n logger: Logger;\n}): ControlPlane {\n const channel = new ControlChannel(runtime.redis, runtime.logger);\n const store = new ControlStore({\n hash: new ControlHash(runtime.redis, runtime.logger),\n publisher: channel,\n mirror: controlMirror(runtime.mongo),\n logger: runtime.logger,\n });\n\n return new ControlPlane({ store, channel, logger: runtime.logger });\n}\n","import { ObjectId, type Collection, type Filter, type WithId } from \"mongodb\";\nimport type { MongoConnection } from \"@/mongo/connection\";\n\nexport type SpoolItem = Record<string, unknown>;\n\nexport interface BacklogEntry {\n item: SpoolItem;\n claimedAt?: Date;\n}\n\nexport type StoredEntry = WithId<BacklogEntry>;\n\nexport interface SpoolPurgeReport {\n dropped: number;\n inFlight: number;\n}\n\nconst BACKLOG_COLLECTION_PREFIX = \"rav:spool-backlog:\";\n\nconst NEVER_CLAIMED: Filter<BacklogEntry> = { claimedAt: { $exists: false } };\n\nconst CLAIMED: Filter<BacklogEntry> = { claimedAt: { $type: \"date\" } };\n\nconst CLAIM_INDEX = { claimedAt: 1, _id: 1 } as const;\n\nconst OLDEST_FIRST = { _id: 1 } as const;\n\nconst MS_PER_SECOND = 1_000;\n\nexport class Backlog {\n constructor(\n readonly spoolName: string,\n private readonly connection: MongoConnection,\n ) {}\n\n async push(item: SpoolItem): Promise<string> {\n const backlog = await this.collection();\n const { insertedId } = await backlog.insertOne({ item });\n return insertedId.toHexString();\n }\n\n async pushMany(items: SpoolItem[]): Promise<string[]> {\n if (items.length === 0) return [];\n const backlog = await this.collection();\n const { insertedIds } = await backlog.insertMany(\n items.map((item) => ({ item })),\n );\n return items.map((_, position) => insertedIds[position].toHexString());\n }\n\n async purge(): Promise<SpoolPurgeReport> {\n const backlog = await this.collection();\n const { deletedCount } = await backlog.deleteMany(NEVER_CLAIMED);\n return {\n dropped: deletedCount,\n inFlight: await backlog.countDocuments(CLAIMED),\n };\n }\n\n async indexForTheClaim(): Promise<void> {\n const backlog = await this.collection();\n await backlog.createIndex(CLAIM_INDEX);\n }\n\n async countInFlight(): Promise<number> {\n const backlog = await this.collection();\n return backlog.countDocuments(CLAIMED);\n }\n\n async expireUnclaimedPushedBefore(pushedBefore: Date): Promise<number> {\n const backlog = await this.collection();\n const { deletedCount } = await backlog.deleteMany({\n ...NEVER_CLAIMED,\n _id: { $lt: ObjectId.createFromTime(secondsOf(pushedBefore)) },\n });\n return deletedCount;\n }\n\n async reclaimStaleClaims(\n claimedBefore: Date,\n now: Date,\n ): Promise<StoredEntry[]> {\n const staleClaim: Filter<BacklogEntry> = {\n claimedAt: { $lte: claimedBefore },\n };\n const backlog = await this.collection();\n const stale = await backlog.find(staleClaim).toArray();\n return this.claimAll(stale, staleClaim, now);\n }\n\n async claimOldestNeverClaimed(\n count: number,\n now: Date,\n ): Promise<StoredEntry[]> {\n if (count <= 0) return [];\n const backlog = await this.collection();\n const oldest = await backlog\n .find(NEVER_CLAIMED, { sort: OLDEST_FIRST, limit: count })\n .toArray();\n return this.claimAll(oldest, NEVER_CLAIMED, now);\n }\n\n async removeAll(ids: ObjectId[]): Promise<void> {\n if (ids.length === 0) return;\n const backlog = await this.collection();\n await backlog.deleteMany({ _id: { $in: ids } });\n }\n\n private async claimAll(\n entries: StoredEntry[],\n stillClaimable: Filter<BacklogEntry>,\n claimedAt: Date,\n ): Promise<StoredEntry[]> {\n if (entries.length === 0) return [];\n const ids = entries.map(({ _id }) => _id);\n const backlog = await this.collection();\n const { modifiedCount } = await backlog.updateMany(\n { _id: { $in: ids }, ...stillClaimable },\n { $set: { claimedAt } },\n );\n if (modifiedCount < entries.length) {\n return this.whatThisClaimTook(ids, claimedAt);\n }\n return entries;\n }\n\n private async whatThisClaimTook(\n ids: ObjectId[],\n claimedAt: Date,\n ): Promise<StoredEntry[]> {\n const backlog = await this.collection();\n return backlog.find({ _id: { $in: ids }, claimedAt }).toArray();\n }\n\n private async collection(): Promise<Collection<BacklogEntry>> {\n const db = await this.connection.connect();\n return db.collection<BacklogEntry>(collectionNameOf(this.spoolName));\n }\n}\n\nfunction collectionNameOf(spoolName: string): string {\n return `${BACKLOG_COLLECTION_PREFIX}${spoolName}`;\n}\n\nfunction secondsOf(moment: Date): number {\n return Math.floor(moment.getTime() / MS_PER_SECOND);\n}\n","import { ObjectId } from \"mongodb\";\nimport { linkIdOf, linkOfItsRun } from \"@/queues\";\n\nexport interface ItemLink {\n itemId: ObjectId;\n link: number;\n}\n\nconst SPOOL_JOB_ID_PREFIX = \"spool\";\n\nconst AN_ITEM_ID = /^[0-9a-f]{24}$/;\n\nexport function spoolJobId(\n spoolName: string,\n { itemId, link }: ItemLink,\n): string {\n return linkIdOf({\n runId: `${prefixOf(spoolName)}${itemId.toHexString()}`,\n link,\n });\n}\n\nexport function isALinkOfAnItem(spoolName: string, jobId: string): boolean {\n const prefix = prefixOf(spoolName);\n const { runId } = linkOfItsRun(jobId);\n return (\n runId.startsWith(prefix) && AN_ITEM_ID.test(runId.slice(prefix.length))\n );\n}\n\nexport function itemLinkOf(spoolName: string, jobId: string): ItemLink {\n if (!isALinkOfAnItem(spoolName, jobId)) {\n throw notALinkOfAnItem(spoolName, jobId);\n }\n const { runId, link } = linkOfItsRun(jobId);\n const itemId = runId.slice(prefixOf(spoolName).length);\n return { itemId: ObjectId.createFromHexString(itemId), link };\n}\n\nfunction prefixOf(spoolName: string): string {\n return `${SPOOL_JOB_ID_PREFIX}:${spoolName}:`;\n}\n\nfunction notALinkOfAnItem(spoolName: string, jobId: string): Error {\n return new Error(\n `[ravenflow] \"${jobId}\" is not the job id of a link of an item of the spool \"${spoolName}\".`,\n );\n}\n","import type { Queue } from \"bullmq\";\nimport type { ObjectId } from \"mongodb\";\n\nimport { itemLinkOf } from \"./spool-job-id\";\n\nexport class ItemRuns {\n constructor(\n private readonly queue: Queue,\n private readonly spoolName: string,\n ) {}\n\n async goOnTo(linkId: string): Promise<void> {\n const { itemId, link } = itemLinkOf(this.spoolName, linkId);\n const client = await this.queue.client;\n await client.set(this.currentLinkKeyOf(itemId), String(link));\n }\n\n async currentLinksOf(itemIds: ObjectId[]): Promise<number[]> {\n if (itemIds.length === 0) return [];\n const client = await this.queue.client;\n const links = await client.mget(\n itemIds.map((itemId) => this.currentLinkKeyOf(itemId)),\n );\n return links.map((link) => Number(link ?? 0));\n }\n\n async forget(itemIds: ObjectId[]): Promise<void> {\n if (itemIds.length === 0) return;\n const client = await this.queue.client;\n await client.del(itemIds.map((itemId) => this.currentLinkKeyOf(itemId)));\n }\n\n private currentLinkKeyOf(itemId: ObjectId): string {\n return this.queue.toKey(\n `rav:spool-run:${this.spoolName}:${itemId.toHexString()}`,\n );\n }\n}\n","import type { AnyJob } from \"@/job\";\nimport type { MongoConnection } from \"@/mongo/connection\";\nimport { Backlog } from \"@/spools\";\n\nexport function buildBacklog(\n definition: AnyJob,\n mongo: MongoConnection,\n): Backlog | undefined {\n const spool = definition.trigger?.spool;\n if (!spool) return undefined;\n return new Backlog(spool.name, mongo);\n}\n","import type { JobControlPlane, JobControls } from \"@/control-plane\";\nimport type { Backlog } from \"@/spools\";\n\nimport type {\n AnyJobControls,\n ClockFedControls,\n ExecutionControls,\n ProxiedJob,\n SpoolFedControls,\n} from \"./types\";\n\ntype SetLevers = (patch: Partial<JobControls>) => Promise<void>;\n\nexport function buildControls(\n job: ProxiedJob,\n plane: JobControlPlane,\n): AnyJobControls {\n const setLevers: SetLevers = (patch) => plane.write(job.name, patch);\n\n if (job.backlog) return spoolFedControls(setLevers, job.backlog);\n if (isClockFed(job)) return clockFedControls(setLevers);\n\n return executionControls(setLevers);\n}\n\nfunction isClockFed(job: ProxiedJob): boolean {\n return typeof job.definition.trigger?.cron === \"string\";\n}\n\nfunction executionControls(setLevers: SetLevers): ExecutionControls {\n return {\n pauseExecution: () => setLevers({ executionPaused: true }),\n resumeExecution: () => setLevers({ executionPaused: false }),\n };\n}\n\nfunction clockFedControls(setLevers: SetLevers): ClockFedControls {\n return {\n ...executionControls(setLevers),\n pauseTrigger: () => setLevers({ triggerPaused: true }),\n resumeTrigger: () => setLevers({ triggerPaused: false }),\n };\n}\n\nfunction spoolFedControls(\n setLevers: SetLevers,\n backlog: Backlog,\n): SpoolFedControls {\n return {\n ...clockFedControls(setLevers),\n pauseIngest: () => setLevers({ ingestPaused: true }),\n resumeIngest: () => setLevers({ ingestPaused: false }),\n purgeBacklog: () => backlog.purge(),\n };\n}\n","import type { JobsOptions } from \"bullmq\";\nimport { namespacedDeduplicationId } from \"@/job\";\n\nimport type { ProxiedJob, SendArguments } from \"./types\";\n\nexport function deduplicationOptions(\n job: ProxiedJob,\n sent: SendArguments,\n): JobsOptions {\n const deduplicationId = deduplicationIdOfTheSend(job, sent);\n if (deduplicationId === undefined) return {};\n return {\n deduplication: { id: namespacedDeduplicationId(job.name, deduplicationId) },\n };\n}\n\nfunction deduplicationIdOfTheSend(\n job: ProxiedJob,\n sent: SendArguments,\n): string | undefined {\n const givenId = sent.perCall.deduplicationId;\n if (givenId !== undefined) return givenId;\n\n const declared = job.definition.deduplicate;\n if (declared === undefined) return undefined;\n if (declared === true) return job.name;\n return declared(sent.payload as never);\n}\n","import { Job, type JobsOptions, type Queue } from \"bullmq\";\n\nimport { deduplicationOptions } from \"./deduplication\";\nimport type { ProxiedJob, SendArguments, SendOptions } from \"./types\";\n\ntype Send = (payload: unknown, options?: SendOptions) => Promise<Job>;\n\nexport function buildSend(job: ProxiedJob): Send {\n return async (payload, perCall = {}) => {\n const options = addOptions(job, { payload, perCall });\n const added = await job.queue.add(job.name, payload, options);\n if (!options.deduplication) return added;\n return jobHoldingTheDeduplicationId(job.queue, added);\n };\n}\n\nfunction addOptions(job: ProxiedJob, sent: SendArguments): JobsOptions {\n return {\n ...job.declaredOptions,\n ...queueingOptions(sent.perCall),\n ...deduplicationOptions(job, sent),\n };\n}\n\nfunction queueingOptions(perCall: SendOptions): JobsOptions {\n const options: JobsOptions = {};\n if (perCall.delayMs !== undefined) options.delay = perCall.delayMs;\n if (perCall.priority !== undefined) options.priority = perCall.priority;\n return options;\n}\n\nasync function jobHoldingTheDeduplicationId(\n queue: Queue,\n added: Job,\n): Promise<Job> {\n return (await Job.fromId(queue, String(added.id))) ?? added;\n}\n","import type { ControlReads } from \"@/control-plane\";\nimport type { Backlog, SpoolItem } from \"@/spools\";\n\nimport type { SpoolIngest } from \"./types\";\n\nexport function buildSpoolIngest(\n jobName: string,\n backlog: Backlog,\n controls: ControlReads,\n): SpoolIngest<SpoolItem> {\n return {\n push: async (item) => {\n await refuseIfIngestPaused(jobName, controls);\n return backlog.push(item);\n },\n pushMany: async (items) => {\n await refuseIfIngestPaused(jobName, controls);\n return backlog.pushMany(items);\n },\n };\n}\n\nasync function refuseIfIngestPaused(\n jobName: string,\n controls: ControlReads,\n): Promise<void> {\n const { ingestPaused } = await controls.read(jobName);\n if (ingestPaused) throw new SpoolIngestPausedError(jobName);\n}\n\nexport class SpoolIngestPausedError extends Error {\n constructor(public readonly job: string) {\n super(\n `[ravenflow] the spool feeding \"${job}\" is not accepting items: its ingest is paused. Call client.jobs.${job}.controls.resumeIngest() to reopen it.`,\n );\n this.name = \"SpoolIngestPausedError\";\n }\n}\n","import type { RavenflowConfig } from \"@/config\";\nimport type { ControlReads } from \"@/control-plane\";\nimport type { AnyJob } from \"@/job\";\nimport { buildJobOptions } from \"@/queues\";\nimport type { SpoolItem } from \"@/spools\";\n\nimport { buildBacklog } from \"./build-backlog\";\nimport { buildControls } from \"./controls\";\nimport { buildSend } from \"./send\";\nimport { buildSpoolIngest } from \"./spool-ingest\";\nimport type {\n JobProxiesRuntime,\n JobSend,\n JobsProxy,\n ProxiedJob,\n SpoolIngest,\n} from \"./types\";\n\nexport function initJobProxies<TConfig extends RavenflowConfig>(\n config: TConfig,\n runtime: JobProxiesRuntime,\n): JobsProxy<TConfig[\"jobs\"]> {\n const proxies: Record<string, object> = {};\n\n for (const [name, definition] of Object.entries<AnyJob>(config.jobs)) {\n const job: ProxiedJob = {\n name,\n definition,\n queue: runtime.queues[definition.queue ?? config.defaultQueue],\n declaredOptions: buildJobOptions(definition),\n backlog: buildBacklog(definition, runtime.mongo),\n };\n\n proxies[name] = {\n ...buildSendOrIngest(job, runtime.controls),\n controls: buildControls(job, runtime.controls),\n };\n }\n\n return proxies as unknown as JobsProxy<TConfig[\"jobs\"]>;\n}\n\nfunction buildSendOrIngest(\n job: ProxiedJob,\n controls: ControlReads,\n): JobSend<unknown, unknown> | SpoolIngest<SpoolItem> {\n if (job.backlog) return buildSpoolIngest(job.name, job.backlog, controls);\n return { send: buildSend(job) };\n}\n","import type { ConnectionOptions as RedisConnectionOptions } from \"bullmq\";\nimport type { RavenflowConfig } from \"@/config\";\nimport { validateConfig } from \"@/config/validate-config\";\n\nimport type { JobsProxy } from \"./job-proxy\";\n\nimport { createLogger, type Logger } from \"@/logger\";\nimport { MongoConnection } from \"@/mongo/connection\";\n\nimport { closeQueues, openQueues, type QueuesByName } from \"@/queues\";\nimport { ControlPlane, initControlPlane } from \"@/control-plane\";\n\nimport { initJobProxies } from \"./job-proxy\";\n\nexport class RavenflowClient<\n TConfig extends RavenflowConfig = RavenflowConfig,\n> {\n public readonly jobs: JobsProxy<TConfig[\"jobs\"]>;\n\n protected readonly redisConnectionOptions: RedisConnectionOptions;\n protected readonly mongoUri: string;\n\n protected readonly mongo: MongoConnection;\n\n protected readonly config: TConfig;\n protected readonly controlPlane: ControlPlane;\n protected readonly queues: QueuesByName;\n protected readonly logger: Logger;\n\n constructor(\n config: TConfig,\n options: {\n redis: RedisConnectionOptions;\n mongo: string;\n },\n ) {\n validateConfig(config);\n\n this.config = config;\n this.mongoUri = options.mongo;\n this.redisConnectionOptions = options.redis;\n\n this.logger = createLogger(config.logger);\n this.mongo = new MongoConnection(options.mongo);\n\n this.queues = openQueues(config, this.redisConnectionOptions);\n\n this.controlPlane = initControlPlane({\n redis: this.redisConnectionOptions,\n mongo: this.mongo,\n logger: this.logger,\n });\n\n this.jobs = initJobProxies(config, {\n queues: this.queues,\n mongo: this.mongo,\n controls: this.controlPlane,\n });\n }\n\n public async close(): Promise<void> {\n await this.controlPlane.close();\n await closeQueues(this.queues);\n await this.mongo.close();\n }\n}\n","import { RavenflowConfig } from \"@/config\";\nimport { RavenflowClient } from \"./ravenflow-client\";\n\nexport function createRavenflowClient<TConfig extends RavenflowConfig>(\n config: TConfig,\n options: ConstructorParameters<typeof RavenflowClient>[1],\n): RavenflowClient<TConfig> {\n return new RavenflowClient(config, options);\n}\n","export function describeError(error: unknown): string {\n return error instanceof Error ? error.message : String(error);\n}\n","import {\n isRedisInstance,\n type ConnectionOptions as RedisConnectionOptions,\n type RedisOptions,\n} from \"bullmq\";\nimport { isSpoolFed, type AnyJob, type AnySpoolFedJob } from \"@/job\";\nimport { inFlightCeilingOf } from \"@/spools\";\n\nimport type { JobResultsRecorderOpening } from \"./job-results-recorder\";\nimport type { SchedulerChanges } from \"./schedulers\";\n\nconst RAVENFLOW = `\n ██████╗ █████╗ ██╗ ██╗███████╗███╗ ██╗███████╗██╗ ██████╗ ██╗ ██╗\n ██╔══██╗██╔══██╗██║ ██║██╔════╝████╗ ██║██╔════╝██║ ██╔═══██╗██║ ██║\n ██████╔╝███████║██║ ██║█████╗ ██╔██╗ ██║█████╗ ██║ ██║ ██║██║ █╗ ██║\n ██╔══██╗██╔══██║╚██╗ ██╔╝██╔══╝ ██║╚██╗██║██╔══╝ ██║ ██║ ██║██║███╗██║\n ██║ ██║██║ ██║ ╚████╔╝ ███████╗██║ ╚████║██║ ███████╗╚██████╔╝╚███╔███╔╝\n ╚═╝ ╚═╝╚═╝ ╚═╝ ╚═══╝ ╚══════╝╚═╝ ╚═══╝╚═╝ ╚══════╝ ╚═════╝ ╚══╝╚══╝\n`;\n\nconst RULE = \"═\".repeat(85);\n\nconst FEEDS_IN_ORDER = [\"nothing\", \"clock\", \"spool\"] as const;\n\ninterface Feed {\n kind: (typeof FEEDS_IN_ORDER)[number];\n label: string;\n}\n\nexport interface BannerFacts {\n queue: string;\n concurrency: number;\n redis: RedisConnectionOptions;\n mongo: string;\n recorderOpening: JobResultsRecorderOpening;\n jobs: Record<string, AnyJob>;\n schedulers: SchedulerChanges;\n}\n\nexport function printBanner(facts: BannerFacts): void {\n console.log(\n [\n RAVENFLOW,\n RULE,\n \"[Config]\",\n ...configLines(facts),\n \"\",\n \"[Registered Jobs]\",\n ...registeredJobLines(facts.jobs),\n \"\",\n \"[Scheduled Jobs]\",\n ...schedulerLines(facts.schedulers),\n RULE,\n \"Ready to process jobs...\",\n ].join(\"\\n\"),\n );\n}\n\nfunction configLines(facts: BannerFacts): string[] {\n return [\n ` -> queue: ${facts.queue}`,\n ` -> concurrency: ${facts.concurrency}`,\n ` -> redis: ${addressOf(facts.redis)}`,\n ` -> mongo: ${mongoLineOf(facts)}`,\n ];\n}\n\nfunction addressOf(redis: RedisConnectionOptions): string {\n if (isRedisInstance(redis)) return \"an ioredis client\";\n\n const {\n url,\n host = \"localhost\",\n port = 6379,\n db = 0,\n } = redis as RedisOptions;\n return url ? withoutPassword(url) : `${host}:${port}/${db}`;\n}\n\nfunction mongoLineOf({ mongo, recorderOpening }: BannerFacts): string {\n const address = withoutPassword(mongo);\n if (!recorderOpening.opened) {\n return `${address} (job results are not recorded: ${recorderOpening.because})`;\n }\n return address;\n}\n\nfunction withoutPassword(uri: string): string {\n return uri.replace(/\\/\\/([^:/@]*):[^@]*@/, \"//$1:***@\");\n}\n\nfunction registeredJobLines(jobs: Record<string, AnyJob>): string[] {\n const lines = Object.entries(jobs)\n .map(([name, job]) => ({ name, feed: feedOf(job) }))\n .sort((a, b) => feedRank(a.feed) - feedRank(b.feed))\n .map(({ name, feed }) => ` . ${name}${feed.label}`);\n return lines.length > 0 ? lines : [\" (none)\"];\n}\n\nfunction feedOf(job: AnyJob): Feed {\n const cron = job.trigger?.cron;\n if (cron) return { kind: \"clock\", label: ` (↻ ${cron})` };\n if (isSpoolFed(job)) return { kind: \"spool\", label: spoolLabelOf(job) };\n return { kind: \"nothing\", label: \"\" };\n}\n\nfunction spoolLabelOf({ trigger, pace }: AnySpoolFedJob): string {\n const ceiling = inFlightCeilingOf(trigger.spool, pace);\n return ` (← ${trigger.spool.name}, ${ceiling} in flight at most)`;\n}\n\nfunction feedRank(feed: Feed): number {\n return FEEDS_IN_ORDER.indexOf(feed.kind);\n}\n\nfunction schedulerLines(changes: SchedulerChanges): string[] {\n const lines = [\n ...changes.added.map(({ name, pattern }) => ` + ${name} → ${pattern}`),\n ...changes.rescheduled.map(\n ({ name, pattern, previousPattern }) =>\n ` ↻ ${name} → ${pattern} (was ${previousPattern})`,\n ),\n ...changes.removed.map((name) => ` - ${name}`),\n ];\n return lines.length > 0 ? lines : [\" (no change)\"];\n}\n","import type { ConnectionOptions as RedisConnectionOptions } from \"bullmq\";\nimport {\n initControlPlane,\n type ControlPlane,\n type ControlReads,\n type JobControls,\n} from \"@/control-plane\";\nimport type { Logger } from \"@/logger\";\nimport { MongoConnection } from \"@/mongo/connection\";\n\nexport interface ControlPlaneReaderSettings {\n redis: RedisConnectionOptions;\n mongo: string;\n logger: Logger;\n}\n\nexport class ControlPlaneReader implements ControlReads {\n private readonly mirrorConnection: MongoConnection;\n private readonly controlPlane: ControlPlane;\n\n constructor(settings: ControlPlaneReaderSettings) {\n this.mirrorConnection = new MongoConnection(settings.mongo);\n this.controlPlane = initControlPlane({\n redis: settings.redis,\n mongo: this.mirrorConnection,\n logger: settings.logger,\n });\n }\n\n async open(): Promise<void> {\n await this.controlPlane.rehydrate();\n await this.mirrorConnection.close();\n }\n\n read(jobName: string): Promise<JobControls> {\n return this.controlPlane.read(jobName);\n }\n\n async close(): Promise<void> {\n await this.controlPlane.close();\n await this.mirrorConnection.close();\n }\n}\n","import type { Logger } from \"@/logger\";\n\ninterface BullmqErrorSource {\n readonly name: string;\n on(event: \"error\", listener: (error: Error) => void): unknown;\n}\n\nexport function logBullmqErrors(\n source: BullmqErrorSource,\n logger: Logger,\n): void {\n source.on(\"error\", (error) => {\n logger.error(\n { err: error, queue: source.name },\n `[ravenflow] BullMQ reported an error on \"${source.name}\".`,\n );\n });\n}\n","export const MONGODB_DEADLINE_ON_CLOSE_MS = 5_000;\n\nexport async function waitOrCutShort(\n waitingOnMongoDB: Promise<void>,\n cutItShort: () => Promise<void>,\n): Promise<void> {\n if (await settlesBeforeTheDeadline(waitingOnMongoDB)) return;\n await cutItShort();\n await waitingOnMongoDB;\n}\n\nasync function settlesBeforeTheDeadline(work: Promise<void>): Promise<boolean> {\n const deadline = new Promise<boolean>((resolve) => {\n setTimeout(() => resolve(false), MONGODB_DEADLINE_ON_CLOSE_MS).unref();\n });\n return Promise.race([work.then(() => true), deadline]);\n}\n","import { MongoBulkWriteError, type Collection } from \"mongodb\";\nimport type { Logger } from \"@/logger\";\n\nimport { MONGODB_DEADLINE_ON_CLOSE_MS } from \"../mongodb-deadline-on-close\";\n\nimport type { JobResult } from \"./job-result\";\n\nconst FLUSH_INTERVAL_MS = 30_000;\n\nconst JOB_RESULTS_PER_BATCH = 1_000;\n\nconst MAX_UNWRITTEN_JOB_RESULTS = 5_000;\n\nconst PAUSE_BETWEEN_FINAL_FLUSHES_MS = 1_000;\n\nexport class BatchWriter {\n private buffered: JobResult[] = [];\n private writing = 0;\n private flushing: Promise<void> | null = null;\n private mayHoldJobs = true;\n private closed = false;\n private readonly heldJobs: Array<() => void> = [];\n private readonly timer: ReturnType<typeof setInterval>;\n\n constructor(\n private readonly collection: Collection<JobResult>,\n private readonly logger: Logger,\n ) {\n this.timer = setInterval(() => this.flush(), FLUSH_INTERVAL_MS);\n this.timer.unref();\n }\n\n add(jobResult: JobResult): void {\n if (this.closed) return this.reportLost(1, \"it arrived after close()\");\n this.buffered.push(jobResult);\n if (this.buffered.length >= JOB_RESULTS_PER_BATCH) this.flush();\n }\n\n async waitForRoom(): Promise<void> {\n if (this.mustHoldJobs()) await this.holdJob();\n }\n\n stopHoldingJobs(): void {\n this.mayHoldJobs = false;\n this.releaseHeldJobs();\n }\n\n async close(): Promise<void> {\n clearInterval(this.timer);\n this.stopHoldingJobs();\n await this.flushUntil(Date.now() + MONGODB_DEADLINE_ON_CLOSE_MS);\n this.closed = true;\n this.dropWhatIsLeft();\n }\n\n private async holdJob(): Promise<void> {\n this.flush();\n await new Promise<void>((resolve) => this.heldJobs.push(resolve));\n }\n\n private mustHoldJobs(): boolean {\n return this.mayHoldJobs && this.unwritten() >= MAX_UNWRITTEN_JOB_RESULTS;\n }\n\n private unwritten(): number {\n return this.buffered.length + this.writing;\n }\n\n private releaseHeldJobs(): void {\n if (this.mustHoldJobs()) return;\n for (const release of this.heldJobs.splice(0)) release();\n }\n\n private async flush(): Promise<void> {\n if (this.flushing) return this.flushing;\n if (this.buffered.length === 0) return;\n\n this.flushing = this.writeBuffered();\n try {\n await this.flushing;\n } finally {\n this.flushing = null;\n this.releaseHeldJobs();\n }\n }\n\n private async writeBuffered(): Promise<void> {\n const batch = this.buffered;\n this.buffered = [];\n this.writing = batch.length;\n try {\n await this.collection.insertMany(batch, {\n ordered: false,\n ignoreUndefined: true,\n });\n } catch (error) {\n this.keepUnlessLost(batch, error);\n } finally {\n this.writing = 0;\n }\n }\n\n private keepUnlessLost(batch: JobResult[], error: unknown): void {\n const refused = countRefusedByMongo(error);\n if (refused > 0) return this.reportLost(refused, \"MongoDB refused them\");\n if (this.closed) return;\n\n this.buffered = [...batch, ...this.buffered];\n this.logger.warn(\n { err: error, jobResults: batch.length },\n \"[ravenflow] job results could not be written; they are kept for the next flush.\",\n );\n }\n\n private async flushUntil(deadline: number): Promise<void> {\n while (this.unwritten() > 0 && Date.now() < deadline) {\n await untilDeadline(this.flush(), deadline);\n if (this.unwritten() > 0) {\n await pause(\n Math.min(PAUSE_BETWEEN_FINAL_FLUSHES_MS, deadline - Date.now()),\n );\n }\n }\n }\n\n private dropWhatIsLeft(): void {\n const left = this.unwritten();\n this.buffered = [];\n if (left === 0) return;\n this.reportLost(\n left,\n `the final flush gave up after ${MONGODB_DEADLINE_ON_CLOSE_MS}ms`,\n );\n }\n\n private reportLost(count: number, why: string): void {\n this.logger.error(\n { lost: count },\n `[ravenflow] ${count} job results were not written: ${why}.`,\n );\n }\n}\n\nfunction countRefusedByMongo(error: unknown): number {\n if (!(error instanceof MongoBulkWriteError)) return 0;\n return [error.writeErrors].flat().length;\n}\n\nfunction untilDeadline(work: Promise<void>, deadline: number): Promise<void> {\n return Promise.race([work, pause(deadline - Date.now())]);\n}\n\nfunction pause(ms: number): Promise<void> {\n return new Promise((resolve) => {\n setTimeout(resolve, Math.max(0, ms)).unref();\n });\n}\n","import type { Collection, Db, IndexDescription } from \"mongodb\";\n\nimport type { JobResult } from \"./job-result\";\n\nconst JOB_RESULTS_COLLECTION = \"rav:job-results\";\n\nconst SECONDS_PER_HOUR = 3_600;\n\nconst ON_FINISHED_AT = { finishedAt: 1 } as const;\n\nconst QUERY_INDEXES: IndexDescription[] = [\n { key: { jobName: 1, finishedAt: -1 } },\n { key: { status: 1, finishedAt: -1 } },\n];\n\nexport function jobResultsCollection(db: Db): Collection<JobResult> {\n return db.collection<JobResult>(JOB_RESULTS_COLLECTION);\n}\n\nexport async function indexJobResults(\n db: Db,\n retentionHours: number,\n): Promise<void> {\n await jobResultsCollection(db).createIndexes(QUERY_INDEXES);\n await expireJobResultsAfter(db, retentionHours * SECONDS_PER_HOUR);\n}\n\nasync function expireJobResultsAfter(db: Db, seconds: number): Promise<void> {\n const collection = jobResultsCollection(db);\n const index = await indexOnFinishedAt(collection);\n if (index === undefined) return createExpiryIndex(collection, seconds);\n if (index.expireAfterSeconds !== seconds) await changeExpiry(db, seconds);\n}\n\nasync function createExpiryIndex(\n collection: Collection<JobResult>,\n seconds: number,\n): Promise<void> {\n await collection.createIndex(ON_FINISHED_AT, { expireAfterSeconds: seconds });\n}\n\nasync function changeExpiry(db: Db, seconds: number): Promise<void> {\n await db.command({\n collMod: JOB_RESULTS_COLLECTION,\n index: { keyPattern: ON_FINISHED_AT, expireAfterSeconds: seconds },\n });\n}\n\nasync function indexOnFinishedAt(collection: Collection<JobResult>) {\n const indexes = await collection.indexes();\n return indexes.find((index) => isOnFinishedAtAlone(index.key));\n}\n\nfunction isOnFinishedAtAlone(key: Record<string, unknown>): boolean {\n const fields = Object.keys(key);\n return fields.length === 1 && key.finishedAt === 1;\n}\n","import { DelayedError, type Job } from \"bullmq\";\nimport type { ControlReads } from \"@/control-plane\";\n\nconst DEFERRED_FOR_MS = 60_000;\n\nexport interface ExecutionGateRuntime {\n controls: ControlReads;\n token: string | undefined;\n}\n\nexport async function deferIfItsExecutionIsPaused(\n job: Job,\n runtime: ExecutionGateRuntime,\n): Promise<void> {\n const { executionPaused } = await runtime.controls.read(job.name);\n if (executionPaused) await deferTheJob(job, runtime.token);\n}\n\nasync function deferTheJob(\n job: Job,\n token: string | undefined,\n): Promise<never> {\n await job.moveToDelayed(Date.now() + DEFERRED_FOR_MS, token);\n throw new DelayedError();\n}\n","import { DelayedError, Worker, type Job, type Queue } from \"bullmq\";\nimport { spacingMsOf, type PacePolicy } from \"@/job\";\n\nconst US_PER_MS = 1_000;\n\nconst KEPT_PAST_THE_LAST_TURN_MS = 10_000;\n\nconst A_TURN_MAY_BE_LATE_BY_MS = 25;\n\nconst SLEPT_IN_PROCESS_UNDER_MS = 500;\n\nconst TAKE_A_TURN = `\nlocal at = redis.call('TIME')\nlocal now = tonumber(at[1]) * 1000000 + tonumber(at[2])\nlocal spacing = tonumber(ARGV[1])\nlocal mayBeLateBy = tonumber(ARGV[2])\nlocal sleptUnder = tonumber(ARGV[3])\nlocal keptMs = tonumber(ARGV[4])\nlocal turn = tonumber(redis.call('HGET', KEYS[2], 'ravPaceTurn'))\nif turn == nil or now - turn > mayBeLateBy then\n turn = tonumber(redis.call('GET', KEYS[1])) or now\n if turn < now then turn = now end\n local untilTheLastTurnMs = math.ceil((turn + spacing - now) / 1000)\n redis.call('SET', KEYS[1], turn + spacing, 'PX', untilTheLastTurnMs + keptMs)\nend\nlocal wait = turn - now\nif wait >= sleptUnder then\n redis.call('HSET', KEYS[2], 'ravPaceTurn', turn)\n return wait\nend\nredis.call('HDEL', KEYS[2], 'ravPaceTurn')\nif wait < 0 then return 0 end\nreturn wait\n`;\n\ninterface PaceRuntime {\n queue: Queue;\n token: string | undefined;\n shutdown: AbortSignal;\n}\n\nexport async function waitForItsTurn(\n job: Job,\n pace: PacePolicy | undefined,\n runtime: PaceRuntime,\n): Promise<void> {\n if (pace === undefined) return;\n if (runtime.shutdown.aborted) return handBackToWait();\n const waitMs = await takeATurn(job, spacingMsOf(pace), runtime.queue);\n if (waitMs >= SLEPT_IN_PROCESS_UNDER_MS) {\n return putOffInDelayed(job, waitMs - SLEPT_IN_PROCESS_UNDER_MS, runtime);\n }\n await sleep(waitMs, runtime.shutdown);\n if (runtime.shutdown.aborted) return handBackToWait();\n}\n\nasync function takeATurn(\n job: Job,\n spacingMs: number,\n queue: Queue,\n): Promise<number> {\n const client = await queue.client;\n const waitUs = await client.eval(\n TAKE_A_TURN,\n 2,\n queue.toKey(`rav:pace:${job.name}`),\n queue.toKey(String(job.id)),\n microseconds(spacingMs),\n microseconds(A_TURN_MAY_BE_LATE_BY_MS),\n microseconds(SLEPT_IN_PROCESS_UNDER_MS),\n String(KEPT_PAST_THE_LAST_TURN_MS),\n );\n return Number(waitUs) / US_PER_MS;\n}\n\nfunction microseconds(ms: number): string {\n return String(Math.round(ms * US_PER_MS));\n}\n\nasync function putOffInDelayed(\n job: Job,\n delayMs: number,\n runtime: PaceRuntime,\n): Promise<never> {\n await job.moveToDelayed(Date.now() + delayMs, runtime.token);\n throw new DelayedError();\n}\n\nfunction handBackToWait(): never {\n throw Worker.RateLimitError();\n}\n\nfunction sleep(ms: number, shutdown: AbortSignal): Promise<void> {\n return new Promise((resolve) => {\n const timer = setTimeout(wakeUp, ms);\n shutdown.addEventListener(\"abort\", wakeUp, { once: true });\n\n function wakeUp(): void {\n clearTimeout(timer);\n shutdown.removeEventListener(\"abort\", wakeUp);\n resolve();\n }\n });\n}\n","export interface ExecutionSignal {\n signal: AbortSignal;\n detach(): void;\n}\n\nexport function attachExecutionSignal(shutdown: AbortSignal): ExecutionSignal {\n const execution = new AbortController();\n const abort = () => execution.abort(shutdown.reason);\n\n if (shutdown.aborted) abort();\n else shutdown.addEventListener(\"abort\", abort, { once: true });\n\n return {\n signal: execution.signal,\n detach: () => shutdown.removeEventListener(\"abort\", abort),\n };\n}\n","import type { Job } from \"bullmq\";\nimport { format, inspect } from \"node:util\";\nimport type { Logger } from \"@/logger\";\n\ntype LogMethod = (...args: unknown[]) => void;\n\ntype ChildMethod = (...args: unknown[]) => Logger;\n\ntype Fields = Record<string, unknown>;\n\nexport function loggerFor(job: Job, logger: Logger): Logger {\n return new JobLogCopier(job).copyingLines(logger.child({ job: job.name }));\n}\n\nclass JobLogCopier {\n constructor(private readonly job: Job) {}\n\n copyingLines(logger: Logger): Logger {\n return new Proxy(logger, {\n get: (target, property) => {\n const value = Reflect.get(target, property);\n if (property === \"child\") {\n return this.childCopyingLines(target, value as ChildMethod);\n }\n if (!isLevelOf(target, property)) return value;\n return this.levelCopyingLines(target, property, value as LogMethod);\n },\n });\n }\n\n private childCopyingLines(parent: Logger, child: ChildMethod): ChildMethod {\n return (...args) => this.copyingLines(child.apply(parent, args));\n }\n\n private levelCopyingLines(\n logger: Logger,\n level: string,\n log: LogMethod,\n ): LogMethod {\n return (...args) => {\n log.apply(logger, args);\n if (!logger.isLevelEnabled(level)) return;\n this.copyLine(logger, lineOf(level, args, contextOf(logger)));\n };\n }\n\n private copyLine(logger: Logger, line: string): void {\n this.job.log(line).catch((error: unknown) => {\n logger.warn(\n { err: error },\n \"[ravenflow] a log line could not be copied into the job's logs.\",\n );\n });\n }\n}\n\nfunction isLevelOf(\n logger: Logger,\n property: string | symbol,\n): property is string {\n return (\n typeof property === \"string\" &&\n Object.keys(logger.levels.values).includes(property)\n );\n}\n\nfunction contextOf(logger: Logger): Fields {\n const bindings = Object.entries(logger.bindings());\n return Object.fromEntries(bindings.filter(([key]) => key !== \"job\"));\n}\n\nfunction lineOf(level: string, args: unknown[], context: Fields): string {\n const { message, fields } = partsOf(args, context);\n const time = `[${utcTimeOfDay(new Date())}]`;\n const words = [time, `${level.toUpperCase()}:`, message, inlined(fields)];\n return words.filter((word) => word !== \"\").join(\" \");\n}\n\nfunction partsOf(\n [first, ...rest]: unknown[],\n context: Fields,\n): { message: string; fields: Fields } {\n if (first instanceof Error) {\n return { message: format(...rest), fields: { ...context, err: first } };\n }\n if (typeof first === \"object\" && first !== null) {\n return { message: format(...rest), fields: { ...context, ...first } };\n }\n return { message: format(first, ...rest), fields: context };\n}\n\nfunction inlined(fields: Fields): string {\n if (Object.keys(fields).length === 0) return \"\";\n return inspect(fields, { breakLength: Infinity });\n}\n\nfunction utcTimeOfDay(date: Date): string {\n return date.toISOString().slice(11, 23);\n}\n","import type { Job } from \"bullmq\";\nimport type { ChainableCommander } from \"ioredis\";\nimport { deduplicationIdOf } from \"@/job\";\n\nconst RELEASE_IF_THE_LINK_HOLDS_IT = `\nif redis.call(\"GET\", KEYS[1]) == ARGV[1] then\n return redis.call(\"DEL\", KEYS[1])\nend\nreturn 0`;\n\nexport function deduplicationIdHeldBy(job: Job): string | undefined {\n const namespacedId = job.deduplicationId;\n if (namespacedId === undefined) return undefined;\n return deduplicationIdOf(job.name, namespacedId);\n}\n\nexport function releaseTheHoldOf(\n job: Job,\n transaction: ChainableCommander,\n): void {\n const namespacedId = job.deduplicationId;\n if (namespacedId === undefined) return;\n transaction.eval(\n RELEASE_IF_THE_LINK_HOLDS_IT,\n 1,\n `${job.queueQualifiedName}:de:${namespacedId}`,\n String(job.id),\n );\n}\n","import { Job, type JobsOptions, type Queue, type RedisClient } from \"bullmq\";\nimport type { ChainableCommander } from \"ioredis\";\nimport { namespacedDeduplicationId, type Continuation } from \"@/job\";\nimport { buildJobOptions, nextLinkIdOf } from \"@/queues\";\nimport { isALinkOfAnItem, ItemRuns } from \"@/spools\";\n\nimport type { Link } from \"./link\";\nimport { releaseTheHoldOf } from \"./link-deduplication\";\n\ninterface NextLink {\n jobName: string;\n id: string;\n params: unknown;\n options: JobsOptions;\n}\n\nexport async function enqueueNextLink(\n { job, definition }: Link,\n next: Continuation<unknown>,\n queue: Queue,\n): Promise<void> {\n const nextLink = nextLinkOf({ job, definition }, next);\n const spoolName = definition.trigger?.spool?.name;\n if (spoolName !== undefined && isALinkOfAnItem(spoolName, nextLink.id)) {\n refuseAnIdForTheRunOfAnItem(nextLink, next);\n await new ItemRuns(queue, spoolName).goOnTo(nextLink.id);\n }\n await addTheNextLink(job, nextLink, queue);\n}\n\nfunction nextLinkOf(\n { job, definition }: Link,\n next: Continuation<unknown>,\n): NextLink {\n const id = nextLinkIdOf(String(job.id));\n const options: JobsOptions = { ...buildJobOptions(definition), jobId: id };\n if (next.delayMs !== undefined) options.delay = next.delayMs;\n if (next.deduplicationId !== undefined) {\n const namespacedId = namespacedDeduplicationId(\n job.name,\n next.deduplicationId,\n );\n options.deduplication = { id: namespacedId };\n }\n return { jobName: job.name, id, params: next.params, options };\n}\n\nfunction refuseAnIdForTheRunOfAnItem(\n nextLink: NextLink,\n next: Continuation<unknown>,\n): void {\n if (next.deduplicationId === undefined) return;\n throw new Error(\n `[ravenflow] \"${nextLink.jobName}\" passes the deduplication id \"${next.deduplicationId}\" on to the next link of a spool item's run, but an item's run holds no deduplication id: each item runs under a job id of its own.`,\n );\n}\n\nasync function addTheNextLink(\n job: Job,\n nextLink: NextLink,\n queue: Queue,\n): Promise<void> {\n const transaction = (await queue.client).multi();\n releaseTheHoldOf(job, transaction);\n await addWithin(transaction, jobOf(nextLink, queue));\n await commit(transaction, nextLink);\n}\n\nfunction jobOf(nextLink: NextLink, queue: Queue): Job {\n const options = { ...queue.defaultJobOptions, ...nextLink.options };\n return new Job(\n queue,\n nextLink.jobName,\n nextLink.params,\n options,\n nextLink.id,\n );\n}\n\nasync function addWithin(\n transaction: ChainableCommander,\n job: Job,\n): Promise<void> {\n await job.addJob(transaction as unknown as RedisClient);\n}\n\nasync function commit(\n transaction: ChainableCommander,\n nextLink: NextLink,\n): Promise<void> {\n const replies = (await transaction.exec()) ?? [];\n for (const [error] of replies) {\n if (error !== null) throw nextLinkNotEnqueued(nextLink, error);\n }\n}\n\nfunction nextLinkNotEnqueued(nextLink: NextLink, cause: Error): Error {\n return new Error(\n `[ravenflow] the next link of \"${nextLink.jobName}\", ${nextLink.id}, could not be enqueued: ${cause.message}`,\n );\n}\n","import type { Job, Queue } from \"bullmq\";\nimport { continueWith, isContinuation, type JobContext } from \"@/job\";\nimport type { Logger } from \"@/logger\";\n\nimport { attachExecutionSignal } from \"./execution-signal\";\nimport { loggerFor } from \"./job-logger\";\nimport type { Link } from \"./link\";\nimport { deduplicationIdHeldBy } from \"./link-deduplication\";\nimport { enqueueNextLink } from \"./next-link\";\n\nexport interface LinkRuntime {\n shutdown: AbortSignal;\n logger: Logger;\n queue: Queue;\n}\n\nexport async function runLink(\n link: Link,\n runtime: LinkRuntime,\n): Promise<unknown> {\n const outcome = await callHandler(link, runtime);\n if (isContinuation(outcome)) {\n await enqueueNextLink(link, outcome, runtime.queue);\n return undefined;\n }\n return outcome;\n}\n\nasync function callHandler(\n { job, definition }: Link,\n runtime: LinkRuntime,\n): Promise<unknown> {\n const execution = attachExecutionSignal(runtime.shutdown);\n try {\n return await definition.handler(\n contextFor(job, runtime.logger, execution.signal),\n );\n } finally {\n execution.detach();\n }\n}\n\nfunction contextFor(\n job: Job,\n logger: Logger,\n signal: AbortSignal,\n): JobContext<never> {\n return {\n params: job.data as never,\n deduplicationId: deduplicationIdHeldBy(job),\n job,\n logger: loggerFor(job, logger),\n signal,\n continueWith,\n };\n}\n","import type { Job } from \"bullmq\";\n\nconst SKIPPED_BY_TRIGGER_PAUSE = \"skippedByTriggerPause\";\n\ntype Progress = Record<string, unknown>;\n\nexport function wasSkippedByATriggerPause(job: Job): boolean {\n return progressOf(job)[SKIPPED_BY_TRIGGER_PAUSE] === true;\n}\n\nexport async function markSkippedByATriggerPause(job: Job): Promise<void> {\n await job.updateProgress({\n ...progressOf(job),\n [SKIPPED_BY_TRIGGER_PAUSE]: true,\n });\n}\n\nfunction progressOf(job: Job): Progress {\n const { progress } = job;\n if (typeof progress !== \"object\" || progress === null) return {};\n return progress as Progress;\n}\n","import type { Job } from \"bullmq\";\nimport type { ControlReads } from \"@/control-plane\";\nimport type { Logger } from \"@/logger\";\n\nimport { markSkippedByATriggerPause } from \"./progress-marks\";\n\nexport async function isAnOccurrenceToSkip(\n job: Job,\n controls: ControlReads,\n): Promise<boolean> {\n return (\n wasProducedByItsScheduler(job) &&\n (await controls.read(job.name)).triggerPaused\n );\n}\n\nexport async function skipTheOccurrence(\n job: Job,\n logger: Logger,\n): Promise<void> {\n try {\n await markSkippedByATriggerPause(job);\n } catch (error) {\n warnOfAnUnmarkedSkip(job, error, logger);\n }\n}\n\nfunction wasProducedByItsScheduler(job: Job): boolean {\n return job.repeatJobKey !== undefined;\n}\n\nfunction warnOfAnUnmarkedSkip(job: Job, error: unknown, logger: Logger): void {\n logger.warn(\n { err: error, jobId: job.id },\n `[ravenflow] an occurrence of \"${job.name}\" was skipped, its trigger being paused, but the mark on it was not written to Redis.`,\n );\n}\n","import type { Job, Processor } from \"bullmq\";\nimport type { ControlReads } from \"@/control-plane\";\nimport type { AnyJob } from \"@/job\";\n\nimport type { JobResultsRecorder } from \"../job-results-recorder\";\n\nimport { deferIfItsExecutionIsPaused } from \"./execution-gate\";\nimport { waitForItsTurn } from \"./pace-gate\";\nimport { runLink, type LinkRuntime } from \"./run-link\";\nimport { isAnOccurrenceToSkip, skipTheOccurrence } from \"./trigger-gate\";\n\nexport interface RouterRuntime extends LinkRuntime {\n jobs: Record<string, AnyJob>;\n controls: ControlReads;\n jobResultsRecorder: Pick<JobResultsRecorder, \"waitForRoom\">;\n}\n\nexport function routeByName(runtime: RouterRuntime): Processor {\n const declared = new Map(Object.entries(runtime.jobs));\n\n return async (job: Job, token?: string) => {\n const definition = declared.get(job.name);\n if (!definition) throw undeclaredJobError(job);\n if (await isAnOccurrenceToSkip(job, runtime.controls)) {\n return skipTheOccurrence(job, runtime.logger);\n }\n await deferIfItsExecutionIsPaused(job, {\n controls: runtime.controls,\n token,\n });\n await runtime.jobResultsRecorder.waitForRoom();\n await waitForItsTurn(job, definition.pace, {\n queue: runtime.queue,\n token,\n shutdown: runtime.shutdown,\n });\n startItsClock(job);\n return runLink({ job, definition }, runtime);\n };\n}\n\nfunction startItsClock(job: Job): void {\n job.processedOn = Date.now();\n}\n\nfunction undeclaredJobError(job: Job): Error {\n return new Error(\n `[ravenflow] \"${job.name}\" is not declared on \"${job.queueName}\", the queue this worker serves, so it has no handler to run.`,\n );\n}\n","export const JOB_RESULT_MAX_BYTES = 128 * 1024;\n\nexport const JOB_RESULT_MESSAGE_MAX_CHARS = 2000;\n\nexport const JOB_RESULT_STACK_MAX_CHARS = 8000;\n\nexport const JOB_RESULT_LOGS_MAX_CHARS = 500_000;\n","import type { Logger } from \"@/logger\";\n\nexport interface CauseChainEntry {\n message: string;\n name: string;\n}\n\nexport interface ExtractedError {\n /** Top-level message + \"\\nCaused by: \" + inner.message chain, truncated after joining. */\n message: string;\n /** Top-level stack trace only, truncated. Inner stacks are omitted to bound payload. */\n stack: string;\n /** Normalized chain beyond the top level. Empty array when the top Error has no `cause`. */\n causeChain: CauseChainEntry[];\n}\n\nexport interface ExtractMessageAndStackOptions {\n messageMaxChars: number;\n stackMaxChars: number;\n /** Depth cap to guard against cycles and pathological nesting. Default 5. */\n maxCauseDepth?: number;\n}\n\nconst DEFAULT_MAX_CAUSE_DEPTH = 5;\nconst NAME_MAX_CHARS = 64;\nconst CHAIN_SEPARATOR = \"\\nCaused by: \";\n\nfunction truncate(value: string, max: number): string {\n return value.length <= max ? value : value.slice(0, max);\n}\n\nfunction safeGet<T>(getter: () => T, fallback: T): T {\n try {\n return getter();\n } catch {\n return fallback;\n }\n}\n\nfunction isErrorLike(\n value: unknown,\n): value is { message: unknown; name?: unknown } {\n if (typeof value !== \"object\" || value === null) return false;\n return safeGet(() => \"message\" in value, false);\n}\n\nfunction normalizeEntry(\n value: unknown,\n messageMaxChars: number,\n): CauseChainEntry {\n const entryMax = Math.max(1, Math.floor(messageMaxChars / 2));\n if (isErrorLike(value)) {\n const rawMessage = safeGet<unknown>(\n () => (value as { message: unknown }).message,\n undefined,\n );\n const rawName = safeGet<unknown>(\n () => (value as { name?: unknown }).name,\n undefined,\n );\n const message = truncate(\n typeof rawMessage === \"string\"\n ? rawMessage\n : safeGet(() => String(rawMessage), \"\"),\n entryMax,\n );\n const name = truncate(\n typeof rawName === \"string\" ? rawName : \"Error\",\n NAME_MAX_CHARS,\n );\n return { message, name };\n }\n return {\n message: truncate(\n safeGet(() => String(value), \"\"),\n entryMax,\n ),\n name: \"NonError\",\n };\n}\n\nfunction walkCauseChain(\n top: { cause?: unknown },\n maxDepth: number,\n messageMaxChars: number,\n): { chain: CauseChainEntry[]; truncated: boolean } {\n const chain: CauseChainEntry[] = [];\n const seen = new WeakSet<object>();\n if (typeof top === \"object\" && top !== null) seen.add(top);\n\n let current: unknown = safeGet<unknown>(() => top.cause, undefined);\n let truncated = false;\n\n while (current !== undefined && current !== null) {\n if (chain.length >= maxDepth) {\n truncated = true;\n break;\n }\n if (typeof current === \"object\" && current !== null) {\n if (seen.has(current)) {\n truncated = true;\n break;\n }\n seen.add(current);\n }\n\n chain.push(normalizeEntry(current, messageMaxChars));\n\n const hasCause =\n typeof current === \"object\" &&\n current !== null &&\n safeGet(() => \"cause\" in (current as object), false);\n if (hasCause) {\n current = safeGet(\n () => (current as { cause?: unknown }).cause,\n undefined,\n );\n } else {\n break;\n }\n }\n\n return { chain, truncated };\n}\n\nexport function extractMessageAndStack(\n err: unknown,\n options: ExtractMessageAndStackOptions,\n logger: Logger,\n): ExtractedError {\n const { messageMaxChars, stackMaxChars } = options;\n const rawMaxDepth = options.maxCauseDepth ?? DEFAULT_MAX_CAUSE_DEPTH;\n const maxCauseDepth =\n Number.isFinite(rawMaxDepth) && rawMaxDepth >= 1\n ? Math.floor(rawMaxDepth)\n : DEFAULT_MAX_CAUSE_DEPTH;\n\n if (!(err instanceof Error)) {\n return {\n message: truncate(\n safeGet(() => String(err), \"\"),\n messageMaxChars,\n ),\n stack: \"\",\n causeChain: [],\n };\n }\n\n const topMessage = safeGet<string>(() => {\n const m = err.message;\n return typeof m === \"string\" ? m : String(m ?? \"\");\n }, \"\");\n const topStack = safeGet<string>(() => {\n const s = err.stack;\n return typeof s === \"string\" ? s : String(s ?? \"\");\n }, \"\");\n\n const { chain, truncated } = walkCauseChain(\n err as { cause?: unknown },\n maxCauseDepth,\n messageMaxChars,\n );\n\n if (truncated) {\n logger.warn(\n { topMessage: truncate(topMessage, 120) },\n \"extractMessageAndStack: maxCauseDepth reached, truncating cause chain.\",\n );\n }\n\n let joinedMessage = topMessage;\n for (const entry of chain) {\n joinedMessage += `${CHAIN_SEPARATOR}${entry.message}`;\n }\n\n return {\n message: truncate(joinedMessage, messageMaxChars),\n stack: truncate(topStack, stackMaxChars),\n causeChain: chain,\n };\n}\n","import { BSON } from \"mongodb\";\n\n/**\n * What a job handed in or handed back, made safe to store as **native BSON**\n * rather than as a serialised string — so `params.tenantId` is a field a query\n * can filter on instead of a substring to grep (D15).\n *\n * The value space is JSON's, whatever the handler declared: BullMQ holds `data`\n * and `returnvalue` as JSON in Redis, so a `Date` is already a string and a\n * `Map` already `{}` by the time this sees them.\n */\n\n/**\n * Whether to write the field at all, and what to write.\n *\n * `stored: false` rather than a sentinel value, because a field set to\n * `undefined` is one BSON drops — leaving a document whose missing key cannot\n * be told from one written before the key existed.\n */\nexport type Storable = { stored: true; value: unknown } | { stored: false };\n\n/**\n * The value to store, the marker that replaces it, or nothing.\n *\n * Two things a JSON value can be that BSON must not hold, and both are answered\n * by **replacing the whole value** rather than repairing it. A repaired value\n * is the failure this collection exists to end: a document that looks like the\n * truth and is not.\n *\n * `maxBytes` is measured in the bytes BSON will occupy, not in characters: the\n * cap bounds a document, and a document is bytes.\n */\nexport function storableValue(value: unknown, maxBytes: number): Storable {\n if (value === undefined) return { stored: false };\n\n const hostile = firstHostileKey(value);\n if (hostile !== null) {\n return {\n stored: true,\n value: { __ravenflow_omitted: true, hostileKey: hostile },\n };\n }\n\n const bytes = bsonBytesOf(value);\n if (bytes > maxBytes) {\n return { stored: true, value: { __ravenflow_omitted: true, bytes } };\n }\n\n return { stored: true, value };\n}\n\n/**\n * The first key BSON would store but nobody could query, or `null`.\n *\n * **Refused, not sanitised**, and the choice is load-bearing. Rewriting\n * `user.name` to `user_name` keeps the document and breaks the question: a\n * filter on the key the payload actually had comes back empty, which reads as\n * *\"no execution was given that\"* rather than as *\"this was not stored\"*. An\n * absent value asks to be looked into; a renamed one does not.\n *\n * A dot is the path separator every filter is written in, and a leading `$` is\n * how every update operator announces itself. A `$` anywhere else is ordinary.\n */\nfunction firstHostileKey(value: unknown): string | null {\n if (Array.isArray(value)) {\n for (const element of value) {\n const hostile = firstHostileKey(element);\n if (hostile !== null) return hostile;\n }\n return null;\n }\n\n if (value === null || typeof value !== \"object\") return null;\n\n for (const [key, nested] of Object.entries(value)) {\n if (key.includes(\".\") || key.startsWith(\"$\")) return key;\n const hostile = firstHostileKey(nested);\n if (hostile !== null) return hostile;\n }\n return null;\n}\n\n/**\n * Wrapped in a document because `calculateObjectSize` sizes documents and a\n * scalar is not one. The wrapper's overhead is counted, which errs a handful of\n * bytes towards refusing — the safe direction for a cap.\n */\nfunction bsonBytesOf(value: unknown): number {\n return BSON.calculateObjectSize({ v: value });\n}\n","import type { Job } from \"bullmq\";\nimport type { Logger } from \"@/logger\";\n\nimport { extractMessageAndStack } from \"./error-extraction\";\nimport {\n JOB_RESULT_MAX_BYTES,\n JOB_RESULT_MESSAGE_MAX_CHARS,\n JOB_RESULT_STACK_MAX_CHARS,\n} from \"./job-result-limits\";\nimport { storableValue } from \"./storable-value\";\n\nexport interface JobResult {\n jobName: string;\n queue: string;\n status: JobResultStatus;\n params?: unknown;\n result?: unknown;\n error?: JobResultError;\n logs?: string;\n finishedAt: Date;\n durationMs?: number;\n attemptsMade: number;\n}\n\nexport type JobResultStatus = \"succeeded\" | \"failed\";\n\nexport interface JobResultError {\n message: string;\n stack: string;\n causeChain?: Array<{ message: string; name: string }>;\n}\n\nexport function succeededJobResult(\n job: Job,\n result: unknown,\n logs: string,\n): JobResult {\n return {\n ...jobResultOf(job, logs),\n status: \"succeeded\",\n result: stored(result),\n error: lastErrorOf(job),\n };\n}\n\nexport function failedJobResult(\n job: Job,\n error: JobResultError,\n logs: string,\n): JobResult {\n return { ...jobResultOf(job, logs), status: \"failed\", error };\n}\n\nexport function willBeRetried(job: Job): boolean {\n return job.finishedOn === undefined;\n}\n\nexport function jobResultErrorOf(\n error: unknown,\n logger: Logger,\n): JobResultError {\n const { message, stack, causeChain } = extractMessageAndStack(\n error,\n {\n messageMaxChars: JOB_RESULT_MESSAGE_MAX_CHARS,\n stackMaxChars: JOB_RESULT_STACK_MAX_CHARS,\n },\n logger,\n );\n return {\n message,\n stack,\n causeChain: causeChain.length > 0 ? causeChain : undefined,\n };\n}\n\nfunction jobResultOf(job: Job, logs: string): Omit<JobResult, \"status\"> {\n return {\n jobName: job.name,\n queue: job.queueName,\n params: isNothing(job.data) ? undefined : stored(job.data),\n logs: logs === \"\" ? undefined : logs,\n finishedAt: finishedAtOf(job),\n durationMs: durationOf(job),\n attemptsMade: job.attemptsMade,\n };\n}\n\nfunction stored(value: unknown): unknown {\n const storable = storableValue(value, JOB_RESULT_MAX_BYTES);\n return storable.stored ? storable.value : undefined;\n}\n\nfunction isNothing(value: unknown): boolean {\n if (value === undefined || value === null) return true;\n if (typeof value !== \"object\" || Array.isArray(value)) return false;\n return Object.keys(value).length === 0;\n}\n\nfunction lastErrorOf(job: Job): JobResultError | undefined {\n if (!job.failedReason) return undefined;\n const stacks = job.stacktrace ?? [];\n return {\n message: job.failedReason.slice(0, JOB_RESULT_MESSAGE_MAX_CHARS),\n stack: (stacks[stacks.length - 1] ?? \"\").slice(\n 0,\n JOB_RESULT_STACK_MAX_CHARS,\n ),\n };\n}\n\nfunction finishedAtOf(job: Job): Date {\n return job.finishedOn === undefined ? new Date() : new Date(job.finishedOn);\n}\n\nfunction durationOf(job: Job): number | undefined {\n if (job.processedOn === undefined || job.finishedOn === undefined) {\n return undefined;\n }\n return job.finishedOn - job.processedOn;\n}\n","import type { Queue } from \"bullmq\";\nimport type { Logger } from \"@/logger\";\n\nexport async function captureJobLogs(\n queue: Queue,\n jobId: string,\n maxChars: number,\n logger: Logger,\n): Promise<string> {\n if (typeof jobId !== \"string\" || jobId.length === 0) {\n throw new Error(\"captureJobLogs: jobId must be a non-empty string\");\n }\n if (!Number.isInteger(maxChars) || maxChars <= 0) {\n throw new Error(\n `captureJobLogs: maxChars must be a positive integer, got ${maxChars}`,\n );\n }\n\n let logs: string[];\n try {\n const result = await queue.getJobLogs(jobId, 0, -1, true);\n logs = result.logs;\n } catch (err) {\n logger.warn(\n { err, jobId },\n \"[log-capture] failed to fetch job logs — returning empty string\",\n );\n return \"\";\n }\n\n const joined = logs.join(\"\\n\");\n if (joined.length <= maxChars) return joined;\n\n const originalLen = joined.length;\n let tailLen = maxChars;\n let marker = \"\";\n for (let i = 0; i < 3; i++) {\n marker = `[truncated — showing last ${tailLen} of ${originalLen} chars]\\n`;\n if (marker.length >= maxChars) {\n return marker.slice(0, maxChars);\n }\n tailLen = maxChars - marker.length;\n }\n return marker + joined.slice(-tailLen);\n}\n","import type { Job, Queue, Worker } from \"bullmq\";\nimport type { AnyJob } from \"@/job\";\nimport type { Logger } from \"@/logger\";\n\nimport { wasSkippedByATriggerPause } from \"../job-router\";\n\nimport type { BatchWriter } from \"./batch-writer\";\nimport { JOB_RESULT_LOGS_MAX_CHARS } from \"./job-result-limits\";\nimport {\n failedJobResult,\n jobResultErrorOf,\n succeededJobResult,\n willBeRetried,\n} from \"./job-result\";\nimport { captureJobLogs } from \"./log-capture\";\n\nexport interface JobResultsListenerSettings {\n queue: Queue;\n jobs: Record<string, AnyJob>;\n logger: Logger;\n batchWriter: Pick<BatchWriter, \"add\">;\n}\n\nexport class JobResultsListener {\n private readonly declared: Set<string>;\n private readonly resultsInProgress = new Set<Promise<void>>();\n\n constructor(private readonly settings: JobResultsListenerSettings) {\n this.declared = new Set(Object.keys(settings.jobs));\n }\n\n listenTo(worker: Worker): void {\n worker.on(\"completed\", (job, result) => {\n if (wasSkippedByATriggerPause(job)) return;\n this.recordIfDeclared(job, () => this.recordSuccess(job, result));\n });\n worker.on(\"failed\", (job, error) => {\n if (job === undefined || willBeRetried(job)) return;\n this.recordIfDeclared(job, () => this.recordFailure(job, error));\n });\n }\n\n async waitForResultsInProgress(): Promise<void> {\n while (this.resultsInProgress.size > 0) {\n await Promise.allSettled([...this.resultsInProgress]);\n }\n }\n\n private recordIfDeclared(job: Job, record: () => Promise<void>): void {\n if (!this.declared.has(job.name)) return;\n this.track(job, record);\n }\n\n private track(job: Job, record: () => Promise<void>): void {\n const inProgress = record()\n .catch((error: unknown) => this.warnOfALostResult(job, error))\n .finally(() => this.resultsInProgress.delete(inProgress));\n this.resultsInProgress.add(inProgress);\n }\n\n private async recordSuccess(job: Job, result: unknown): Promise<void> {\n const logs = await this.logsOf(job);\n this.settings.batchWriter.add(succeededJobResult(job, result, logs));\n }\n\n private async recordFailure(job: Job, error: Error): Promise<void> {\n const logs = await this.logsOf(job);\n const failure = jobResultErrorOf(error, this.settings.logger);\n this.settings.batchWriter.add(failedJobResult(job, failure, logs));\n }\n\n private async logsOf(job: Job): Promise<string> {\n return captureJobLogs(\n this.settings.queue,\n String(job.id),\n JOB_RESULT_LOGS_MAX_CHARS,\n this.settings.logger,\n );\n }\n\n private warnOfALostResult(job: Job, error: unknown): void {\n this.settings.logger.warn(\n { err: error, jobId: job.id },\n `[ravenflow] the job result of \"${job.name}\" #${job.id} could not be recorded.`,\n );\n }\n}\n","import type { Queue, Worker } from \"bullmq\";\nimport type { AnyJob } from \"@/job\";\nimport type { Logger } from \"@/logger\";\nimport { MongoConnection } from \"@/mongo/connection\";\n\nimport { BatchWriter } from \"./batch-writer\";\nimport {\n indexJobResults,\n jobResultsCollection,\n} from \"./job-results-collection\";\nimport { JobResultsListener } from \"./job-results-listener\";\n\nexport interface JobResultsRecorderSettings {\n mongo: string;\n retentionHours: number;\n queue: Queue;\n jobs: Record<string, AnyJob>;\n logger: Logger;\n}\n\nexport type JobResultsRecorderOpening =\n | { opened: true }\n | { opened: false; because: string };\n\ninterface ActiveRecording {\n writer: BatchWriter;\n listener: JobResultsListener;\n}\n\nexport class JobResultsRecorder {\n private readonly connection: MongoConnection;\n private recording: ActiveRecording | null = null;\n\n constructor(private readonly settings: JobResultsRecorderSettings) {\n this.connection = new MongoConnection(settings.mongo);\n }\n\n async open(worker: Worker): Promise<void> {\n try {\n this.recording = await this.openRecording(worker);\n } catch (error) {\n await this.connection.close();\n throw error;\n }\n }\n\n async waitForRoom(): Promise<void> {\n await this.recording?.writer.waitForRoom();\n }\n\n stopHoldingJobs(): void {\n this.recording?.writer.stopHoldingJobs();\n }\n\n async close(): Promise<void> {\n await this.closeRecording();\n await this.connection.close();\n }\n\n private async openRecording(worker: Worker): Promise<ActiveRecording> {\n const { queue, jobs, logger } = this.settings;\n const db = await this.connection.connect();\n await indexJobResults(db, this.settings.retentionHours);\n\n const writer = new BatchWriter(jobResultsCollection(db), logger);\n const listener = new JobResultsListener({\n queue,\n jobs,\n logger,\n batchWriter: writer,\n });\n listener.listenTo(worker);\n return { writer, listener };\n }\n\n private async closeRecording(): Promise<void> {\n const recording = this.recording;\n this.recording = null;\n if (!recording) return;\n\n await recording.listener.waitForResultsInProgress();\n await recording.writer.close();\n }\n}\n","import type { Collection, Db } from \"mongodb\";\n\nconst AGGREGATED_RESULTS_COLLECTION = \"rav:aggregated-results\";\n\nconst SECONDS_PER_HOUR = 3_600;\n\nconst THE_BEGINNING = new Date(0);\n\nexport interface AggregatedResult {\n minute: Date;\n job: { name: string; queue: string };\n succeeded: number;\n failed: number;\n}\n\nexport interface Minutes {\n from: Date;\n until: Date;\n}\n\nexport async function createAggregatedResultsIfMissing(\n db: Db,\n retentionHours: number,\n): Promise<void> {\n if (await isMissing(db)) await createTimeSeries(db, retentionHours);\n}\n\nexport async function changeRetentionIfItDiffers(\n db: Db,\n retentionHours: number,\n): Promise<void> {\n if (await retentionDiffers(db, retentionHours)) {\n await changeRetention(db, retentionHours);\n }\n}\n\nexport async function watermarkOf(db: Db): Promise<Date> {\n const newest = await aggregatedResultsCollection(db).findOne(\n {},\n { sort: { minute: -1 } },\n );\n if (newest === null) return THE_BEGINNING;\n return newest.minute;\n}\n\nexport async function replaceAggregatedResults(\n db: Db,\n minutes: Minutes,\n aggregatedResults: AggregatedResult[],\n): Promise<void> {\n const collection = aggregatedResultsCollection(db);\n await collection.deleteMany({\n minute: { $gte: minutes.from, $lt: minutes.until },\n });\n if (aggregatedResults.length === 0) return;\n await collection.insertMany(aggregatedResults, {\n forceServerObjectId: true,\n });\n}\n\nasync function isMissing(db: Db): Promise<boolean> {\n return (await collectionInfoOf(db)) === undefined;\n}\n\nasync function retentionDiffers(\n db: Db,\n retentionHours: number,\n): Promise<boolean> {\n const info = await collectionInfoOf(db);\n return info?.options?.expireAfterSeconds !== secondsOf(retentionHours);\n}\n\nasync function createTimeSeries(db: Db, retentionHours: number): Promise<void> {\n await db.createCollection(AGGREGATED_RESULTS_COLLECTION, {\n timeseries: {\n timeField: \"minute\",\n metaField: \"job\",\n granularity: \"minutes\",\n },\n expireAfterSeconds: secondsOf(retentionHours),\n });\n}\n\nasync function changeRetention(db: Db, retentionHours: number): Promise<void> {\n await db.command({\n collMod: AGGREGATED_RESULTS_COLLECTION,\n expireAfterSeconds: secondsOf(retentionHours),\n });\n}\n\nasync function collectionInfoOf(db: Db) {\n const [info] = await db\n .listCollections(\n { name: AGGREGATED_RESULTS_COLLECTION },\n { nameOnly: false },\n )\n .toArray();\n return info;\n}\n\nfunction secondsOf(hours: number): number {\n return hours * SECONDS_PER_HOUR;\n}\n\nfunction aggregatedResultsCollection(db: Db): Collection<AggregatedResult> {\n return db.collection<AggregatedResult>(AGGREGATED_RESULTS_COLLECTION);\n}\n","import type { Db } from \"mongodb\";\nimport {\n jobResultsCollection,\n type JobResult,\n} from \"@/worker/job-results-recorder\";\n\nimport {\n replaceAggregatedResults,\n watermarkOf,\n type AggregatedResult,\n type Minutes,\n} from \"./aggregated-results-collection\";\n\nconst MINUTE_MS = 60_000;\n\nconst HOUR_MS = 60 * MINUTE_MS;\n\nconst COUNT_MINUTES_OLDER_THAN_MS = 2 * MINUTE_MS;\n\nconst RECOUNT_WINDOW_MS = 10 * MINUTE_MS;\n\nexport async function aggregateJobResults(\n db: Db,\n now: Date,\n retentionHours: number,\n): Promise<void> {\n const minutes = await minutesToCount(db, now, retentionHours);\n await replaceAggregatedResults(db, minutes, await countByMinute(db, minutes));\n}\n\nasync function minutesToCount(\n db: Db,\n now: Date,\n retentionHours: number,\n): Promise<Minutes> {\n const until = minuteOf(now.getTime() - COUNT_MINUTES_OLDER_THAN_MS);\n const recountFrom = new Date(until.getTime() - RECOUNT_WINDOW_MS);\n const oldestKept = minuteOf(now.getTime() - retentionHours * HOUR_MS);\n const counted = earliestOf(await watermarkOf(db), recountFrom);\n return { from: latestOf(counted, oldestKept), until };\n}\n\nasync function countByMinute(\n db: Db,\n { from, until }: Minutes,\n): Promise<AggregatedResult[]> {\n return jobResultsCollection(db)\n .aggregate<AggregatedResult>([\n { $match: { finishedAt: { $gte: from, $lt: until } } },\n {\n $group: {\n _id: {\n minute: { $dateTrunc: { date: \"$finishedAt\", unit: \"minute\" } },\n name: \"$jobName\",\n queue: \"$queue\",\n },\n succeeded: { $sum: countWhenStatusIs(\"succeeded\") },\n failed: { $sum: countWhenStatusIs(\"failed\") },\n },\n },\n {\n $project: {\n _id: 0,\n minute: \"$_id.minute\",\n job: { name: \"$_id.name\", queue: \"$_id.queue\" },\n succeeded: 1,\n failed: 1,\n },\n },\n { $sort: { minute: 1, \"job.name\": 1 } },\n ])\n .toArray();\n}\n\nfunction countWhenStatusIs(status: JobResult[\"status\"]): object {\n return { $cond: [{ $eq: [\"$status\", status] }, 1, 0] };\n}\n\nfunction minuteOf(timestamp: number): Date {\n return new Date(Math.floor(timestamp / MINUTE_MS) * MINUTE_MS);\n}\n\nfunction earliestOf(first: Date, second: Date): Date {\n return first < second ? first : second;\n}\n\nfunction latestOf(first: Date, second: Date): Date {\n return first > second ? first : second;\n}\n","import {\n Queue,\n Worker,\n type ConnectionOptions as RedisConnectionOptions,\n} from \"bullmq\";\nimport type { Db } from \"mongodb\";\nimport type { Logger } from \"@/logger\";\nimport { MongoConnection } from \"@/mongo/connection\";\n\nimport { logBullmqErrors } from \"../../log-bullmq-errors\";\nimport { waitOrCutShort } from \"../../mongodb-deadline-on-close\";\n\nimport { aggregateJobResults } from \"./aggregate-job-results\";\nimport {\n changeRetentionIfItDiffers,\n createAggregatedResultsIfMissing,\n} from \"./aggregated-results-collection\";\n\nconst AGGREGATOR_QUEUE = \"rav-internal-aggregate-results\";\n\nconst TICK_NAME = \"aggregate-results\";\n\nconst AT_THE_FIFTEENTH_SECOND = \"15 * * * * *\";\n\nconst ONE_TICK_AT_A_TIME = 1;\n\nconst TICKS_KEPT = 100;\n\nexport interface JobResultsAggregatorSettings {\n redis: RedisConnectionOptions;\n mongo: string;\n retentionHours: number;\n logger: Logger;\n}\n\ninterface Ticking {\n aggregatorQueue: Queue;\n tickWorker: Worker;\n}\n\nexport class JobResultsAggregator {\n private readonly connection: MongoConnection;\n private ticking: Ticking | null = null;\n\n constructor(private readonly settings: JobResultsAggregatorSettings) {\n this.connection = new MongoConnection(settings.mongo);\n }\n\n async open(): Promise<void> {\n const aggregatorQueue = new Queue(AGGREGATOR_QUEUE, {\n connection: this.settings.redis,\n });\n logBullmqErrors(aggregatorQueue, this.settings.logger);\n const tickWorker = this.openTickWorker();\n this.ticking = { aggregatorQueue, tickWorker };\n await aggregatorQueue.setGlobalConcurrency(ONE_TICK_AT_A_TIME);\n await scheduleTicks(aggregatorQueue);\n }\n\n async stopTicking(): Promise<void> {\n const ticking = this.ticking;\n this.ticking = null;\n if (!ticking) return;\n\n await waitOrCutShort(ticking.tickWorker.close(), () =>\n this.connection.close(),\n );\n await ticking.aggregatorQueue.close();\n }\n\n async close(): Promise<void> {\n await this.stopTicking();\n await this.connection.close();\n }\n\n private openTickWorker(): Worker {\n const worker = new Worker(AGGREGATOR_QUEUE, () => this.tick(), {\n connection: this.settings.redis,\n });\n worker.on(\"failed\", (_tick, error) => this.warnOfAFailedTick(error));\n logBullmqErrors(worker, this.settings.logger);\n return worker;\n }\n\n private async tick(): Promise<void> {\n const db = await this.connection.connect();\n const { retentionHours } = this.settings;\n await createAggregatedResultsIfMissing(db, retentionHours);\n await this.applyTheConfiguredRetention(db);\n await aggregateJobResults(db, new Date(), retentionHours);\n }\n\n private async applyTheConfiguredRetention(db: Db): Promise<void> {\n try {\n await changeRetentionIfItDiffers(db, this.settings.retentionHours);\n } catch (error) {\n this.warnOfAnUnchangedRetention(error);\n }\n }\n\n private warnOfAFailedTick(error: Error): void {\n this.settings.logger.warn(\n { err: error },\n \"[ravenflow] a tick of the job results aggregator failed; its minutes are counted by the next tick that succeeds.\",\n );\n }\n\n private warnOfAnUnchangedRetention(error: unknown): void {\n this.settings.logger.warn(\n { err: error },\n `[ravenflow] the aggregated results' retention could not be changed to ${this.settings.retentionHours} hours; they are counted all the same, and kept as long as before.`,\n );\n }\n}\n\nasync function scheduleTicks(queue: Queue): Promise<void> {\n await queue.upsertJobScheduler(\n TICK_NAME,\n { pattern: AT_THE_FIFTEENTH_SECOND },\n {\n name: TICK_NAME,\n opts: {\n removeOnComplete: { count: TICKS_KEPT },\n removeOnFail: { count: TICKS_KEPT },\n },\n },\n );\n}\n","import type { Queue } from \"bullmq\";\nimport type { ControlReads } from \"@/control-plane\";\nimport type { Logger } from \"@/logger\";\nimport {\n ItemRuns,\n claimHoldMsOf,\n mayPull,\n roomUnderTheCeiling,\n spoolJobId,\n type Backlog,\n type StoredEntry,\n} from \"@/spools\";\n\nimport type { Stage } from \"./stage\";\n\nexport interface FeedingRuntime {\n backlog: Backlog;\n queue: Queue;\n controls: ControlReads;\n logger: Logger;\n}\n\ninterface Release {\n entry: StoredEntry;\n link: number;\n}\n\nexport async function feedSpool(\n stage: Stage,\n runtime: FeedingRuntime,\n): Promise<void> {\n await expireWhatWaitedTooLong(stage, runtime);\n if (await isItsTriggerPaused(stage, runtime.controls)) return;\n if (!(await mayPull(stage.spool))) return;\n const now = new Date();\n const staleRuns = await reclaimTheStaleRuns(stage, runtime, now);\n const newRuns = await claimWhatTheCeilingAllows(stage, runtime.backlog, now);\n await release(stage, [...staleRuns, ...newRuns], runtime.queue);\n}\n\nasync function expireWhatWaitedTooLong(\n stage: Stage,\n { backlog, logger }: FeedingRuntime,\n): Promise<void> {\n const { expireUnclaimedAfterMs } = stage.spool;\n if (expireUnclaimedAfterMs === undefined) return;\n const pushedBefore = new Date(Date.now() - expireUnclaimedAfterMs);\n const expired = await backlog.expireUnclaimedPushedBefore(pushedBefore);\n if (expired > 0) warnOfExpiredItems(stage, expired, logger);\n}\n\nfunction warnOfExpiredItems(\n stage: Stage,\n expired: number,\n logger: Logger,\n): void {\n const { name, expireUnclaimedAfterMs } = stage.spool;\n logger.warn(\n { spool: name, expired },\n `[ravenflow] ${expired} items of the spool \"${name}\" expired: they waited more than ${expireUnclaimedAfterMs} ms without being claimed.`,\n );\n}\n\nasync function isItsTriggerPaused(\n stage: Stage,\n controls: ControlReads,\n): Promise<boolean> {\n const { triggerPaused } = await controls.read(stage.jobName);\n return triggerPaused;\n}\n\nasync function reclaimTheStaleRuns(\n stage: Stage,\n { backlog, queue }: FeedingRuntime,\n now: Date,\n): Promise<Release[]> {\n const claimedBefore = new Date(now.getTime() - claimHoldMsOf(stage.spool));\n const entries = await backlog.reclaimStaleClaims(claimedBefore, now);\n const runs = new ItemRuns(queue, stage.spool.name);\n const currentLinks = await runs.currentLinksOf(entries.map(({ _id }) => _id));\n return entries.map((entry, position) => ({\n entry,\n link: currentLinks[position],\n }));\n}\n\nasync function claimWhatTheCeilingAllows(\n stage: Stage,\n backlog: Backlog,\n now: Date,\n): Promise<Release[]> {\n const inFlight = await backlog.countInFlight();\n const room = roomUnderTheCeiling(stage.spool, stage.pace, inFlight);\n const entries = await backlog.claimOldestNeverClaimed(room, now);\n return entries.map((entry) => ({ entry, link: 0 }));\n}\n\nasync function release(\n stage: Stage,\n releases: Release[],\n queue: Queue,\n): Promise<void> {\n if (releases.length === 0) return;\n await queue.addBulk(\n releases.map(({ entry, link }) => ({\n name: stage.jobName,\n data: entry.item,\n opts: {\n ...stage.jobOptions,\n jobId: spoolJobId(stage.spool.name, { itemId: entry._id, link }),\n },\n })),\n );\n}\n","import type { Job, Queue, Worker } from \"bullmq\";\nimport type { ObjectId } from \"mongodb\";\nimport type { Logger } from \"@/logger\";\nimport type { MongoConnection } from \"@/mongo/connection\";\nimport {\n Backlog,\n ItemRuns,\n isALinkOfAnItem,\n itemLinkOf,\n type ItemLink,\n} from \"@/spools\";\n\nimport { willBeRetried } from \"../../job-results-recorder/job-result\";\n\nimport type { StagesByJobName } from \"./stage\";\n\nexport interface ItemRemovalsSettings {\n stages: StagesByJobName;\n queue: Queue;\n connection: MongoConnection;\n logger: Logger;\n}\n\ntype EndedLinksBySpoolName = Map<string, ItemLink[]>;\n\nexport class ItemRemovals {\n private endedLinks: EndedLinksBySpoolName = new Map();\n private removing: Promise<void> | null = null;\n\n constructor(private readonly settings: ItemRemovalsSettings) {}\n\n listenTo(worker: Worker): void {\n worker.on(\"completed\", (job) => this.noteTheEndOf(job));\n worker.on(\"failed\", (job) => {\n if (job === undefined || willBeRetried(job)) return;\n this.noteTheEndOf(job);\n });\n }\n\n async waitForRemovalsInProgress(): Promise<void> {\n while (this.removing) await this.removing;\n }\n\n private noteTheEndOf(job: Job): void {\n const stage = this.settings.stages.get(job.name);\n if (stage === undefined) return;\n const jobId = String(job.id);\n if (!isALinkOfAnItem(stage.spool.name, jobId)) return;\n\n this.addToEndedLinks(stage.spool.name, itemLinkOf(stage.spool.name, jobId));\n this.removing ??= this.removeTheItemsWhoseRunEnded();\n }\n\n private addToEndedLinks(spoolName: string, endedLink: ItemLink): void {\n const endedLinks = this.endedLinks.get(spoolName) ?? [];\n endedLinks.push(endedLink);\n this.endedLinks.set(spoolName, endedLinks);\n }\n\n private async removeTheItemsWhoseRunEnded(): Promise<void> {\n while (this.endedLinks.size > 0) {\n const batch = this.endedLinks;\n this.endedLinks = new Map();\n await Promise.all(\n [...batch].map(([spoolName, endedLinks]) =>\n this.removeWhereTheRunEnded(spoolName, endedLinks),\n ),\n );\n }\n this.removing = null;\n }\n\n private async removeWhereTheRunEnded(\n spoolName: string,\n endedLinks: ItemLink[],\n ): Promise<void> {\n try {\n const itemIds = await this.itemsWhoseRunEnded(spoolName, endedLinks);\n await new Backlog(spoolName, this.settings.connection).removeAll(itemIds);\n await new ItemRuns(this.settings.queue, spoolName).forget(itemIds);\n } catch (error) {\n this.warnOfItemsLeftBehind(spoolName, endedLinks, error);\n }\n }\n\n private async itemsWhoseRunEnded(\n spoolName: string,\n endedLinks: ItemLink[],\n ): Promise<ObjectId[]> {\n const runs = new ItemRuns(this.settings.queue, spoolName);\n const currentLinks = await runs.currentLinksOf(\n endedLinks.map(({ itemId }) => itemId),\n );\n return endedLinks\n .filter(({ link }, position) => currentLinks[position] <= link)\n .map(({ itemId }) => itemId);\n }\n\n private warnOfItemsLeftBehind(\n spoolName: string,\n endedLinks: ItemLink[],\n error: unknown,\n ): void {\n this.settings.logger.warn(\n { err: error, itemIds: endedLinks.map(({ itemId }) => String(itemId)) },\n `[ravenflow] ${endedLinks.length} links of the spool \"${spoolName}\" ended, but their items could not be removed from its backlog: they stay in it, and are released again ten ticks after their claim.`,\n );\n }\n}\n","import type { JobsOptions } from \"bullmq\";\nimport {\n isSpoolFed,\n type AnyJob,\n type PacePolicy,\n type SpoolTrigger,\n} from \"@/job\";\nimport { buildJobOptions } from \"@/queues\";\n\nexport interface Stage {\n jobName: string;\n spool: SpoolTrigger;\n pace: PacePolicy;\n jobOptions: JobsOptions;\n}\n\nexport type StagesByJobName = Map<string, Stage>;\n\nexport function stagesOf(jobs: Record<string, AnyJob>): StagesByJobName {\n return new Map(\n Object.entries(jobs).flatMap(([jobName, job]) =>\n stageEntriesOf(jobName, job),\n ),\n );\n}\n\nfunction stageEntriesOf(jobName: string, job: AnyJob): Array<[string, Stage]> {\n if (!isSpoolFed(job)) return [];\n const { trigger, pace } = job;\n const jobOptions = buildJobOptions(job);\n return [[jobName, { jobName, spool: trigger.spool, pace, jobOptions }]];\n}\n","import type { Queue } from \"bullmq\";\nimport { tickMsOf } from \"@/spools\";\n\nimport type { Stage, StagesByJobName } from \"./stage\";\n\nconst TICKS_KEPT = 100;\n\nexport async function reconcileTicks(\n feederQueue: Queue,\n stages: StagesByJobName,\n): Promise<void> {\n await removeTicksOfUndeclaredStages(feederQueue, stages);\n await Promise.all(\n [...stages.values()].map((stage) => scheduleTicks(feederQueue, stage)),\n );\n}\n\nasync function removeTicksOfUndeclaredStages(\n feederQueue: Queue,\n stages: StagesByJobName,\n): Promise<void> {\n const schedulers = await feederQueue.getJobSchedulers();\n const undeclared = schedulers.filter(({ key }) => !stages.has(key));\n await Promise.all(\n undeclared.map(({ key }) => feederQueue.removeJobScheduler(key)),\n );\n}\n\nasync function scheduleTicks(feederQueue: Queue, stage: Stage): Promise<void> {\n await feederQueue.upsertJobScheduler(\n stage.jobName,\n { every: tickMsOf(stage.spool) },\n {\n name: stage.jobName,\n opts: {\n removeOnComplete: { count: TICKS_KEPT },\n removeOnFail: { count: TICKS_KEPT },\n },\n },\n );\n}\n","import {\n Queue,\n Worker,\n type ConnectionOptions as RedisConnectionOptions,\n type Job,\n} from \"bullmq\";\nimport type { ControlReads } from \"@/control-plane\";\nimport type { AnyJob } from \"@/job\";\nimport type { Logger } from \"@/logger\";\nimport { MongoConnection } from \"@/mongo/connection\";\nimport { Backlog } from \"@/spools\";\n\nimport { logBullmqErrors } from \"../../log-bullmq-errors\";\nimport { waitOrCutShort } from \"../../mongodb-deadline-on-close\";\n\nimport { feedSpool } from \"./feed-spool\";\nimport { ItemRemovals } from \"./item-removals\";\nimport { stagesOf, type StagesByJobName } from \"./stage\";\nimport { reconcileTicks } from \"./ticks\";\n\nconst FEEDER_QUEUE_PREFIX = \"rav-internal-feed-spools-\";\n\nconst ONE_TICK_AT_A_TIME = 1;\n\nexport interface SpoolFeederSettings {\n redis: RedisConnectionOptions;\n mongo: string;\n queue: Queue;\n controls: ControlReads;\n jobs: Record<string, AnyJob>;\n logger: Logger;\n}\n\ninterface Feeding {\n feederQueue: Queue;\n tickWorker: Worker;\n}\n\nexport class SpoolFeeder {\n private readonly stages: StagesByJobName;\n private readonly connection: MongoConnection;\n private readonly itemRemovals: ItemRemovals;\n private readonly indexedBacklogs = new Set<string>();\n private feeding: Feeding | null = null;\n\n constructor(private readonly settings: SpoolFeederSettings) {\n this.stages = stagesOf(settings.jobs);\n this.connection = new MongoConnection(settings.mongo);\n this.itemRemovals = new ItemRemovals({\n stages: this.stages,\n queue: settings.queue,\n connection: this.connection,\n logger: settings.logger,\n });\n }\n\n async open(worker: Worker): Promise<void> {\n if (this.stages.size === 0) return;\n const feederQueue = new Queue(feederQueueNameOf(this.settings.queue), {\n connection: this.settings.redis,\n });\n logBullmqErrors(feederQueue, this.settings.logger);\n const tickWorker = this.openTickWorker(feederQueue.name);\n this.feeding = { feederQueue, tickWorker };\n this.itemRemovals.listenTo(worker);\n await feederQueue.setGlobalConcurrency(ONE_TICK_AT_A_TIME);\n await reconcileTicks(feederQueue, this.stages);\n }\n\n async stopTicking(): Promise<void> {\n const feeding = this.feeding;\n this.feeding = null;\n if (!feeding) return;\n\n await waitOrCutShort(feeding.tickWorker.close(), () =>\n this.connection.close(),\n );\n await feeding.feederQueue.close();\n }\n\n async finishTheRemovals(): Promise<void> {\n await waitOrCutShort(this.itemRemovals.waitForRemovalsInProgress(), () =>\n this.connection.close(),\n );\n }\n\n async close(): Promise<void> {\n await this.stopTicking();\n await this.finishTheRemovals();\n await this.connection.close();\n }\n\n private openTickWorker(feederQueueName: string): Worker {\n const worker = new Worker(feederQueueName, (tick) => this.tick(tick), {\n connection: this.settings.redis,\n });\n worker.on(\"failed\", (tick, error) => this.warnOfAFailedTick(tick, error));\n logBullmqErrors(worker, this.settings.logger);\n return worker;\n }\n\n private async tick(tick: Job): Promise<void> {\n const stage = this.stages.get(tick.name);\n if (stage === undefined) throw this.undeclaredSpoolError(tick);\n const backlog = new Backlog(stage.spool.name, this.connection);\n await this.indexOnce(backlog);\n await feedSpool(stage, {\n backlog,\n queue: this.settings.queue,\n controls: this.settings.controls,\n logger: this.settings.logger,\n });\n }\n\n private async indexOnce(backlog: Backlog): Promise<void> {\n if (this.indexedBacklogs.has(backlog.spoolName)) return;\n await backlog.indexForTheClaim();\n this.indexedBacklogs.add(backlog.spoolName);\n }\n\n private undeclaredSpoolError(tick: Job): Error {\n return new Error(\n `[ravenflow] no spool of \"${this.settings.queue.name}\" feeds \"${tick.name}\": its config does not declare one.`,\n );\n }\n\n private warnOfAFailedTick(tick: Job | undefined, error: Error): void {\n this.settings.logger.warn(\n { err: error },\n `[ravenflow] a tick of the spool feeding \"${tick?.name}\" failed; the next one releases what it did not.`,\n );\n }\n}\n\nfunction feederQueueNameOf(queue: Queue): string {\n return `${FEEDER_QUEUE_PREFIX}${queue.name}`;\n}\n","import { MetricsTime, Worker } from \"bullmq\";\n\nimport { routeByName, type RouterRuntime } from \"./job-router\";\nimport { logBullmqErrors } from \"./log-bullmq-errors\";\nimport type { RavenflowWorkerOptions } from \"./types\";\n\nconst DEFAULT_CONCURRENCY = 5;\n\nexport type WorkerRuntime = Omit<RouterRuntime, \"shutdown\">;\n\nexport function openWorker(\n options: RavenflowWorkerOptions,\n runtime: WorkerRuntime,\n): Worker {\n const shutdown = new AbortController();\n const route = routeByName({ ...runtime, shutdown: shutdown.signal });\n const worker = new Worker(options.queue, route, {\n connection: options.redis,\n concurrency: options.concurrency ?? DEFAULT_CONCURRENCY,\n metrics: { maxDataPoints: MetricsTime.ONE_WEEK },\n autorun: false,\n });\n abortWhenClosing(worker, shutdown);\n logBullmqErrors(worker, runtime.logger);\n return worker;\n}\n\nfunction abortWhenClosing(worker: Worker, shutdown: AbortController): void {\n worker.once(\"closing\", () => {\n shutdown.abort(new Error(\"[ravenflow] the worker is shutting down\"));\n });\n}\n","import type { JobSchedulerTemplateOptions, Queue } from \"bullmq\";\nimport { describeError } from \"@/describe-error\";\nimport type { AnyJob } from \"@/job\";\nimport { buildJobOptions } from \"@/queues\";\n\nexport interface CronSchedule {\n name: string;\n pattern: string;\n options: JobSchedulerTemplateOptions;\n}\n\nexport interface Rescheduled extends CronSchedule {\n previousPattern: string;\n}\n\nexport interface SchedulerChanges {\n added: CronSchedule[];\n rescheduled: Rescheduled[];\n removed: string[];\n}\n\ntype PatternsByScheduler = Map<string, string>;\n\nexport async function reconcileSchedulers(\n queue: Queue,\n jobs: Record<string, AnyJob>,\n): Promise<SchedulerChanges> {\n const declared = cronSchedulesOf(jobs);\n const existing = await patternsByScheduler(queue);\n const changes = changesBetween(declared, existing);\n\n await Promise.all(\n changes.removed.map((key) => queue.removeJobScheduler(key)),\n );\n await Promise.all(declared.map((schedule) => upsert(queue, schedule)));\n return changes;\n}\n\nfunction cronSchedulesOf(jobs: Record<string, AnyJob>): CronSchedule[] {\n return Object.entries(jobs).flatMap(([name, job]) => {\n const pattern = job.trigger?.cron;\n if (pattern === undefined) return [];\n return [{ name, pattern, options: buildJobOptions(job) }];\n });\n}\n\nasync function patternsByScheduler(queue: Queue): Promise<PatternsByScheduler> {\n const schedulers = await queue.getJobSchedulers();\n return new Map(\n schedulers.map(({ key, pattern }) => [key, pattern ?? \"no pattern\"]),\n );\n}\n\nfunction changesBetween(\n declared: CronSchedule[],\n existing: PatternsByScheduler,\n): SchedulerChanges {\n const declaredNames = new Set(declared.map(({ name }) => name));\n return {\n added: declared.filter(({ name }) => !existing.has(name)),\n rescheduled: declared.flatMap((schedule) =>\n reschedulingOf(schedule, existing),\n ),\n removed: [...existing.keys()].filter((key) => !declaredNames.has(key)),\n };\n}\n\nfunction reschedulingOf(\n schedule: CronSchedule,\n existing: PatternsByScheduler,\n): Rescheduled[] {\n const previousPattern = existing.get(schedule.name);\n if (previousPattern === undefined) return [];\n if (previousPattern === schedule.pattern) return [];\n return [{ ...schedule, previousPattern }];\n}\n\nasync function upsert(\n queue: Queue,\n { name, pattern, options }: CronSchedule,\n): Promise<void> {\n try {\n await queue.upsertJobScheduler(name, { pattern }, { name, opts: options });\n } catch (error) {\n throw new Error(\n `[ravenflow] \"${name}\" could not be scheduled on \"${pattern}\": ${describeError(error)}`,\n );\n }\n}\n","import type { RavenflowConfig } from \"@/config\";\nimport { declaredQueueNames } from \"@/queues\";\n\nexport function refuseAQueueItsConfigDoesNotDeclare(\n queue: string,\n config: RavenflowConfig,\n): void {\n const declared = declaredQueueNames(config);\n if (declared.includes(queue)) return;\n\n const quoted = declared.map((name) => `\"${name}\"`).join(\", \");\n throw new Error(\n `[ravenflow] no job of this config runs on \"${queue}\": its queues are ${quoted}.`,\n );\n}\n","import type { Queue, Worker } from \"bullmq\";\n\nimport type { ControlPlaneReader } from \"./control-plane-reader\";\nimport type { JobResultsAggregator } from \"./internal-jobs/job-results-aggregator\";\nimport type { SpoolFeeder } from \"./internal-jobs/spool-feeder\";\nimport type { JobResultsRecorder } from \"./job-results-recorder\";\nimport type { MongoWatch } from \"./withdrawal\";\n\nexport interface Serving {\n queue: Queue;\n controlPlaneReader: ControlPlaneReader;\n jobResultsRecorder: JobResultsRecorder;\n jobResultsAggregator: JobResultsAggregator;\n spoolFeeder: SpoolFeeder;\n mongoWatch: MongoWatch;\n worker: Worker;\n}\n\nexport async function closeInOrder(serving: Serving): Promise<void> {\n await stopWatchingMongoDB(serving);\n await stopTheTicks(serving);\n await stopTheWorker(serving);\n await writeWhatItsJobsLeft(serving);\n await closeTheConnections(serving);\n}\n\nasync function stopWatchingMongoDB(serving: Serving): Promise<void> {\n await serving.mongoWatch.close();\n}\n\nasync function stopTheTicks(serving: Serving): Promise<void> {\n await Promise.all([\n serving.jobResultsAggregator.stopTicking(),\n serving.spoolFeeder.stopTicking(),\n ]);\n}\n\nasync function stopTheWorker(serving: Serving): Promise<void> {\n serving.jobResultsRecorder.stopHoldingJobs();\n await serving.worker.close();\n}\n\nasync function writeWhatItsJobsLeft(serving: Serving): Promise<void> {\n await Promise.all([\n serving.jobResultsRecorder.close(),\n serving.spoolFeeder.finishTheRemovals(),\n ]);\n}\n\nasync function closeTheConnections(serving: Serving): Promise<void> {\n await serving.spoolFeeder.close();\n await serving.jobResultsAggregator.close();\n await serving.controlPlaneReader.close();\n await serving.queue.close();\n}\n","import { MongoClient, type TopologyDescriptionChangedEvent } from \"mongodb\";\nimport type { Logger } from \"@/logger\";\n\nconst THE_DRIVERS_RECOVERY_LAG_MS = 10_000;\n\nexport interface MongoWatchSettings {\n mongo: string;\n gracePeriodMs: number;\n logger: Logger;\n onDurableLoss: (unreachableForMs: number) => void;\n}\n\nexport class MongoWatch {\n private readonly client: MongoClient;\n private unreachableSince = 0;\n private graceTimer: ReturnType<typeof setTimeout> | null = null;\n private answeredOnce = false;\n\n constructor(private readonly settings: MongoWatchSettings) {\n this.client = new MongoClient(settings.mongo, {\n serverSelectionTimeoutMS:\n settings.gracePeriodMs + THE_DRIVERS_RECOVERY_LAG_MS,\n });\n }\n\n open(): void {\n this.client.on(\"topologyDescriptionChanged\", this.onTopologyChange);\n this.startTheGracePeriod();\n this.client.connect().catch((error: unknown) => this.noteItGaveUp(error));\n }\n\n async close(): Promise<void> {\n this.client.off(\"topologyDescriptionChanged\", this.onTopologyChange);\n this.stopTheGracePeriod();\n await this.client.close();\n }\n\n private readonly onTopologyChange = (\n event: TopologyDescriptionChangedEvent,\n ): void => {\n if (!event.newDescription.hasDataBearingServers) {\n this.noteUnreachable();\n return;\n }\n this.noteReachable();\n };\n\n private noteUnreachable(): void {\n if (this.graceTimer !== null) return;\n this.warnOfALoss();\n this.startTheGracePeriod();\n }\n\n private noteReachable(): void {\n if (this.graceTimer === null) return;\n if (this.answeredOnce) this.sayItIsBack();\n this.answeredOnce = true;\n this.stopTheGracePeriod();\n }\n\n private startTheGracePeriod(): void {\n this.unreachableSince = Date.now();\n this.graceTimer = setTimeout(\n () => this.settings.onDurableLoss(Date.now() - this.unreachableSince),\n this.settings.gracePeriodMs,\n );\n }\n\n private stopTheGracePeriod(): void {\n if (this.graceTimer === null) return;\n clearTimeout(this.graceTimer);\n this.graceTimer = null;\n }\n\n private noteItGaveUp(error: unknown): void {\n this.settings.logger.debug(\n { err: error },\n \"[ravenflow] the worker's watch on MongoDB stopped trying to connect.\",\n );\n }\n\n private warnOfALoss(): void {\n this.settings.logger.warn(\n { gracePeriodMs: this.settings.gracePeriodMs },\n \"[ravenflow] MongoDB is unreachable: the worker withdraws if it stays so for its whole grace period.\",\n );\n }\n\n private sayItIsBack(): void {\n this.settings.logger.info(\n { outageMs: Date.now() - this.unreachableSince },\n \"[ravenflow] MongoDB is reachable again, within the worker's grace period.\",\n );\n }\n}\n","import type { Logger } from \"@/logger\";\n\nconst EXIT_CODE_OF_A_WITHDRAWAL = 1;\n\nexport interface WithdrawingWorker {\n queue: string;\n logger: Logger;\n onWithdraw?: (reason: string) => void | Promise<void>;\n close: () => Promise<void>;\n}\n\nexport async function withdraw(\n worker: WithdrawingWorker,\n unreachableForMs: number,\n): Promise<void> {\n const reason = reasonOf(unreachableForMs);\n sayItWithdraws(worker, reason);\n await closeTheWorker(worker);\n process.exitCode = EXIT_CODE_OF_A_WITHDRAWAL;\n sayItHasWithdrawn(worker, reason);\n await callOnWithdraw(worker, reason);\n}\n\nfunction reasonOf(unreachableForMs: number): string {\n return `MongoDB has been unreachable for ${Math.round(unreachableForMs / 1_000)}s`;\n}\n\nfunction sayItWithdraws({ queue, logger }: WithdrawingWorker, reason: string) {\n logger.fatal(\n { reason },\n `[ravenflow] the worker serving \"${queue}\" withdraws: ${reason}. It takes no new job, and finishes the ones it holds.`,\n );\n}\n\nasync function closeTheWorker({\n queue,\n logger,\n close,\n}: WithdrawingWorker): Promise<void> {\n try {\n await close();\n } catch (error) {\n logger.error(\n { err: error },\n `[ravenflow] the worker serving \"${queue}\" could not close all it opened; it withdraws all the same.`,\n );\n }\n}\n\nfunction sayItHasWithdrawn(\n { queue, logger }: WithdrawingWorker,\n reason: string,\n) {\n logger.warn(\n { reason },\n `[ravenflow] the worker serving \"${queue}\" has withdrawn, and closed: the process exits with code ${EXIT_CODE_OF_A_WITHDRAWAL} once nothing else holds it.`,\n );\n}\n\nasync function callOnWithdraw(\n { logger, onWithdraw }: WithdrawingWorker,\n reason: string,\n): Promise<void> {\n try {\n await onWithdraw?.(reason);\n } catch (error) {\n logger.error(\n { err: error },\n \"[ravenflow] onWithdraw threw; the withdrawal itself stands.\",\n );\n }\n}\n","import type { Queue, Worker } from \"bullmq\";\nimport type { RavenflowConfig } from \"@/config\";\nimport {\n DEFAULT_AGGREGATED_RESULTS_RETENTION_HOURS,\n DEFAULT_GRACE_PERIOD_MS,\n DEFAULT_JOB_RESULTS_RETENTION_HOURS,\n} from \"@/config/constants\";\nimport { validateConfig } from \"@/config/validate-config\";\nimport { describeError } from \"@/describe-error\";\nimport type { AnyJob } from \"@/job\";\nimport { createLogger, type Logger } from \"@/logger\";\nimport { jobsDeclaredOn, openQueue } from \"@/queues\";\n\nimport { printBanner } from \"./banner\";\nimport { ControlPlaneReader } from \"./control-plane-reader\";\nimport { JobResultsAggregator } from \"./internal-jobs/job-results-aggregator\";\nimport { SpoolFeeder } from \"./internal-jobs/spool-feeder\";\nimport {\n JobResultsRecorder,\n type JobResultsRecorderOpening,\n} from \"./job-results-recorder\";\nimport { logBullmqErrors } from \"./log-bullmq-errors\";\nimport { openWorker } from \"./open-worker\";\nimport { reconcileSchedulers } from \"./schedulers\";\nimport { refuseAQueueItsConfigDoesNotDeclare } from \"./served-queue\";\nimport { closeInOrder, type Serving } from \"./serving\";\nimport type { RavenflowWorkerOptions } from \"./types\";\nimport { MongoWatch, withdraw } from \"./withdrawal\";\n\nexport class RavenflowWorker {\n private readonly config: RavenflowConfig;\n private readonly options: RavenflowWorkerOptions;\n private readonly jobs: Record<string, AnyJob>;\n private readonly logger: Logger;\n\n private serving: Serving | null = null;\n private starting: Promise<void> | null = null;\n private closing: Promise<void> | null = null;\n\n constructor(config: RavenflowConfig, options: RavenflowWorkerOptions) {\n validateConfig(config);\n refuseAQueueItsConfigDoesNotDeclare(options.queue, config);\n\n this.config = config;\n this.options = options;\n this.jobs = jobsDeclaredOn(options.queue, config);\n this.logger = createLogger(config.logger);\n }\n\n public async start(): Promise<void> {\n this.refuseASecondStart();\n\n const serving = this.openServing();\n this.serving = serving;\n this.starting = this.serveOrStop(serving);\n try {\n await this.starting;\n } finally {\n this.starting = null;\n }\n }\n\n public async close(): Promise<void> {\n await Promise.allSettled([this.starting]);\n if (this.serving === null) return;\n this.closing ??= this.stopServing(this.serving);\n await this.closing;\n }\n\n private async serveOrStop(serving: Serving): Promise<void> {\n try {\n await this.serve(serving);\n } catch (error) {\n await this.stopServing(serving);\n throw error;\n }\n }\n\n private async stopServing(serving: Serving): Promise<void> {\n try {\n await closeInOrder(serving);\n } finally {\n this.serving = null;\n this.closing = null;\n }\n }\n\n private refuseASecondStart(): void {\n if (!this.serving) return;\n throw new Error(\n `[ravenflow] this worker has already started on \"${this.options.queue}\".`,\n );\n }\n\n private openServing(): Serving {\n const queue = openQueue(this.options.queue, {\n connection: this.options.redis,\n retention: this.config.queuesRetention,\n });\n logBullmqErrors(queue, this.logger);\n const controlPlaneReader = this.buildControlPlaneReader();\n const jobResultsRecorder = this.buildJobResultsRecorder(queue);\n const worker = openWorker(this.options, {\n jobs: this.jobs,\n logger: this.logger,\n queue,\n controls: controlPlaneReader,\n jobResultsRecorder,\n });\n return {\n queue,\n controlPlaneReader,\n jobResultsRecorder,\n jobResultsAggregator: this.buildJobResultsAggregator(),\n spoolFeeder: this.buildSpoolFeeder(queue, controlPlaneReader),\n mongoWatch: this.buildMongoWatch(),\n worker,\n };\n }\n\n private buildControlPlaneReader(): ControlPlaneReader {\n return new ControlPlaneReader({\n redis: this.options.redis,\n mongo: this.options.mongo,\n logger: this.logger,\n });\n }\n\n private buildJobResultsRecorder(queue: Queue): JobResultsRecorder {\n return new JobResultsRecorder({\n mongo: this.options.mongo,\n retentionHours:\n this.config.jobResultsRetentionHours ??\n DEFAULT_JOB_RESULTS_RETENTION_HOURS,\n queue,\n jobs: this.jobs,\n logger: this.logger,\n });\n }\n\n private buildJobResultsAggregator(): JobResultsAggregator {\n return new JobResultsAggregator({\n redis: this.options.redis,\n mongo: this.options.mongo,\n retentionHours:\n this.config.aggregatedResultsRetentionHours ??\n DEFAULT_AGGREGATED_RESULTS_RETENTION_HOURS,\n logger: this.logger,\n });\n }\n\n private buildSpoolFeeder(\n queue: Queue,\n controls: ControlPlaneReader,\n ): SpoolFeeder {\n return new SpoolFeeder({\n redis: this.options.redis,\n mongo: this.options.mongo,\n queue,\n controls,\n jobs: this.jobs,\n logger: this.logger,\n });\n }\n\n private buildMongoWatch(): MongoWatch {\n return new MongoWatch({\n mongo: this.options.mongo,\n gracePeriodMs:\n this.options.withdrawal?.afterMs ?? DEFAULT_GRACE_PERIOD_MS,\n logger: this.logger,\n onDurableLoss: (unreachableForMs) =>\n this.beginAWithdrawal(unreachableForMs),\n });\n }\n\n private beginAWithdrawal(unreachableForMs: number): void {\n const withdrawing = {\n queue: this.options.queue,\n logger: this.logger,\n onWithdraw: this.options.withdrawal?.onWithdraw,\n close: () => this.close(),\n };\n void withdraw(withdrawing, unreachableForMs);\n }\n\n private async serve({\n queue,\n controlPlaneReader,\n jobResultsRecorder,\n jobResultsAggregator,\n spoolFeeder,\n mongoWatch,\n worker,\n }: Serving): Promise<void> {\n mongoWatch.open();\n await controlPlaneReader.open();\n const recorderOpening = await this.openRecorder(jobResultsRecorder, worker);\n await jobResultsAggregator.open();\n await spoolFeeder.open(worker);\n const schedulers = await reconcileSchedulers(queue, this.jobs);\n this.takeJobs(worker);\n await worker.waitUntilReady();\n\n printBanner({\n queue: this.options.queue,\n concurrency: worker.concurrency,\n redis: this.options.redis,\n mongo: this.options.mongo,\n recorderOpening,\n jobs: this.jobs,\n schedulers,\n });\n }\n\n private async openRecorder(\n jobResultsRecorder: JobResultsRecorder,\n worker: Worker,\n ): Promise<JobResultsRecorderOpening> {\n try {\n await jobResultsRecorder.open(worker);\n } catch (error) {\n this.sayJobResultsAreNotRecorded(error);\n return { opened: false, because: describeError(error) };\n }\n return { opened: true };\n }\n\n private sayJobResultsAreNotRecorded(error: unknown): void {\n this.logger.error(\n { err: error },\n `[ravenflow] the job results recorder could not start: the worker serves \"${this.options.queue}\", and its job results are not recorded.`,\n );\n }\n\n private takeJobs(worker: Worker): void {\n worker.run().catch((error: unknown) => {\n this.logger.error(\n { err: error },\n `[ravenflow] the worker serving \"${this.options.queue}\" stopped taking jobs.`,\n );\n });\n }\n}\n","import type { RavenflowConfig } from \"@/config\";\nimport { RavenflowWorker } from \"./ravenflow-worker\";\nimport type { RavenflowWorkerOptions } from \"./types\";\n\nexport function createRavenflowWorker(\n config: RavenflowConfig,\n options: RavenflowWorkerOptions,\n): RavenflowWorker {\n return new RavenflowWorker(config, options);\n}\n","import { AnyJob } from \"@/job\";\nimport { LoggerOptions } from \"@/logger\";\n\nexport interface RavenflowConfig<TJobs extends string = string> {\n defaultQueue: string;\n jobs: Record<TJobs, AnyJob>;\n\n logger?: LoggerOptions;\n queuesRetention?: QueuesRetentionConfig;\n jobResultsRetentionHours?: number;\n aggregatedResultsRetentionHours?: number;\n}\n\nexport interface QueuesRetentionConfig {\n completedCount?: number;\n failedCount?: number;\n}\n\nexport function defineConfig<const T extends RavenflowConfig>(config: T): T {\n return config;\n}\n"]}