Listen to user.deleted events to delete the corresponding user ads
This commit is contained in:
parent
492bb3ca44
commit
9fb7ef2eac
|
@ -20,6 +20,10 @@ export const MATCHER_AD_CREATION_FAILED_ROUTING_KEY =
|
||||||
'matcher-ad.creation-failed';
|
'matcher-ad.creation-failed';
|
||||||
export const MATCHER_AD_CREATION_FAILED_QUEUE = 'ad.matcher-ad.creation-failed';
|
export const MATCHER_AD_CREATION_FAILED_QUEUE = 'ad.matcher-ad.creation-failed';
|
||||||
|
|
||||||
|
export const USER_DELETED_MESSAGE_HANDLER = 'userDeleted';
|
||||||
|
export const USER_DELETED_ROUTING_KEY = 'user.deleted';
|
||||||
|
export const USER_DELETED_QUEUE = 'ad.user.deleted';
|
||||||
|
|
||||||
// configuration
|
// configuration
|
||||||
export const SERVICE_CONFIGURATION_SET_QUEUE = 'ad-configuration-set';
|
export const SERVICE_CONFIGURATION_SET_QUEUE = 'ad-configuration-set';
|
||||||
export const SERVICE_CONFIGURATION_DELETE_QUEUE = 'ad-configuration-delete';
|
export const SERVICE_CONFIGURATION_DELETE_QUEUE = 'ad-configuration-delete';
|
||||||
|
|
|
@ -12,6 +12,7 @@ import {
|
||||||
import { AdMapper } from './ad.mapper';
|
import { AdMapper } from './ad.mapper';
|
||||||
import { CreateAdService } from './core/application/commands/create-ad/create-ad.service';
|
import { CreateAdService } from './core/application/commands/create-ad/create-ad.service';
|
||||||
import { DeleteAdService } from './core/application/commands/delete-ad/delete-ad.service';
|
import { DeleteAdService } from './core/application/commands/delete-ad/delete-ad.service';
|
||||||
|
import { DeleteUserAdsService } from './core/application/commands/delete-user-ads/delete-user-ads.service';
|
||||||
import { InvalidateAdService } from './core/application/commands/invalidate-ad/invalidate-ad.service';
|
import { InvalidateAdService } from './core/application/commands/invalidate-ad/invalidate-ad.service';
|
||||||
import { ValidateAdService } from './core/application/commands/validate-ad/validate-ad.service';
|
import { ValidateAdService } from './core/application/commands/validate-ad/validate-ad.service';
|
||||||
import { PublishMessageWhenAdIsDeletedDomainEventHandler } from './core/application/event-handlers/publish-message-when-ad-deleted.domain-event-handler';
|
import { PublishMessageWhenAdIsDeletedDomainEventHandler } from './core/application/event-handlers/publish-message-when-ad-deleted.domain-event-handler';
|
||||||
|
@ -32,6 +33,7 @@ import { FindAdsByIdsGrpcController } from './interface/grpc-controllers/find-ad
|
||||||
import { FindAdsByUserIdGrpcController } from './interface/grpc-controllers/find-ads-by-user-id.grpc.controller';
|
import { FindAdsByUserIdGrpcController } from './interface/grpc-controllers/find-ads-by-user-id.grpc.controller';
|
||||||
import { MatcherAdCreatedMessageHandler } from './interface/message-handlers/matcher-ad-created.message-handler';
|
import { MatcherAdCreatedMessageHandler } from './interface/message-handlers/matcher-ad-created.message-handler';
|
||||||
import { MatcherAdCreationFailedMessageHandler } from './interface/message-handlers/matcher-ad-creation-failed.message-handler';
|
import { MatcherAdCreationFailedMessageHandler } from './interface/message-handlers/matcher-ad-creation-failed.message-handler';
|
||||||
|
import { UserDeletedMessageHandler } from './interface/message-handlers/user-deleted.message-handler';
|
||||||
|
|
||||||
const grpcControllers = [
|
const grpcControllers = [
|
||||||
CreateAdGrpcController,
|
CreateAdGrpcController,
|
||||||
|
@ -44,6 +46,7 @@ const grpcControllers = [
|
||||||
const messageHandlers = [
|
const messageHandlers = [
|
||||||
MatcherAdCreatedMessageHandler,
|
MatcherAdCreatedMessageHandler,
|
||||||
MatcherAdCreationFailedMessageHandler,
|
MatcherAdCreationFailedMessageHandler,
|
||||||
|
UserDeletedMessageHandler,
|
||||||
];
|
];
|
||||||
|
|
||||||
const eventHandlers: Provider[] = [
|
const eventHandlers: Provider[] = [
|
||||||
|
@ -54,6 +57,7 @@ const eventHandlers: Provider[] = [
|
||||||
const commandHandlers: Provider[] = [
|
const commandHandlers: Provider[] = [
|
||||||
CreateAdService,
|
CreateAdService,
|
||||||
DeleteAdService,
|
DeleteAdService,
|
||||||
|
DeleteUserAdsService,
|
||||||
ValidateAdService,
|
ValidateAdService,
|
||||||
InvalidateAdService,
|
InvalidateAdService,
|
||||||
];
|
];
|
||||||
|
|
|
@ -0,0 +1,7 @@
|
||||||
|
import { Command, CommandProps } from '@mobicoop/ddd-library';
|
||||||
|
|
||||||
|
export class DeleteUserAdsCommand extends Command {
|
||||||
|
constructor(props: CommandProps<DeleteUserAdsCommand>) {
|
||||||
|
super(props);
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,29 @@
|
||||||
|
import { AdEntity } from '@modules/ad/core/domain/ad.entity';
|
||||||
|
import {
|
||||||
|
CommandBus,
|
||||||
|
CommandHandler,
|
||||||
|
ICommandHandler,
|
||||||
|
QueryBus,
|
||||||
|
} from '@nestjs/cqrs';
|
||||||
|
import { FindAdsByUserIdQuery } from '../../queries/find-ads-by-user-id/find-ads-by-user-id.query';
|
||||||
|
import { DeleteAdCommand } from '../delete-ad/delete-ad.command';
|
||||||
|
import { DeleteUserAdsCommand } from './delete-user-ads.command';
|
||||||
|
|
||||||
|
@CommandHandler(DeleteUserAdsCommand)
|
||||||
|
export class DeleteUserAdsService implements ICommandHandler {
|
||||||
|
constructor(
|
||||||
|
private readonly queryBus: QueryBus,
|
||||||
|
private readonly commandBus: CommandBus,
|
||||||
|
) {}
|
||||||
|
|
||||||
|
async execute(command: DeleteUserAdsCommand): Promise<void> {
|
||||||
|
const ads: AdEntity[] = await this.queryBus.execute(
|
||||||
|
new FindAdsByUserIdQuery(command.id),
|
||||||
|
);
|
||||||
|
await Promise.all(
|
||||||
|
ads.map((ad) =>
|
||||||
|
this.commandBus.execute(new DeleteAdCommand({ id: ad.id })),
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,23 @@
|
||||||
|
import { IntegrationEvent } from '@mobicoop/ddd-library';
|
||||||
|
import { RabbitSubscribe } from '@mobicoop/message-broker-module';
|
||||||
|
import { DeleteUserAdsCommand } from '@modules/ad/core/application/commands/delete-user-ads/delete-user-ads.command';
|
||||||
|
import { Injectable } from '@nestjs/common';
|
||||||
|
import { CommandBus } from '@nestjs/cqrs';
|
||||||
|
import { USER_DELETED_MESSAGE_HANDLER } from '@src/app.constants';
|
||||||
|
|
||||||
|
type UserDeletedEvent = IntegrationEvent;
|
||||||
|
|
||||||
|
@Injectable()
|
||||||
|
export class UserDeletedMessageHandler {
|
||||||
|
constructor(private readonly commandBus: CommandBus) {}
|
||||||
|
|
||||||
|
@RabbitSubscribe({
|
||||||
|
name: USER_DELETED_MESSAGE_HANDLER,
|
||||||
|
})
|
||||||
|
public async userDeleted(message: string) {
|
||||||
|
const deletedUser: UserDeletedEvent = JSON.parse(message);
|
||||||
|
await this.commandBus.execute(
|
||||||
|
new DeleteUserAdsCommand({ id: deletedUser.id }),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
|
@ -1,6 +1,11 @@
|
||||||
import { Module, Provider } from '@nestjs/common';
|
import { Module, Provider } from '@nestjs/common';
|
||||||
import { MESSAGE_PUBLISHER } from './messager.di-tokens';
|
import { MESSAGE_PUBLISHER } from './messager.di-tokens';
|
||||||
|
|
||||||
|
import {
|
||||||
|
MessageBrokerModule,
|
||||||
|
MessageBrokerModuleOptions,
|
||||||
|
MessageBrokerPublisher,
|
||||||
|
} from '@mobicoop/message-broker-module';
|
||||||
import { ConfigModule, ConfigService } from '@nestjs/config';
|
import { ConfigModule, ConfigService } from '@nestjs/config';
|
||||||
import {
|
import {
|
||||||
MATCHER_AD_CREATED_MESSAGE_HANDLER,
|
MATCHER_AD_CREATED_MESSAGE_HANDLER,
|
||||||
|
@ -10,12 +15,10 @@ import {
|
||||||
MATCHER_AD_CREATION_FAILED_QUEUE,
|
MATCHER_AD_CREATION_FAILED_QUEUE,
|
||||||
MATCHER_AD_CREATION_FAILED_ROUTING_KEY,
|
MATCHER_AD_CREATION_FAILED_ROUTING_KEY,
|
||||||
SERVICE_NAME,
|
SERVICE_NAME,
|
||||||
|
USER_DELETED_MESSAGE_HANDLER,
|
||||||
|
USER_DELETED_QUEUE,
|
||||||
|
USER_DELETED_ROUTING_KEY,
|
||||||
} from '@src/app.constants';
|
} from '@src/app.constants';
|
||||||
import {
|
|
||||||
MessageBrokerModule,
|
|
||||||
MessageBrokerModuleOptions,
|
|
||||||
MessageBrokerPublisher,
|
|
||||||
} from '@mobicoop/message-broker-module';
|
|
||||||
|
|
||||||
const imports = [
|
const imports = [
|
||||||
MessageBrokerModule.forRootAsync({
|
MessageBrokerModule.forRootAsync({
|
||||||
|
@ -41,6 +44,10 @@ const imports = [
|
||||||
routingKey: MATCHER_AD_CREATION_FAILED_ROUTING_KEY,
|
routingKey: MATCHER_AD_CREATION_FAILED_ROUTING_KEY,
|
||||||
queue: MATCHER_AD_CREATION_FAILED_QUEUE,
|
queue: MATCHER_AD_CREATION_FAILED_QUEUE,
|
||||||
},
|
},
|
||||||
|
[USER_DELETED_MESSAGE_HANDLER]: {
|
||||||
|
routingKey: USER_DELETED_ROUTING_KEY,
|
||||||
|
queue: USER_DELETED_QUEUE,
|
||||||
|
},
|
||||||
},
|
},
|
||||||
}),
|
}),
|
||||||
}),
|
}),
|
||||||
|
|
|
@ -0,0 +1,53 @@
|
||||||
|
import { DeleteUserAdsCommand } from '@modules/ad/core/application/commands/delete-user-ads/delete-user-ads.command';
|
||||||
|
import { DeleteUserAdsService } from '@modules/ad/core/application/commands/delete-user-ads/delete-user-ads.service';
|
||||||
|
import { AdEntity } from '@modules/ad/core/domain/ad.entity';
|
||||||
|
import { CommandBus, QueryBus } from '@nestjs/cqrs';
|
||||||
|
import { Test, TestingModule } from '@nestjs/testing';
|
||||||
|
import { punctualPassengerCreateAdProps } from './ad.fixtures';
|
||||||
|
|
||||||
|
const userAds = [
|
||||||
|
AdEntity.create(punctualPassengerCreateAdProps()),
|
||||||
|
AdEntity.create(punctualPassengerCreateAdProps()),
|
||||||
|
];
|
||||||
|
|
||||||
|
const mockQueryBus = {
|
||||||
|
execute: jest.fn().mockImplementation(() => userAds),
|
||||||
|
};
|
||||||
|
|
||||||
|
const mockCommandBus = {
|
||||||
|
execute: jest.fn(),
|
||||||
|
};
|
||||||
|
|
||||||
|
describe('delete-user-ads.service', () => {
|
||||||
|
let deleteUserAdsService: DeleteUserAdsService;
|
||||||
|
|
||||||
|
beforeAll(async () => {
|
||||||
|
const module: TestingModule = await Test.createTestingModule({
|
||||||
|
providers: [
|
||||||
|
{
|
||||||
|
provide: QueryBus,
|
||||||
|
useValue: mockQueryBus,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
provide: CommandBus,
|
||||||
|
useValue: mockCommandBus,
|
||||||
|
},
|
||||||
|
DeleteUserAdsService,
|
||||||
|
],
|
||||||
|
}).compile();
|
||||||
|
|
||||||
|
deleteUserAdsService =
|
||||||
|
module.get<DeleteUserAdsService>(DeleteUserAdsService);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should be defined', () => {
|
||||||
|
expect(deleteUserAdsService).toBeDefined();
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should call the delete command for each ad returned by the query', async () => {
|
||||||
|
await deleteUserAdsService.execute(
|
||||||
|
new DeleteUserAdsCommand({ id: userAds[0].getProps().userId }),
|
||||||
|
);
|
||||||
|
expect(mockCommandBus.execute).toHaveBeenCalledTimes(userAds.length);
|
||||||
|
});
|
||||||
|
});
|
|
@ -0,0 +1,43 @@
|
||||||
|
import { UserDeletedMessageHandler } from '@modules/ad/interface/message-handlers/user-deleted.message-handler';
|
||||||
|
import { CommandBus } from '@nestjs/cqrs';
|
||||||
|
import { Test, TestingModule } from '@nestjs/testing';
|
||||||
|
|
||||||
|
const mockCommandBus = {
|
||||||
|
execute: jest.fn(),
|
||||||
|
};
|
||||||
|
|
||||||
|
describe('Matcher Ad Created Message Handler', () => {
|
||||||
|
let userDeletedMessageHandler: UserDeletedMessageHandler;
|
||||||
|
|
||||||
|
beforeAll(async () => {
|
||||||
|
const module: TestingModule = await Test.createTestingModule({
|
||||||
|
providers: [
|
||||||
|
{
|
||||||
|
provide: CommandBus,
|
||||||
|
useValue: mockCommandBus,
|
||||||
|
},
|
||||||
|
UserDeletedMessageHandler,
|
||||||
|
],
|
||||||
|
}).compile();
|
||||||
|
|
||||||
|
userDeletedMessageHandler = module.get<UserDeletedMessageHandler>(
|
||||||
|
UserDeletedMessageHandler,
|
||||||
|
);
|
||||||
|
});
|
||||||
|
|
||||||
|
afterEach(async () => {
|
||||||
|
jest.clearAllMocks();
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should be defined', () => {
|
||||||
|
expect(userDeletedMessageHandler).toBeDefined();
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should call the command bus', async () => {
|
||||||
|
const userId = '4eb6a6af-ecfd-41c3-9118-473a507014d4';
|
||||||
|
const userDeletedMessage = `{"id":"${userId}"}`;
|
||||||
|
await userDeletedMessageHandler.userDeleted(userDeletedMessage);
|
||||||
|
expect(mockCommandBus.execute).toHaveBeenCalledTimes(1);
|
||||||
|
expect(mockCommandBus.execute.mock.lastCall[0].id).toBe(userId);
|
||||||
|
});
|
||||||
|
});
|
Loading…
Reference in New Issue