Take the 2-minute tour ×
Salesforce Stack Exchange is a question and answer site for Salesforce administrators, implementation experts, developers and anybody in-between. It's 100% free, no registration required.

How to dispatch records from trigger to be processed by different threads in order to accelerate trigger execution and not to fail the whole trigger if the error happens.

if we update another records from trigger then they are locked. is there the idea of dispatching logic to process records in multiple threads so records will be locked seperatly?

What isues with locking should be considered with the following trigger code:

Database.update(highPriorityRecords, false);
Database.update(mediumPriorityRecords, false);
Database.update(lowPriorityRecords, false);

As I understand Database.update doesn't throw errors. How this can affects trigger execution time and record locking if there are large volumes of data(if we don't update all records at once but with seperate call - can we avoid full lock at once or it doesn't make sence, except that we use extra DMLs)

From devforce:

Triggers Although the flexibility of triggers is a great asset, triggers can cause many kinds of problems in your loads and integrations. Locks are one of those problems. When you’re loading records that fire one or more triggers, and any of those triggers performs either a select for update or a DML operation on records other than the record that you’re inserting, updating, or deleting, Salesforce locks those other records. These locks can in turn cause lock exceptions. Consider disabling trigger logic for your loads and integrations, or having a special, optimized code path for such activities.

share|improve this question
    
Can you explain a bit more about why you'd want to do 3 separate updates? whats the concern with locking? –  Kevin P Apr 23 at 15:03
    
Based on statement from devforce(see original message with quote) I am worried about overhead of locking if there are large volume of data(10000-50000) is inserted and trigger is running to update(to make synch with) other records –  Natallia Apr 23 at 19:29
add comment

3 Answers 3

up vote 7 down vote accepted

Natallia,

Force.com doesn't expose "threads" as an interface that we as developers can utilize.

Thats the bad news.

The good news is this: Triggers will never be executed with more than 200 records at a given time. In other words if you insert 1000 records, and the trigger fires on all of them, that trigger will fire 5 times, each with 200 records.

To ensure speedy trigger execution, here are a few general rules:

  1. Ensure that your triggers work on lists or maps of records -- in other words bulkify your triggers.
  2. Utilize a trigger framework. I like this one: https://github.com/kevinohara80/sfdc-trigger-framework
  3. Try to utilize before triggers. These triggers run before the executing context. Ie: if your trigger is a before update it will fire before the updated record is saved. This eliminates extra DML calls. Note: Records are automatically saved as they exist at the end of the before trigger.
  4. if you're updating records that are not of the object type that fired the trigger, learn and understand the way relationship queries work.
share|improve this answer
1  
Very precise answer and I am pointing few developers to here who don't follow best practice when they do trigger code –  Mohith Shrivastava Apr 23 at 15:29
add comment

Natallia, if you want to execute code in separate threats, you can use future calls: (https://www.salesforce.com/us/developer/docs/apexcode/Content/apex_classes_annotation_future.htm.

Future methods will be scheduled by the Salesforce plattform, so there is no guarantee that it is run immediately, but you have a separate execution context with higher limits. You could do all updates in the trigger itself, and call a future method for everything else that doesn't need to be done immediately. You have to think about error handling, though, because you cannot make error messages visible on the UI.

share|improve this answer
    
@future call is good alternative but there is limit in 10 calls per apex execution and if there are 2200 records then we hit the limit: 2200:200=11>10... –  Natallia Apr 23 at 19:22
add comment

Natalia, you may want to read Dan Appleman's book Advanced Apex Programming. Dan's book goes into detail of the theory and practice of developing the type of trigger framework that Kevin P is referring to. Using a trigger Dispatcher Class, one could certainly sort and direct data to different classes based on priority as you're asking. Dan describes methods for directing to different classes in his book.

As others have pointed out, Salesforce doesn't do "multiple threading" in the sense of what a typical server or your desktop computer does. But, you could send lower priority data to to classes that use @future calls. I really don't know what benefit there'd be to that.

As to your question about "not to fail the whole trigger if the error happens", there are several methods for handling this. One is to do something like this:

Database.SaveResult[] nwOppsUpsertResults = Database.Upsert(nwOpps,false);
for(Database.Saveresult nwo:nwOppspsertResults){
   if(nwo.IsSuccess()){
      nwOppsIdsLst.add(nwo.getId());
   }else{
      nwOpFailIdsLst.add(nwo.getId());
   }
}

The above would give you a list of Id's that were upserted and another list of Id's that weren't so you could put the latter into an error log, send an email, or send them to some other class for a 2nd attempt at processing, etc.

share|improve this answer
add comment

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.