send messages on CUD

This commit is contained in:
Gsk54
2022-12-22 14:24:51 +01:00
parent a08468bddc
commit 55383c879d
16 changed files with 624 additions and 17 deletions

View File

@@ -92,10 +92,7 @@ export class UsersController {
@GrpcMethod('UsersService', 'Delete')
async deleteUser(data: FindUserByUuidRequest): Promise<void> {
try {
// eslint-disable-next-line @typescript-eslint/no-unused-vars
const user = await this._commandBus.execute(
new DeleteUserCommand(data.uuid),
);
await this._commandBus.execute(new DeleteUserCommand(data.uuid));
return Promise.resolve();
} catch (e) {

View File

@@ -0,0 +1,18 @@
import { AmqpConnection } from '@golevelup/nestjs-rabbitmq';
import { Injectable } from '@nestjs/common';
import { ConfigService } from '@nestjs/config';
import { IMessageUser } from '../../domain/interfaces/user-messager';
@Injectable()
export class UserMessager extends IMessageUser {
constructor(
private readonly _configService: ConfigService,
private readonly _amqpConnection: AmqpConnection,
) {
super(_configService.get<string>('RMQ_EXCHANGE_NAME'));
}
publish(routingKey: string, message: string): void {
this._amqpConnection.publish(this.exchange, routingKey, message);
}
}

View File

@@ -0,0 +1,12 @@
import { Injectable } from '@nestjs/common';
@Injectable()
export abstract class IMessageUser {
exchange: string;
constructor(exchange: string) {
this.exchange = exchange;
}
abstract publish(routingKey: string, message: string): void;
}

View File

@@ -1,6 +1,7 @@
import { Mapper } from '@automapper/core';
import { InjectMapper } from '@automapper/nestjs';
import { CommandHandler } from '@nestjs/cqrs';
import { UserMessager } from '../../adapters/secondaries/user.messager';
import { UsersRepository } from '../../adapters/secondaries/users.repository';
import { CreateUserCommand } from '../../commands/create-user.command';
import { CreateUserRequest } from '../dtos/create-user.request';
@@ -10,6 +11,7 @@ import { User } from '../entities/user';
export class CreateUserUseCase {
constructor(
private readonly _repository: UsersRepository,
private readonly _messager: UserMessager,
@InjectMapper() private readonly _mapper: Mapper,
) {}
@@ -20,6 +22,12 @@ export class CreateUserUseCase {
User,
);
return this._repository.create(entity);
const user = await this._repository.create(entity);
if (user) {
this._messager.publish('user.create', JSON.stringify(user));
}
return user;
}
}

View File

@@ -1,12 +1,26 @@
import { CommandHandler } from '@nestjs/cqrs';
import { UserMessager } from '../../adapters/secondaries/user.messager';
import { UsersRepository } from '../../adapters/secondaries/users.repository';
import { DeleteUserCommand } from '../../commands/delete-user.command';
import { User } from '../entities/user';
@CommandHandler(DeleteUserCommand)
export class DeleteUserUseCase {
constructor(private readonly _repository: UsersRepository) {}
constructor(
private readonly _repository: UsersRepository,
private readonly _messager: UserMessager,
) {}
async execute(command: DeleteUserCommand): Promise<void> {
return this._repository.delete(command.uuid);
async execute(command: DeleteUserCommand): Promise<User> {
const user = await this._repository.delete(command.uuid);
if (user) {
this._messager.publish(
'user.delete',
JSON.stringify({ uuid: user.uuid }),
);
}
return user;
}
}

View File

@@ -1,6 +1,7 @@
import { Mapper } from '@automapper/core';
import { InjectMapper } from '@automapper/nestjs';
import { CommandHandler } from '@nestjs/cqrs';
import { UserMessager } from '../../adapters/secondaries/user.messager';
import { UsersRepository } from '../../adapters/secondaries/users.repository';
import { UpdateUserCommand } from '../../commands/update-user.command';
import { UpdateUserRequest } from '../dtos/update-user.request';
@@ -10,6 +11,7 @@ import { User } from '../entities/user';
export class UpdateUserUseCase {
constructor(
private readonly _repository: UsersRepository,
private readonly _messager: UserMessager,
@InjectMapper() private readonly _mapper: Mapper,
) {}
@@ -20,6 +22,17 @@ export class UpdateUserUseCase {
User,
);
return this._repository.update(command.updateUserRequest.uuid, entity);
const user = await this._repository.update(
command.updateUserRequest.uuid,
entity,
);
if (user) {
this._messager.publish(
'user.update',
JSON.stringify(command.updateUserRequest),
);
}
return user;
}
}

View File

@@ -1,6 +1,7 @@
import { classes } from '@automapper/classes';
import { AutomapperModule } from '@automapper/nestjs';
import { Test, TestingModule } from '@nestjs/testing';
import { UserMessager } from '../../adapters/secondaries/user.messager';
import { UsersRepository } from '../../adapters/secondaries/users.repository';
import { CreateUserCommand } from '../../commands/create-user.command';
import { CreateUserRequest } from '../../domain/dtos/create-user.request';
@@ -23,6 +24,10 @@ const mockUsersRepository = {
}),
};
const mockUserMessager = {
publish: jest.fn().mockImplementation(),
};
describe('CreateUserUseCase', () => {
let createUserUseCase: CreateUserUseCase;
@@ -36,6 +41,10 @@ describe('CreateUserUseCase', () => {
},
CreateUserUseCase,
UserProfile,
{
provide: UserMessager,
useValue: mockUserMessager,
},
],
}).compile();

View File

@@ -1,4 +1,5 @@
import { Test, TestingModule } from '@nestjs/testing';
import { UserMessager } from '../../adapters/secondaries/user.messager';
import { UsersRepository } from '../../adapters/secondaries/users.repository';
import { DeleteUserCommand } from '../../commands/delete-user.command';
import { DeleteUserUseCase } from '../../domain/usecases/delete-user.usecase';
@@ -38,6 +39,10 @@ const mockUsersRepository = {
}),
};
const mockUserMessager = {
publish: jest.fn().mockImplementation(),
};
describe('DeleteUserUseCase', () => {
let deleteUserUseCase: DeleteUserUseCase;
@@ -49,6 +54,10 @@ describe('DeleteUserUseCase', () => {
useValue: mockUsersRepository,
},
DeleteUserUseCase,
{
provide: UserMessager,
useValue: mockUserMessager,
},
],
}).compile();

View File

@@ -1,6 +1,7 @@
import { classes } from '@automapper/classes';
import { AutomapperModule } from '@automapper/nestjs';
import { Test, TestingModule } from '@nestjs/testing';
import { UserMessager } from '../../adapters/secondaries/user.messager';
import { UsersRepository } from '../../adapters/secondaries/users.repository';
import { UpdateUserCommand } from '../../commands/update-user.command';
import { UpdateUserRequest } from '../../domain/dtos/update-user.request';
@@ -29,6 +30,10 @@ const mockUsersRepository = {
}),
};
const mockUserMessager = {
publish: jest.fn().mockImplementation(),
};
describe('UpdateUserUseCase', () => {
let updateUserUseCase: UpdateUserUseCase;
@@ -43,6 +48,10 @@ describe('UpdateUserUseCase', () => {
},
UpdateUserUseCase,
UserProfile,
{
provide: UserMessager,
useValue: mockUserMessager,
},
],
}).compile();
@@ -54,7 +63,7 @@ describe('UpdateUserUseCase', () => {
});
describe('execute', () => {
it('should update an User', async () => {
it('should update a user', async () => {
const updatedUser: User = await updateUserUseCase.execute(
updateUserCommand,
);

View File

@@ -1,7 +1,10 @@
import { RabbitMQModule } from '@golevelup/nestjs-rabbitmq';
import { Module } from '@nestjs/common';
import { ConfigModule, ConfigService } from '@nestjs/config';
import { CqrsModule } from '@nestjs/cqrs';
import { DatabaseModule } from '../database/database.module';
import { UsersController } from './adapters/primaries/users.controller';
import { UserMessager } from './adapters/secondaries/user.messager';
import { UsersRepository } from './adapters/secondaries/users.repository';
import { CreateUserUseCase } from './domain/usecases/create-user.usecase';
import { DeleteUserUseCase } from './domain/usecases/delete-user.usecase';
@@ -11,11 +14,28 @@ import { UpdateUserUseCase } from './domain/usecases/update-user.usecase';
import { UserProfile } from './mappers/user.profile';
@Module({
imports: [DatabaseModule, CqrsModule],
imports: [
DatabaseModule,
CqrsModule,
RabbitMQModule.forRootAsync(RabbitMQModule, {
imports: [ConfigModule],
useFactory: async (configService: ConfigService) => ({
exchanges: [
{
name: configService.get<string>('RMQ_EXCHANGE_NAME'),
type: configService.get<string>('RMQ_EXCHANGE_TYPE'),
},
],
uri: configService.get<string>('RMQ_URI'),
}),
inject: [ConfigService],
}),
],
controllers: [UsersController],
providers: [
UserProfile,
UsersRepository,
UserMessager,
FindAllUsersUseCase,
FindUserByUuidUseCase,
CreateUserUseCase,