{"version":3,"sources":["jsdelivr-header.js","/npm/agenda@6.2.3/dist/index.js"],"names":[],"mappings":"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","file":"/npm/agenda@6.2.3/dist/index.js","sourceRoot":"","sourcesContent":["/**\n * Minified by jsDelivr using Terser v5.39.0.\n * Original file: /npm/agenda@6.2.3/dist/index.js\n *\n * Do NOT use SRI with dynamically generated files! More information: https://www.jsdelivr.com/using-sri-with-dynamic-files\n */\n","import { EventEmitter } from 'events';\nimport debug from 'debug';\nimport { Job } from './Job.js';\nimport { parsePriority } from './utils/priority.js';\nimport { JobProcessor } from './JobProcessor.js';\nimport { calculateProcessEvery } from './utils/processEvery.js';\nimport { getCallerFilePath } from './utils/stack.js';\nconst log = debug('agenda');\nconst DefaultOptions = {\n    processEvery: 5000,\n    defaultConcurrency: 5,\n    maxConcurrency: 20,\n    defaultLockLimit: 0,\n    lockLimit: 0,\n    defaultLockLifetime: 10 * 60 * 1000,\n    forkHelper: { path: 'dist/childWorker.js' },\n    removeOnComplete: false\n};\n/**\n * @class\n */\nexport class Agenda extends EventEmitter {\n    attrs;\n    forkedWorker;\n    forkHelper;\n    backend;\n    db;\n    notificationChannel;\n    stateSubscriptionUnsubscribe;\n    /**\n     * The persistent job logger for storing job lifecycle events in the database.\n     * Disabled by default. Enable via `logging: true` (uses backend's built-in logger)\n     * or by passing a custom `JobLogger` implementation.\n     */\n    jobLogger;\n    /**\n     * Default logging behavior for job definitions that don't explicitly set `logging`.\n     * When `true` (default when logging is enabled), all jobs are logged.\n     * When `false`, only jobs with `logging: true` in their definition are logged.\n     */\n    loggingDefault;\n    // Implementation (eslint-disable needed because overloads provide the public type safety)\n    // eslint-disable-next-line @typescript-eslint/no-explicit-any\n    on(event, listener) {\n        if (this.forkedWorker && event !== 'ready' && event !== 'error') {\n            const warning = new Error(`calling on(${event}) during a forkedWorker has no effect!`);\n            log('WARNING: %s %s', warning.message, warning.stack);\n            return this;\n        }\n        return super.on(event, listener);\n    }\n    definitions = {};\n    jobProcessor;\n    ready;\n    isActiveJobProcessor() {\n        return !!this.jobProcessor;\n    }\n    async runForkedJob(jobId) {\n        const jobData = await this.db.getJobById(jobId);\n        if (!jobData) {\n            throw new Error('db entry not found');\n        }\n        const job = new Job(this, jobData);\n        await job.runJob();\n    }\n    async getRunningStats(fullDetails = false) {\n        if (!this.jobProcessor) {\n            throw new Error('agenda not running!');\n        }\n        const status = await this.jobProcessor.getStatus(fullDetails);\n        // Add backend info (stored in Agenda, not JobProcessor)\n        status.backend = {\n            name: this.backend.name,\n            hasNotificationChannel: this.hasNotificationChannel()\n        };\n        return status;\n    }\n    /**\n     * @param config - Agenda configuration with backend\n     * @param cb - Optional callback after Agenda is ready\n     */\n    constructor(config, cb) {\n        super();\n        // Prevent unhandled 'error' events from crashing the process.\n        // Users can still attach their own 'error' listener to handle errors.\n        this.on('error', () => { });\n        this.attrs = {\n            name: config.name || '',\n            processEvery: calculateProcessEvery(config.processEvery) || DefaultOptions.processEvery,\n            defaultConcurrency: config.defaultConcurrency || DefaultOptions.defaultConcurrency,\n            maxConcurrency: config.maxConcurrency || DefaultOptions.maxConcurrency,\n            defaultLockLimit: config.defaultLockLimit || DefaultOptions.defaultLockLimit,\n            lockLimit: config.lockLimit || DefaultOptions.lockLimit,\n            defaultLockLifetime: config.defaultLockLifetime || DefaultOptions.defaultLockLifetime,\n            removeOnComplete: config.removeOnComplete ?? DefaultOptions.removeOnComplete\n        };\n        this.forkedWorker = config.forkedWorker;\n        this.forkHelper = config.forkHelper;\n        // Initialize persistent job logger: disabled by default\n        if (config.logging === true) {\n            // Use backend's built-in logger, all jobs logged\n            this.jobLogger = config.backend.logger;\n            this.loggingDefault = true;\n        }\n        else if (config.logging && typeof config.logging === 'object' && 'log' in config.logging) {\n            // Passed a JobLogger instance directly — all jobs logged\n            this.jobLogger = config.logging;\n            this.loggingDefault = true;\n        }\n        else if (config.logging && typeof config.logging === 'object') {\n            // Options object: { logger?, default? }\n            const opts = config.logging;\n            this.jobLogger = opts.logger ?? config.backend.logger;\n            this.loggingDefault = opts.default ?? true;\n        }\n        else {\n            // Logging disabled (false / omitted)\n            this.loggingDefault = true;\n        }\n        // Store backend and get repository\n        this.backend = config.backend;\n        this.db = config.backend.repository;\n        // Notification channel priority: explicit config > backend's channel\n        this.notificationChannel = config.notificationChannel ?? config.backend.notificationChannel;\n        // Ready promise resolves when backend is connected\n        this.ready = new Promise(resolve => {\n            this.once('ready', resolve);\n        });\n        // Connect the backend\n        this.backend.connect().then(() => this.emit('ready'));\n        if (cb) {\n            this.ready.then(() => cb());\n        }\n    }\n    /**\n     * Cancels any jobs matching the passed options, and removes them from the database.\n     * @param options Options for which jobs to cancel\n     */\n    async cancel(options) {\n        log('attempting to cancel all Agenda jobs', options);\n        await this.ready;\n        try {\n            const amountOfRemovedJobs = await this.db.removeJobs(options);\n            log('%s jobs cancelled', amountOfRemovedJobs);\n            return amountOfRemovedJobs;\n        }\n        catch (error) {\n            log('error trying to delete jobs from database');\n            throw error;\n        }\n    }\n    /**\n     * Disables any jobs matching the passed options, preventing them from being run.\n     * @param options Options for which jobs to disable\n     * @returns Number of jobs disabled\n     */\n    async disable(options) {\n        log('attempting to disable Agenda jobs', options);\n        await this.ready;\n        try {\n            const numDisabled = await this.db.disableJobs(options);\n            log('%s jobs disabled', numDisabled);\n            return numDisabled;\n        }\n        catch (error) {\n            log('error trying to disable jobs');\n            throw error;\n        }\n    }\n    /**\n     * Enables any jobs matching the passed options, allowing them to be run.\n     * @param options Options for which jobs to enable\n     * @returns Number of jobs enabled\n     */\n    async enable(options) {\n        log('attempting to enable Agenda jobs', options);\n        await this.ready;\n        try {\n            const numEnabled = await this.db.enableJobs(options);\n            log('%s jobs enabled', numEnabled);\n            return numEnabled;\n        }\n        catch (error) {\n            log('error trying to enable jobs');\n            throw error;\n        }\n    }\n    /**\n     * Set name of queue\n     * @param name\n     */\n    name(name) {\n        log('Agenda.name(%s)', name);\n        this.attrs.name = name;\n        return this;\n    }\n    /**\n     * Set the time how often the job processor checks for new jobs to process\n     * @param time\n     */\n    processEvery(time) {\n        if (this.jobProcessor) {\n            throw new Error('job processor is already running, you need to set processEvery before calling start');\n        }\n        log('Agenda.processEvery(%d)', time);\n        this.attrs.processEvery = calculateProcessEvery(time);\n        return this;\n    }\n    /**\n     * Set the concurrency for jobs (globally), type does not matter\n     * @param num\n     */\n    maxConcurrency(num) {\n        log('Agenda.maxConcurrency(%d)', num);\n        this.attrs.maxConcurrency = num;\n        return this;\n    }\n    /**\n     * Set the default concurrency for each job\n     * @param num number of max concurrency\n     */\n    defaultConcurrency(num) {\n        log('Agenda.defaultConcurrency(%d)', num);\n        this.attrs.defaultConcurrency = num;\n        return this;\n    }\n    /**\n     * Set the default amount jobs that are allowed to be locked at one time (GLOBAL)\n     * @param num\n     */\n    lockLimit(num) {\n        log('Agenda.lockLimit(%d)', num);\n        this.attrs.lockLimit = num;\n        return this;\n    }\n    /**\n     * Set default lock limit per job type\n     * @param num\n     */\n    defaultLockLimit(num) {\n        log('Agenda.defaultLockLimit(%d)', num);\n        this.attrs.defaultLockLimit = num;\n        return this;\n    }\n    /**\n     * Set the default lock time (in ms)\n     * Default is 10 * 60 * 1000 ms (10 minutes)\n     * @param ms\n     */\n    defaultLockLifetime(ms) {\n        log('Agenda.defaultLockLifetime(%d)', ms);\n        this.attrs.defaultLockLifetime = ms;\n        return this;\n    }\n    /**\n     * Set a notification channel for real-time job notifications\n     * @param channel - The notification channel implementation\n     */\n    notifyVia(channel) {\n        if (this.jobProcessor) {\n            throw new Error('job processor is already running, you need to set notificationChannel before calling start');\n        }\n        log('Agenda.notifyVia([NotificationChannel])');\n        this.notificationChannel = channel;\n        return this;\n    }\n    /**\n     * Check if a notification channel is configured\n     */\n    hasNotificationChannel() {\n        return !!this.notificationChannel;\n    }\n    /**\n     * Check if persistent job logging is enabled\n     */\n    hasJobLogger() {\n        return !!this.jobLogger;\n    }\n    /**\n     * Log a job lifecycle event to the persistent job logger (fire-and-forget).\n     * Does nothing if no job logger is configured or if logging is disabled\n     * for the job definition (respects per-definition `logging` and the global `loggingDefault`).\n     * @internal\n     */\n    logJobEvent(entry) {\n        if (!this.jobLogger)\n            return;\n        // Per-definition logging overrides the global default.\n        // If definition.logging is undefined, fall back to loggingDefault.\n        const definition = this.definitions[entry.jobName];\n        const enabled = definition?.logging ?? this.loggingDefault;\n        if (!enabled)\n            return;\n        this.jobLogger\n            .log({\n            ...entry,\n            timestamp: new Date(),\n            agendaName: this.attrs.name || undefined\n        })\n            .catch(err => {\n            log('failed to write job log entry: %O', err);\n        });\n    }\n    /**\n     * Query persistent job logs.\n     * Returns empty result if no job logger is configured.\n     */\n    async getLogs(query) {\n        if (!this.jobLogger) {\n            return { entries: [], total: 0 };\n        }\n        return this.jobLogger.getLogs(query);\n    }\n    /**\n     * Clear persistent job logs matching the query.\n     * Returns 0 if no job logger is configured.\n     */\n    async clearLogs(query) {\n        if (!this.jobLogger) {\n            return 0;\n        }\n        return this.jobLogger.clearLogs(query);\n    }\n    /**\n     * Publish a job notification to the notification channel\n     * @internal\n     */\n    async publishJobNotification(job) {\n        if (!this.notificationChannel || this.notificationChannel.state !== 'connected') {\n            // Channel not configured or not connected - skip publishing\n            return;\n        }\n        const notification = {\n            jobId: job.attrs._id,\n            jobName: job.attrs.name,\n            nextRunAt: job.attrs.nextRunAt,\n            priority: job.attrs.priority,\n            timestamp: new Date(),\n            source: this.attrs.name || undefined\n        };\n        try {\n            await this.notificationChannel.publish(notification);\n            log('published job notification for [%s:%s]', job.attrs.name, job.attrs._id);\n        }\n        catch (error) {\n            log('failed to publish job notification for [%s:%s]', job.attrs.name, job.attrs._id, error);\n            this.emit('error', error);\n        }\n    }\n    /**\n     * Publish a job state notification to the notification channel.\n     * This enables bi-directional communication so that all subscribers\n     * can receive job lifecycle events (start, success, fail, complete, etc.)\n     * @internal\n     */\n    publishJobStateNotification(job, type, extra) {\n        if (!this.notificationChannel ||\n            this.notificationChannel.state !== 'connected' ||\n            !this.notificationChannel.publishState) {\n            // Channel not configured, not connected, or doesn't support state notifications\n            return;\n        }\n        const notification = {\n            type,\n            jobId: job.attrs._id,\n            jobName: job.attrs.name,\n            timestamp: new Date(),\n            source: this.attrs.name || undefined,\n            ...extra\n        };\n        // fire+forget\n        this.notificationChannel\n            .publishState(notification)\n            .then(() => {\n            log('published job state notification [%s] for [%s:%s]', type, job.attrs.name, job.attrs._id);\n        })\n            .catch(error => {\n            log('failed to publish job state notification [%s] for [%s:%s]', type, job.attrs.name, job.attrs._id, error);\n            this.emit('error', error);\n        });\n    }\n    /**\n     * Subscribe to state notifications and re-emit them as regular events.\n     * This allows `agenda.on('success:jobName', ...)` to work across processes.\n     * @internal\n     */\n    subscribeToStateNotifications() {\n        if (!this.notificationChannel?.subscribeState) {\n            return () => { };\n        }\n        return this.notificationChannel.subscribeState(notification => {\n            // Skip events from our own instance to avoid double-firing\n            // (we already emit locally in Job.run())\n            // Handle both empty strings and undefined as \"same source\" when both are falsy\n            const notificationSource = notification.source || '';\n            const ourSource = this.attrs.name || '';\n            if (notificationSource === ourSource) {\n                return;\n            }\n            log('received remote state notification [%s] for [%s:%s]', notification.type, notification.jobName, notification.jobId);\n            // Use nextTick to ensure local events are processed first\n            // This prevents race conditions where remote events arrive before local processing completes\n            process.nextTick(() => {\n                // Re-emit as regular events with remote=true flag\n                // For 'fail' events, the first argument is the error\n                if (notification.type === 'fail') {\n                    this.emit('fail', notification.error, notification, true);\n                    this.emit(`fail:${notification.jobName}`, notification.error, notification, true);\n                }\n                else if (notification.type === 'retry') {\n                    // For 'retry' events, pass retry details as second argument\n                    const retryDetails = {\n                        attempt: notification.retryAttempt || 1,\n                        delay: 0, // Not available in notification\n                        nextRunAt: notification.retryAt || new Date(),\n                        error: new Error(notification.error || 'Unknown error')\n                    };\n                    this.emit('retry', notification, retryDetails, true);\n                    this.emit(`retry:${notification.jobName}`, notification, retryDetails, true);\n                }\n                else {\n                    this.emit(notification.type, notification, true);\n                    this.emit(`${notification.type}:${notification.jobName}`, notification, true);\n                }\n            });\n        });\n    }\n    /**\n     * Query jobs with database-agnostic options.\n     * Returns jobs with computed states and supports filtering by state.\n     *\n     * @param options - Query options (name, state, search, pagination)\n     * @returns Jobs with computed states and total count\n     */\n    async queryJobs(options) {\n        await this.ready;\n        return this.db.queryJobs(options);\n    }\n    /**\n     * Get overview statistics for jobs grouped by name.\n     * Returns counts of jobs in each state for each job name.\n     *\n     * @returns Array of job overviews with state counts\n     */\n    async getJobsOverview() {\n        await this.ready;\n        return this.db.getJobsOverview();\n    }\n    /**\n     * Removes all jobs from queue\n     * @note: Only use after defining your jobs\n     */\n    async purge() {\n        const definedNames = Object.keys(this.definitions);\n        log('Agenda.purge(%o)', definedNames);\n        return this.cancel({ notNames: definedNames });\n    }\n    define(name, processor, options) {\n        if (this.definitions[name]) {\n            log('overwriting already defined agenda job', name);\n        }\n        const filePath = getCallerFilePath();\n        this.definitions[name] = {\n            fn: processor,\n            filePath,\n            concurrency: options?.concurrency || this.attrs.defaultConcurrency,\n            lockLimit: options?.lockLimit || this.attrs.defaultLockLimit,\n            priority: parsePriority(options?.priority),\n            lockLifetime: options?.lockLifetime || this.attrs.defaultLockLifetime,\n            backoff: options?.backoff,\n            removeOnComplete: options?.removeOnComplete ?? this.attrs.removeOnComplete,\n            logging: options?.logging\n        };\n        log('job [%s] defined with following options: \\n%O', name, this.definitions[name]);\n    }\n    /**\n     * Internal helper method that uses createJob to create jobs for an array of names\n     * @param names - Job names to schedule\n     * @param createJob - Factory function to create each job\n     * @returns Array of created jobs\n     */\n    async createJobs(names, createJob) {\n        try {\n            const jobs = await Promise.all(names.map(name => createJob(name)));\n            log('createJobs() -> all jobs created successfully');\n            return jobs;\n        }\n        catch (error) {\n            log('createJobs() -> error creating one or more of the jobs', error);\n            throw error;\n        }\n    }\n    // eslint-disable-next-line @typescript-eslint/no-explicit-any\n    create(name, data) {\n        log('Agenda.create(%s, [Object])', name);\n        const priority = this.definitions[name] ? this.definitions[name].priority : 0;\n        return new Job(this, { name, data, type: 'normal', priority });\n    }\n    async every(interval, names, data, options) {\n        log('Agenda.every(%s, %O, %O)', interval, names, options);\n        /** Internal method to setup job that gets run every interval */\n        const createJob = async (name) => {\n            const job = this.create(name, data);\n            job.attrs.type = 'single';\n            // Apply date constraints before repeatEvery (so they're used in nextRunAt computation)\n            if (options?.startDate) {\n                job.startDate(options.startDate);\n            }\n            if (options?.endDate) {\n                job.endDate(options.endDate);\n            }\n            if (options?.skipDays) {\n                job.skipDays(options.skipDays);\n            }\n            job.repeatEvery(interval, options);\n            if (options?.forkMode) {\n                job.forkMode(options.forkMode);\n            }\n            await job.save();\n            return job;\n        };\n        if (typeof names === 'string') {\n            return createJob(names);\n        }\n        log('Agenda.every(%s, %s, %O)', interval, names, options);\n        return this.createJobs(names, createJob);\n    }\n    async schedule(when, names, data, options) {\n        const createJob = async (name) => {\n            const job = this.create(name, data);\n            // Apply date constraints before scheduling\n            if (options?.startDate) {\n                job.startDate(options.startDate);\n            }\n            if (options?.endDate) {\n                job.endDate(options.endDate);\n            }\n            if (options?.skipDays) {\n                job.skipDays(options.skipDays);\n            }\n            await job.schedule(when).save();\n            return job;\n        };\n        if (typeof names === 'string') {\n            log('Agenda.schedule(%s, %O, [%O])', when, names);\n            return createJob(names);\n        }\n        log('Agenda.schedule(%s, %O, [%O])', when, names);\n        return this.createJobs(names, createJob);\n    }\n    async now(name, data) {\n        log('Agenda.now(%s, [Object])', name);\n        try {\n            const job = this.create(name, data);\n            job.schedule(new Date());\n            await job.save();\n            return job;\n        }\n        catch (error) {\n            log('error trying to create a job for this exact moment');\n            throw error;\n        }\n    }\n    /**\n     * Create a debounced job that combines rapid submissions into a single execution.\n     * Requires a unique key to identify which jobs should be debounced together.\n     *\n     * @param name - Job name\n     * @param data - Job data\n     * @param uniqueKey - Unique constraint to identify jobs (e.g., { 'data.userId': 123 })\n     * @param debounceMs - Debounce delay in milliseconds\n     * @param options - Optional debounce options (maxWait, strategy)\n     *\n     * @example\n     * ```ts\n     * // Debounce search index updates by entity type\n     * await agenda.nowDebounced(\n     *   'updateSearchIndex',\n     *   { entityType: 'products' },\n     *   { 'data.entityType': 'products' },\n     *   2000\n     * );\n     *\n     * // With maxWait to guarantee execution within 30s\n     * await agenda.nowDebounced(\n     *   'syncUser',\n     *   { userId: 123 },\n     *   { 'data.userId': 123 },\n     *   5000,\n     *   { maxWait: 30000 }\n     * );\n     * ```\n     */\n    async nowDebounced(name, data, uniqueKey, debounceMs, options) {\n        log('Agenda.nowDebounced(%s, [Object], %O, %d)', name, uniqueKey, debounceMs);\n        try {\n            const job = this.create(name, data);\n            job.schedule(new Date()).unique(uniqueKey).debounce(debounceMs, options);\n            await job.save();\n            return job;\n        }\n        catch (error) {\n            log('error trying to create a debounced job');\n            throw error;\n        }\n    }\n    /**\n     * Starts processing jobs using processJobs() methods, storing an interval ID\n     * This method will only resolve if a db has been set up beforehand.\n     */\n    async start() {\n        log('Agenda.start called, waiting for agenda to be initialized (db connection)', this.attrs.processEvery);\n        await this.ready;\n        if (this.jobProcessor) {\n            log('Agenda.start was already called, ignoring');\n            return;\n        }\n        // Connect notification channel if configured\n        if (this.notificationChannel) {\n            log('Agenda.start connecting notification channel');\n            await this.notificationChannel.connect();\n            // Subscribe to state notifications for cross-process event propagation\n            this.stateSubscriptionUnsubscribe = this.subscribeToStateNotifications();\n        }\n        this.jobProcessor = new JobProcessor(this, this.attrs.maxConcurrency, this.attrs.lockLimit, this.attrs.processEvery, this.notificationChannel);\n    }\n    /**\n     * Clear the interval that processes the jobs and unlocks all currently locked jobs\n     * @param closeConnection - Whether to close the database connection.\n     *   Defaults to backend.ownsConnection (true if backend created the connection,\n     *   false if connection was passed in by user).\n     */\n    async stop(closeConnection) {\n        if (!this.jobProcessor) {\n            log('Agenda.stop called, but agenda has never started!');\n            return;\n        }\n        log('Agenda.stop called, clearing interval for processJobs()');\n        const lockedJobs = this.jobProcessor.stop();\n        log('Agenda._unlockJobs()');\n        const jobIds = lockedJobs?.map(job => job.attrs._id) || [];\n        if (jobIds.length > 0) {\n            log('about to unlock jobs with ids: %O', jobIds);\n            await this.db.unlockJobs(jobIds);\n        }\n        // Unsubscribe from state notifications\n        if (this.stateSubscriptionUnsubscribe) {\n            this.stateSubscriptionUnsubscribe();\n            this.stateSubscriptionUnsubscribe = undefined;\n        }\n        // Disconnect notification channel if configured (we always disconnect since we connected it in start)\n        if (this.notificationChannel) {\n            log('Agenda.stop disconnecting notification channel');\n            await this.notificationChannel.disconnect();\n        }\n        // Determine whether to close backend connection\n        const shouldClose = closeConnection ?? this.backend.ownsConnection ?? true;\n        // Disconnect the backend\n        if (shouldClose) {\n            log('Agenda.stop disconnecting backend');\n            await this.backend.disconnect();\n        }\n        this.jobProcessor = undefined;\n    }\n    /**\n     * Waits for all currently running jobs to finish before stopping.\n     * This allows for a graceful shutdown where jobs complete their work.\n     * Unlike stop(), this method waits for running jobs to complete instead of unlocking them.\n     *\n     * @param options - Drain options or timeout in milliseconds\n     *   - `timeout`: Maximum time to wait for jobs to complete\n     *   - `signal`: AbortSignal to cancel the drain operation\n     *   - `closeConnection`: Whether to close the database connection (default: backend.ownsConnection)\n     * @returns DrainResult with completion statistics\n     *\n     * @example\n     * // Wait indefinitely for all jobs to complete\n     * await agenda.drain();\n     *\n     * @example\n     * // Wait up to 30 seconds\n     * const result = await agenda.drain(30000);\n     * if (result.timedOut) console.log(`${result.running} jobs still running`);\n     *\n     * @example\n     * // Use AbortSignal for external control\n     * const controller = new AbortController();\n     * setTimeout(() => controller.abort(), 30000);\n     * await agenda.drain({ signal: controller.signal });\n     */\n    async drain(options) {\n        if (!this.jobProcessor) {\n            log('Agenda.drain called, but agenda has never started!');\n            return { completed: 0, running: 0, timedOut: false, aborted: false };\n        }\n        // Normalize options\n        const opts = typeof options === 'number' ? { timeout: options } : options ?? {};\n        log('Agenda.drain called, waiting for jobs to finish');\n        const result = await this.jobProcessor.drain(opts);\n        // Unsubscribe from state notifications\n        if (this.stateSubscriptionUnsubscribe) {\n            this.stateSubscriptionUnsubscribe();\n            this.stateSubscriptionUnsubscribe = undefined;\n        }\n        // Disconnect notification channel if configured (we always disconnect since we connected it in start)\n        if (this.notificationChannel) {\n            log('Agenda.drain disconnecting notification channel');\n            await this.notificationChannel.disconnect();\n        }\n        // Determine whether to close backend connection\n        const shouldClose = opts.closeConnection ?? this.backend.ownsConnection ?? true;\n        // Disconnect the backend\n        if (shouldClose) {\n            log('Agenda.drain disconnecting backend');\n            await this.backend.disconnect();\n        }\n        this.jobProcessor = undefined;\n        return result;\n    }\n}\nexport * from './types/AgendaConfig.js';\nexport * from './types/JobDefinition.js';\nexport * from './types/JobParameters.js';\nexport * from './types/DbOptions.js';\nexport * from './Job.js';\nexport * from './types/JobQuery.js';\nexport * from './types/JobRepository.js';\nexport * from './types/NotificationChannel.js';\nexport * from './types/AgendaBackend.js';\nexport * from './types/AgendaStatus.js';\nexport * from './types/DrainOptions.js';\nexport * from './notifications/index.js';\nexport * from './types/JobLogger.js';\nexport { applyAllDateConstraints, applyDateRangeConstraints, applySkipDays, shouldSkipDay, isWithinDateRange } from './utils/dateConstraints.js';\nexport * from './decorators/index.js';\nexport { backoffStrategies, constant, linear, exponential, combine, when } from './utils/backoff.js';\n"]}