0

I have a class that places an order to an external API. This order sometimes takes a few minutes to complete. When the order is placed, I immediately get an Order Id in return, and the only way to see if the order completed is to make another query using this Order Id.

Ideally, this is how the flow would normally go:

public class CalloutClass() {
    public static void Walkthrough() {
        string orderId = PlaceOrder();
        DoSomethingWithOrder(orderId);
    }
    
    public static string PlaceOrder() {
        //Make REST call here. 
        return orderId;
    }
    
    public static void DoSomethingWithOrder(string OrderId) {
        if(VerifyOrderComplete(OrderId)) {
            //Do other stuff
        }
        
        else {
            //Try again after 30 seconds
            //If it has been two minutes, send an email
        }
    }
    
    public static boolean VerifyOrderComplete(string OrderId) {
        //Make another REST call with the OrderId to verify 
        //the order is complete
        return true;
    }
}

So I place the order, get an Id back, then check if the order is complete using that Id. If the order is not complete, I would like to wait a certain amount of time (30 seconds), then try again. Once I've tried for 2 minutes and the order still isn't ready, then send an email.

What would be the best way to accomplish this waiting period? Would I need to create some class that interacts with the Scheduler or something?

Thank you!

  • schedulable supports cron expressions so you can run every two minutes (it will need to schedule itself at end of execute() - it should query all orders that have been unconfirmed as callout complete since presumably, many callouts could be done in the space of 2 minutes – cropredy Jun 19 at 3:50
2

There are many possible alternatives, depending on your circumstances.

Long Timeout

If your API has a synchronous callout that will wait until the order is complete, you can set the timeout to 120 seconds on the callout, thus eliminating the need to do any theatrics.

Visualforce

You can use an apex:actionPoller to call the server every 30 seconds.

JavaScript (LWC, Aura, Visualforce)

You can use the client to call the service every 30 seconds, either directly or by proxy (Apex).

Asynchronous Code

This one is a bit tricky, but a Scheduled job may be appropriate. Note that you can only have a total of 100 scheduled jobs, so this might prove limiting.

Scheduled Actions

The Process Builder can trigger an asynchronous action, but you may need to wait more than 2 minutes and a record to update to trigger the action.

Paused Flow

If you do this from a Flow, the Pause action can wait a period of time, then call some Apex. Also requires a lot of setup, but technically feasible. You can also call Flows directly from Apex.

Queueable

Queueable can execute for 60 seconds of CPU per transaction, so it is technically possible that you could spin-wait for 30 seconds and then call the service, and if not ready, chain to another call to Queueable. Be aware that this will eat up some of your org's "long running transaction" slots, so if you do this too frequently, users may be denied access to some resources while your code runs.

Outside Help

You could easily spin up a Heroku app or other cloud-container service to do the polling. This is arguably a bit easier since those services allow more control over CPU time and other resources. A simple $5/month Heroku app could easily cover thousands of requests per month without breaking a sweat (or the bank).

Other (?)

I'm probably missing a few ideas, but this should be enough to get you started.

| improve this answer | |
  • Queueable can execute for max 60 secs of CPU in a transaction? I didn't find it by googling, could you provide the ref? – Xi Xiao Jun 19 at 5:49
  • @XiXiao Yes, it's in the Execution Governors and Limits documentation. See "Maximum CPU time on the Salesforce servers." Schedulable, Batchable, future, and Queueable are all asynchronous transactions. – sfdcfox Jun 19 at 6:13
  • got it thanks! @sfdcfox – Xi Xiao Jun 19 at 10:27

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.