diff --git a/README.md b/README.md
index 00a13b1..70d770a 100644
--- a/README.md
+++ b/README.md
@@ -1,30 +1,6 @@
-
-
-
-
-[circleci-image]: https://img.shields.io/circleci/build/github/nestjs/nest/master?token=abc123def456
-[circleci-url]: https://circleci.com/gh/nestjs/nest
-
- A progressive Node.js framework for building efficient and scalable server-side applications.
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
## Description
-[Nest](https://github.com/nestjs/nest) framework TypeScript starter repository.
+[LeyuChat](https://dev.leyuchat.com/) A Message Automation tool
## Installation
@@ -32,42 +8,19 @@
$ npm install
```
-## Running the app
+## Running Mini App
```bash
# development
$ npm run start
-# watch mode
-$ npm run start:dev
+# run database consumer
+$ pm2 start dist/src/apps/consumers/database-consumer/main.js --no-daemon
-# production mode
-$ npm run start:prod
+# run chat consumer
+$ pm2 start dist/src/apps/consumers/chat-consumer/main.js --no-daemon
```
-## Test
-
-```bash
-# unit tests
-$ npm run test
-
-# e2e tests
-$ npm run test:e2e
-
-# test coverage
-$ npm run test:cov
-```
-
-## Support
-
-Nest is an MIT-licensed open source project. It can grow thanks to the sponsors and support by the amazing backers. If you'd like to join them, please [read more here](https://docs.nestjs.com/support).
-
-## Stay in touch
-
-- Author - [Kamil MyĆliwiec](https://kamilmysliwiec.com)
-- Website - [https://nestjs.com](https://nestjs.com/)
-- Twitter - [@nestframework](https://twitter.com/nestframework)
-
## License
-Nest is [MIT licensed](LICENSE).
+LeyuChat is [MIT licensed](LICENSE).
diff --git a/docker-compose.yml b/docker-compose.yml
index dc7d514..eb7880a 100644
--- a/docker-compose.yml
+++ b/docker-compose.yml
@@ -51,6 +51,22 @@ services:
environment:
RABBITMQ_DEFAULT_USER: user
RABBITMQ_DEFAULT_PASS: password
+
+ chat-consumer:
+ build:
+ context: .
+ platform: linux/amd64
+ environment:
+ - RABBITMQ_URL=${RABBITMQ_URL}
+ command: ["node", "dist/src/apps/consumers/chat-consumer/main.js"]
+
+ database-consumer:
+ build:
+ context: .
+ platform: linux/amd64
+ environment:
+ - RABBITMQ_URL=${RABBITMQ_URL}
+ command: ["node", "dist/src/apps/consumers/database-consumer/main.js"]
volumes:
postgres_data:
diff --git a/package-lock.json b/package-lock.json
index 9763a7e..5329e8f 100644
--- a/package-lock.json
+++ b/package-lock.json
@@ -25,6 +25,7 @@
"@nestjs/websockets": "^10.4.15",
"@prisma/client": "^5.22.0",
"@types/ioredis": "^4.28.10",
+ "amqp-connection-manager": "^4.1.14",
"amqplib": "^0.10.5",
"bcryptjs": "^2.4.3",
"class-transformer": "^0.5.1",
@@ -3778,6 +3779,22 @@
"node": ">=0.10.0"
}
},
+ "node_modules/amqp-connection-manager": {
+ "version": "4.1.14",
+ "resolved": "https://registry.npmjs.org/amqp-connection-manager/-/amqp-connection-manager-4.1.14.tgz",
+ "integrity": "sha512-1km47dIvEr0HhMUazqovSvNwIlSvDX2APdUpULaINtHpiki1O+cLRaTeXb/jav4OLtH+k6GBXx5gsKOT9kcGKQ==",
+ "license": "MIT",
+ "dependencies": {
+ "promise-breaker": "^6.0.0"
+ },
+ "engines": {
+ "node": ">=10.0.0",
+ "npm": ">5.0.0"
+ },
+ "peerDependencies": {
+ "amqplib": "*"
+ }
+ },
"node_modules/amqplib": {
"version": "0.10.5",
"resolved": "https://registry.npmjs.org/amqplib/-/amqplib-0.10.5.tgz",
@@ -11045,6 +11062,12 @@
"asap": "~2.0.3"
}
},
+ "node_modules/promise-breaker": {
+ "version": "6.0.0",
+ "resolved": "https://registry.npmjs.org/promise-breaker/-/promise-breaker-6.0.0.tgz",
+ "integrity": "sha512-BthzO9yTPswGf7etOBiHCVuugs2N01/Q/94dIPls48z2zCmrnDptUUZzfIb+41xq0MnYZ/BzmOd6ikDR4ibNZA==",
+ "license": "MIT"
+ },
"node_modules/prompts": {
"version": "2.4.2",
"resolved": "https://registry.npmjs.org/prompts/-/prompts-2.4.2.tgz",
diff --git a/package.json b/package.json
index c505937..d09aaaf 100644
--- a/package.json
+++ b/package.json
@@ -38,6 +38,7 @@
"@nestjs/websockets": "^10.4.15",
"@prisma/client": "^5.22.0",
"@types/ioredis": "^4.28.10",
+ "amqp-connection-manager": "^4.1.14",
"amqplib": "^0.10.5",
"bcryptjs": "^2.4.3",
"class-transformer": "^0.5.1",
diff --git a/src/apps/consumers/chat-consumer/chat-consumer.controller.spec.ts b/src/apps/consumers/chat-consumer/chat-consumer.controller.spec.ts
new file mode 100644
index 0000000..6dad5f0
--- /dev/null
+++ b/src/apps/consumers/chat-consumer/chat-consumer.controller.spec.ts
@@ -0,0 +1,18 @@
+import { Test, TestingModule } from '@nestjs/testing';
+import { ChatConsumerController } from './chat-consumer.controller';
+
+describe('ChatConsumerController', () => {
+ let controller: ChatConsumerController;
+
+ beforeEach(async () => {
+ const module: TestingModule = await Test.createTestingModule({
+ controllers: [ChatConsumerController],
+ }).compile();
+
+ controller = module.get(ChatConsumerController);
+ });
+
+ it('should be defined', () => {
+ expect(controller).toBeDefined();
+ });
+});
diff --git a/src/apps/consumers/chat-consumer/chat-consumer.controller.ts b/src/apps/consumers/chat-consumer/chat-consumer.controller.ts
new file mode 100644
index 0000000..cc767ea
--- /dev/null
+++ b/src/apps/consumers/chat-consumer/chat-consumer.controller.ts
@@ -0,0 +1,4 @@
+import { Controller } from '@nestjs/common';
+
+@Controller('chat-consumer')
+export class ChatConsumerController {}
diff --git a/src/apps/consumers/chat-consumer/chat-consumer.module.ts b/src/apps/consumers/chat-consumer/chat-consumer.module.ts
new file mode 100644
index 0000000..83b52ac
--- /dev/null
+++ b/src/apps/consumers/chat-consumer/chat-consumer.module.ts
@@ -0,0 +1,18 @@
+import { Module } from '@nestjs/common';
+import { ChatConsumerController } from './chat-consumer.controller';
+import { ChatConsumerService } from './chat-consumer.service';
+import { ConfigModule } from '@nestjs/config';
+import { PrismaModule } from 'src/modules/prisma/prisma.module';
+
+@Module({
+ imports: [
+ ConfigModule.forRoot({
+ isGlobal: true,
+ envFilePath: '.env',
+ }),
+ PrismaModule,
+ ],
+ controllers: [ChatConsumerController],
+ providers: [ChatConsumerService],
+})
+export class ChatConsumerModule {}
diff --git a/src/apps/consumers/chat-consumer/chat-consumer.service.spec.ts b/src/apps/consumers/chat-consumer/chat-consumer.service.spec.ts
new file mode 100644
index 0000000..c0ea396
--- /dev/null
+++ b/src/apps/consumers/chat-consumer/chat-consumer.service.spec.ts
@@ -0,0 +1,18 @@
+import { Test, TestingModule } from '@nestjs/testing';
+import { ChatConsumerService } from './chat-consumer.service';
+
+describe('ChatConsumerService', () => {
+ let service: ChatConsumerService;
+
+ beforeEach(async () => {
+ const module: TestingModule = await Test.createTestingModule({
+ providers: [ChatConsumerService],
+ }).compile();
+
+ service = module.get(ChatConsumerService);
+ });
+
+ it('should be defined', () => {
+ expect(service).toBeDefined();
+ });
+});
diff --git a/src/apps/consumers/chat-consumer/chat-consumer.service.ts b/src/apps/consumers/chat-consumer/chat-consumer.service.ts
new file mode 100644
index 0000000..c4753b1
--- /dev/null
+++ b/src/apps/consumers/chat-consumer/chat-consumer.service.ts
@@ -0,0 +1,4 @@
+import { Injectable } from '@nestjs/common';
+
+@Injectable()
+export class ChatConsumerService {}
diff --git a/src/apps/consumers/chat-consumer/main.ts b/src/apps/consumers/chat-consumer/main.ts
new file mode 100644
index 0000000..44ac168
--- /dev/null
+++ b/src/apps/consumers/chat-consumer/main.ts
@@ -0,0 +1,26 @@
+import { NestFactory } from '@nestjs/core';
+import { MicroserviceOptions, Transport } from '@nestjs/microservices';
+import { ChatConsumerModule } from './chat-consumer.module';
+
+async function bootstrap() {
+ const app = await NestFactory.createMicroservice(
+ ChatConsumerModule,
+ {
+ transport: Transport.RMQ,
+ options: {
+ urls: [process.env.RABBITMQ_URL],
+ queue: 'chat',
+ queueOptions: {
+ durable: true,
+ messageTtl: 60000,
+ deadLetterExchange: 'message',
+ deadLetterRoutingKey: 'dead',
+ },
+ noAck: false,
+ prefetchCount: 1,
+ },
+ },
+ );
+ await app.listen();
+}
+bootstrap();
diff --git a/src/apps/consumers/database-consumer/database-consumer.controller.spec.ts b/src/apps/consumers/database-consumer/database-consumer.controller.spec.ts
new file mode 100644
index 0000000..b5f898e
--- /dev/null
+++ b/src/apps/consumers/database-consumer/database-consumer.controller.spec.ts
@@ -0,0 +1,20 @@
+import { Test, TestingModule } from '@nestjs/testing';
+import { DatabaseConsumerController } from './database-consumer.controller';
+
+describe('DatabaseConsumerController', () => {
+ let controller: DatabaseConsumerController;
+
+ beforeEach(async () => {
+ const module: TestingModule = await Test.createTestingModule({
+ controllers: [DatabaseConsumerController],
+ }).compile();
+
+ controller = module.get(
+ DatabaseConsumerController,
+ );
+ });
+
+ it('should be defined', () => {
+ expect(controller).toBeDefined();
+ });
+});
diff --git a/src/apps/consumers/database-consumer/database-consumer.controller.ts b/src/apps/consumers/database-consumer/database-consumer.controller.ts
new file mode 100644
index 0000000..6e65260
--- /dev/null
+++ b/src/apps/consumers/database-consumer/database-consumer.controller.ts
@@ -0,0 +1,16 @@
+import { Controller } from '@nestjs/common';
+import { Ctx, EventPattern, Payload, RmqContext } from '@nestjs/microservices';
+import { MessagePayload } from 'src/types/message';
+import { DatabaseConsumerService } from './database-consumer.service';
+
+@Controller('database-consumer')
+export class DatabaseConsumerController {
+ constructor(private readonly databaseService: DatabaseConsumerService) {}
+ @EventPattern()
+ async handleMessage(
+ @Payload() data: MessagePayload,
+ @Ctx() context: RmqContext,
+ ) {
+ this.databaseService.handleMessage(data, context);
+ }
+}
diff --git a/src/apps/consumers/database-consumer/database-consumer.module.ts b/src/apps/consumers/database-consumer/database-consumer.module.ts
new file mode 100644
index 0000000..75af18a
--- /dev/null
+++ b/src/apps/consumers/database-consumer/database-consumer.module.ts
@@ -0,0 +1,18 @@
+import { Module } from '@nestjs/common';
+import { DatabaseConsumerController } from './database-consumer.controller';
+import { DatabaseConsumerService } from './database-consumer.service';
+import { ConfigModule } from '@nestjs/config';
+import { PrismaModule } from 'src/modules/prisma/prisma.module';
+
+@Module({
+ imports: [
+ ConfigModule.forRoot({
+ isGlobal: true,
+ envFilePath: '.env',
+ }),
+ PrismaModule,
+ ],
+ controllers: [DatabaseConsumerController],
+ providers: [DatabaseConsumerService],
+})
+export class DatabaseConsumerModule {}
diff --git a/src/apps/consumers/database-consumer/database-consumer.service.spec.ts b/src/apps/consumers/database-consumer/database-consumer.service.spec.ts
new file mode 100644
index 0000000..915e605
--- /dev/null
+++ b/src/apps/consumers/database-consumer/database-consumer.service.spec.ts
@@ -0,0 +1,18 @@
+import { Test, TestingModule } from '@nestjs/testing';
+import { DatabaseConsumerService } from './database-consumer.service';
+
+describe('DatabaseConsumerService', () => {
+ let service: DatabaseConsumerService;
+
+ beforeEach(async () => {
+ const module: TestingModule = await Test.createTestingModule({
+ providers: [DatabaseConsumerService],
+ }).compile();
+
+ service = module.get(DatabaseConsumerService);
+ });
+
+ it('should be defined', () => {
+ expect(service).toBeDefined();
+ });
+});
diff --git a/src/apps/consumers/database-consumer/database-consumer.service.ts b/src/apps/consumers/database-consumer/database-consumer.service.ts
new file mode 100644
index 0000000..c31c1c1
--- /dev/null
+++ b/src/apps/consumers/database-consumer/database-consumer.service.ts
@@ -0,0 +1,11 @@
+import { Injectable } from '@nestjs/common';
+import { RmqContext } from '@nestjs/microservices';
+import { MessagePayload } from 'src/types/message';
+
+@Injectable()
+export class DatabaseConsumerService {
+ async handleMessage(data: MessagePayload, context: RmqContext) {
+ console.log(data);
+ console.log(context);
+ }
+}
diff --git a/src/apps/consumers/database-consumer/main.ts b/src/apps/consumers/database-consumer/main.ts
new file mode 100644
index 0000000..bafadfd
--- /dev/null
+++ b/src/apps/consumers/database-consumer/main.ts
@@ -0,0 +1,26 @@
+import { NestFactory } from '@nestjs/core';
+import { MicroserviceOptions, Transport } from '@nestjs/microservices';
+import { DatabaseConsumerModule } from './database-consumer.module';
+
+async function bootstrap() {
+ const app = await NestFactory.createMicroservice(
+ DatabaseConsumerModule,
+ {
+ transport: Transport.RMQ,
+ options: {
+ urls: [process.env.RABBITMQ_URL],
+ queue: 'database',
+ queueOptions: {
+ durable: true,
+ messageTtl: 60000,
+ deadLetterExchange: 'message',
+ deadLetterRoutingKey: 'dead',
+ },
+ noAck: false,
+ prefetchCount: 1,
+ },
+ },
+ );
+ await app.listen();
+}
+bootstrap();
diff --git a/src/types/message.ts b/src/types/message.ts
new file mode 100644
index 0000000..c7979a8
--- /dev/null
+++ b/src/types/message.ts
@@ -0,0 +1,7 @@
+import { Message } from '@prisma/client';
+
+export interface MessagePayload {
+ type?: string;
+ metadata?: Record;
+ payload?: Message;
+}