Queues.js 2.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107
  1. const Queue = require('bull')
  2. const Settings = require('@overleaf/settings')
  3. const { addConnectionDrainer } = require('./GracefulShutdown')
  4. // Bull will keep a fixed number of the most recently completed jobs. This is
  5. // useful to inspect recently completed jobs. The bull prometheus exporter also
  6. // uses the completed job records to report on job duration.
  7. const MAX_COMPLETED_JOBS_RETAINED = 10000
  8. const MAX_FAILED_JOBS_RETAINED = 50000
  9. const MAX_FAILED_JOBS_RETAINED_ANALYTICS = 3000000
  10. const QUEUES_JOB_OPTIONS = {
  11. 'analytics-events': {
  12. removeOnFail: MAX_FAILED_JOBS_RETAINED_ANALYTICS,
  13. },
  14. 'analytics-editing-sessions': {
  15. removeOnFail: MAX_FAILED_JOBS_RETAINED_ANALYTICS,
  16. },
  17. 'analytics-user-properties': {
  18. removeOnFail: MAX_FAILED_JOBS_RETAINED_ANALYTICS,
  19. },
  20. 'refresh-features': {
  21. removeOnFail: MAX_FAILED_JOBS_RETAINED,
  22. attempts: 3,
  23. },
  24. 'emails-onboarding': {
  25. removeOnFail: MAX_FAILED_JOBS_RETAINED,
  26. },
  27. 'post-registration-analytics': {
  28. removeOnFail: MAX_FAILED_JOBS_RETAINED_ANALYTICS,
  29. },
  30. 'scheduled-jobs': {
  31. removeOnFail: MAX_FAILED_JOBS_RETAINED,
  32. attempts: 1,
  33. },
  34. 'confirm-institution-domain': {
  35. removeOnFail: MAX_FAILED_JOBS_RETAINED,
  36. attempts: 3,
  37. },
  38. 'group-sso-reminder': {
  39. removeOnFail: MAX_FAILED_JOBS_RETAINED,
  40. attempts: 3,
  41. },
  42. }
  43. const QUEUE_OPTIONS = {
  44. 'confirm-institution-domain': {
  45. limiter: {
  46. max: 1,
  47. duration: 60 * 1000,
  48. },
  49. },
  50. }
  51. const ANALYTICS_QUEUES = [
  52. 'analytics-events',
  53. 'analytics-editing-sessions',
  54. 'analytics-user-properties',
  55. 'post-registration-analytics',
  56. ]
  57. const queues = {}
  58. function getQueue(queueName) {
  59. if (!queues[queueName]) {
  60. const redisOptions = ANALYTICS_QUEUES.includes(queueName)
  61. ? Settings.redis.analyticsQueues
  62. : Settings.redis.queues
  63. const queueOptions = QUEUE_OPTIONS[queueName] || {}
  64. const jobOptions = QUEUES_JOB_OPTIONS[queueName] || {}
  65. queues[queueName] = new Queue(queueName, {
  66. // this configuration is duplicated in /services/analytics/app/js/Queues.js
  67. // and needs to be manually kept in sync whenever modified
  68. redis: redisOptions,
  69. ...queueOptions,
  70. defaultJobOptions: {
  71. removeOnComplete: MAX_COMPLETED_JOBS_RETAINED,
  72. attempts: 11,
  73. backoff: {
  74. type: 'exponential',
  75. delay: 3000,
  76. },
  77. ...jobOptions,
  78. },
  79. })
  80. // Disconnect from redis eventually.
  81. addConnectionDrainer(`bull queue ${queueName}`, async () => {
  82. await queues[queueName].disconnect()
  83. })
  84. }
  85. return queues[queueName]
  86. }
  87. async function createScheduledJob(queueName, { name, data, options }, delay) {
  88. await getQueue('scheduled-jobs').add(
  89. { queueName, name, data, options },
  90. {
  91. delay,
  92. }
  93. )
  94. }
  95. module.exports = {
  96. getQueue,
  97. createScheduledJob,
  98. }