Skip to content

Commit

Permalink
refactor: improve external events type safety
Browse files Browse the repository at this point in the history
  • Loading branch information
getlarge committed Jan 7, 2024
1 parent 11ae5b7 commit 8ac6657
Show file tree
Hide file tree
Showing 8 changed files with 32 additions and 39 deletions.
4 changes: 2 additions & 2 deletions apps/expiration/src/app/orders/orders-ms.controller.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ import {
Transport,
} from '@nestjs/microservices';
import { ApiExcludeEndpoint } from '@nestjs/swagger';
import { Patterns } from '@ticketing/microservices/shared/events';
import { EventsMap, Patterns } from '@ticketing/microservices/shared/events';
import { GlobalErrorFilter } from '@ticketing/microservices/shared/filters';
import { requestValidationErrorFactory } from '@ticketing/shared/errors';
import { Order } from '@ticketing/shared/models';
Expand Down Expand Up @@ -44,7 +44,7 @@ export class OrdersMSController {
@EventPattern(Patterns.OrderCreated, Transport.RMQ)
async onCreated(
@Payload(new ValidationPipe(validationPipeOptions))
data: Order,
data: EventsMap[Patterns.OrderCreated],
@Ctx() context: RmqContext,
): Promise<{
ok: boolean;
Expand Down
10 changes: 3 additions & 7 deletions apps/orders/src/app/orders/orders-ms.controller.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,12 +14,8 @@ import {
Transport,
} from '@nestjs/microservices';
import { ApiExcludeEndpoint } from '@nestjs/swagger';
import {
ExpirationCompletedEvent,
Patterns,
} from '@ticketing/microservices/shared/events';
import { EventsMap, Patterns } from '@ticketing/microservices/shared/events';
import { requestValidationErrorFactory } from '@ticketing/shared/errors';
import { Payment } from '@ticketing/shared/models';
import type { Channel } from 'amqp-connection-manager';
import type { Message } from 'amqplib';

Expand All @@ -44,7 +40,7 @@ export class OrdersMSController {
@ApiExcludeEndpoint()
@EventPattern(Patterns.ExpirationCompleted, Transport.RMQ)
async onExpiration(
@Payload() data: ExpirationCompletedEvent['data'],
@Payload() data: EventsMap[Patterns.ExpirationCompleted],
@Ctx() context: RmqContext,
): Promise<void> {
const channel = context.getChannelRef() as Channel;
Expand All @@ -67,7 +63,7 @@ export class OrdersMSController {
@MessagePattern(Patterns.PaymentCreated, Transport.RMQ)
async onPaymentCreated(
@Payload(new ValidationPipe(validationPipeOptions))
data: Payment,
data: EventsMap[Patterns.PaymentCreated],
@Ctx() context: RmqContext,
): Promise<OrderDto> {
const channel = context.getChannelRef() as Channel;
Expand Down
12 changes: 7 additions & 5 deletions apps/orders/src/app/orders/orders.service.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,8 +10,7 @@ import { ClientProxy } from '@nestjs/microservices';
import { InjectModel } from '@nestjs/mongoose';
import { OryPermissionsService } from '@ticketing/microservices/ory-client';
import {
OrderCancelledEvent,
OrderCreatedEvent,
EventsMap,
Patterns,
PaymentCreatedEvent,
} from '@ticketing/microservices/shared/events';
Expand Down Expand Up @@ -56,9 +55,12 @@ export class OrdersService {
);
}

private sendEvent(
pattern: Patterns.OrderCreated | Patterns.OrderCancelled,
event: OrderCreatedEvent['data'] | OrderCancelledEvent['data'],
private sendEvent<
P extends Patterns.OrderCreated | Patterns.OrderCancelled,
E extends EventsMap[P],
>(
pattern: P,
event: E,
): Observable<[Ticket, { ok: boolean }, { ok: boolean }]> {
return zip(
this.ticketsClient.send(pattern, event).pipe(timeout(5000)),
Expand Down
7 changes: 3 additions & 4 deletions apps/orders/src/app/tickets/tickets-ms.controller.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,9 +13,8 @@ import {
Transport,
} from '@nestjs/microservices';
import { ApiExcludeEndpoint } from '@nestjs/swagger';
import { Patterns } from '@ticketing/microservices/shared/events';
import { EventsMap, Patterns } from '@ticketing/microservices/shared/events';
import { requestValidationErrorFactory } from '@ticketing/shared/errors';
import { Ticket } from '@ticketing/shared/models';
import type { Channel } from 'amqp-connection-manager';
import type { Message } from 'amqplib';

Expand All @@ -42,7 +41,7 @@ export class TicketsMSController {
@MessagePattern(Patterns.TicketCreated, Transport.RMQ)
async onCreated(
@Payload(new ValidationPipe(validationPipeOptions))
data: Ticket,
data: EventsMap[Patterns.TicketCreated],
@Ctx() context: RmqContext,
): Promise<TicketDto> {
const channel = context.getChannelRef() as Channel;
Expand All @@ -66,7 +65,7 @@ export class TicketsMSController {
@MessagePattern(Patterns.TicketUpdated, Transport.RMQ)
async onUpdated(
@Payload(new ValidationPipe(validationPipeOptions))
data: Ticket,
data: EventsMap[Patterns.TicketUpdated],
@Ctx() context: RmqContext,
): Promise<TicketDto> {
const channel = context.getChannelRef() as Channel;
Expand Down
7 changes: 3 additions & 4 deletions apps/payments/src/app/orders/orders-ms.controller.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,8 +7,7 @@ import {
Transport,
} from '@nestjs/microservices';
import { ApiExcludeEndpoint } from '@nestjs/swagger';
import { Patterns } from '@ticketing/microservices/shared/events';
import { Order } from '@ticketing/shared/models';
import { EventsMap, Patterns } from '@ticketing/microservices/shared/events';
import type { Channel } from 'amqp-connection-manager';
import type { Message } from 'amqplib';

Expand All @@ -25,7 +24,7 @@ export class OrdersMSController {
@ApiExcludeEndpoint()
@MessagePattern(Patterns.OrderCreated, Transport.RMQ)
async onCreated(
@Payload() data: Order,
@Payload() data: EventsMap[Patterns.OrderCreated],
@Ctx() context: RmqContext,
): Promise<{
ok: boolean;
Expand All @@ -49,7 +48,7 @@ export class OrdersMSController {
@ApiExcludeEndpoint()
@MessagePattern(Patterns.OrderCancelled, Transport.RMQ)
async onCancelled(
@Payload() data: Order,
@Payload() data: EventsMap[Patterns.OrderCancelled],
@Ctx() context: RmqContext,
): Promise<{
ok: boolean;
Expand Down
7 changes: 3 additions & 4 deletions apps/tickets/src/app/orders/orders-ms.controller.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,9 +13,8 @@ import {
Transport,
} from '@nestjs/microservices';
import { ApiExcludeEndpoint } from '@nestjs/swagger';
import { Patterns } from '@ticketing/microservices/shared/events';
import { EventsMap, Patterns } from '@ticketing/microservices/shared/events';
import { requestValidationErrorFactory } from '@ticketing/shared/errors';
import { Order } from '@ticketing/shared/models';
import type { Channel } from 'amqp-connection-manager';
import type { Message } from 'amqplib';

Expand All @@ -42,7 +41,7 @@ export class OrdersMSController {
@MessagePattern(Patterns.OrderCreated, Transport.RMQ)
async onCreated(
@Payload(new ValidationPipe(validationPipeOptions))
data: Order,
data: EventsMap[Patterns.OrderCreated],
@Ctx() context: RmqContext,
): Promise<TicketDto> {
const channel = context.getChannelRef() as Channel;
Expand All @@ -66,7 +65,7 @@ export class OrdersMSController {
@MessagePattern(Patterns.OrderCancelled, Transport.RMQ)
async onCancelled(
@Payload(new ValidationPipe(validationPipeOptions))
data: Order,
data: EventsMap[Patterns.OrderCancelled],
@Ctx() context: RmqContext,
): Promise<TicketDto> {
const channel = context.getChannelRef() as Channel;
Expand Down
12 changes: 5 additions & 7 deletions apps/tickets/src/app/tickets/tickets.service.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,11 +9,10 @@ import { ClientProxy } from '@nestjs/microservices';
import { InjectModel } from '@nestjs/mongoose';
import { OryPermissionsService } from '@ticketing/microservices/ory-client';
import {
EventsMap,
OrderCancelledEvent,
OrderCreatedEvent,
Patterns,
TicketCreatedEvent,
TicketUpdatedEvent,
} from '@ticketing/microservices/shared/events';
import {
NextPaginationDto,
Expand Down Expand Up @@ -45,10 +44,10 @@ export class TicketsService {
@Inject(ORDERS_CLIENT) private readonly client: ClientProxy,
) {}

private sendEvent(
pattern: Patterns.TicketCreated | Patterns.TicketUpdated,
event: TicketCreatedEvent['data'] | TicketUpdatedEvent['data'],
): Observable<Ticket> {
private sendEvent<
P extends Patterns.TicketCreated | Patterns.TicketUpdated,
E extends EventsMap[P],
>(pattern: P, event: E): Observable<Ticket> {
return this.client.send(pattern, event).pipe(timeout(5000));
}

Expand Down Expand Up @@ -189,7 +188,6 @@ export class TicketsService {

async cancelOrder(event: OrderCancelledEvent['data']): Promise<Ticket> {
const ticketId = event.ticket.id;

await using manager = await transactionManager(this.ticketModel);
const result = await manager.wrap(async (session) => {
const ticket = await this.ticketModel
Expand Down
12 changes: 6 additions & 6 deletions libs/microservices/shared/events/src/events-map.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,10 +5,10 @@ import { PaymentCreatedEvent } from './payment-events';
import { TicketCreatedEvent, TicketUpdatedEvent } from './ticket-events';

export type EventsMap = {
[Patterns.TicketCreated]: TicketCreatedEvent;
[Patterns.TicketUpdated]: TicketUpdatedEvent;
[Patterns.OrderCreated]: OrderCreatedEvent;
[Patterns.OrderCancelled]: OrderCancelledEvent;
[Patterns.ExpirationCompleted]: ExpirationCompletedEvent;
[Patterns.PaymentCreated]: PaymentCreatedEvent;
[Patterns.TicketCreated]: TicketCreatedEvent['data'];
[Patterns.TicketUpdated]: TicketUpdatedEvent['data'];
[Patterns.OrderCreated]: OrderCreatedEvent['data'];
[Patterns.OrderCancelled]: OrderCancelledEvent['data'];
[Patterns.ExpirationCompleted]: ExpirationCompletedEvent['data'];
[Patterns.PaymentCreated]: PaymentCreatedEvent['data'];
};

0 comments on commit 8ac6657

Please sign in to comment.