Bulk API and Static Variable State
Has anyone else experienced this?
I have and to say it was quite annoying was an understatement. I had to call an update trigger either after it was inserted or after it's second update. I got it to work fine, but as soon as the records were inserted through DataLoader, it bombed because of this issue.
I asked a similar question and the response reflected the following:
Answered by @ScottW
From the documentation:
Use static variables to store information that is shared within the confines of the class. All instances of the same class share a single copy of the static variables. For example, all triggers that are spawned by the same transaction can communicate with each other by viewing and updating static variables in a related class. A recursive trigger might use the value of a class variable to determine when to exit the recursion.
So apparently, even though the trigger limits are being reset, it is still considering a bulk API call a single transaction. For example, a bulk API insert of 700 records is broken up into 200 records to be worked on by trigger, each batch is given of 200 records is given its own API limits. However, this is still one transaction, which means the static variables are never reset.
It is actually recommended for complex triggers that you avoid using the Bulk API altogether (this was found here):
Minimize Number of Triggers
You can use parallel mode with objects that have associated triggers if the triggers don't cause side-effects that interfere with other parallel transactions. However, salesforce.com doesn't recommend loading large batches for objects with complex triggers. Instead, you should rewrite the trigger logic as a batch Apex job that is executed after all the data has loaded.
Interestingly, recommendation eh?
Also, within a trigger, is there a way to detect whether the current transaction is running within the Bulk API?
From what I could find, no. The only way I could see to resolve this is possibly a reset for your counter; essentially toggling when a certain event should fire.
I hope that clears some things up.
Is there a way to detect whether the current transaction is running within the Bulk API?
Yes.
Use Url.getCurrentRequestUrl()
/**
* System.isBatch() //false
* System.isFuture() //false
* System.isQueueable() //false
* System.isScheduled() //false
*
* AsyncApiJob KeyPrefix is 750
* AsyncApiBatch KeyPrefix is 751
* Example of getCurrentRequestUrl()
* http://eu6.salesforce.com/mockRequest/bulkapi/process/00D000000000000/750000000000000/751000000000000
*/
Boolean isBulkApi() {
return Url.getCurrentRequestUrl().getPath().contains('/bulkapi/');
}
The returned string allows us to infer the Apex Execution Event Type or "Quiddity"