1
- import { Controller } from '@nestjs/common' ;
1
+ import { Controller , Inject } from '@nestjs/common' ;
2
2
import { Ctx , EventPattern , KafkaContext } from '@nestjs/microservices' ;
3
3
import { config } from '../../infrastructure/config/config' ;
4
4
import { getMessageByContext } from '../../infrastructure/shared/utils/getMessageByContext' ;
@@ -9,23 +9,50 @@ import {
9
9
} from './dto/input/createSalesProductEventPayload.dto' ;
10
10
import { SalesACLService } from './salesACL.service' ;
11
11
import { InventoryItemCreateService } from '../application/inventoryItem/services/inventoryItemCreate.service' ;
12
+ import { TRANSACTION_SERVICE } from '../../infrastructure/transaction/shared/constants' ;
13
+ import { ITransactionService } from '../../infrastructure/transaction/ITransaction.service' ;
14
+ import { CreateInventoryItemOutputDto } from '../application/inventoryItem/dto/output/createInventoryItemOutput.dto' ;
15
+ import { ITransaction } from '../../infrastructure/transaction/shared/types/ITransaction' ;
16
+ import { Message } from '../../infrastructure/shared/utils/extractMessage' ;
17
+ import {
18
+ ISalesProductIdempMessagesService ,
19
+ } from '../application/services/interfaces/ISalesProductIdempMessagesService' ;
20
+ import { SALES_PRODUCT_IDEMP_MESSAGES_SERVICE } from '../../infrastructure/idempotency/constants' ;
12
21
13
22
@Controller ( )
14
23
export class SalesMessagesController {
15
24
constructor (
16
25
private readonly salesACLService : SalesACLService ,
17
26
private readonly inventoryItemCreateService : InventoryItemCreateService ,
27
+ @Inject ( TRANSACTION_SERVICE )
28
+ private readonly transactionService : ITransactionService ,
29
+ @Inject ( SALES_PRODUCT_IDEMP_MESSAGES_SERVICE )
30
+ private readonly idempService : ISalesProductIdempMessagesService ,
18
31
) { }
19
32
33
+ // TODO: handle errors
20
34
@EventPattern ( config . kafka . kafkaProductsTopic )
21
35
async handleSalesProductEvent ( @Ctx ( ) context : KafkaContext ) : Promise < void > {
22
36
const message = getMessageByContext ( context ) ;
23
37
const plainPayload = JSON . parse ( message . value . payload ) ;
38
+ const { messageId } = message . headers ;
39
+
40
+ await this . transactionService . withTransaction ( 'READ COMMITTED' , async transaction => {
41
+ await this . idempService . assertMessageIsNotAlreadyProcessed ( messageId , transaction ) ;
42
+ await this . idempService . insertMessage ( messageId , transaction ) ;
43
+ await this . handle ( message , plainPayload , transaction ) ;
44
+ } ) ;
45
+ }
24
46
47
+ private async handle ( message : Message , plainPayload : any , transaction : ITransaction ) : Promise < void > {
25
48
if ( message . headers . messageName === MessageNamesEnum . ProductCreated ) {
26
- const event = await validatePayload ( CreateSalesProductEventPayload , plainPayload ) ;
27
- const dto = await this . salesACLService . mapCreateSalesProductPayloadToCreateInventoryItem ( event ) ;
28
- await this . inventoryItemCreateService . runTransaction ( dto ) ;
49
+ await this . handleProductCreated ( plainPayload , transaction ) ;
29
50
}
30
51
}
52
+
53
+ private async handleProductCreated ( plain : any , transaction : ITransaction ) : Promise < CreateInventoryItemOutputDto > {
54
+ const event = await validatePayload ( CreateSalesProductEventPayload , plain ) ;
55
+ const dto = await this . salesACLService . mapCreateSalesProductPayloadToCreateInventoryItem ( event ) ;
56
+ return this . inventoryItemCreateService . create ( dto , transaction ) ;
57
+ }
31
58
}
0 commit comments