Skip to content

Instantly share code, notes, and snippets.

@c4tch
Created February 5, 2020 18:06
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 1 You must be signed in to fork a gist
  • Save c4tch/1a0c8a0c9e92c2eb6aeb76ac73c5dbe6 to your computer and use it in GitHub Desktop.
Save c4tch/1a0c8a0c9e92c2eb6aeb76ac73c5dbe6 to your computer and use it in GitHub Desktop.
Throttle Apex Platform Events to avoid overloading trigger DML
/**
* Entrypoint from the Trigger, dispatch the events here
* Bobby White
* The use case is universal... you're never going to be able to consume 2000 PE in a single Apex transaction if the PE are independent.
* You have to "clip" the executions into manageable chunks.
* Best case N = 200, in practice if the DML's will touch objects that are poorly governed, it could hit limits at a lower number like 25 or 50.
* Q: What is "Independent"?
* A: Let's say that you had a flood of PE's that had the applied to the same ExternalId, you might be able to consume these with a single DML (e.g. 10 meter readings for the same Meter, or a series of notifications for the same Client) -- if your use case doesn't demand that you preserve every state change, you could collapse them into one. My default assumption is that you need to design your PE trigger with the premise that the PE's stand alone and have no correlation to other PE's in the same invocation.
* I get you, so in the PE loop you have here you might collapse similar items, so the end list for processing by triggers is much lower
**/
public static void handleEvents(final List<NewClientAccount__e> events) {
try{
// lean data to pass to the handler - in this case a list of account ID's
final Set<Id> newAccountIds = new Set<Id>();
Integer counter=0;
for(NewClientAccount__e current : events) {
++counter;
// Limit the Trigger execution to avoid hitting SOQL limits.
if (counter > MAX_EVENTS_PER_CHUNK) {
// When hit, set the resume checkpoint to the current ID, handle events should re-fire at this replay point.
EventBus.TriggerContext.currentContext().setResumeCheckpoint(current.ReplayId);
limitExceeded=true;
break;
}
newAccountIds.add(current.AccountId__c);
}
// Process the lead data - in this case a new Account method
processAccounts(newAccountIds);
} catch(Exception ex) {
ExceptionUtil.logError(ex,'Exception in setting checkpoints New Client Account events','Account Update',null);
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment