3

When my CustomObject1 is inserted or updated, I need to update a field on the Account object potentially traversing all the CustomObject1 who have a lookup-relationship to given accounts.

In principle, this was done using in-transaction update, but this quickly resulted in a violation of the limits, so the approach I took was to use QueueableApex. When a transaction of CustomObject1 insert or update occurs: - I collect all the Accounts who are impacted - I perform a count query for CustomObject1 instances on accounts.

Then I queue separately the jobs for accounts with many CustomObject1 (one job for account) from the one that have less than 5 CustomObject1 per account (single job). However this approach doesn't work, for example, when there are other jobs scheduled or other transaction on the same objects executed within short time interval.

I imagine a better approach would be to use all the limits in the current job and then when close to the limits queue a new one, but it is not obvious to me how to implement such a pattern.

What are the queueable design patterns available?

3
  • Do you have something to achieve like rollup summary in master-detail? Mar 14, 2020 at 12:05
  • It is a lookup, I am trying to achieve something similar but obviously it cannot be executed in a trigger
    – Edmondo
    Mar 14, 2020 at 12:05
  • If similar as rollup summary from lookup relationship type, there is a package available which might work for you, github.com/afawcett/declarative-lookup-rollup-summaries or may be you want to describe what exactly you are trying to achieve..! Mar 14, 2020 at 12:23

1 Answer 1

6

The "too many queueable jobs" error is a per transaction error. You can have an "unlimited" number of queueable and future items in the queue of jobs to execute, unlike scheduled and batchable jobs. The only rule is you can only enqueue 50 at once, or 1 when you're already in asynchronous context. You need to change your Queueable design so that you only add as few jobs as necessary to get your business logic done. Also remember that a Queueable job can "chain" itself, so a better design is to use obe job, start executing your logic, and when you reach a certain threshold of governor limits, chain to another job.

public void execute(QueueableContext context) {
  while(freeLimitsAvailable() && !recordsToProcess.isEmpty()) {
    proessMore(recordsToProcess);
  }
  if(!recordsToProcess.isEmpty()) { // Still more work to do... //
    System.enqueueJob(this);
  }
}
Boolean freeLimitsLeft() {
  return Limits.getDmlRows()/(Decimal)Limits.getLimitDmlRows() < 0.8 &&
         Limits.getDmlStatements()/(Decimal)LImits.getLimitDmlStatements() < 0.8 &&
         ...; // check all the limits you care about... //
1
  • thanks, but I see you are setting a 0.8 limit, but that's what I wanted to avoid. Isn't that arbitrary or dangerous?
    – Edmondo
    Mar 23, 2020 at 11:52

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

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