A naive implementation of this approach could be very costly. Consider, for example, if you insert
and delete
shares on each object separately (I will assume you don't update
or undelete
the custom share records since that is usually not necessary). In the worst case, that would be 48 DML Statements
consumed by your trigger logic. So in the worst case scenario, your package consumes almost a third of the available limit!
True, you can combine up to ten separate object types into one DML Statement
. So you could combine many of the above operations and reduce 24 insert
calls and 24 delete
calls to 3 of each. But this all takes time, and you will chew through CPU
and Heap
limits in addition to DML Statements
.
You might consider processing these shares asynchronously to reduce strain on the system. It can be a lot of work to figure out an asynchronous processing framework that performs well across the various conditions you may find in a customer org. If you really want to get some good ideas about how to build an asynchronous framework, Advanced Apex Programming by Dan Appleman would be a good buy.
As a basic example, it isn't too hard to wrap your head around how to dump this logic in a @future
method, but then what if it gets kicked off from within a @future
method? You cannot call a @future
method from inside a @future
method!
You can get around this limitation by processing synchronously when you are already in a @future
context:
public void process(Map<Id, Set<Id>> toCreate, Map<Id, Set<Id>> toDelete)
{
if (!system.isFuture)
{
processAsync(userToRecords);
return;
}
// insert new shares, delete old shares
// parameters can be of whatever form you like
// (within the constraints of a @future method)
// it seems best to map the user added to all the records they were added to
// and the same structure for the old lookup values
// (where you want to remove shares)
}
@future
public void processAsync(Map<Id, Set<Id>> toCreate, Map<Id, Set<Id>> toDelete)
{
processCreate(userToRecords);
}
The above might work out for you. You could also consider chained jobs (likely using the Queueable
interface), which are a lot more work to set up but may be more robust. Appleman lays it out in a lot more detail and I don't have much experience in setting up such a framework. My main point is that if you have this much logic, trying to process it synchronously might result in a lot of CPU timeouts.