From 705de1bcf8d213a640d9e3c25b047073f31c1cac Mon Sep 17 00:00:00 2001 From: sbriat Date: Wed, 15 Mar 2023 17:01:23 +0100 Subject: [PATCH] refactor broker to use a single exchange --- .env.dist | 1 + .../{logging.messager.ts => messager.ts} | 10 ++++-- .../adapters/secondaries/user.messager.ts | 14 -------- .../domain/usecases/create-user.usecase.ts | 16 ++++----- .../domain/usecases/delete-user.usecase.ts | 19 +++++----- .../usecases/find-user-by-uuid.usecase.ts | 8 ++--- .../domain/usecases/update-user.usecase.ts | 18 +++++----- .../tests/unit/create-user.usecase.spec.ts | 9 ++--- .../tests/unit/delete-user.usecase.spec.ts | 9 ++--- .../unit/find-user-by-uuid.usecase.spec.ts | 4 +-- ...sager.usecase.spec.ts => messager.spec.ts} | 25 +++++++++---- .../tests/unit/update-user.usecase.spec.ts | 9 ++--- .../tests/unit/user.messager.usecase.spec.ts | 36 ------------------- src/modules/users/users.module.ts | 12 ++----- 14 files changed, 66 insertions(+), 124 deletions(-) rename src/modules/users/adapters/secondaries/{logging.messager.ts => messager.ts} (56%) delete mode 100644 src/modules/users/adapters/secondaries/user.messager.ts rename src/modules/users/tests/unit/{logging.messager.usecase.spec.ts => messager.spec.ts} (56%) delete mode 100644 src/modules/users/tests/unit/user.messager.usecase.spec.ts diff --git a/.env.dist b/.env.dist index 80a314c..6ae3d9e 100644 --- a/.env.dist +++ b/.env.dist @@ -8,6 +8,7 @@ DATABASE_URL="postgresql://user:user@v3-user-db:5432/user?schema=public" # RABBIT MQ RMQ_URI=amqp://v3-broker:5672 +RMQ_EXCHANGE=mobicoop # POSTGRES POSTGRES_IMAGE=postgres:15.0 diff --git a/src/modules/users/adapters/secondaries/logging.messager.ts b/src/modules/users/adapters/secondaries/messager.ts similarity index 56% rename from src/modules/users/adapters/secondaries/logging.messager.ts rename to src/modules/users/adapters/secondaries/messager.ts index 00988ec..0ee32e3 100644 --- a/src/modules/users/adapters/secondaries/logging.messager.ts +++ b/src/modules/users/adapters/secondaries/messager.ts @@ -1,11 +1,15 @@ import { AmqpConnection } from '@golevelup/nestjs-rabbitmq'; import { Injectable } from '@nestjs/common'; +import { ConfigService } from '@nestjs/config'; import { IMessageBroker } from '../../domain/interfaces/message-broker'; @Injectable() -export class LoggingMessager extends IMessageBroker { - constructor(private readonly _amqpConnection: AmqpConnection) { - super('logging'); +export class Messager extends IMessageBroker { + constructor( + private readonly _amqpConnection: AmqpConnection, + configService: ConfigService, + ) { + super(configService.get('RMQ_EXCHANGE')); } publish(routingKey: string, message: string): void { diff --git a/src/modules/users/adapters/secondaries/user.messager.ts b/src/modules/users/adapters/secondaries/user.messager.ts deleted file mode 100644 index 4653d9d..0000000 --- a/src/modules/users/adapters/secondaries/user.messager.ts +++ /dev/null @@ -1,14 +0,0 @@ -import { AmqpConnection } from '@golevelup/nestjs-rabbitmq'; -import { Injectable } from '@nestjs/common'; -import { IMessageBroker } from '../../domain/interfaces/message-broker'; - -@Injectable() -export class UserMessager extends IMessageBroker { - constructor(private readonly _amqpConnection: AmqpConnection) { - super('user'); - } - - publish(routingKey: string, message: string): void { - this._amqpConnection.publish(this.exchange, routingKey, message); - } -} diff --git a/src/modules/users/domain/usecases/create-user.usecase.ts b/src/modules/users/domain/usecases/create-user.usecase.ts index 1947ed2..25771d4 100644 --- a/src/modules/users/domain/usecases/create-user.usecase.ts +++ b/src/modules/users/domain/usecases/create-user.usecase.ts @@ -1,8 +1,7 @@ import { Mapper } from '@automapper/core'; import { InjectMapper } from '@automapper/nestjs'; import { CommandHandler } from '@nestjs/cqrs'; -import { LoggingMessager } from '../../adapters/secondaries/logging.messager'; -import { UserMessager } from '../../adapters/secondaries/user.messager'; +import { Messager } from '../../adapters/secondaries/messager'; import { UsersRepository } from '../../adapters/secondaries/users.repository'; import { CreateUserCommand } from '../../commands/create-user.command'; import { CreateUserRequest } from '../dtos/create-user.request'; @@ -12,8 +11,7 @@ import { User } from '../entities/user'; export class CreateUserUseCase { constructor( private readonly _repository: UsersRepository, - private readonly _userMessager: UserMessager, - private readonly _loggingMessager: LoggingMessager, + private readonly _messager: Messager, @InjectMapper() private readonly _mapper: Mapper, ) {} @@ -26,15 +24,15 @@ export class CreateUserUseCase { try { const user = await this._repository.create(entity); - this._userMessager.publish('create', JSON.stringify(user)); - this._loggingMessager.publish('user.create.info', JSON.stringify(user)); + this._messager.publish('user.create', JSON.stringify(user)); + this._messager.publish('logging.user.create.info', JSON.stringify(user)); return user; } catch (error) { - let key = 'user.create.crit'; + let key = 'logging.user.create.crit'; if (error.message.includes('Already exists')) { - key = 'user.create.warning'; + key = 'logging.user.create.warning'; } - this._loggingMessager.publish( + this._messager.publish( key, JSON.stringify({ command, diff --git a/src/modules/users/domain/usecases/delete-user.usecase.ts b/src/modules/users/domain/usecases/delete-user.usecase.ts index d406ff5..1b575cd 100644 --- a/src/modules/users/domain/usecases/delete-user.usecase.ts +++ b/src/modules/users/domain/usecases/delete-user.usecase.ts @@ -1,6 +1,5 @@ import { CommandHandler } from '@nestjs/cqrs'; -import { LoggingMessager } from '../../adapters/secondaries/logging.messager'; -import { UserMessager } from '../../adapters/secondaries/user.messager'; +import { Messager } from '../../adapters/secondaries/messager'; import { UsersRepository } from '../../adapters/secondaries/users.repository'; import { DeleteUserCommand } from '../../commands/delete-user.command'; import { User } from '../entities/user'; @@ -9,22 +8,24 @@ import { User } from '../entities/user'; export class DeleteUserUseCase { constructor( private readonly _repository: UsersRepository, - private readonly _userMessager: UserMessager, - private readonly _loggingMessager: LoggingMessager, + private readonly _messager: Messager, ) {} async execute(command: DeleteUserCommand): Promise { try { const user = await this._repository.delete(command.uuid); - this._userMessager.publish('delete', JSON.stringify({ uuid: user.uuid })); - this._loggingMessager.publish( - 'user.delete.info', + this._messager.publish( + 'user.delete', + JSON.stringify({ uuid: user.uuid }), + ); + this._messager.publish( + 'logging.user.delete.info', JSON.stringify({ uuid: user.uuid }), ); return user; } catch (error) { - this._loggingMessager.publish( - 'user.delete.crit', + this._messager.publish( + 'logging.user.delete.crit', JSON.stringify({ command, error, diff --git a/src/modules/users/domain/usecases/find-user-by-uuid.usecase.ts b/src/modules/users/domain/usecases/find-user-by-uuid.usecase.ts index a49fe3f..8c5d3d1 100644 --- a/src/modules/users/domain/usecases/find-user-by-uuid.usecase.ts +++ b/src/modules/users/domain/usecases/find-user-by-uuid.usecase.ts @@ -1,6 +1,6 @@ import { NotFoundException } from '@nestjs/common'; import { QueryHandler } from '@nestjs/cqrs'; -import { LoggingMessager } from '../../adapters/secondaries/logging.messager'; +import { Messager } from '../../adapters/secondaries/messager'; import { UsersRepository } from '../../adapters/secondaries/users.repository'; import { FindUserByUuidQuery } from '../../queries/find-user-by-uuid.query'; import { User } from '../entities/user'; @@ -9,7 +9,7 @@ import { User } from '../entities/user'; export class FindUserByUuidUseCase { constructor( private readonly _repository: UsersRepository, - private readonly _loggingMessager: LoggingMessager, + private readonly _messager: Messager, ) {} async execute(findUserByUuid: FindUserByUuidQuery): Promise { @@ -18,8 +18,8 @@ export class FindUserByUuidUseCase { if (!user) throw new NotFoundException(); return user; } catch (error) { - this._loggingMessager.publish( - 'user.read.warning', + this._messager.publish( + 'logging.user.read.warning', JSON.stringify({ query: findUserByUuid, error, diff --git a/src/modules/users/domain/usecases/update-user.usecase.ts b/src/modules/users/domain/usecases/update-user.usecase.ts index e2e9ddd..e7e370b 100644 --- a/src/modules/users/domain/usecases/update-user.usecase.ts +++ b/src/modules/users/domain/usecases/update-user.usecase.ts @@ -1,8 +1,7 @@ import { Mapper } from '@automapper/core'; import { InjectMapper } from '@automapper/nestjs'; import { CommandHandler } from '@nestjs/cqrs'; -import { LoggingMessager } from '../../adapters/secondaries/logging.messager'; -import { UserMessager } from '../../adapters/secondaries/user.messager'; +import { Messager } from '../../adapters/secondaries/messager'; import { UsersRepository } from '../../adapters/secondaries/users.repository'; import { UpdateUserCommand } from '../../commands/update-user.command'; import { UpdateUserRequest } from '../dtos/update-user.request'; @@ -12,8 +11,7 @@ import { User } from '../entities/user'; export class UpdateUserUseCase { constructor( private readonly _repository: UsersRepository, - private readonly _userMessager: UserMessager, - private readonly _loggingMessager: LoggingMessager, + private readonly _messager: Messager, @InjectMapper() private readonly _mapper: Mapper, ) {} @@ -29,18 +27,18 @@ export class UpdateUserUseCase { command.updateUserRequest.uuid, entity, ); - this._userMessager.publish( - 'update', + this._messager.publish( + 'user.update', JSON.stringify(command.updateUserRequest), ); - this._loggingMessager.publish( - 'user.update.info', + this._messager.publish( + 'logging.user.update.info', JSON.stringify(command.updateUserRequest), ); return user; } catch (error) { - this._loggingMessager.publish( - 'user.update.crit', + this._messager.publish( + 'logging.user.update.crit', JSON.stringify({ command, error, diff --git a/src/modules/users/tests/unit/create-user.usecase.spec.ts b/src/modules/users/tests/unit/create-user.usecase.spec.ts index 18bbefc..207f044 100644 --- a/src/modules/users/tests/unit/create-user.usecase.spec.ts +++ b/src/modules/users/tests/unit/create-user.usecase.spec.ts @@ -1,8 +1,7 @@ import { classes } from '@automapper/classes'; import { AutomapperModule } from '@automapper/nestjs'; import { Test, TestingModule } from '@nestjs/testing'; -import { LoggingMessager } from '../../adapters/secondaries/logging.messager'; -import { UserMessager } from '../../adapters/secondaries/user.messager'; +import { Messager } from '../../adapters/secondaries/messager'; import { UsersRepository } from '../../adapters/secondaries/users.repository'; import { CreateUserCommand } from '../../commands/create-user.command'; import { CreateUserRequest } from '../../domain/dtos/create-user.request'; @@ -50,11 +49,7 @@ describe('CreateUserUseCase', () => { CreateUserUseCase, UserProfile, { - provide: UserMessager, - useValue: mockMessager, - }, - { - provide: LoggingMessager, + provide: Messager, useValue: mockMessager, }, ], diff --git a/src/modules/users/tests/unit/delete-user.usecase.spec.ts b/src/modules/users/tests/unit/delete-user.usecase.spec.ts index 1a90137..e28dfdb 100644 --- a/src/modules/users/tests/unit/delete-user.usecase.spec.ts +++ b/src/modules/users/tests/unit/delete-user.usecase.spec.ts @@ -1,6 +1,5 @@ import { Test, TestingModule } from '@nestjs/testing'; -import { LoggingMessager } from '../../adapters/secondaries/logging.messager'; -import { UserMessager } from '../../adapters/secondaries/user.messager'; +import { Messager } from '../../adapters/secondaries/messager'; import { UsersRepository } from '../../adapters/secondaries/users.repository'; import { DeleteUserCommand } from '../../commands/delete-user.command'; import { DeleteUserUseCase } from '../../domain/usecases/delete-user.usecase'; @@ -63,11 +62,7 @@ describe('DeleteUserUseCase', () => { }, DeleteUserUseCase, { - provide: UserMessager, - useValue: mockMessager, - }, - { - provide: LoggingMessager, + provide: Messager, useValue: mockMessager, }, ], diff --git a/src/modules/users/tests/unit/find-user-by-uuid.usecase.spec.ts b/src/modules/users/tests/unit/find-user-by-uuid.usecase.spec.ts index ed6bf87..6d24c25 100644 --- a/src/modules/users/tests/unit/find-user-by-uuid.usecase.spec.ts +++ b/src/modules/users/tests/unit/find-user-by-uuid.usecase.spec.ts @@ -1,6 +1,6 @@ import { NotFoundException } from '@nestjs/common'; import { Test, TestingModule } from '@nestjs/testing'; -import { LoggingMessager } from '../../adapters/secondaries/logging.messager'; +import { Messager } from '../../adapters/secondaries/messager'; import { UsersRepository } from '../../adapters/secondaries/users.repository'; import { FindUserByUuidRequest } from '../../domain/dtos/find-user-by-uuid.request'; import { FindUserByUuidUseCase } from '../../domain/usecases/find-user-by-uuid.usecase'; @@ -42,7 +42,7 @@ describe('FindUserByUuidUseCase', () => { useValue: mockUserRepository, }, { - provide: LoggingMessager, + provide: Messager, useValue: mockMessager, }, FindUserByUuidUseCase, diff --git a/src/modules/users/tests/unit/logging.messager.usecase.spec.ts b/src/modules/users/tests/unit/messager.spec.ts similarity index 56% rename from src/modules/users/tests/unit/logging.messager.usecase.spec.ts rename to src/modules/users/tests/unit/messager.spec.ts index 85082c8..4a3c396 100644 --- a/src/modules/users/tests/unit/logging.messager.usecase.spec.ts +++ b/src/modules/users/tests/unit/messager.spec.ts @@ -1,36 +1,47 @@ import { AmqpConnection } from '@golevelup/nestjs-rabbitmq'; +import { ConfigService } from '@nestjs/config'; import { Test, TestingModule } from '@nestjs/testing'; -import { LoggingMessager } from '../../adapters/secondaries/logging.messager'; +import { Messager } from '../../adapters/secondaries/messager'; const mockAmqpConnection = { publish: jest.fn().mockImplementation(), }; -describe('LoggingMessager', () => { - let loggingMessager: LoggingMessager; +const mockConfigService = { + get: jest.fn().mockResolvedValue({ + RMQ_EXCHANGE: 'mobicoop', + }), +}; + +describe('Messager', () => { + let messager: Messager; beforeAll(async () => { const module: TestingModule = await Test.createTestingModule({ imports: [], providers: [ - LoggingMessager, + Messager, { provide: AmqpConnection, useValue: mockAmqpConnection, }, + { + provide: ConfigService, + useValue: mockConfigService, + }, ], }).compile(); - loggingMessager = module.get(LoggingMessager); + messager = module.get(Messager); }); it('should be defined', () => { - expect(LoggingMessager).toBeDefined(); + expect(messager).toBeDefined(); }); it('should publish a message', async () => { jest.spyOn(mockAmqpConnection, 'publish'); - await loggingMessager.publish('user.create.info', 'my-test'); + messager.publish('user.create.info', 'my-test'); expect(mockAmqpConnection.publish).toHaveBeenCalledTimes(1); }); }); diff --git a/src/modules/users/tests/unit/update-user.usecase.spec.ts b/src/modules/users/tests/unit/update-user.usecase.spec.ts index 21a65cf..4255a59 100644 --- a/src/modules/users/tests/unit/update-user.usecase.spec.ts +++ b/src/modules/users/tests/unit/update-user.usecase.spec.ts @@ -1,8 +1,7 @@ import { classes } from '@automapper/classes'; import { AutomapperModule } from '@automapper/nestjs'; import { Test, TestingModule } from '@nestjs/testing'; -import { LoggingMessager } from '../../adapters/secondaries/logging.messager'; -import { UserMessager } from '../../adapters/secondaries/user.messager'; +import { Messager } from '../../adapters/secondaries/messager'; import { UsersRepository } from '../../adapters/secondaries/users.repository'; import { UpdateUserCommand } from '../../commands/update-user.command'; import { UpdateUserRequest } from '../../domain/dtos/update-user.request'; @@ -55,11 +54,7 @@ describe('UpdateUserUseCase', () => { UpdateUserUseCase, UserProfile, { - provide: UserMessager, - useValue: mockMessager, - }, - { - provide: LoggingMessager, + provide: Messager, useValue: mockMessager, }, ], diff --git a/src/modules/users/tests/unit/user.messager.usecase.spec.ts b/src/modules/users/tests/unit/user.messager.usecase.spec.ts deleted file mode 100644 index 0a0f11c..0000000 --- a/src/modules/users/tests/unit/user.messager.usecase.spec.ts +++ /dev/null @@ -1,36 +0,0 @@ -import { AmqpConnection } from '@golevelup/nestjs-rabbitmq'; -import { Test, TestingModule } from '@nestjs/testing'; -import { UserMessager } from '../../adapters/secondaries/user.messager'; - -const mockAmqpConnection = { - publish: jest.fn().mockImplementation(), -}; - -describe('UserMessager', () => { - let userMessager: UserMessager; - - beforeAll(async () => { - const module: TestingModule = await Test.createTestingModule({ - imports: [], - providers: [ - UserMessager, - { - provide: AmqpConnection, - useValue: mockAmqpConnection, - }, - ], - }).compile(); - - userMessager = module.get(UserMessager); - }); - - it('should be defined', () => { - expect(userMessager).toBeDefined(); - }); - - it('should publish a message', async () => { - jest.spyOn(mockAmqpConnection, 'publish'); - await userMessager.publish('user.create.info', 'my-test'); - expect(mockAmqpConnection.publish).toHaveBeenCalledTimes(1); - }); -}); diff --git a/src/modules/users/users.module.ts b/src/modules/users/users.module.ts index 33b34a7..d8731fe 100644 --- a/src/modules/users/users.module.ts +++ b/src/modules/users/users.module.ts @@ -6,8 +6,7 @@ import { CqrsModule } from '@nestjs/cqrs'; import { redisStore } from 'cache-manager-ioredis-yet'; import { DatabaseModule } from '../database/database.module'; import { UsersController } from './adapters/primaries/users.controller'; -import { LoggingMessager } from './adapters/secondaries/logging.messager'; -import { UserMessager } from './adapters/secondaries/user.messager'; +import { Messager } from './adapters/secondaries/messager'; import { UsersRepository } from './adapters/secondaries/users.repository'; import { CreateUserUseCase } from './domain/usecases/create-user.usecase'; import { DeleteUserUseCase } from './domain/usecases/delete-user.usecase'; @@ -25,11 +24,7 @@ import { UserProfile } from './mappers/user.profile'; useFactory: async (configService: ConfigService) => ({ exchanges: [ { - name: 'user', - type: 'topic', - }, - { - name: 'logging', + name: configService.get('RMQ_EXCHANGE'), type: 'topic', }, ], @@ -54,8 +49,7 @@ import { UserProfile } from './mappers/user.profile'; providers: [ UserProfile, UsersRepository, - UserMessager, - LoggingMessager, + Messager, FindAllUsersUseCase, FindUserByUuidUseCase, CreateUserUseCase,