Page 1 of 2

Async Delegate Doesn't Save Order in Any Event

PostPosted: Thu Aug 24, 2023 3:22 pm
by sameermoin
Hello Everyone,

I am calling an API during sales order processing. To prevent the UI from blocking, I made the delegate asynchronous. However, this led to another problem: the 'Save' button on the sales order remains enabled even after the event has been completed, and the custom field is not being set correctly. It only sets the value for the first custom field.

I attached the plugin to demonstrate the issue
Plugin test async method.xml
(35.18 KiB) Downloaded 1186 times

Re: Async Delegate Doesn't Save Order in Any Event

PostPosted: Thu Aug 24, 2023 3:52 pm
by Mike.Sheen
sameermoin wrote:Hello Everyone,

I am calling an API during sales order processing. To prevent the UI from blocking, I made the delegate asynchronous. However, this led to another problem: the 'Save' button on the sales order remains enabled even after the event has been completed, and the custom field is not being set correctly. It only sets the value for the first custom field.

I attached the plugin to demonstrate the issue
Plugin test async method.xml


We don't support asynchronous operations during save or write operations.

Doing so lets the user interrupt and interfere with the in-progress SQL transaction and will compromise the integrity of the database.

Re: Async Delegate Doesn't Save Order in Any Event

PostPosted: Thu Aug 24, 2023 6:15 pm
by SBarnes
sameermoin wrote:Hello Everyone,

I am calling an API during sales order processing. To prevent the UI from blocking, I made the delegate asynchronous.


What blocking are you trying to prevent in accessing custom fields either on the sales order object or the line, everything is in memory, I have on multiple events updated custom field values with no real hits to the performance?

If you are getting a delay in saving the order its not from the code you provided if its done synchronously.

Like Mike said trying to do something asynchronously to the data on the object you are saving is a recipe for data corruption.

Re: Async Delegate Doesn't Save Order in Any Event

PostPosted: Thu Aug 24, 2023 6:22 pm
by Mike.Sheen
SBarnes wrote:
What blocking are you trying to prevent in accessing custom fields either on the sales order object or the line


I'm pretty sure the mention of custom fields is simply the observation that they're not being shown correctly after using an asynchronous delegate to process.

My interpretation of the post is that they're finding processing a sales order too slow, so have tried to perform that asynchronously, but as a result the form is not displaying things, like custom fields, quite right.

Re: Async Delegate Doesn't Save Order in Any Event

PostPosted: Thu Aug 24, 2023 6:28 pm
by SBarnes
Mike.Sheen wrote:My interpretation of the post is that they're finding processing a sales order too slow, so have tried to perform that asynchronously, but as a result the form is not displaying things, like custom fields, quite right.


That's my interpretation too, that the processing or saving is slow, what I meant is the accessing or setting the custom field values shouldn't effect anything in terms of performance.

Re: Async Delegate Doesn't Save Order in Any Event

PostPosted: Thu Aug 24, 2023 6:32 pm
by Mike.Sheen
Actually, after looking at the plugin code I think I understand it now.

The call to the external API is being done in a handler for sales order processing start...and one of the things it does is not just call an external API, but set some custom field values.

When that's done asynchronously, it means it may complete well after the sales order has finished saving - so as a result it's setting the custom field value after the order has processed, saved and re-read and so that would explain why the Save' button on the sales order remains enabled - it's modified the custom field after saving and re-reading.

Re: Async Delegate Doesn't Save Order in Any Event

PostPosted: Thu Aug 24, 2023 6:43 pm
by Mike.Sheen
So, the solution to this is that you can't perform your call to an external API and update a custom field on the sales order during the save or process of a sales order without blocking.

Either you make the call synchronously and live with the User being forced to wait, or you move your call to the external API to a process like the Plugin Scheduler.

The Plugin Scheduler could, on a periodic basis, look for all the orders queued to be sent to the external API, and in there make the API call and update the sales order custom field.

Re: Async Delegate Doesn't Save Order in Any Event

PostPosted: Thu Aug 24, 2023 7:01 pm
by SBarnes
Or use the rest api and call a custom route asynchronously and do a double hop to the external api and let the custom route update the order, if you want it more instantaneously than when a schedule runs.

But with a custom route you'd need some sort of retry mechanism like web hooks does which might be overkill if it doesn't need to be instantaneous at which point your scheduled process option is the better choice.

Re: Async Delegate Doesn't Save Order in Any Event

PostPosted: Thu Aug 24, 2023 7:12 pm
by Mike.Sheen
I suppose you could always asynchronously do it in the processing end - don't interact with the sales order instance, but create a new one, read, make external call, save

Code: Select all
salesOrder.ProcessingEnd += async delegate (object sender, EventArgs e)
{
   // create new sales order object   
   // read order (use salesOrder.RecID)
   // Make external API call
   // update custom field (on the sales order instance we created and read in here)
   // Save (not the sales order outside the delegate, the one we created in here)
}

Re: Async Delegate Doesn't Save Order in Any Event

PostPosted: Fri Aug 25, 2023 11:44 am
by SBarnes
Couldn't that cause a concurrency exception, if someone then edited the sales order?