Saga Completion best practice for Single Saga instance with multiple messages

I am having a Saga and complete message handler as below. Saga initiates multiple messages and then expects reply back.

        public class CustomSaga : Saga<CustomSagaData>, IAmStartedByMessages<StartSagaMessage>, IHandleMessages<CompletedMessage>
        {
              public async Task Handle(StartSagaMessage message, IMessageHandlerContext context)
              {
                    // Send multiple messages to be handled by some other handler
                    // All the messages are of the same type and is handled by a single handler
                   
                    for(int messageNo = 0; messageNo  < 10; messageNo +)
                    {
                         // Send messages
                         // Set the Saga Data to pending for these messages
                         Data.Status[messageNo] = Status.IN_PROGRESS
                    }
                    
              }

              public async Task Handle(CompletedMessage message, IMessageHandlerContext context) 
              {
                  // Handle reply messages by the handler. 
                   
                   // Update Saga Data with the correct status, which is got from the CompletedMessage
                  Data.Status[message.messageNo] = message.Status;
                   
                  // Check if any pending message is present, if not complete 
                  // PROBLEM 
                  if(!Data.Status.Any(status => status.Value == MessageStatus.IN_PROGRESS))
                  {
                        // Execute some custom finishing logic. 
                        MarkAsComplete();
                  }
               }
        } 

        public class CustomSagaData: ContainSagaData
        {
                public virtual string OperationId { get; set; }
                public virtual IDictionary<int, MessageStatus> Status{ get; set; }
        }
         
        public enum MessageStatus {
             IN_PROGRESS, COMPLETED, FAILED
        }

        public CompletedMessage {
            public int MessageId {get; set;}
            public MessageStatus Status {get; set;}    
        }

I am referring to the line where I am checking for the Saga status(Please refer the line where I have put the comment “PROBLEM”)
The Data would be the same for multiple messages which are processed in parallel and will lead to the custom finishing logic not to be executed.

Can you please let us know what would be the best practice for marking a saga complete which handles multiple messages.

I’m not sure what you mean with “The Data would be the same for multiple messages”.

Saga state is never updated concurrently. We prevent this via pessimistic locking if supported by the configured persistence or via optimistic concurrency control.

Your logic should work as-is.

Do note that you are not doing any non-transactional work at that location as due to the concurrent access of all replies on the same saga instance it is very likely you run into transaction rollbacks.