What is the best practice to organize workflow with one to many relationship (each child is also flow of actions that could be organized as workflow)

Hello team. We trying to implement order system with payments. Order could have multiple payments (like many credit cards), all service will be supported by us. We designed an order workflow for it and currently figuring out how it is would be better to implement payment processing as separately workflows or just do it in signal method with Promises and put them in order workflow state as collection or maybe it is better to implement as async child workflow? The problem as i see now with separately workflows is that payment and order could be coupled.

// Order Workflow here
Map<UUID, Promise> promisesMap;

//example: add payment to order with signal
@SignalMethod
void addPayment() {
     
     // add payment saga
     Saga saga;

     var paymentPromise = Async.procedure(() -> {
         paymentActivities.authorize(paymentId, idempotencyKey)
         saga.addCompensation(paymentActivities::toVoid, paymentId, idempotencyKey)
     })
          .thenApply(() -> {
              Workflow.sleep(tillAuthorizationPeriodExpires)
          })
          .thenApply(() -> {
              paymentActivities.capture(paymentId, idempotencyKey)
          })
          .exceptionally(e -> {
               saga.compensate()
          });
     promises.add(paymentPromise)
     promisesMap.add(paymentId, promise)
}

Thanks in advance for any advice

Hi, whats the life time of an order, are the payments determined up-front or can be updated during the order workflow execution for example as you show via signals?
What is the max number of payments included in a single order? What do you think would be the max number of orders your system would have at peak times?

Are you waiting for your payment activity promises at some point during workflow execution? Can they all be done in parallel?

Hello, and thanks for reply @tihomir . For more context, we are doing food delivery app.

Usually from 1 day to a week

The number of payments around 1 - 2, rare more

I believe it will be around 100-200 order workflows per day, but it might grow up

It could be possible to update(change the amount of money)/remove/add payment methods

Yes, planned to do Promise.allOf(Promises) and if some payment is failed, need to add a new payment method and wait for all promises again and after that workflow will continue

Yes

1 Like

I would implement your logic inside the procedure synchronously first. Mixing async and sync code (like calling sleep inside a callback) is not the best approach in my opinion.

Hi, thanks for the advise, I agree with that, we decided to implement a separate scheduler, that will signal workflow to start a capture activity and workflow will just authorize payments

@SignalMethod
void addPayment(PaymentId paymentId) {
        paymentActivities.capture(paymentId, idempotencyKey)
        this.isCaptured = true;
}
// workflow code
@WorkflowMethod
void process(Order order) {

        // ...
        paymentActivities.authorize(idempotencyKey);
        // ...
}

Possibly in future it might be reworked as separate workflow for payment with signaling between order and payment workflows

I don’t understand why you need to have a separate scheduler workflow. You can have a scheduler object running inside the workflow.

yes, You are right.
So we have a scheduler workflow that orchestrate 2 activities: retrieve from db and process, which runs every 15 mins. It is also possible to implement with yours approach. I will check proposals for scheduler workflow, maybe it doesn’t suits my use case, But form implementation point of view with ‘scheduler object’’ we will need to provide continue as new feature since event history have limit of 50k events.