I need to call two functions where the second function need to wait for the first function to finish its execution and to be delayed by 10 seconds. What I have in mind that after the fist function finished and after 10 seconds has passed, only then the second function should be invoked. It is an apex code related question.
4 Answers
In apex you can not have wait time. You can not suspend a thread. If you use while loop to create such time gap then you may face 10 seconds transaction time limit. I would suggest you make use of visual force page and have your control returned to page and then via JavaScript call your second function after 10seconds.
You can use action function to delay the invoking method only if you are using visual force page. In Apex there is no function to delay the code execution. You can use loop something like this but it's not a best practice to do it.
Integer start = System.Now().millisecond();
while(System.Now().millisecond()< start+10){
}
There is an idea posted for this function but Salesforce does not seem to implement it asIn the mutli-tenant world, a sleeping thread is one that cannot be used by another customer. If this happens once and again, yeah, it's fine. But, if used poorly, this could harm our service.
https://success.salesforce.com/ideaview?id=08730000000Bq2HAAS
A simple solution to this would be to callout to an HTTP endpoint which has a delay in the response.
HttpRequest request = new HttpRequest();
request.setEndpoint('https://example.org/sleep/1');
request.setMethod('GET');
new Http().send(request);
Because Salesforce delays execution of any further code until the request returns, this is an effective way to sleep without blowing up your CPU etc
If you don't have an endpoint available to you that offers this, you can technically host it in Salesforce apex itself like this.
@RestResource(urlMapping='/Sleep/*')
global with sharing class RestSleep {
@HttpGet
global static void getTimeout() {
RestRequest req = RestContext.request;
RestResponse res = RestContext.response;
String timeoutString = req.requestURI.substring(req.requestURI.lastIndexOf('/')+1);
sleep(Long.valueOf(timeoutString));
}
static void sleep(Long milliseconds){
Integer start = System.Now().millisecond();
while(System.now().millisecond() < start + milliseconds) {
}
}
}
and then callout to it in Apex like so
try {
HttpRequest request = new HttpRequest();
request.setEndpoint(URL.getOrgDomainUrl().toExternalForm() + '/services/apexrest/Timeout/150');
request.setHeader('Authorization', 'Bearer ' + UserInfo.getSessionID());
request.setMethod('GET');
new Http().send(request);
}
catch (CalloutException e) {}
The advantage of using an endpoint instead of calling the sleep method within the original apex code, is that the risk of a uncatchable CPU timeout now only applies to the Apex REST endpoint's execution, whereas the apex context that is calling the endpoint will get a "Read timed out" Callout Exception instead of the CPU Limit. This can be handled in a try catch and the code will proceed execution (after some delay, even if not the exact milliseconds provided).
You didn't relate from where the Apex originates, what context it is running in, and whether you need to wait for the second function to complete. Those things will definitely control what solutions are viable.
Indeed you can't suspend a thread in Apex, SF doesn't want you to be wasting resources keeping a translation open on their server. Things like long while loops are only useful for ad-hoc experimentation, not for production.
If you do not need the result, you can use scheduled apex to run the next function ten seconds after the current time. If you need the result, then the context you are running in will make a difference and it's not easy to propose a solution. If you need processing after the 2nd function but you aren't waiting for the result, the scheduled apex can pick up the rest of processing. But, if something else is waiting, then that something, be it, VF, flow, or whatever, is going to have to poll for the result to be completed.