plugin.ts 5.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159
  1. import { PluginCommonModule, VendurePlugin } from '@vendure/core';
  2. import { BullMQJobQueueStrategy } from './bullmq-job-queue-strategy';
  3. import { BULLMQ_PLUGIN_OPTIONS } from './constants';
  4. import { RedisHealthCheckStrategy } from './redis-health-check-strategy';
  5. import { RedisHealthIndicator } from './redis-health-indicator';
  6. import { RedisJobBufferStorageStrategy } from './redis-job-buffer-storage-strategy';
  7. import { BullMQPluginOptions } from './types';
  8. /**
  9. * @description
  10. * This plugin is a drop-in replacement of the DefaultJobQueuePlugin, which implements a push-based
  11. * job queue strategy built on top of the popular [BullMQ](https://github.com/taskforcesh/bullmq) library.
  12. *
  13. * ## Advantages over the DefaultJobQueuePlugin
  14. *
  15. * The advantage of this approach is that jobs are stored in Redis rather than in the database. For more complex
  16. * applications with many job queues and/or multiple worker instances, this can massively reduce the load on the
  17. * DB server. The reason for this is that the DefaultJobQueuePlugin uses polling to check for new jobs. By default
  18. * it will poll every 200ms. A typical Vendure instance uses at least 3 queues (handling emails, collections, search index),
  19. * so even with a single worker instance this results in 15 queries per second to the DB constantly. Adding more
  20. * custom queues and multiple worker instances can easily result in 50 or 100 queries per second. At this point
  21. * performance may be impacted.
  22. *
  23. * Using this plugin, no polling is needed, as BullMQ will _push_ jobs to the worker(s) as and when they are added
  24. * to the queue. This results in significantly more scalable performance characteristics, as well as lower latency
  25. * in processing jobs.
  26. *
  27. * ## Installation
  28. *
  29. * `yarn add \@vendure/job-queue-plugin bullmq@1`
  30. *
  31. * or
  32. *
  33. * `npm install \@vendure/job-queue-plugin bullmq@1`
  34. *
  35. * **Note:** The v1.x version of this plugin is designed to work with bullmq v1.x.
  36. *
  37. * @example
  38. * ```ts
  39. * import { BullMQJobQueuePlugin } from '\@vendure/job-queue-plugin/package/bullmq';
  40. *
  41. * const config: VendureConfig = {
  42. * // Add an instance of the plugin to the plugins array
  43. * plugins: [
  44. * // DefaultJobQueuePlugin should be removed from the plugins array
  45. * BullMQJobQueuePlugin.init({
  46. * connection: {
  47. * port: 6379
  48. * }
  49. * }),
  50. * ],
  51. * };
  52. * ```
  53. *
  54. * ### Running Redis locally
  55. *
  56. * To develop with this plugin, you'll need an instance of Redis to connect to. Here's a docker-compose config
  57. * that will set up [Redis](https://redis.io/) as well as [Redis Commander](https://github.com/joeferner/redis-commander),
  58. * which is a web-based UI for interacting with Redis:
  59. *
  60. * ```YAML
  61. * version: "3"
  62. * services:
  63. * redis:
  64. * image: bitnami/redis:6.2
  65. * hostname: redis
  66. * container_name: redis
  67. * environment:
  68. * - ALLOW_EMPTY_PASSWORD=yes
  69. * ports:
  70. * - "6379:6379"
  71. * redis-commander:
  72. * container_name: redis-commander
  73. * hostname: redis-commander
  74. * image: rediscommander/redis-commander:latest
  75. * environment:
  76. * - REDIS_HOSTS=local:redis:6379
  77. * ports:
  78. * - "8085:8081"
  79. * ```
  80. *
  81. * ## Concurrency
  82. *
  83. * The default concurrency of a single worker is 3, i.e. up to 3 jobs will be processed at the same time.
  84. * You can change the concurrency in the `workerOptions` passed to the `init()` method:
  85. *
  86. * @example
  87. * ```ts
  88. * const config: VendureConfig = {
  89. * plugins: [
  90. * BullMQJobQueuePlugin.init({
  91. * workerOptions: {
  92. * concurrency: 10,
  93. * },
  94. * }),
  95. * ],
  96. * };
  97. * ```
  98. *
  99. * ## Removing old jobs
  100. *
  101. * By default, BullMQ will keep completed jobs in the `completed` set and failed jobs in the `failed` set. Over time,
  102. * these sets can grow very large. Since Vendure v2.1, the default behaviour is to remove jobs from these sets after
  103. * 30 days or after a maximum of 5,000 completed or failed jobs.
  104. *
  105. * This can be configured using the `removeOnComplete` and `removeOnFail` options:
  106. *
  107. * @example
  108. * ```ts
  109. * const config: VendureConfig = {
  110. * plugins: [
  111. * BullMQJobQueuePlugin.init({
  112. * workerOptions: {
  113. * removeOnComplete: {
  114. * count: 500,
  115. * },
  116. * removeOnFail: {
  117. * age: 60 * 60 * 24 * 7, // 7 days
  118. * count: 1000,
  119. * },
  120. * }
  121. * }),
  122. * ],
  123. * };
  124. * ```
  125. *
  126. * The `count` option specifies the maximum number of jobs to keep in the set, while the `age` option specifies the
  127. * maximum age of a job in seconds. If both options are specified, then the jobs kept will be the ones that satisfy
  128. * both properties.
  129. *
  130. * @docsCategory core plugins/JobQueuePlugin
  131. */
  132. @VendurePlugin({
  133. imports: [PluginCommonModule],
  134. configuration: config => {
  135. config.jobQueueOptions.jobQueueStrategy = new BullMQJobQueueStrategy();
  136. config.jobQueueOptions.jobBufferStorageStrategy = new RedisJobBufferStorageStrategy();
  137. config.systemOptions.healthChecks.push(new RedisHealthCheckStrategy());
  138. return config;
  139. },
  140. providers: [
  141. { provide: BULLMQ_PLUGIN_OPTIONS, useFactory: () => BullMQJobQueuePlugin.options },
  142. RedisHealthIndicator,
  143. ],
  144. compatibility: '^2.0.0',
  145. })
  146. export class BullMQJobQueuePlugin {
  147. static options: BullMQPluginOptions;
  148. /**
  149. * @description
  150. * Configures the plugin.
  151. */
  152. static init(options: BullMQPluginOptions) {
  153. this.options = options;
  154. return this;
  155. }
  156. }