[SalesForce] Saleforce Too many future calls: 11

I have a business logic as follows.

1. A web service class parses XML file containing case data and loads the case to SF.
2. Trigger that on update of case email field make a call to future method to generate attachment ,send email and update case owner field.

trigger CaseUpdate on Case (After update) 
{ 
for(case c : trigger.old)
 {
    for(case ca : trigger.new)
    {
        if((c.Email__c != ca.Email__c) && (c.CS_ID__c != null) && (c.Count__c == 1))
        {
          UtilsClass.generateReport_Future(c.id);
        }
    }
 }
}


 @Future(callout=true)
 public static void generateReport_future(String caseId)
 {
String result = '';
result = generateReport(caseId);
if(result == '') 
{ 
   result = emailReport(caseId);
}
UtilsClass.ChangeOwner(caseId);

}

The issue i am facing is, System.LimitException: Too many future calls: 11, even though single case record is loaded.

Multiple records may be loaded at the same time, but they are sequential(One By One).

Are the records coming in a single batch even though they are being loaded individually..?

Best Answer

The governor limit is that no more than 10 future calls may be made in a single request so your trigger is broken as soon as more than 10 Case objects are updated at once that match you if condition.

If you want to use a future method call it once and pass it the set of case IDs i.e. collect the set if IDs first then make a single call to the future method.

Add debugging to your trigger to see how many Case objects are coming through at once if you are not sure. But the trigger needs bulkifying anyway.

Note that if you are using this sort of code in other triggers and those triggers run as part of the same request their future method calls will also be counted so they all need bulkifying.

PS

Noticed your trigger has an unnecessary nested loop pattern. This would be a typical way to accomplish what I think you are trying to do:

trigger CaseUpdate on Case (After update) {
    Set<Id> ids = new Set<Id>();
    for(Case c : Trigger.new) {
        Case old = Trigger.oldMap.get(c.Id)
        if (c.Email__c != old.Email__c && c.CS_ID__c != null && c.Count__c == 1) {
            ids.add(c.Id);
        }
    }
    if (ids.size() > 0) {
        // Change the future method to take a set of IDs
        UtilsClass.generateReport_Future(uds);
    }
}

PPS

If the web service API you are calling only allows a request for a single Case to be made at once (and can't be changed) you can use a Batchable marked with Database.AllowsCallouts and set the batch size to 10 instead of the future. But there are governor limit traps there too to watch out for (that will be eased when the "Apex Flex Queue" eventually becomes generally available).