The fault may be accompanied by a 500 status code (for SOAP that is likely to be the case - see 6.2 SOAP HTTP Response - but I guess the API you are calling isn't SOAP as you mention JSON) so your code could do this:
res = http.send(req);
if (res.getStatusCode() < 500) {
// Process a non-fault response (JSON?)
} else {
// Process the fault response (XML?)
}
Worth checking (e.g. by using System.debug) because it is a simple way to tell the difference between the two cases.
On throttling your requests, Apex does not have any sleep mechanism and if you attempt to run a busy wait you will exceed the CPU governor limit (after 10 seconds).
I believe you can schedule a job for say 1 minute in the future and when that runs schedule another job for a minute later. (I have not tried that though.) Note that there is no guarantee that the job will run at a specific time as the platform reserves the right to delay when busy. Perhaps someone with experience of using scheduled Apex in this way will provide a definitive answer on the viable patterns and the rates they achieve.
(From 2 years ago: Are there best practices to get scheduled apex scheduled to run faster than once per hour?.)
In a comment, I pointed you to this answer from sfdcfox, which is a nice explanation of how particular static Boolean-based recursion guards fail and can be made effective using a different pattern. I'll expand on that a little to apply it here.
You have two triggers, each of which makes changes to the object on which the other is defined. Your objective is to ensure that when Trigger A on Object 1 goes off and updates Object 2, Trigger B on Object 2 doesn't then recursively update Object 1.
The safe static Boolean pattern for this situation would look something like this, using Account
and Opportunity
as the sObjects involved.
public class AccountTriggerHandler {
@TestVisible
private static Boolean inhibit = false;
public void beforeUpdate(List<Account> newList, Map<Id, Account> oldMap) {
if (inhibit) return;
// Do stuff... create a `List<Opportunity>` to update.
// Set the flag to inhibit re-firing of *this* trigger before we update
// the other object.
inhibit = true;
update opportunitiesToUpdate;
// Reset the inhibit flag so that all other trigger action
// completes normally.
inhibit = false;
}
}
Here, we set the inhibit
flag only within the trigger handler itself, and only around the actual DML operation on the other object (Opportunity
, here) that will result in a recursive update of our own object (Account
, here). We don't set the flag at any other time, so that, for example, 400-record transactions will stilltri complete successfully with two trigger invocations, and we will not interfere with retries when DML is performed with allOrNone=false
.
If we needed the Opportunity
trigger to access the flag (I don't think we do here), it could be made public
rather than @TestVisible private
, which allows us to set it in test context and thereby validate its operation.
To save a little on limits, you might consider a similar design where the inhibitor flag is set on the other object:
OpportunityTriggerHandler.inhibitAccountUpdates = true;
update opportunitiesToUpdate;
OpportunityTriggerHandler.inhibitAccountUpdates = false;
Then, your OpportunityTriggerHandler
can avoid running SOQL or performing expensive processing it might execute in an attempt to update the Accounts that actually started this sequence of functionality.
Best Answer
Your code with line "myBooleanVar = value;" is creating problem for you. If Salesforce debug log is too large then it can skip some part and don't show in debug log. Try to replce the line "myBooleanVar = value;" with "myBooleanVar = False;" and perform the DML to run the trigger again. Now check the debug log to find out True and if you don't it then am correct, So findout from where that variable is set to True.