11/* eslint-disable @nx/enforce-module-boundaries */
22import {
33 allHandlersFinished ,
4+ ApplicationFailure ,
45 ChildWorkflowHandle ,
56 condition ,
67 proxyActivities ,
78 setHandler ,
89 startChild ,
10+ log ,
911} from '@temporalio/workflow' ;
1012
13+ // Typescript alias issue while importing files from other libraries from workflows.
1114import {
1215 OrderProcessPaymentStatus ,
1316 OrderWorkflowData ,
1417 OrderWorkflowNonRetryableErrors ,
15- OrderWorkflowState ,
16- OrderWorkflowStatus ,
1718 createOrderUpdate ,
1819 getOrderStateQuery ,
1920 getWorkflowIdByPaymentOrder ,
2021} from '../../../../libs/backend/core/src/lib/order/workflow.utils' ;
21- import {
22- cancelWorkflowSignal ,
23- } from '../../../../libs/backend/core/src/lib/workflows' ;
22+ import { cancelWorkflowSignal } from '../../../../libs/backend/core/src/lib/workflows' ;
23+ import type { OrderStatusResponseDto } from '../../../../libs/models/src/order/order.dto' ;
2424import type { ActivitiesService } from '../main' ;
2525
26- const { createOrder : createOrderActivity } = proxyActivities < ActivitiesService > ( {
27- startToCloseTimeout : '5 seconds' ,
28- retry : {
29- initialInterval : '2s' ,
30- maximumInterval : '10s' ,
31- maximumAttempts : 10 ,
32- backoffCoefficient : 1.5 ,
33- nonRetryableErrorTypes : [ OrderWorkflowNonRetryableErrors . UNKNOWN_ERROR ] ,
34- } ,
35- } ) ;
26+ const { createOrder : createOrderActivity } = proxyActivities < ActivitiesService > (
27+ {
28+ startToCloseTimeout : '5 seconds' ,
29+ retry : {
30+ initialInterval : '2s' ,
31+ maximumInterval : '10s' ,
32+ maximumAttempts : 10 ,
33+ backoffCoefficient : 1.5 ,
34+ nonRetryableErrorTypes : [ OrderWorkflowNonRetryableErrors . UNKNOWN_ERROR ] ,
35+ } ,
36+ }
37+ ) ;
3638import { processPayment } from './process-payment.workflow' ;
3739
38- const initialState : OrderWorkflowState = {
39- status : OrderWorkflowStatus . PENDING ,
40+ export enum OrderStatus {
41+ Pending = 'Pending' ,
42+ Confirmed = 'Confirmed' ,
43+ Shipped = 'Shipped' ,
44+ Delivered = 'Delivered' ,
45+ Cancelled = 'Cancelled' ,
46+ Failed = 'Failed' ,
47+ }
48+
49+ const initialState : OrderStatusResponseDto = {
50+ status : OrderStatus . Pending ,
4051 orderId : undefined ,
4152 referenceId : '' ,
4253 clientSecret : undefined ,
@@ -46,15 +57,27 @@ export async function createOrder(
4657 data : OrderWorkflowData ,
4758 state = initialState
4859) : Promise < void > {
60+ state . referenceId = data . order . referenceId ;
4961 // Define references to child workflows
5062 let processPaymentWorkflow : ChildWorkflowHandle < typeof processPayment > ;
5163
5264 // Attach queries, signals and updates
5365 setHandler ( getOrderStateQuery , ( ) => state ) ;
54- setHandler (
55- cancelWorkflowSignal ,
56- ( ) => processPaymentWorkflow ?. signal ( cancelWorkflowSignal )
57- ) ;
66+ setHandler ( cancelWorkflowSignal , ( ) => {
67+ log . info ( 'Requesting order cancellation' ) ;
68+ if ( ! state ?. orderId ) {
69+ throw ApplicationFailure . nonRetryable (
70+ OrderWorkflowNonRetryableErrors . CANCELLED ,
71+ 'Order cancelled'
72+ ) ;
73+ }
74+ if ( processPaymentWorkflow ) {
75+ processPaymentWorkflow . signal ( cancelWorkflowSignal ) ;
76+ } else {
77+ log . error ( 'The payment process has already finished, cannot cancel' ) ;
78+ }
79+ } ) ;
80+ // Create the order and the payment intent with the payment provider
5881 setHandler ( createOrderUpdate , async ( ) => {
5982 const { order, clientSecret } = await createOrderActivity ( data ) ;
6083 state . orderId = order . id ;
@@ -63,25 +86,30 @@ export async function createOrder(
6386 return state ;
6487 } ) ;
6588
66- // Wait to create the order in the database
89+ // Wait the order to be ready to be processed
6790 await condition ( ( ) => ! ! state ?. orderId ) ;
68-
69- // First step: Process payment
70- if ( state . status === OrderWorkflowStatus . PENDING ) {
91+
92+ // First step - Process payment
93+ if ( state . status === OrderStatus . Pending ) {
7194 processPaymentWorkflow = await startChild ( processPayment , {
7295 args : [ data ] ,
7396 workflowId : getWorkflowIdByPaymentOrder ( state . referenceId ) ,
7497 } ) ;
7598 const processPaymentResult = await processPaymentWorkflow . result ( ) ;
76- if ( processPaymentResult . status === OrderProcessPaymentStatus . SUCCESS ) {
77- state . status = OrderWorkflowStatus . PAYMENT_COMPLETED ;
78- } else {
79- state . status = OrderWorkflowStatus . FAILED ;
80- return ;
99+ if ( processPaymentResult . status !== OrderProcessPaymentStatus . SUCCESS ) {
100+ state . status = OrderStatus . Failed ;
101+ // TODO: Send email to the user
102+ throw ApplicationFailure . nonRetryable (
103+ OrderWorkflowNonRetryableErrors . UNKNOWN_ERROR ,
104+ 'Payment failed'
105+ ) ;
81106 }
82107 processPaymentWorkflow = undefined ;
83- state . status = OrderWorkflowStatus . COMPLETED ;
108+ state . status = OrderStatus . Confirmed ;
84109 }
110+
111+ // TODO: Second step - Ship the order
112+
85113 // Wait for all handlers to finish before workflow completion
86114 await condition ( allHandlersFinished ) ;
87115}
0 commit comments