From 288d7342e7241a8ecbf2825b152192938f4993b5 Mon Sep 17 00:00:00 2001 From: wajeht <58354193+wajeht@users.noreply.github.com> Date: Thu, 8 Aug 2024 10:07:03 -0500 Subject: [PATCH] docs: Update email sending functionality and dependencies with BullMQ --- .vscode/settings.json | 2 +- package-lock.json | 181 +++++++++++++++++++- package.json | 1 + src/jobs/discord.job.ts | 0 src/jobs/email.job.ts | 30 ++++ src/jobs/jobs.ts | 0 src/jobs/notification.job.ts | 0 src/jobs/sms.job.ts | 0 src/{notification => jobs/utils}/discord.ts | 0 src/{notification => jobs/utils}/email.ts | 4 +- src/{notification => jobs/utils}/sms.ts | 2 +- 11 files changed, 215 insertions(+), 5 deletions(-) create mode 100644 src/jobs/discord.job.ts create mode 100644 src/jobs/email.job.ts create mode 100644 src/jobs/jobs.ts create mode 100644 src/jobs/notification.job.ts create mode 100644 src/jobs/sms.job.ts rename src/{notification => jobs/utils}/discord.ts (100%) rename src/{notification => jobs/utils}/email.ts (87%) rename src/{notification => jobs/utils}/sms.ts (91%) diff --git a/.vscode/settings.json b/.vscode/settings.json index 638eb25..c36ae7e 100644 --- a/.vscode/settings.json +++ b/.vscode/settings.json @@ -1,3 +1,3 @@ { - "cSpell.words": ["healthz", "knexfile", "tseslint", "wajeht"] + "cSpell.words": ["bullmq", "healthz", "knexfile", "tseslint", "wajeht"] } diff --git a/package-lock.json b/package-lock.json index dc392e1..455e58b 100644 --- a/package-lock.json +++ b/package-lock.json @@ -10,6 +10,7 @@ "license": "MIT", "dependencies": { "bcrypt": "^5.1.1", + "bullmq": "^5.12.1", "compression": "^1.7.4", "cors": "^2.8.5", "dotenv": "^16.4.5", @@ -643,6 +644,84 @@ "node-pre-gyp": "bin/node-pre-gyp" } }, + "node_modules/@msgpackr-extract/msgpackr-extract-darwin-arm64": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/@msgpackr-extract/msgpackr-extract-darwin-arm64/-/msgpackr-extract-darwin-arm64-3.0.3.tgz", + "integrity": "sha512-QZHtlVgbAdy2zAqNA9Gu1UpIuI8Xvsd1v8ic6B2pZmeFnFcMWiPLfWXh7TVw4eGEZ/C9TH281KwhVoeQUKbyjw==", + "cpu": [ + "arm64" + ], + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ] + }, + "node_modules/@msgpackr-extract/msgpackr-extract-darwin-x64": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/@msgpackr-extract/msgpackr-extract-darwin-x64/-/msgpackr-extract-darwin-x64-3.0.3.tgz", + "integrity": "sha512-mdzd3AVzYKuUmiWOQ8GNhl64/IoFGol569zNRdkLReh6LRLHOXxU4U8eq0JwaD8iFHdVGqSy4IjFL4reoWCDFw==", + "cpu": [ + "x64" + ], + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ] + }, + "node_modules/@msgpackr-extract/msgpackr-extract-linux-arm": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/@msgpackr-extract/msgpackr-extract-linux-arm/-/msgpackr-extract-linux-arm-3.0.3.tgz", + "integrity": "sha512-fg0uy/dG/nZEXfYilKoRe7yALaNmHoYeIoJuJ7KJ+YyU2bvY8vPv27f7UKhGRpY6euFYqEVhxCFZgAUNQBM3nw==", + "cpu": [ + "arm" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@msgpackr-extract/msgpackr-extract-linux-arm64": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/@msgpackr-extract/msgpackr-extract-linux-arm64/-/msgpackr-extract-linux-arm64-3.0.3.tgz", + "integrity": "sha512-YxQL+ax0XqBJDZiKimS2XQaf+2wDGVa1enVRGzEvLLVFeqa5kx2bWbtcSXgsxjQB7nRqqIGFIcLteF/sHeVtQg==", + "cpu": [ + "arm64" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@msgpackr-extract/msgpackr-extract-linux-x64": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/@msgpackr-extract/msgpackr-extract-linux-x64/-/msgpackr-extract-linux-x64-3.0.3.tgz", + "integrity": "sha512-cvwNfbP07pKUfq1uH+S6KJ7dT9K8WOE4ZiAcsrSes+UY55E/0jLYc+vq+DO7jlmqRb5zAggExKm0H7O/CBaesg==", + "cpu": [ + "x64" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@msgpackr-extract/msgpackr-extract-win32-x64": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/@msgpackr-extract/msgpackr-extract-win32-x64/-/msgpackr-extract-win32-x64-3.0.3.tgz", + "integrity": "sha512-x0fWaQtYp4E6sktbsdAqnehxDgEc/VwM7uLsRCYWaiGu0ykYdZPiS8zCWdnjHwyiumousxfBm4SO31eXqwEZhQ==", + "cpu": [ + "x64" + ], + "license": "MIT", + "optional": true, + "os": [ + "win32" + ] + }, "node_modules/@nodelib/fs.scandir": { "version": "2.1.5", "resolved": "https://registry.npmjs.org/@nodelib/fs.scandir/-/fs.scandir-2.1.5.tgz", @@ -1662,6 +1741,21 @@ "integrity": "sha512-zRpUiDwd/xk6ADqPMATG8vc9VPrkck7T07OIx0gnjmJAnHnTVXNQG3vfvWNuiZIkwu9KrKdA1iJKfsfTVxE6NA==", "license": "BSD-3-Clause" }, + "node_modules/bullmq": { + "version": "5.12.1", + "resolved": "https://registry.npmjs.org/bullmq/-/bullmq-5.12.1.tgz", + "integrity": "sha512-XNUnT4+hJ/bnu3HkIeauN/i+fU+DwC74rubPLktoUsds7zBfugN3jF8XbaT7Ya4U+SANR+3T4u9YG8KUbsp2+g==", + "license": "MIT", + "dependencies": { + "cron-parser": "^4.6.0", + "ioredis": "^5.4.1", + "msgpackr": "^1.10.1", + "node-abort-controller": "^3.1.1", + "semver": "^7.5.4", + "tslib": "^2.0.0", + "uuid": "^9.0.0" + } + }, "node_modules/bytes": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/bytes/-/bytes-3.0.0.tgz", @@ -1906,6 +2000,18 @@ "node": ">= 0.10" } }, + "node_modules/cron-parser": { + "version": "4.9.0", + "resolved": "https://registry.npmjs.org/cron-parser/-/cron-parser-4.9.0.tgz", + "integrity": "sha512-p0SaNjrHOnQeR8/VnfGbmg9te2kfyYSQ7Sc/j/6DtPL3JQvKxmjO9TSjNFpujqV3vEYYBvNNvXSxzyksBWAx1Q==", + "license": "MIT", + "dependencies": { + "luxon": "^3.2.1" + }, + "engines": { + "node": ">=12.0.0" + } + }, "node_modules/cross-spawn": { "version": "7.0.3", "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.3.tgz", @@ -3594,6 +3700,15 @@ "integrity": "sha512-Sb487aTOCr9drQVL8pIxOzVhafOjZN9UU54hiN8PU3uAiSV7lx1yYNpbNmex2PK6dSJoNTSJUUswT651yww3Mg==", "license": "MIT" }, + "node_modules/luxon": { + "version": "3.5.0", + "resolved": "https://registry.npmjs.org/luxon/-/luxon-3.5.0.tgz", + "integrity": "sha512-rh+Zjr6DNfUYR3bPwJEnuwDdqMbxZW7LOQfUN4B54+Cl+0o5zaU9RJ6bcidfDtC1cWCZXQ+nvX8bf6bAji37QQ==", + "license": "MIT", + "engines": { + "node": ">=12" + } + }, "node_modules/make-dir": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/make-dir/-/make-dir-3.1.0.tgz", @@ -3772,6 +3887,37 @@ "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==", "license": "MIT" }, + "node_modules/msgpackr": { + "version": "1.11.0", + "resolved": "https://registry.npmjs.org/msgpackr/-/msgpackr-1.11.0.tgz", + "integrity": "sha512-I8qXuuALqJe5laEBYoFykChhSXLikZmUhccjGsPuSJ/7uPip2TJ7lwdIQwWSAi0jGZDXv4WOP8Qg65QZRuXxXw==", + "license": "MIT", + "optionalDependencies": { + "msgpackr-extract": "^3.0.2" + } + }, + "node_modules/msgpackr-extract": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/msgpackr-extract/-/msgpackr-extract-3.0.3.tgz", + "integrity": "sha512-P0efT1C9jIdVRefqjzOQ9Xml57zpOXnIuS+csaB4MdZbTdmGDLo8XhzBG1N7aO11gKDDkJvBLULeFTo46wwreA==", + "hasInstallScript": true, + "license": "MIT", + "optional": true, + "dependencies": { + "node-gyp-build-optional-packages": "5.2.2" + }, + "bin": { + "download-msgpackr-prebuilds": "bin/download-prebuilds.js" + }, + "optionalDependencies": { + "@msgpackr-extract/msgpackr-extract-darwin-arm64": "3.0.3", + "@msgpackr-extract/msgpackr-extract-darwin-x64": "3.0.3", + "@msgpackr-extract/msgpackr-extract-linux-arm": "3.0.3", + "@msgpackr-extract/msgpackr-extract-linux-arm64": "3.0.3", + "@msgpackr-extract/msgpackr-extract-linux-x64": "3.0.3", + "@msgpackr-extract/msgpackr-extract-win32-x64": "3.0.3" + } + }, "node_modules/natural-compare": { "version": "1.4.0", "resolved": "https://registry.npmjs.org/natural-compare/-/natural-compare-1.4.0.tgz", @@ -3788,6 +3934,12 @@ "node": ">= 0.6" } }, + "node_modules/node-abort-controller": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/node-abort-controller/-/node-abort-controller-3.1.1.tgz", + "integrity": "sha512-AGK2yQKIjRuqnc6VkX2Xj5d+QW8xZ87pa1UK6yA6ouUyuxfHuMP6umE5QK7UmTeOAymo+Zx1Fxiuw9rVx8taHQ==", + "license": "MIT" + }, "node_modules/node-addon-api": { "version": "5.1.0", "resolved": "https://registry.npmjs.org/node-addon-api/-/node-addon-api-5.1.0.tgz", @@ -3814,6 +3966,21 @@ } } }, + "node_modules/node-gyp-build-optional-packages": { + "version": "5.2.2", + "resolved": "https://registry.npmjs.org/node-gyp-build-optional-packages/-/node-gyp-build-optional-packages-5.2.2.tgz", + "integrity": "sha512-s+w+rBWnpTMwSFbaE0UXsRlg7hU4FjekKU4eyAih5T8nJuNZT1nNsskXpxmeqSK9UzkBl6UgRlnKc8hz8IEqOw==", + "license": "MIT", + "optional": true, + "dependencies": { + "detect-libc": "^2.0.1" + }, + "bin": { + "node-gyp-build-optional-packages": "bin.js", + "node-gyp-build-optional-packages-optional": "optional.js", + "node-gyp-build-optional-packages-test": "build-test.js" + } + }, "node_modules/nodemailer": { "version": "6.9.14", "resolved": "https://registry.npmjs.org/nodemailer/-/nodemailer-6.9.14.tgz", @@ -4880,7 +5047,6 @@ "version": "2.6.3", "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.6.3.tgz", "integrity": "sha512-xNvxJEOUiWPGhUuUdQgAJPKOOJfGnIyKySOc09XkKsgdUV/3E2zvwZYdejjmRgPCgcym1juLH3226yA7sEFJKQ==", - "dev": true, "license": "0BSD" }, "node_modules/tsx": { @@ -5018,6 +5184,19 @@ "node": ">= 0.4.0" } }, + "node_modules/uuid": { + "version": "9.0.1", + "resolved": "https://registry.npmjs.org/uuid/-/uuid-9.0.1.tgz", + "integrity": "sha512-b+1eJOlsR9K8HJpow9Ok3fiWOWSIcIzXodvv0rQjVoOVNpWMpxf1wZNpt4y9h10odCNrqnYp1OBzRktckBe3sA==", + "funding": [ + "https://github.com/sponsors/broofa", + "https://github.com/sponsors/ctavan" + ], + "license": "MIT", + "bin": { + "uuid": "dist/bin/uuid" + } + }, "node_modules/vary": { "version": "1.1.2", "resolved": "https://registry.npmjs.org/vary/-/vary-1.1.2.tgz", diff --git a/package.json b/package.json index 46835d7..12800e3 100644 --- a/package.json +++ b/package.json @@ -37,6 +37,7 @@ }, "dependencies": { "bcrypt": "^5.1.1", + "bullmq": "^5.12.1", "compression": "^1.7.4", "cors": "^2.8.5", "dotenv": "^16.4.5", diff --git a/src/jobs/discord.job.ts b/src/jobs/discord.job.ts new file mode 100644 index 0000000..e69de29 diff --git a/src/jobs/email.job.ts b/src/jobs/email.job.ts new file mode 100644 index 0000000..4566e0b --- /dev/null +++ b/src/jobs/email.job.ts @@ -0,0 +1,30 @@ +import { Queue, Worker } from 'bullmq'; +import { redis } from '../database/db'; +import { sendEmail } from './utils/email'; + +const queueName = 'sendEmailQueue'; + +export const sendEmailQueue = new Queue(queueName, { + connection: redis, +}); + +const processSendEmailJob = async (job: any) => { + try { + job.updateProgress(0); + await sendEmail({ tenant: job.data.tenant, coach: job.data.coach }); + job.updateProgress(100); + console.info(`Email successfully sent for tenant: ${job.data.tenant}`); + } catch (error) { + console.error(`Failed to send email for tenant: ${job.data.tenant}`, error); + } +}; + +new Worker(queueName, processSendEmailJob, { connection: redis }); + +export async function sendApproveTenantEmailJob(data: any) { + try { + await sendEmailQueue.add('sendEmailJob', data); + } catch (error) { + console.error(`Failed to add job to queue for tenant: ${data.tenant}`, error); + } +} diff --git a/src/jobs/jobs.ts b/src/jobs/jobs.ts new file mode 100644 index 0000000..e69de29 diff --git a/src/jobs/notification.job.ts b/src/jobs/notification.job.ts new file mode 100644 index 0000000..e69de29 diff --git a/src/jobs/sms.job.ts b/src/jobs/sms.job.ts new file mode 100644 index 0000000..e69de29 diff --git a/src/notification/discord.ts b/src/jobs/utils/discord.ts similarity index 100% rename from src/notification/discord.ts rename to src/jobs/utils/discord.ts diff --git a/src/notification/email.ts b/src/jobs/utils/email.ts similarity index 87% rename from src/notification/email.ts rename to src/jobs/utils/email.ts index 4f8f989..88fb38f 100644 --- a/src/notification/email.ts +++ b/src/jobs/utils/email.ts @@ -1,6 +1,6 @@ import nodemailer from 'nodemailer'; -import { emailConfig, appConfig } from '../config'; +import { emailConfig, appConfig } from '../../config'; const transporter = nodemailer.createTransport(emailConfig); @@ -15,7 +15,7 @@ interface SendMailOptions { const template = `

hello world

`; -export async function send({ +export async function sendEmail({ to = `${domain} <${emailConfig.alias}>`, subject, html: template, diff --git a/src/notification/sms.ts b/src/jobs/utils/sms.ts similarity index 91% rename from src/notification/sms.ts rename to src/jobs/utils/sms.ts index 0854118..e0ddab6 100644 --- a/src/notification/sms.ts +++ b/src/jobs/utils/sms.ts @@ -1,5 +1,5 @@ import twilio from 'twilio'; -import { smsConfig } from '../config'; +import { smsConfig } from '../../config'; const client = twilio(smsConfig.accountSid, smsConfig.authToken);