{"id":14984826,"url":"https://github.com/rocketseat/adonis-bull","last_synced_at":"2025-04-12T19:46:15.725Z","repository":{"id":36495360,"uuid":"226330598","full_name":"Rocketseat/adonis-bull","owner":"Rocketseat","description":"The easiest way to start using an asynchronous job queue with AdonisJS. Ready for Adonis v5 ⚡️","archived":false,"fork":false,"pushed_at":"2023-09-27T20:57:55.000Z","size":1302,"stargazers_count":311,"open_issues_count":41,"forks_count":57,"subscribers_count":6,"default_branch":"master","last_synced_at":"2025-04-03T21:14:43.155Z","etag":null,"topics":["adonis","adonis5","bull","provider","redis","schedule"],"latest_commit_sha":null,"homepage":"","language":"JavaScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/Rocketseat.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":".github/CONTRIBUTING.md","funding":null,"license":"LICENSE.md","code_of_conduct":".github/CODE_OF_CONDUCT.md","threat_model":null,"audit":null,"citation":null,"codeowners":".github/CODEOWNERS","security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2019-12-06T12:58:35.000Z","updated_at":"2025-03-06T14:35:25.000Z","dependencies_parsed_at":"2024-06-18T18:16:04.541Z","dependency_job_id":"6a347005-9ab3-4ad0-a0a0-65779b28f60c","html_url":"https://github.com/Rocketseat/adonis-bull","commit_stats":{"total_commits":54,"total_committers":13,"mean_commits":4.153846153846154,"dds":0.7037037037037037,"last_synced_commit":"2331e07a3869b37176f955e1422a2346a8e73c62"},"previous_names":[],"tags_count":8,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Rocketseat%2Fadonis-bull","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Rocketseat%2Fadonis-bull/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Rocketseat%2Fadonis-bull/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Rocketseat%2Fadonis-bull/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/Rocketseat","download_url":"https://codeload.github.com/Rocketseat/adonis-bull/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":248625497,"owners_count":21135513,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["adonis","adonis5","bull","provider","redis","schedule"],"created_at":"2024-09-24T14:09:43.471Z","updated_at":"2025-04-12T19:46:15.705Z","avatar_url":"https://github.com/Rocketseat.png","language":"JavaScript","funding_links":[],"categories":[],"sub_categories":[],"readme":"\u003cbr /\u003e\n\n\u003cimg width=\"275\" alt=\"Adonis Bull\" src=\"https://user-images.githubusercontent.com/16545335/71373449-f2146880-2595-11ea-8a8c-9f51384a3f22.png\"\u003e\n\n\u003cp align=\"center\"\u003e\n  \u003ch2\u003eA \u003ca href=\"https://github.com/taskforcesh/bullmq\"\u003eBull\u003c/a\u003e provider for \u003ca href=\"https://adonisjs.com/\"\u003eAdonisJS\u003c/a\u003e \u003c/br\u003e\n  Adonis Bull provides an easy way to start using Bull.\n  \u003c/h2\u003e\n\u003c/p\u003e\n\n\u003cdiv\u003e\n\n[![build-image]][build-url] [![coveralls-image]][coveralls-url] [![license-image]][license-url] [![npm-image]][npm-url]\n\n\u003c/div\u003e\n\n\u003cbr /\u003e\n\n\u003e **This documentation refers to the stable version of Adonis Bull, for Adonis v4.x** \u003cbr /\u003e \u003e **If you are using Adonis v5, [click here](https://github.com/Rocketseat/adonis-bull/tree/alpha).**\n\n## Why\n\nUsing Bull with Adonis shouldn't be hard. It shouldn't require dozens of steps to configure it. That's why adonis-bull exists. It provides an easy way to use queues when developing applications with AdonisJS.\n\n## Install\n\n```sh\nadonis install @rocketseat/adonis-bull\n```\n\n## Usage\n\nRegister the Bull commands at `start/app.js`\n\n```js\nconst aceProviders = ['@rocketseat/adonis-bull/providers/Command']\n```\n\nRegister the Bull provider at `start/app.js`\n\n```js\nconst providers = [\n  //...\n  '@rocketseat/adonis-bull/providers/Bull',\n]\n```\n\nCreate a file with the `jobs` that will be processed at `start/jobs.js`:\n\n```js\nmodule.exports = ['App/Jobs/UserRegisterEmail']\n```\n\nAdd the config file at `config/bull.js`:\n\n```js\n'use strict'\n\nconst Env = use('Env')\n\nmodule.exports = {\n  // redis connection\n  connection: Env.get('BULL_CONNECTION', 'bull'),\n  bull: {\n    redis: {\n      host: '127.0.0.1',\n      port: 6379,\n      password: null,\n      db: 0,\n      keyPrefix: '',\n    },\n  },\n  remote: 'redis://redis.example.com?password=correcthorsebatterystaple',\n}\n```\n\nIn the above file you can define redis connections, there you can pass all `Bull` queue configurations described [here](https://github.com/OptimalBits/bull/blob/develop/REFERENCE.md#queue).\n\nCreate a file to initiate `Bull` at `preloads/bull.js`:\n\n```js\nconst Bull = use('Rocketseat/Bull')\n\nBull.process()\n  // Optionally you can start BullBoard:\n  .ui(9999, 'localhost') // http://localhost:9999\n// You don't need to specify either port or hostname, the default port number is 9999 and the default hostname is localhost\n```\n\nAdd .preLoad in server.js to initialize the bull preload\n\n```js\nnew Ignitor(require('@adonisjs/fold'))\n  .appRoot(__dirname)\n  .preLoad('preloads/bull') // Add This Line\n  .fireHttpServer()\n  .catch(console.error)\n```\n\n## Creating your job\n\nCreate a class that mandatorily has the methods `key` and `handle`.\n\nThe `key` method is the unique identification of each job. It has to be a `static get` method.\n\nThe `handle` is the method that contains the functionality of your `job`.\n\n```js\nconst Mail = use('Mail')\n\nclass UserRegisterEmail {\n  static get key() {\n    return 'UserRegisterEmail-key'\n  }\n\n  async handle(job) {\n    const { data } = job // the 'data' variable has user data\n\n    await Mail.send('emails.welcome', data, (message) =\u003e {\n      message\n        .to(data.email)\n        .from('\u003cfrom-email\u003e')\n        .subject('Welcome to yardstick')\n    })\n\n    return data\n  }\n}\n\nmodule.exports = UserRegisterEmail\n```\n\nYou can use the `connection` static get method to specify which connection your `job` will work.\n\n```js\nclass UserRegisterEmail {\n  // ...\n  static get connection() {\n    return 'remote'\n  }\n}\n```\n\n### Events\n\nThe package has support for all events triggered in the bull, just add \"on\" and complete with the name of the event\nEx: `onCompleted()`, `onActive()`, `onWaiting()` and etc.\n\n```js\nclass UserRegisterEmail {\n  ...\n  onCompleted(job, result) {}\n  onActive(job) {}\n  ...\n}\n\nmodule.exports = UserRegisterEmail;\n\n```\n\n## Processing the jobs\n\n### Simple job\n\nYou can share the `job` of any `controller`, `hook` or any other place you might like:\n\n```js\nconst User = use('App/Models/User')\nconst Bull = use('Rocketseat/Bull')\nconst Job = use('App/Jobs/UserRegisterEmail')\n\nclass UserController {\n  store ({ request, response }) {\n    const data = request.only(['email', 'name', 'password'])\n\n    const user = await User.create(data)\n\n\n    Bull.add(Job.key, user)\n  }\n}\n\nmodule.exports = UserController\n```\n\n### Scheduled job\n\nSometimes it is necessary to schedule a job instead of shooting it imediately. You should use `schedule` for that:\n\n```js\nconst User = use('App/Models/User')\nconst Bull = use('Rocketseat/Bull')\nconst Job = use('App/Jobs/HolidayOnSaleEmail')\n\nclass HolidayOnSaleController {\n  store ({ request, response }) {\n    const data = request.only(['date', 'product_list']) // 2019-11-15 12:00:00\n\n    const products = await ProductOnSale.create(data)\n\n\n    Bull.schedule(Job.key, products, data.date)\n  }\n}\n\nmodule.exports = HolidayOnSaleController\n```\n\nThis `job` will be sent only on the specific date, wich for example here is on November 15th at noon.\n\nWhen finishing a date, never use past dates because it will cause an error.\n\nother ways of using `schedule`:\n\n```js\nBull.schedule(key, data, new Date('2019-11-15 12:00:00'))\nBull.schedule(key, data, '2 hours') // 2 hours from now\nBull.schedule(key, data, 60 * 1000) // 1 minute from now.\n```\n\n### Advanced jobs\n\nYou can use the own `Bull` configs to improve your job:\n\n```js\nBull.add(key, data, {\n  repeat: {\n    cron: '0 30 12 * * WED,FRI',\n  },\n})\n```\n\nThis `job` will be run at 12:30 PM, only on wednesdays and fridays.\n\n### Exceptions\n\nTo have a bigger control over errors that might occur on the line, the events that fail can be manipulated at the file `App/Exceptions/QueueHandler.js`:\n\n```js\nconst Sentry = use('Sentry')\n\nclass QueueHandler {\n  async report(error, job) {\n    Sentry.configureScope((scope) =\u003e {\n      scope.setExtra(job)\n    })\n\n    Sentry.captureException(error)\n  }\n}\n\nmodule.exports = QueueHandler\n```\n\n## Contributing\n\nThank you for being interested in making this package better. We encourage everyone to help improve this project with new features, bug fixes, or performance improvements. Please take a little bit of your time to read our guide to make this process faster and easier.\n\n### Contribution Guidelines\n\nTo understand how to submit an issue, commit and create pull requests, check our [Contribution Guidelines](/.github/CONTRIBUTING.md).\n\n### Code of Conduct\n\nWe expect you to follow our [Code of Conduct](/.github/CODE_OF_CONDUCT.md). You can read it to understand what kind of behavior will and will not be tolerated.\n\n## License\n\nMIT License © [Rocketseat](https://github.com/Rocketseat)\n\n[npm-image]: https://img.shields.io/npm/v/@rocketseat/adonis-bull?color=8257E5\u0026style=for-the-badge\n[npm-url]: https://www.npmjs.com/package/@rocketseat/adonis-bull 'npm'\n[license-url]: LICENSE.md\n[license-image]: https://img.shields.io/github/license/adonisjs/adonis-framework?color=8257E5\u0026style=for-the-badge\n[build-url]: https://github.com/Rocketseat/adonis-bull/actions\n[build-image]: https://img.shields.io/github/workflow/status/Rocketseat/adonis-bull/Node.js/master?color=8257E5\u0026style=for-the-badge\n[coveralls-image]: https://img.shields.io/coveralls/github/Rocketseat/adonis-bull/master?color=8257E5\u0026style=for-the-badge\n[coveralls-url]: https://coveralls.io/github/Rocketseat/adonis-bull?branch=master\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Frocketseat%2Fadonis-bull","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Frocketseat%2Fadonis-bull","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Frocketseat%2Fadonis-bull/lists"}