From f9a2eaa9b3cf649da3244b8af07cff09cb0f1e2c Mon Sep 17 00:00:00 2001 From: Harminder Virk Date: Tue, 28 Apr 2026 15:34:59 +0530 Subject: [PATCH] refactor: start queue in all environments except the console environment and during start phase BREAKING CHANGE: Any custom console commands relying on jobs to be registered with the queue manager will not work. They will have to resolve the queue.manager from the container and explicitly invoke the start method --- .github/workflows/stale.yml | 12 +++++----- README.md | 7 ++---- commands/queue_work.ts | 10 ++++----- providers/queue_provider.ts | 44 ++++++++++++++++--------------------- src/types/extended.ts | 4 +++- src/utils.ts | 19 ++++++++++++++++ 6 files changed, 54 insertions(+), 42 deletions(-) diff --git a/.github/workflows/stale.yml b/.github/workflows/stale.yml index b750bf5..cad5c91 100644 --- a/.github/workflows/stale.yml +++ b/.github/workflows/stale.yml @@ -1,7 +1,7 @@ -name: "Close stale issues and PRs" +name: 'Close stale issues and PRs' on: schedule: - - cron: "30 0 * * *" + - cron: '30 0 * * *' jobs: stale: @@ -9,9 +9,9 @@ jobs: steps: - uses: actions/stale@v9 with: - stale-issue-message: "This issue has been marked as stale because it has been inactive for more than 21 days. Please reopen if you still need help on this issue" - stale-pr-message: "This pull request has been marked as stale because it has been inactive for more than 21 days. Please reopen if you still intend to submit this pull request" - close-issue-message: "This issue has been automatically closed because it has been inactive for more than 4 weeks. Please reopen if you still need help on this issue" - close-pr-message: "This pull request has been automatically closed because it has been inactive for more than 4 weeks. Please reopen if you still intend to submit this pull request" + stale-issue-message: 'This issue has been marked as stale because it has been inactive for more than 21 days. Please reopen if you still need help on this issue' + stale-pr-message: 'This pull request has been marked as stale because it has been inactive for more than 21 days. Please reopen if you still intend to submit this pull request' + close-issue-message: 'This issue has been automatically closed because it has been inactive for more than 4 weeks. Please reopen if you still need help on this issue' + close-pr-message: 'This pull request has been automatically closed because it has been inactive for more than 4 weeks. Please reopen if you still intend to submit this pull request' days-before-stale: 21 days-before-close: 5 diff --git a/README.md b/README.md index 2bfc420..412a59c 100644 --- a/README.md +++ b/README.md @@ -27,12 +27,9 @@ In order to ensure that the AdonisJS community is welcoming to all, please revie AdonisJS Queue is open-sourced software licensed under the [MIT license](LICENSE.md). [gh-workflow-image]: https://img.shields.io/github/actions/workflow/status/adonisjs/queue/checks.yml?style=for-the-badge -[gh-workflow-url]: https://github.com/adonisjs/queue/actions/workflows/checks.yml "Github action" - +[gh-workflow-url]: https://github.com/adonisjs/queue/actions/workflows/checks.yml 'Github action' [npm-image]: https://img.shields.io/npm/v/@adonisjs/queue/latest.svg?style=for-the-badge&logo=npm -[npm-url]: https://www.npmjs.com/package/@adonisjs/queue/v/latest "npm" - +[npm-url]: https://www.npmjs.com/package/@adonisjs/queue/v/latest 'npm' [typescript-image]: https://img.shields.io/badge/Typescript-294E80.svg?style=for-the-badge&logo=typescript - [license-url]: LICENSE.md [license-image]: https://img.shields.io/github/license/adonisjs/queue?style=for-the-badge diff --git a/commands/queue_work.ts b/commands/queue_work.ts index aba1b97..538223f 100644 --- a/commands/queue_work.ts +++ b/commands/queue_work.ts @@ -8,8 +8,8 @@ */ import { flags, BaseCommand } from '@adonisjs/core/ace' -import { resolveAdapters, resolveJobFactory } from '../src/utils.js' import type { CommandOptions } from '@adonisjs/core/types/ace' +import { resolveAdapters, resolveJobFactory } from '../src/utils.js' import type { QueueConfig, QueueManagerConfig } from '../src/types/main.js' export default class QueueWork extends BaseCommand { @@ -30,8 +30,9 @@ export default class QueueWork extends BaseCommand { async run() { const { Worker } = await import('@boringnode/queue') const config = this.app.config.get('queue') - const queueManager = await this.app.container.make('queue.manager') const logger = await this.app.container.make('logger') + const QueueManager = await this.app.container.make('queue.manager') + await QueueManager.start() /** * Commit the router to ensure all routes are registered. @@ -45,12 +46,11 @@ export default class QueueWork extends BaseCommand { const queues = this.queue ? this.queue.split(',').map((q) => q.trim()) : ['default'] this.logger.info(`Starting worker for queues: ${queues.join(', ')}`) - const jobFactory = resolveJobFactory(config, this.app) const workerConfig = { ...config, adapters: resolvedAdapters, - jobFactory, + jobFactory: resolveJobFactory(config, this.app), logger: config.logger ?? logger, worker: { ...config.worker, @@ -63,7 +63,7 @@ export default class QueueWork extends BaseCommand { try { await worker.start(queues) } finally { - await queueManager.destroy() + await QueueManager.destroy() } } } diff --git a/providers/queue_provider.ts b/providers/queue_provider.ts index dbbe2e2..36be066 100644 --- a/providers/queue_provider.ts +++ b/providers/queue_provider.ts @@ -7,10 +7,11 @@ * file that was distributed with this source code. */ -import '../src/types/extended.js' -import { resolveAdapters, resolveJobFactory } from '../src/utils.js' import type { ApplicationService } from '@adonisjs/core/types' -import type { QueueConfig } from '../src/types/main.js' + +import '../src/types/extended.js' +import { initQueue } from '../src/utils.ts' +import { type QueueConfig } from '../src/types/main.ts' export default class QueueProvider { constructor(protected app: ApplicationService) {} @@ -18,35 +19,28 @@ export default class QueueProvider { register() { this.app.container.singleton('queue.manager', async () => { const { QueueManager } = await import('@boringnode/queue') - const config = this.app.config.get('queue') - - const resolvedAdapters = await resolveAdapters(config, this.app) - - /** - * Inject jobFactory if not already defined. - * This enables automatic dependency injection for job classes. - */ - const jobFactory = resolveJobFactory(config, this.app) - - const logger = await this.app.container.make('logger') - await QueueManager.init({ - ...config, - adapters: resolvedAdapters, - jobFactory, - logger: config.logger ?? (logger as any), - }) + ;(QueueManager as any)['start'] = async () => { + const config = this.app.config.get('queue') + const logger = await this.app.container.make('logger') + return initQueue(QueueManager, this.app, config, logger) + } - return QueueManager + return QueueManager as typeof QueueManager & { + start(): Promise + } }) } - async boot() { - await this.app.container.make('queue.manager') + async start() { + if (this.app.getEnvironment() !== 'console') { + const QueueManager = await this.app.container.make('queue.manager') + await QueueManager.start() + } } async shutdown() { - const queueManager = await this.app.container.make('queue.manager') - await queueManager.destroy() + const QueueManager = await this.app.container.make('queue.manager') + await QueueManager.destroy() } } diff --git a/src/types/extended.ts b/src/types/extended.ts index 8dda43c..3db423c 100644 --- a/src/types/extended.ts +++ b/src/types/extended.ts @@ -11,6 +11,8 @@ import type { QueueManager } from '@boringnode/queue' declare module '@adonisjs/core/types' { export interface ContainerBindings { - 'queue.manager': typeof QueueManager + 'queue.manager': typeof QueueManager & { + start(): Promise + } } } diff --git a/src/utils.ts b/src/utils.ts index 8861b4f..246ecec 100644 --- a/src/utils.ts +++ b/src/utils.ts @@ -7,7 +7,9 @@ * file that was distributed with this source code. */ +import { type Logger } from '@adonisjs/core/logger' import type { ApplicationService } from '@adonisjs/core/types' +import type { QueueManager as QueueManagerSingleton } from '@boringnode/queue' import type { AdapterFactory, JobFactory, QueueConfig } from './types/main.js' /** @@ -39,3 +41,20 @@ export async function resolveAdapters( export function resolveJobFactory(config: QueueConfig, app: ApplicationService): JobFactory { return config.jobFactory ?? ((jobClass: any) => app.container.make(jobClass)) } + +export async function initQueue( + manager: typeof QueueManagerSingleton, + app: ApplicationService, + config: QueueConfig, + logger: Logger +) { + const resolvedAdapters = await resolveAdapters(config, app) + const jobFactory = resolveJobFactory(config, app) + + await manager.init({ + ...config, + adapters: resolvedAdapters, + jobFactory, + logger: config.logger ?? logger, + }) +}