ravenflow 0.1.0 → 0.2.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/processor.ts","../src/logger.ts","../src/banner.ts","../src/app.ts","../src/index.ts"],"names":["pino","Queue","QueueEvents","Worker"],"mappings":"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","file":"index.js","sourcesContent":["import { Job, Queue, QueueEvents } from \"bullmq\";\nimport { EtlJobConfig } from \"./types\";\n\nexport async function processEtlJob<TRaw, TProcessed>(\n job: Job,\n etlConfig: EtlJobConfig<TRaw, TProcessed>,\n transformQueue: Queue,\n transformQueueEvents: QueueEvents\n) {\n let currentPage = 1;\n let run = true;\n const metadata = {\n count: 0,\n pages: 0,\n currentPage,\n startedAt: new Date(),\n endedAt: undefined,\n };\n const pagination = {\n pageSize: 100,\n maxPages: Infinity,\n pageParam: \"page\",\n };\n\n while (run && currentPage <= (pagination.maxPages || Infinity)) {\n metadata.currentPage = currentPage;\n metadata.pages = currentPage;\n\n const {\n data: rawElements,\n hasNextPage: nextPageExists = false,\n }: {\n data: TRaw[];\n hasNextPage?: boolean;\n } = await etlConfig.extract(currentPage);\n\n const processedElements: TProcessed[] = [];\n\n for (const element of rawElements) {\n const transformJobName = `${job.name}:transform`;\n const transformJob = await transformQueue.add(transformJobName, element, {\n attempts: etlConfig.attempts,\n backoff: etlConfig.backoff,\n });\n const processedElement =\n await transformJob.waitUntilFinished(transformQueueEvents);\n\n processedElements.push(processedElement as TProcessed);\n }\n\n await etlConfig.load(processedElements);\n metadata.count += processedElements.length;\n\n run = nextPageExists;\n if (run) {\n currentPage++;\n }\n }\n return metadata;\n}\n","import pino from \"pino\";\n\nexport interface LoggerOptions {\n level?: \"trace\" | \"debug\" | \"info\" | \"warn\" | \"error\" | \"fatal\";\n pretty?: boolean;\n}\n\nexport function createLogger(options: LoggerOptions = {}) {\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\",\n },\n }\n : undefined,\n });\n}\n\nexport type Logger = ReturnType<typeof createLogger>;\n","import { JobConfig } from \"./types\";\n\nconst RAVENFLOW_ASCII = `\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 jobs: Record<string, JobConfig>;\n}\n\nexport function printWorkerBanner(config: BannerConfig): void {\n const { queueName, concurrency, redis, jobs } = config;\n\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\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 { ConnectionOptions, Queue, Worker, Job, QueueEvents } from \"bullmq\";\nimport {\n RavenflowConfig,\n QueueNames,\n JobConfig,\n JobNames,\n JobsProxy,\n} from \"./types\";\nimport { processEtlJob } from \"./processor\";\nimport { createLogger, Logger, LoggerOptions } from \"./logger\";\nimport { printWorkerBanner } from \"./banner\";\n\nexport class RavenflowApp<TConfig extends RavenflowConfig = RavenflowConfig> {\n protected connection: ConnectionOptions;\n protected defaultConcurrency: number = 5;\n protected logger: Logger;\n\n protected config: TConfig;\n\n public jobs: JobsProxy<TConfig[\"jobs\"]>;\n protected jobConfigs: Record<JobNames<TConfig>, JobConfig>;\n protected queues: Record<\n QueueNames<TConfig>,\n { queue: Queue; events: QueueEvents }\n >;\n\n constructor(\n connection: ConnectionOptions,\n config: TConfig,\n loggerOptions?: LoggerOptions\n ) {\n this.connection = connection;\n this.config = config;\n this.logger = createLogger(loggerOptions);\n\n if (!config.queues.includes(config.defaultQueue)) {\n throw new Error(\n `Default queue ${config.defaultQueue} is not in the list of queues`\n );\n }\n\n const { jobsProxy, jobConfigs } = this.initJobs(config);\n this.jobs = jobsProxy;\n this.jobConfigs = jobConfigs;\n\n this.queues = this.initQueues(config);\n }\n\n private initQueues(\n config: TConfig\n ): Record<QueueNames<TConfig>, { queue: Queue; events: QueueEvents }> {\n const queues: Record<string, { queue: Queue; events: QueueEvents }> = {};\n for (const queueName of config.queues) {\n queues[queueName] = {\n queue: new Queue(queueName, {\n connection: this.connection,\n }),\n events: new QueueEvents(queueName, {\n connection: this.connection,\n }),\n };\n }\n return queues;\n }\n\n private initJobs(config: TConfig): {\n jobsProxy: JobsProxy<TConfig[\"jobs\"]>;\n jobConfigs: Record<JobNames<TConfig>, JobConfig>;\n } {\n const jobsProxy: Record<string, { send: (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 jobsProxy[jobName] = {\n send: async (params: any) => {\n return this.sendJob(jobName as JobNames<TConfig>, params);\n },\n };\n }\n return {\n jobsProxy: jobsProxy as JobsProxy<TConfig[\"jobs\"]>,\n jobConfigs,\n };\n }\n\n private async sendJob(jobName: JobNames<TConfig>, params: any) {\n const jobConfig = this.jobConfigs[jobName];\n if (!jobConfig) {\n throw new Error(`Job ${jobName} not found`);\n }\n const queueData = this.queues[jobConfig.queueName as QueueNames<TConfig>];\n if (!queueData) {\n throw new Error(`Queue ${jobConfig.queueName} not found`);\n }\n return await queueData.queue.add(jobName, params);\n }\n\n public startWorker(\n queueName: QueueNames<TConfig>,\n options?: {\n concurrency?: number;\n }\n ) {\n const queueConfig = this.queues[queueName];\n if (!queueConfig) {\n throw new Error(`Queue ${queueName} not found in config.`);\n }\n\n const workerConcurrency = options?.concurrency || this.defaultConcurrency;\n\n this.printWorkerBanner(queueName, workerConcurrency);\n\n this.syncJobSchedulers(queueName);\n\n const worker = new Worker(queueName, (job) => this.processJob(job), {\n connection: this.connection,\n autorun: false,\n concurrency: workerConcurrency,\n });\n this.setupWorkerEvents(worker, queueName);\n worker.run();\n }\n\n private printWorkerBanner(\n queueName: QueueNames<TConfig>,\n concurrency: number\n ): void {\n const redisInfo = {\n host:\n typeof this.connection === \"object\" && \"host\" in this.connection\n ? (this.connection.host as string)\n : \"localhost\",\n port:\n typeof this.connection === \"object\" && \"port\" in this.connection\n ? (this.connection.port as number)\n : 6379,\n db:\n typeof this.connection === \"object\" && \"db\" in this.connection\n ? (this.connection.db as number)\n : 0,\n };\n\n printWorkerBanner({\n queueName: queueName as string,\n concurrency,\n redis: redisInfo,\n jobs: this.jobConfigs,\n });\n }\n\n private setupWorkerEvents(worker: Worker, queueName: string): void {\n worker.on(\"active\", (job) => {\n this.logger.info(`[${queueName}] ${job.name} - active`);\n });\n\n worker.on(\"completed\", (job) => {\n this.logger.info(`[${queueName}] ${job.name} - completed`);\n });\n\n worker.on(\"failed\", (job, error) => {\n this.logger.error(\n `[${queueName}] ${job?.name} - failed: ${error.message}`\n );\n });\n }\n\n private async syncJobSchedulers(queueName: QueueNames<TConfig>) {\n const queueData = this.queues[queueName];\n if (!queueData) {\n throw new Error(`Queue ${queueName} not found in config.`);\n }\n const queue = queueData.queue;\n\n console.log(\"[Scheduled Jobs]\");\n\n const jobConfigsWithCron: Record<string, JobConfig> = {};\n for (const jobName in this.jobConfigs) {\n const jobConfig = this.jobConfigs[jobName as JobNames<TConfig>];\n if (jobConfig.cron) {\n jobConfigsWithCron[jobName] = jobConfig;\n }\n }\n\n const registeredJobSchedulers = await queue.getJobSchedulers();\n const existingSchedulerKeys = new Set(\n registeredJobSchedulers.map((s) => s.key)\n );\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 if (newJobs.length > 0) {\n newJobs.forEach((name) =>\n console.log(` + ${name} → ${jobConfigsWithCron[name].cron}`)\n );\n }\n if (updated.length > 0) {\n updated.forEach((name) =>\n console.log(` ↻ ${name} → ${jobConfigsWithCron[name].cron}`)\n );\n }\n if (removed.length > 0) {\n removed.forEach((name) => console.log(` - ${name}`));\n }\n if (newJobs.length === 0 && updated.length === 0 && removed.length === 0) {\n console.log(` (no scheduled jobs)`);\n }\n\n console.log(\"\");\n }\n\n async processJob(job: Job) {\n const isEtlTransformJob = job.name.endsWith(\":transform\");\n const jobName = isEtlTransformJob\n ? job.name.slice(0, -\":transform\".length)\n : job.name;\n\n const jobConfig = this.jobConfigs[jobName as JobNames<TConfig>];\n if (!jobConfig) {\n throw new Error(`Job handler not found: ${jobName}`);\n }\n\n if (jobConfig.type === \"job\") {\n return await jobConfig.handler(job, job.data);\n }\n\n if (jobConfig.type === \"etl\" && !isEtlTransformJob) {\n const transformQueueName =\n jobConfig.transformQueue || jobConfig.queueName;\n const queueData = this.queues[transformQueueName as QueueNames<TConfig>];\n\n if (!queueData) {\n throw new Error(`Queue ${transformQueueName} not found in config.`);\n }\n return await processEtlJob(\n job,\n jobConfig,\n queueData.queue,\n queueData.events\n );\n }\n\n if (jobConfig.type === \"etl\" && isEtlTransformJob) {\n return await jobConfig.transform(job.data);\n }\n\n throw new Error(`Unknown job type: ${jobConfig.type}`);\n }\n}\n","import { RavenflowApp } from \"./app\";\nimport { RavenflowConfig } from \"./types\";\nimport { ConnectionOptions } from \"bullmq\";\n\nexport { RavenflowApp } from \"./app\";\nexport { createLogger } from \"./logger\";\n\nexport type {\n JobConfig,\n RavenflowConfig,\n SimpleJobConfig,\n EtlJobConfig,\n} from \"./types\";\n\nexport type { Logger, LoggerOptions } from \"./logger\";\n\nexport function createRavenflowApp<TConfig extends RavenflowConfig>(\n config: TConfig,\n connection: ConnectionOptions,\n loggerOptions?: {\n level?: \"trace\" | \"debug\" | \"info\" | \"warn\" | \"error\" | \"fatal\";\n pretty?: boolean;\n }\n): RavenflowApp<TConfig> {\n return new RavenflowApp(connection, config, loggerOptions);\n}\n"]}
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/active-hours.ts","../src/processors/token-bucket-job.processor/budget.ts","../src/processors/token-bucket-job.processor/process.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/app/app.ts","../src/index.ts"],"names":["pino","Queue","QueueEvents","z","resolve","logger","MongoClient","ObjectId","collection","processJob","Worker","db"],"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\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\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","export const TOKEN_BUCKET_PROCESS_SUFFIX = \":process\";\n\nexport const INTERVAL_MS = {\n minute: 60_000,\n hour: 3_600_000,\n day: 86_400_000,\n} as const;\n","export const ETL_EXTRACT_SUFFIX = \":extract\";\nexport const ETL_TRANSFORM_SUFFIX = \":transform\";\nexport const ETL_LOAD_SUFFIX = \":load\";\nexport { TOKEN_BUCKET_PROCESS_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, StepConfig } from \"./common\";\n\n// ---------------------------------------------------------------------------\n// Config\n// ---------------------------------------------------------------------------\n\nexport interface TokenBucketJobConfig<TItem, TResult> extends BaseJobConfig {\n type: \"token-bucket\";\n cron: string;\n\n rate: {\n amount: number;\n interval: \"minute\" | \"hour\" | \"day\";\n };\n\n activeHours?: {\n start: number; // 0-23\n end: number; // 0-23\n timezone?: string; // IANA timezone, default UTC\n };\n\n maxPerBeat?: number;\n\n getItems: (budget: number) => Promise<TItem[]>;\n process: (item: TItem) => Promise<TResult>;\n\n steps?: {\n process?: StepConfig;\n };\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 windowDispatched: z.number().int().nonnegative(),\n windowResetAt: z.date(),\n});\n\nexport type TokenBucketState = z.infer<typeof zTokenBucketState>;\n\nexport function defineTokenBucketJob<TItem, TResult>(\n config: Omit<TokenBucketJobConfig<TItem, TResult>, \"type\">,\n): TokenBucketJobConfig<TItem, TResult> {\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 | SimpleJobConfig<any, any>\n | MemoryEtlJobConfig<any, any, any>\n | DistributedEtlJobConfig<any, any, any>\n | StatefulEtlJobConfig<any, any, any>\n | TokenBucketJobConfig<any, 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 windowResetAt: 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 windowDispatched: 0,\n windowResetAt,\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 windowDispatched: number,\n windowResetAt: Date,\n): Promise<void> {\n await collection().updateOne(\n { _id: jobName },\n {\n $set: {\n accumulatedCredit,\n lastTickAt,\n windowDispatched,\n windowResetAt,\n },\n },\n );\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 { TokenBucketJobConfig } from \"@/types\";\n\nexport function isWithinActiveHours(\n config: TokenBucketJobConfig<any, any>,\n now: Date,\n): boolean {\n if (!config.activeHours) return true;\n\n const { start, end, timezone } = config.activeHours;\n const hour = getHourInTimezone(now, timezone);\n\n if (start <= end) {\n // e.g., 8-18: active when hour >= 8 AND hour < 18\n return hour >= start && hour < end;\n }\n // e.g., 22-6: active when hour >= 22 OR hour < 6 (overnight)\n return hour >= start || hour < end;\n}\n\nexport function getActiveWindowMs(config: TokenBucketJobConfig<any, any>): number {\n if (!config.activeHours) {\n return getFullIntervalMs(config.rate.interval);\n }\n\n const { start, end } = config.activeHours;\n let hours: number;\n\n if (start <= end) {\n hours = end - start;\n } else {\n hours = 24 - start + end;\n }\n\n if (hours <= 0) hours = 24;\n\n if (config.rate.interval === \"day\") {\n return hours * 3_600_000;\n }\n\n // For minute/hour rates, the active window doesn't change the interval\n return getFullIntervalMs(config.rate.interval);\n}\n\nfunction getFullIntervalMs(interval: \"minute\" | \"hour\" | \"day\"): number {\n switch (interval) {\n case \"minute\": return 60_000;\n case \"hour\": return 3_600_000;\n case \"day\": return 86_400_000;\n }\n}\n\nfunction getHourInTimezone(date: Date, timezone?: string): number {\n if (!timezone) return date.getUTCHours();\n\n const formatted = new Intl.DateTimeFormat(\"en-US\", {\n hour: \"numeric\",\n hour12: false,\n timeZone: timezone,\n }).format(date);\n\n return parseInt(formatted, 10);\n}\n","import type { TokenBucketJobConfig, TokenBucketState } from \"@/types\";\nimport { getActiveWindowMs } from \"./active-hours\";\nimport { INTERVAL_MS } from \"./constants\";\n\nexport interface BudgetResult {\n budget: number;\n newCredit: number;\n newWindowDispatched: number;\n newWindowResetAt: Date;\n}\n\nexport function calculateBudget(\n state: TokenBucketState,\n config: TokenBucketJobConfig<any, any>,\n now: Date,\n): BudgetResult {\n const nowMs = now.getTime();\n const windowResetMs = state.windowResetAt.getTime();\n\n // Reset window if expired\n let windowDispatched = state.windowDispatched;\n let windowResetAt = state.windowResetAt;\n\n if (nowMs >= windowResetMs) {\n windowDispatched = 0;\n windowResetAt = computeNextWindowReset(now, config.rate.interval);\n }\n\n // Calculate credit\n const elapsedMs = nowMs - state.lastTickAt.getTime();\n if (elapsedMs <= 0) {\n return { budget: 0, newCredit: state.accumulatedCredit, newWindowDispatched: windowDispatched, newWindowResetAt: windowResetAt };\n }\n\n const activeWindowMs = getActiveWindowMs(config);\n const msPerItem = activeWindowMs / config.rate.amount;\n const earnedCredit = elapsedMs / msPerItem;\n let credit = state.accumulatedCredit + earnedCredit;\n\n // Cap at maxPerBeat\n const maxPerBeat = config.maxPerBeat ?? computeDefaultMaxPerBeat(config);\n credit = Math.min(credit, maxPerBeat);\n\n // Budget = floor(credit), capped at remaining window allowance\n const remaining = Math.max(0, config.rate.amount - windowDispatched);\n const budget = Math.min(Math.floor(credit), remaining);\n\n return {\n budget,\n newCredit: credit - budget,\n newWindowDispatched: windowDispatched + budget,\n newWindowResetAt: windowResetAt,\n };\n}\n\nfunction computeDefaultMaxPerBeat(config: TokenBucketJobConfig<any, any>): number {\n // Default max per beat: allow at most 1 full interval's worth, minimum 1\n return Math.max(1, Math.ceil(config.rate.amount / 10));\n}\n\nfunction computeNextWindowReset(now: Date, interval: \"minute\" | \"hour\" | \"day\"): Date {\n return new Date(now.getTime() + INTERVAL_MS[interval]);\n}\n","import { Job, Queue, QueueEvents } from \"bullmq\";\nimport type { TokenBucketJobConfig, ResolvedJobConfig } from \"@/types\";\nimport { tokenBucketRepo } from \"@/mongo\";\nimport { getLogger } from \"@/logger\";\nimport { isWithinActiveHours } from \"./active-hours\";\nimport { calculateBudget } from \"./budget\";\nimport { TOKEN_BUCKET_PROCESS_SUFFIX, INTERVAL_MS } from \"./constants\";\nimport { dispatchSubJobsFireAndForget, type SubJobOptions } from \"../sub-job\";\n\nexport async function processTokenBucketJob<TItem, TResult>(\n job: Job,\n config: ResolvedJobConfig<TokenBucketJobConfig<TItem, TResult>>,\n queues: Record<string, { queue: Queue; events: QueueEvents }>,\n): Promise<{ dispatched: number }> {\n const logger = getLogger();\n const jobName = job.name;\n const now = new Date();\n\n // Check active hours\n if (!isWithinActiveHours(config, now)) {\n logger.debug({ jobName }, \"[token-bucket] outside active hours, skipping\");\n return { dispatched: 0 };\n }\n\n // Load or create state\n const initialWindowReset = new Date(now.getTime() + INTERVAL_MS[config.rate.interval]);\n const state = await tokenBucketRepo.getOrCreateState(jobName, now, initialWindowReset);\n\n // Calculate budget\n const { budget, newCredit, newWindowDispatched, newWindowResetAt } = calculateBudget(state, config, now);\n\n if (budget <= 0) {\n // Still update lastTickAt so elapsed time doesn't balloon\n await tokenBucketRepo.updateState(jobName, newCredit, now, newWindowDispatched, newWindowResetAt);\n logger.debug({ jobName, credit: newCredit }, \"[token-bucket] no budget, skipping\");\n return { dispatched: 0 };\n }\n\n // Fetch items\n const items = await config.getItems(budget);\n\n if (items.length === 0) {\n await tokenBucketRepo.updateState(jobName, newCredit, now, newWindowDispatched, newWindowResetAt);\n logger.debug({ jobName }, \"[token-bucket] no items to dispatch\");\n return { dispatched: 0 };\n }\n\n // Dispatch sub-jobs (fire-and-forget)\n const queueData = queues[config.queue];\n if (!queueData) {\n throw new Error(`[token-bucket] queue \"${config.queue}\" not found`);\n }\n\n const subJobOptions: SubJobOptions | undefined = config.steps?.process\n ? { attempts: config.steps.process.attempts, backoff: config.steps.process.backoff }\n : undefined;\n\n const subJobName = `${jobName}${TOKEN_BUCKET_PROCESS_SUFFIX}`;\n await dispatchSubJobsFireAndForget(queueData.queue, subJobName, items, subJobOptions);\n\n // Update state — adjust credit and window count for actual items dispatched\n const actualDispatched = items.length;\n const adjustedCredit = Math.max(0, newCredit - Math.max(0, budget - actualDispatched));\n const adjustedWindowDispatched = newWindowDispatched - (budget - actualDispatched);\n\n await tokenBucketRepo.updateState(jobName, adjustedCredit, now, adjustedWindowDispatched, newWindowResetAt);\n\n logger.info(\n { jobName, dispatched: actualDispatched, credit: adjustedCredit, windowDispatched: adjustedWindowDispatched },\n \"[token-bucket] dispatched items\",\n );\n\n return { dispatched: actualDispatched };\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_PROCESS_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 const jobsProxy: Record<string, { send: (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\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_PROCESS_SUFFIX,\n] as const;\n\nfunction 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_PROCESS_SUFFIX) {\n return await jobConfig.process(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 { ConnectionOptions, Worker, Job } from \"bullmq\";\nimport { getLogger } from \"../logger\";\nimport { printWorkerBanner } from \"../banner\";\nimport { JobConfig } from \"../types\";\n\nexport function createWorker(\n queueName: string,\n connection: ConnectionOptions,\n concurrency: number,\n processJob: (job: Job) => Promise<any>\n): Worker {\n const worker = new Worker(queueName, processJob, {\n connection,\n autorun: false,\n concurrency,\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 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 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 { 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 } from \"../mongo\";\nimport { StallWatcher } from \"../internal-jobs\";\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}\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) {\n errors.push(`\"${jobName}\" (token-bucket) requires a cron schedule.`);\n }\n\n // Step queue references must exist in config\n if (\"steps\" in jc && jc.steps) {\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\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\n public async startWorker(\n queueName: string,\n options?: { concurrency?: number },\n ) {\n if (this.mongoUri) {\n await connectMongo(this.mongoUri);\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 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) => {\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 (this.stallWatcher) {\n await this.stallWatcher.start();\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 await closeWorkers(this.workers);\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\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 function createRavenflowApp<TConfig extends RavenflowConfig>(\n config: TConfig,\n options: RavenflowAppOptions,\n): RavenflowApp<TConfig> {\n return new RavenflowApp(config, options);\n}\n"]}