diff --git a/docker-compose.db.yml b/docker-compose.db.yml index 1deaa800..9580e90e 100644 --- a/docker-compose.db.yml +++ b/docker-compose.db.yml @@ -11,6 +11,20 @@ services: volumes: - postgres:/var/lib/postgresql/data + redis: + image: redis:6 + container_name: redis + restart: always + ports: + - 6379:6379 + env_file: + - .env + volumes: + - redis:/data + volumes: postgres: name: nest-db + redis: + name: nest-redis + diff --git a/docker-compose.yml b/docker-compose.yml index beafa251..67dad496 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -23,6 +23,19 @@ services: volumes: - postgres:/var/lib/postgresql/data + redis: + image: redis:6 + container_name: redis + restart: always + ports: + - 6379:6379 + env_file: + - .env + volumes: + - redis:/data + volumes: postgres: name: nest-db + redis: + name: nest-redis \ No newline at end of file diff --git a/nest-cli-worker.json b/nest-cli-worker.json new file mode 100644 index 00000000..ea86a19b --- /dev/null +++ b/nest-cli-worker.json @@ -0,0 +1,12 @@ +{ + "language": "ts", + "collection": "@nestjs/schematics", + "sourceRoot": "src", + "entryFile": "worker.js", + "compilerOptions": { + "plugins": [ + "@nestjs/swagger/plugin", + "@nestjs/graphql/plugin" + ] + } +} \ No newline at end of file diff --git a/package-lock.json b/package-lock.json index 34baad22..a6c74916 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1254,6 +1254,11 @@ } } }, + "@nestjs/bull": { + "version": "0.4.2", + "resolved": "https://registry.npmmirror.com/@nestjs/bull/-/bull-0.4.2.tgz", + "integrity": "sha512-HYRMbgqoUIpGplXN8kaZ23E/yHn6TRrQ297ILRqaHTxBp4vO+XNLfL1qUmJ4Z6weufsNKGg0xcX4dSC5AhXV9g==" + }, "@nestjs/cli": { "version": "8.2.0", "resolved": "https://registry.npmjs.org/@nestjs/cli/-/cli-8.2.0.tgz", @@ -2220,6 +2225,16 @@ "@types/node": "*" } }, + "@types/bull": { + "version": "3.15.7", + "resolved": "https://registry.npmmirror.com/@types/bull/-/bull-3.15.7.tgz", + "integrity": "sha512-7NC7XN5NoS0A+leJ/dR69ZfKaegOlCZaii/xGgKnCyh1UYisRncibImb7VMwrc3OdJcbDJt6+4om70TeNl3J7g==", + "dev": true, + "requires": { + "@types/ioredis": "*", + "@types/redis": "^2.8.0" + } + }, "@types/chance": { "version": "1.1.3", "resolved": "https://registry.npmjs.org/@types/chance/-/chance-1.1.3.tgz", @@ -2319,6 +2334,15 @@ "@types/node": "*" } }, + "@types/ioredis": { + "version": "4.28.7", + "resolved": "https://registry.npmmirror.com/@types/ioredis/-/ioredis-4.28.7.tgz", + "integrity": "sha512-jnSGCD2/TPk02j6v6CGqaCEl0LbmLgK6jUuk/AFaSNUBV+SCHiG7E7fnwJreN6hw9GqtLAFkJs4zFbkJrz11mQ==", + "dev": true, + "requires": { + "@types/node": "*" + } + }, "@types/istanbul-lib-coverage": { "version": "2.0.3", "resolved": "https://registry.npmjs.org/@types/istanbul-lib-coverage/-/istanbul-lib-coverage-2.0.3.tgz", @@ -2422,6 +2446,15 @@ "resolved": "https://registry.npmjs.org/@types/range-parser/-/range-parser-1.2.3.tgz", "integrity": "sha512-ewFXqrQHlFsgc09MK5jP5iR7vumV/BYayNC6PgJO2LPe8vrnNFyjQjSppfEngITi0qvfKtzFvgKymGheFM9UOA==" }, + "@types/redis": { + "version": "2.8.32", + "resolved": "https://registry.npmmirror.com/@types/redis/-/redis-2.8.32.tgz", + "integrity": "sha512-7jkMKxcGq9p242exlbsVzuJb57KqHRhNl4dHoQu2Y5v9bCAbtIXXH0R3HleSQW4CTOqpHIYUW3t6tpUj4BVQ+w==", + "dev": true, + "requires": { + "@types/node": "*" + } + }, "@types/retry": { "version": "0.12.1", "resolved": "https://registry.npmjs.org/@types/retry/-/retry-0.12.1.tgz", @@ -3474,6 +3507,32 @@ "resolved": "https://registry.npmjs.org/buffer-from/-/buffer-from-1.1.2.tgz", "integrity": "sha512-E+XQCRwSbaaiChtv6k6Dwgc+bx+Bs6vuKJHHl5kox/BaKbhiXzqQOwK4cO22yElGp2OCmjwVhT3HmxgyPGnJfQ==" }, + "bull": { + "version": "4.5.0", + "resolved": "https://registry.npmmirror.com/bull/-/bull-4.5.0.tgz", + "integrity": "sha512-BejJxGwNNQPIrK1jFTN74kymFORYQ6ZyXWNsZx+6jtDtafQNUMHNSdoepabLLmeldmUvgAHvZDDIJWFGEo2MYg==", + "requires": { + "cron-parser": "^4.2.1", + "debuglog": "^1.0.0", + "get-port": "^5.1.1", + "ioredis": "^4.27.0", + "lodash": "^4.17.21", + "msgpackr": "^1.5.2", + "p-timeout": "^3.2.0", + "semver": "^7.3.2", + "uuid": "^8.3.0" + }, + "dependencies": { + "semver": { + "version": "7.3.5", + "resolved": "https://registry.npmmirror.com/semver/-/semver-7.3.5.tgz", + "integrity": "sha512-PoeGJYh8HK4BTO/a9Tf6ZG3veo/A7ZVsYrSA6J8ny9nb3B1VrpkuN+z9OE5wfE5p6H4LchYZsegiQgbJD94ZFQ==", + "requires": { + "lru-cache": "^6.0.0" + } + } + } + }, "busboy": { "version": "0.2.14", "resolved": "https://registry.npmjs.org/busboy/-/busboy-0.2.14.tgz", @@ -3819,6 +3878,11 @@ "resolved": "https://registry.npmjs.org/clone/-/clone-1.0.4.tgz", "integrity": "sha1-2jCcwmPfFZlMaIypAheco8fNfH4=" }, + "cluster-key-slot": { + "version": "1.1.0", + "resolved": "https://registry.npmmirror.com/cluster-key-slot/-/cluster-key-slot-1.1.0.tgz", + "integrity": "sha512-2Nii8p3RwAPiFwsnZvukotvow2rIHM+yQ6ZcBXGHdniadkYGZYiGmkHJIbZPIV9nfv7m/U1IPMVVcAhoWFeklw==" + }, "co": { "version": "4.6.0", "resolved": "https://registry.npmjs.org/co/-/co-4.6.0.tgz", @@ -4039,6 +4103,14 @@ "integrity": "sha512-dcKFX3jn0MpIaXjisoRvexIJVEKzaq7z2rZKxf+MSr9TkdmHmsU4m2lcLojrj/FHl8mk5VxMmYA+ftRkP/3oKQ==", "dev": true }, + "cron-parser": { + "version": "4.2.1", + "resolved": "https://registry.npmmirror.com/cron-parser/-/cron-parser-4.2.1.tgz", + "integrity": "sha512-5sJBwDYyCp+0vU5b7POl8zLWfgV5fOHxlc45FWoWdHecGC7MQHCjx0CHivCMRnGFovghKhhyYM+Zm9DcY5qcHg==", + "requires": { + "luxon": "^1.28.0" + } + }, "cross-spawn": { "version": "7.0.3", "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.3.tgz", @@ -4103,6 +4175,11 @@ "ms": "2.1.2" } }, + "debuglog": { + "version": "1.0.1", + "resolved": "https://registry.npmmirror.com/debuglog/-/debuglog-1.0.1.tgz", + "integrity": "sha512-syBZ+rnAK3EgMsH2aYEOLUW7mZSY9Gb+0wUMCFsZvcmiz+HigA0LOcq/HoQqVuGG+EKykunc7QG2bzrponfaSw==" + }, "decimal.js": { "version": "10.3.1", "resolved": "https://registry.npmjs.org/decimal.js/-/decimal.js-10.3.1.tgz", @@ -4162,6 +4239,11 @@ "resolved": "https://registry.npmjs.org/delegates/-/delegates-1.0.0.tgz", "integrity": "sha1-hMbhWbgZBP3KWaDvRM2HDTElD5o=" }, + "denque": { + "version": "1.5.1", + "resolved": "https://registry.npmmirror.com/denque/-/denque-1.5.1.tgz", + "integrity": "sha512-XwE+iZ4D6ZUB7mfYRMb5wByE8L74HCn30FBN7sWnXksWc1LO1bPDl67pBR9o/kC4z/xSNAwkMYcGgqDV3BE3Hw==" + }, "depd": { "version": "1.1.2", "resolved": "https://registry.npmjs.org/depd/-/depd-1.1.2.tgz", @@ -5232,6 +5314,11 @@ "integrity": "sha512-pjzuKtY64GYfWizNAJ0fr9VqttZkNiK2iS430LtIHzjBEr6bX8Am2zm4sW4Ro5wjWW5cAlRL1qAMTcXbjNAO2Q==", "dev": true }, + "get-port": { + "version": "5.1.1", + "resolved": "https://registry.npmmirror.com/get-port/-/get-port-5.1.1.tgz", + "integrity": "sha512-g/Q1aTSDOxFpchXC4i8ZWvxA1lnPqx/JHqcpIw0/LX9T8x/GBbi6YnlN5nhaKIFkT8oFsscUKgDJYxfwfS6QsQ==" + }, "get-stream": { "version": "5.2.0", "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-5.2.0.tgz", @@ -5608,6 +5695,39 @@ "integrity": "sha512-agE4QfB2Lkp9uICn7BAqoscw4SZP9kTE2hxiFI3jBPmXJfdqiahTbUuKGsMoN2GtqL9AxhYioAcVvgsb1HvRbA==", "dev": true }, + "ioredis": { + "version": "4.28.4", + "resolved": "https://registry.npmmirror.com/ioredis/-/ioredis-4.28.4.tgz", + "integrity": "sha512-KmG3FDd1pKZcWQ7/fIbwzvpkZ50NwRJ3RBK9dpetJrNfC+sxhK6TzaVkExvh9AiF+rAVSUmvqfHyQp5U418aDw==", + "requires": { + "cluster-key-slot": "^1.1.0", + "debug": "^4.3.1", + "denque": "^1.1.0", + "lodash.defaults": "^4.2.0", + "lodash.flatten": "^4.4.0", + "lodash.isarguments": "^3.1.0", + "p-map": "^2.1.0", + "redis-commands": "1.7.0", + "redis-errors": "^1.2.0", + "redis-parser": "^3.0.0", + "standard-as-callback": "^2.1.0" + }, + "dependencies": { + "debug": { + "version": "4.3.3", + "resolved": "https://registry.npmmirror.com/debug/-/debug-4.3.3.tgz", + "integrity": "sha512-/zxw5+vh1Tfv+4Qn7a5nsbcJKPaSvCDhojn6FEl9vupwK2VCSDtEiEtqr8DFtzYFOdz63LBkxec7DYuc2jon6Q==", + "requires": { + "ms": "2.1.2" + } + }, + "p-map": { + "version": "2.1.0", + "resolved": "https://registry.npmmirror.com/p-map/-/p-map-2.1.0.tgz", + "integrity": "sha512-y3b8Kpd8OAN444hxfBbFfj1FY/RjtTd8tzYwhUqNYXx0fXx2iX4maP4Qr6qhIKbQXI02wTLAda4fYUbDagTUFw==" + } + } + }, "ipaddr.js": { "version": "1.9.1", "resolved": "https://registry.npmjs.org/ipaddr.js/-/ipaddr.js-1.9.1.tgz", @@ -7140,8 +7260,7 @@ "lodash.defaults": { "version": "4.2.0", "resolved": "https://registry.npmjs.org/lodash.defaults/-/lodash.defaults-4.2.0.tgz", - "integrity": "sha1-0JF4cW/+pN3p5ft7N/bwgCJ0WAw=", - "dev": true + "integrity": "sha1-0JF4cW/+pN3p5ft7N/bwgCJ0WAw=" }, "lodash.difference": { "version": "4.5.0", @@ -7152,14 +7271,18 @@ "lodash.flatten": { "version": "4.4.0", "resolved": "https://registry.npmjs.org/lodash.flatten/-/lodash.flatten-4.4.0.tgz", - "integrity": "sha1-8xwiIlqWMtK7+OSt2+8kCqdlph8=", - "dev": true + "integrity": "sha1-8xwiIlqWMtK7+OSt2+8kCqdlph8=" }, "lodash.includes": { "version": "4.3.0", "resolved": "https://registry.npmjs.org/lodash.includes/-/lodash.includes-4.3.0.tgz", "integrity": "sha1-YLuYqHy5I8aMoeUTJUgzFISfVT8=" }, + "lodash.isarguments": { + "version": "3.1.0", + "resolved": "https://registry.npmmirror.com/lodash.isarguments/-/lodash.isarguments-3.1.0.tgz", + "integrity": "sha512-chi4NHZlZqZD18a0imDHnZPrDeBbTtVN7GXMwuGdRH9qotxAjYs3aVLKc7zNOG9eddR5Ksd8rvFEBc9SsggPpg==" + }, "lodash.isboolean": { "version": "3.0.3", "resolved": "https://registry.npmjs.org/lodash.isboolean/-/lodash.isboolean-3.0.3.tgz", @@ -7255,6 +7378,11 @@ } } }, + "luxon": { + "version": "1.28.0", + "resolved": "https://registry.npmmirror.com/luxon/-/luxon-1.28.0.tgz", + "integrity": "sha512-TfTiyvZhwBYM/7QdAVDh+7dBTBA29v4ik0Ce9zda3Mnf8on1S5KJI8P2jKFZ8+5C0jhmr0KwJEO/Wdpm0VeWJQ==" + }, "macos-release": { "version": "2.5.0", "resolved": "https://registry.npmjs.org/macos-release/-/macos-release-2.5.0.tgz", @@ -7426,6 +7554,24 @@ "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==" }, + "msgpackr": { + "version": "1.5.4", + "resolved": "https://registry.npmmirror.com/msgpackr/-/msgpackr-1.5.4.tgz", + "integrity": "sha512-Z7w5Jg+2Q9z9gJxeM68d7tSuWZZGnFIRhZnyqcZCa/1dKkhOCNvR1TUV3zzJ3+vj78vlwKRzUgVDlW4jiSOeDA==", + "requires": { + "msgpackr-extract": "^1.0.14" + } + }, + "msgpackr-extract": { + "version": "1.0.16", + "resolved": "https://registry.npmmirror.com/msgpackr-extract/-/msgpackr-extract-1.0.16.tgz", + "integrity": "sha512-fxdRfQUxPrL/TizyfYfMn09dK58e+d65bRD/fcaVH4052vj30QOzzqxcQIS7B0NsqlypEQ/6Du3QmP2DhWFfCA==", + "optional": true, + "requires": { + "nan": "^2.14.2", + "node-gyp-build": "^4.2.3" + } + }, "multer": { "version": "1.4.4", "resolved": "https://registry.npmjs.org/multer/-/multer-1.4.4.tgz", @@ -7457,6 +7603,12 @@ "integrity": "sha512-nnbWWOkoWyUsTjKrhgD0dcz22mdkSnpYqbEjIm2nhwhuxlSkpywJmBo8h0ZqJdkp73mb90SssHkN4rsRaBAfAA==", "dev": true }, + "nan": { + "version": "2.15.0", + "resolved": "https://registry.npmmirror.com/nan/-/nan-2.15.0.tgz", + "integrity": "sha512-8ZtvEnA2c5aYCZYd1cvgdnU6cqwixRoYg70xPLWUws5ORTa/lnw+u4amixRS/Ac5U5mQVgp9pnlSUnbNWFaWZQ==", + "optional": true + }, "natural-compare": { "version": "1.4.0", "resolved": "https://registry.npmjs.org/natural-compare/-/natural-compare-1.4.0.tgz", @@ -7558,6 +7710,12 @@ "resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-2.6.1.tgz", "integrity": "sha512-V4aYg89jEoVRxRb2fJdAg8FHvI7cEyYdVAh94HH0UIK8oJxUfkjlDQN9RbMx+bEjP7+ggMiFRprSti032Oipxw==" }, + "node-gyp-build": { + "version": "4.3.0", + "resolved": "https://registry.npmmirror.com/node-gyp-build/-/node-gyp-build-4.3.0.tgz", + "integrity": "sha512-iWjXZvmboq0ja1pUGULQBexmxq8CV4xBhX7VDOTbL7ZR4FOowwY/VOtRxBN/yKxmdGoIp4j5ysNT4u3S2pDQ3Q==", + "optional": true + }, "node-int64": { "version": "0.4.0", "resolved": "https://registry.npmjs.org/node-int64/-/node-int64-0.4.0.tgz", @@ -7750,6 +7908,11 @@ } } }, + "p-finally": { + "version": "1.0.0", + "resolved": "https://registry.npmmirror.com/p-finally/-/p-finally-1.0.0.tgz", + "integrity": "sha512-LICb2p9CB7FS+0eR1oqWnHhp0FljGLZCWBE9aix0Uye9W8LTQPwMTYVGWQWIw9RdQiDg4+epXQODwIYJtSJaow==" + }, "p-limit": { "version": "2.3.0", "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.3.0.tgz", @@ -7787,6 +7950,14 @@ "retry": "^0.13.1" } }, + "p-timeout": { + "version": "3.2.0", + "resolved": "https://registry.npmmirror.com/p-timeout/-/p-timeout-3.2.0.tgz", + "integrity": "sha512-rhIwUycgwwKcP9yTOOFK/AKsAopjjCakVqLHePO3CC6Mir1Z99xT+R63jZxAT5lFZLa2inS5h+ZS2GvR99/FBg==", + "requires": { + "p-finally": "^1.0.0" + } + }, "p-try": { "version": "2.2.0", "resolved": "https://registry.npmjs.org/p-try/-/p-try-2.2.0.tgz", @@ -8169,6 +8340,24 @@ "resolve": "^1.1.6" } }, + "redis-commands": { + "version": "1.7.0", + "resolved": "https://registry.npmmirror.com/redis-commands/-/redis-commands-1.7.0.tgz", + "integrity": "sha512-nJWqw3bTFy21hX/CPKHth6sfhZbdiHP6bTawSgQBlKOVRG7EZkfHbbHwQJnrE4vsQf0CMNE+3gJ4Fmm16vdVlQ==" + }, + "redis-errors": { + "version": "1.2.0", + "resolved": "https://registry.npmmirror.com/redis-errors/-/redis-errors-1.2.0.tgz", + "integrity": "sha512-1qny3OExCf0UvUV/5wpYKf2YwPcOqXzkwKKSmKHiE6ZMQs5heeE/c8eXK+PNllPvmjgAbfnsbpkGZWy8cBpn9w==" + }, + "redis-parser": { + "version": "3.0.0", + "resolved": "https://registry.npmmirror.com/redis-parser/-/redis-parser-3.0.0.tgz", + "integrity": "sha512-DJnGAeenTdpMEH6uAJRK/uiyEIH9WVsUmoLwzudwGJUwZPp80PDBWPHXSAGNPwNvIXAbe7MSUB1zQFugFml66A==", + "requires": { + "redis-errors": "^1.0.0" + } + }, "reflect-metadata": { "version": "0.1.13", "resolved": "https://registry.npmjs.org/reflect-metadata/-/reflect-metadata-0.1.13.tgz", @@ -8600,6 +8789,11 @@ } } }, + "standard-as-callback": { + "version": "2.1.0", + "resolved": "https://registry.npmmirror.com/standard-as-callback/-/standard-as-callback-2.1.0.tgz", + "integrity": "sha512-qoRRSyROncaz1z0mvYqIE4lCd9p2R90i6GxW3uZv5ucSu8tU7B5HXUP1gG8pVZsYNVaXjk8ClXHPttLyxAL48A==" + }, "statuses": { "version": "1.5.0", "resolved": "https://registry.npmjs.org/statuses/-/statuses-1.5.0.tgz", diff --git a/package.json b/package.json index 95482a15..0f491fee 100644 --- a/package.json +++ b/package.json @@ -27,6 +27,9 @@ "start:dev": "nest start --watch", "start:debug": "nest start --debug --watch", "start:prod": "node dist/main", + "start:consumer:dev": "nest start -c nest-cli-worker.json --watch", + "start:consumer:debug": "nest start -c nest-cli-worker.json --debug --watch", + "start:consumer:prod": "node dist/worker", "lint": "eslint \"{src,apps,libs,test}/**/*.ts\" --fix", "migrate:dev": "prisma migrate dev --preview-feature", "migrate:dev:create": "prisma migrate dev --create-only --preview-feature", @@ -53,6 +56,7 @@ }, "dependencies": { "@devoxa/prisma-relay-cursor-connection": "2.0.3", + "@nestjs/bull": "^0.4.2", "@nestjs/common": "8.2.5", "@nestjs/config": "1.1.6", "@nestjs/core": "8.2.5", @@ -64,6 +68,7 @@ "@prisma/client": "3.8.1", "apollo-server-express": "3.6.1", "bcrypt": "5.0.1", + "bull": "^4.5.0", "class-transformer": "0.5.1", "class-validator": "0.13.2", "graphql": "15.6.0", @@ -80,6 +85,7 @@ "@nestjs/cli": "8.2.0", "@nestjs/testing": "8.2.5", "@types/bcrypt": "5.0.0", + "@types/bull": "^3.15.7", "@types/chance": "1.1.3", "@types/express": "4.17.13", "@types/jest": "27.0.1", diff --git a/src/app.module.ts b/src/app.module.ts index 0ef7ff10..d4e98e6b 100644 --- a/src/app.module.ts +++ b/src/app.module.ts @@ -1,5 +1,5 @@ import { GraphQLModule } from '@nestjs/graphql'; -import { Module } from '@nestjs/common'; +import { Module, Logger } from '@nestjs/common'; import { AppController } from './controllers/app.controller'; import { AppService } from './services/app.service'; import { AuthModule } from './resolvers/auth/auth.module'; @@ -12,14 +12,16 @@ import config from './configs/config'; import { GraphqlConfig } from './configs/config.interface'; import { PrismaModule } from 'nestjs-prisma'; import { loggingMiddleware } from './logging.middleware'; - +import { BullModule } from '@nestjs/bull'; +import { QueueOptions } from 'bull'; @Module({ imports: [ ConfigModule.forRoot({ isGlobal: true, load: [config] }), - PrismaModule.forRoot({ + PrismaModule.forRootAsync({ isGlobal: true, - prismaServiceOptions: { - middlewares: [loggingMiddleware()], // configure your prisma middleware + useFactory: () => { + const logger = new Logger('PrismaMiddleware'); + return { middlewares: [loggingMiddleware(logger)] }; // configure your prisma middleware }, }), GraphQLModule.forRootAsync({ @@ -40,7 +42,15 @@ import { loggingMiddleware } from './logging.middleware'; }, inject: [ConfigService], }), - + BullModule.registerQueueAsync({ + name: 'nest-worker', + useFactory: async (configService: ConfigService) => { + const bullConfig = await configService.get('bull'); + return bullConfig; + }, + imports: [ConfigModule], + inject: [ConfigService], + }), AuthModule, UserModule, PostModule, diff --git a/src/configs/config.interface.ts b/src/configs/config.interface.ts index c078e58c..790911d1 100644 --- a/src/configs/config.interface.ts +++ b/src/configs/config.interface.ts @@ -1,9 +1,12 @@ +import { QueueOptions } from 'bull'; +export { QueueOptions } from 'bull'; export interface Config { nest: NestConfig; cors: CorsConfig; swagger: SwaggerConfig; graphql: GraphqlConfig; security: SecurityConfig; + bull: QueueOptions; } export interface NestConfig { diff --git a/src/configs/config.ts b/src/configs/config.ts index ffd4db0f..1b409ea8 100644 --- a/src/configs/config.ts +++ b/src/configs/config.ts @@ -25,6 +25,25 @@ const config: Config = { refreshIn: '7d', bcryptSaltOrRound: 10, }, + bull: { + redis: { + host: process.env.REDIS_HOST || 'localhost', + port: Number(process.env.REDIS_PORT || 6379), + password: process.env.REDIS_PASSWORD, + }, + limiter: { + max: 1000, + duration: 60000, + }, + prefix: 'bull', + defaultJobOptions: { + attempts: 3, + backoff: { + type: 'exponential', + delay: 1000, + }, + }, + }, }; export default (): Config => config; diff --git a/src/controllers/app.controller.ts b/src/controllers/app.controller.ts index ffe0b8bc..57950071 100644 --- a/src/controllers/app.controller.ts +++ b/src/controllers/app.controller.ts @@ -14,4 +14,9 @@ export class AppController { getHelloName(@Param('name') name: string): string { return this.appService.getHelloName(name); } + + @Get('hello/:name/async') + async getHelloNameAsync(@Param('name') name: string) { + return this.appService.sayHello(name); + } } diff --git a/src/logging.middleware.ts b/src/logging.middleware.ts index a52bb1c8..de36fcb6 100644 --- a/src/logging.middleware.ts +++ b/src/logging.middleware.ts @@ -1,6 +1,6 @@ import { Prisma } from '@prisma/client'; -export function loggingMiddleware(): Prisma.Middleware { +export function loggingMiddleware(logger: any = console): Prisma.Middleware { return async (params, next) => { const before = Date.now(); @@ -8,7 +8,7 @@ export function loggingMiddleware(): Prisma.Middleware { const after = Date.now(); - console.log( + logger.debug( `Prisma Query ${params.model}.${params.action} took ${after - before}ms` ); diff --git a/src/processors/index.ts b/src/processors/index.ts new file mode 100644 index 00000000..81461f28 --- /dev/null +++ b/src/processors/index.ts @@ -0,0 +1 @@ +export * from './nest.processor'; diff --git a/src/processors/nest.processor.ts b/src/processors/nest.processor.ts new file mode 100644 index 00000000..8ed5b6ef --- /dev/null +++ b/src/processors/nest.processor.ts @@ -0,0 +1,12 @@ +import { Process, Processor } from '@nestjs/bull'; +import { Logger } from '@nestjs/common'; +@Processor('nest-worker') +export class NestConsumer { + logger = new Logger('NestConsumer'); + @Process('say-hello') + async sayHello(job) { + const { name } = job.data; + this.logger.log(`Hello ${name}!`); + return job.data; + } +} diff --git a/src/services/app.service.ts b/src/services/app.service.ts index 641629a0..c939facf 100644 --- a/src/services/app.service.ts +++ b/src/services/app.service.ts @@ -1,7 +1,10 @@ import { Injectable } from '@nestjs/common'; +import { InjectQueue } from '@nestjs/bull'; +import { Queue } from 'bull'; @Injectable() export class AppService { + constructor(@InjectQueue('nest-worker') private nestWorkerQueue: Queue) {} getHello(): string { return 'Hello World!'; } @@ -9,4 +12,8 @@ export class AppService { getHelloName(name: string): string { return `Hello ${name}!`; } + + async sayHello(name: string) { + return await this.nestWorkerQueue.add('say-hello', { name }); + } } diff --git a/src/worker.ts b/src/worker.ts new file mode 100644 index 00000000..05d29532 --- /dev/null +++ b/src/worker.ts @@ -0,0 +1,19 @@ +import 'dotenv/config'; +import { NestFactory } from '@nestjs/core'; +import { AppModule } from './app.module'; +import { Module, OnModuleInit } from '@nestjs/common'; +import { NestConsumer } from './processors'; +@Module({ + imports: [AppModule], + providers: [NestConsumer], +}) +export class WorkerModule implements OnModuleInit { + onModuleInit() { + console.log('WORKER: ', process.pid); + } +} +async function bootstrap() { + const app = await NestFactory.create(WorkerModule); + app.init(); +} +bootstrap();