QueueWorkers.js 3.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122
  1. const Features = require('./Features')
  2. const Queues = require('./Queues')
  3. const UserOnboardingEmailManager = require('../Features/User/UserOnboardingEmailManager')
  4. const UserPostRegistrationAnalyticsManager = require('../Features/User/UserPostRegistrationAnalyticsManager')
  5. const FeaturesUpdater = require('../Features/Subscription/FeaturesUpdater')
  6. const InstitutionsManager = require('../Features/Institutions/InstitutionsManager')
  7. const {
  8. addOptionalCleanupHandlerBeforeStoppingTraffic,
  9. addRequiredCleanupHandlerBeforeDrainingConnections,
  10. } = require('./GracefulShutdown')
  11. const EmailHandler = require('../Features/Email/EmailHandler')
  12. const logger = require('@overleaf/logger')
  13. const OError = require('@overleaf/o-error')
  14. const Modules = require('./Modules')
  15. function start() {
  16. if (!Features.hasFeature('saas')) {
  17. return
  18. }
  19. const scheduledJobsQueue = Queues.getQueue('scheduled-jobs')
  20. scheduledJobsQueue.process(async job => {
  21. const { queueName, name, data, options } = job.data
  22. const queue = Queues.getQueue(queueName)
  23. if (name) {
  24. await queue.add(name, data || {}, options || {})
  25. } else {
  26. await queue.add(data || {}, options || {})
  27. }
  28. })
  29. registerCleanup(scheduledJobsQueue)
  30. const onboardingEmailsQueue = Queues.getQueue('emails-onboarding')
  31. onboardingEmailsQueue.process(async job => {
  32. const { userId } = job.data
  33. await UserOnboardingEmailManager.sendOnboardingEmail(userId)
  34. })
  35. registerCleanup(onboardingEmailsQueue)
  36. const postRegistrationAnalyticsQueue = Queues.getQueue(
  37. 'post-registration-analytics'
  38. )
  39. postRegistrationAnalyticsQueue.process(async job => {
  40. const { userId } = job.data
  41. await UserPostRegistrationAnalyticsManager.postRegistrationAnalytics(userId)
  42. })
  43. registerCleanup(postRegistrationAnalyticsQueue)
  44. const refreshFeaturesQueue = Queues.getQueue('refresh-features')
  45. refreshFeaturesQueue.process(async job => {
  46. const { userId, reason } = job.data
  47. await FeaturesUpdater.promises.refreshFeatures(userId, reason)
  48. })
  49. registerCleanup(refreshFeaturesQueue)
  50. const deferredEmailsQueue = Queues.getQueue('deferred-emails')
  51. deferredEmailsQueue.process(async job => {
  52. const { emailType, opts } = job.data
  53. try {
  54. await EmailHandler.promises.sendEmail(emailType, opts)
  55. } catch (e) {
  56. const error = OError.tag(e, 'failed to send deferred email')
  57. logger.warn(error)
  58. throw error
  59. }
  60. })
  61. registerCleanup(deferredEmailsQueue)
  62. const confirmInstitutionDomainQueue = Queues.getQueue(
  63. 'confirm-institution-domain'
  64. )
  65. confirmInstitutionDomainQueue.process(async job => {
  66. const { hostname } = job.data
  67. try {
  68. await InstitutionsManager.promises.affiliateUsers(hostname)
  69. } catch (e) {
  70. const error = OError.tag(e, 'failed to confirm university domain')
  71. logger.warn(error)
  72. throw error
  73. }
  74. })
  75. registerCleanup(confirmInstitutionDomainQueue)
  76. const groupSSOReminderQueue = Queues.getQueue('group-sso-reminder')
  77. groupSSOReminderQueue.process(async job => {
  78. const { userId, subscriptionId } = job.data
  79. try {
  80. await Modules.promises.hooks.fire(
  81. 'sendGroupSSOReminder',
  82. userId,
  83. subscriptionId
  84. )
  85. } catch (e) {
  86. const error = OError.tag(
  87. e,
  88. 'failed to send scheduled Group SSO account linking reminder'
  89. )
  90. logger.warn(error)
  91. throw error
  92. }
  93. })
  94. registerCleanup(groupSSOReminderQueue)
  95. }
  96. function registerCleanup(queue) {
  97. const label = `bull queue ${queue.name}`
  98. // Stop accepting new jobs.
  99. addOptionalCleanupHandlerBeforeStoppingTraffic(label, async () => {
  100. const justThisWorker = true
  101. await queue.pause(justThisWorker)
  102. })
  103. // Wait for all jobs to process before shutting down connections.
  104. addRequiredCleanupHandlerBeforeDrainingConnections(label, async () => {
  105. await queue.close()
  106. })
  107. // Disconnect from redis is scheduled in queue setup.
  108. }
  109. module.exports = { start }