Race condition with Integration Bus for new Orders

Andy Bochmann asked on July 26, 2019 03:05

Hello,

I'm tyring to use the Integration Bus to send new orders to an external ERP system.

My code looks like this:

public class ErpConnector : BaseIntegrationConnector
{
    public override void Init()
    {
        ConnectorName = "ErpConnector";
        SubscribeToObjects(TaskProcessTypeEnum.AsyncSnapshot, OrderInfo.OBJECT_TYPE);
    }
    public override IntegrationProcessResultEnum ProcessInternalTaskAsync(GeneralizedInfo infoObj,
        TranslationHelper translations, TaskTypeEnum taskType, TaskDataTypeEnum dataType, string siteName,
        out string errorMessage)
    {
        // Runs when processing Snapshot type tasks for order objects
        if (infoObj.TypeInfo.ObjectType == OrderInfo.OBJECT_TYPE &&
            dataType == TaskDataTypeEnum.Snapshot &&
            taskType == TaskTypeEnum.CreateObject)
        {
            var orderInfo = (OrderInfo)(infoObj.MainObject);
            ...
        }
    }
}

I'm basically subscribing to changes to the OrderInfo object and execute my custom code if the taskType is CreateObject.

The problem is, when the OrderInfo object gets created, and my integration gets called, the addresses (Shipping or Billing) are sometimes null. It's a race condition. As far as I can tell from the Event Log, Kentico updates the order object one more time after creation. My guess is that Kentico creates the OrderInfo object first and adds the addresses later.

Here is a screenshot of the Event Log: https://drive.google.com/file/d/1TUN-E9RYRyBSOzcg6a6lw479q5ZZYNyj/view?usp=sharing

You can see that the first run of the integration failed, because of the NullReference on the address field. It worked fine during the second try a few seconds later.

Is that a bug in Kentico or am I doing something wrong? I don't really want to listen to the UpdateObject event because we only want to send the data once on the first creation of an order but no updates.

I'm using Kentico 12.0.31.

Thanks, Andy

Recent Answers


Dmitry Bastron answered on July 26, 2019 10:06 (last edited on July 26, 2019 10:09)

Hi Andy!

Is there any chance that you have a custom order creation code as well? For example, if in your custom code you create order, save via provider, add addresses and save again (I did it once for reason) - then you should amend it to save only once. In the following article there is a recommendation to use transactions in the custom order code.

0 votesVote for this answer Mark as a Correct answer

Andy Bochmann answered on July 26, 2019 17:48

Thanks Dmitry.

No, I'm not using a custom OrderInfoProvider. I don't do anything else to the order after calling ShoppingService.CreateOrder();. I also noticed the same behavour in the Event Log of the DancingGoatMvc sample site.

0 votesVote for this answer Mark as a Correct answer

Andy Bochmann answered on July 26, 2019 18:19 (last edited on July 26, 2019 18:19)

After reading this page again, it makes a little bit more sense. The OrderInfo object will get updated with the payment status. That would explain the second update event. I will have to update my code to wait for that event.

I believe the best would be to add a custom field to the OrderInfo class, which indicates, if the order has been synced to the external system. I should be able to subscribe to update events and then use that field and the payment status to determine if it needs to be synced.

0 votesVote for this answer Mark as a Correct answer

   Please, sign in to be able to submit a new answer.