Skip to content

AfterUndelete.Dispatcher

Makes one bulk call per chunk with the restored records that qualify: enqueue a Queueable, publish platform events or send email.

Interface

apex
public class AfterUndelete {
    public interface Dispatcher extends Handler {
        Boolean dispatchOnAfterUndeleteWhen(TriggerHandler.UndeleteRecord record);
        void dispatchOnAfterUndelete(TriggerHandler.UndeleteRecords records);
    }
}
  • dispatchOnAfterUndeleteWhen(record): called once per record in the chunk; it only selects records. Return true to include the record in the dispatch.
  • dispatchOnAfterUndelete(records): called once, after every record was checked, with the qualified records; not called when none qualified.

Example

apex
public with sharing class ContactDispatcher implements AfterUndelete.Dispatcher {
    public Boolean dispatchOnAfterUndeleteWhen(TriggerHandler.UndeleteRecord record) {
        return record.isNotNull(Contact.Email);
    }

    public void dispatchOnAfterUndelete(TriggerHandler.UndeleteRecords records) {
        System.enqueueJob(new ContactSyncJob(records.getIds()));
    }

    public class ContactSyncJob implements Queueable {
        private Set<Id> recordIds;

        public ContactSyncJob(Set<Id> recordIds) {
            this.recordIds = recordIds;
        }

        public void execute(QueueableContext context) {
        }
    }
}

Good to Know

  • Pass Ids, not rows. Hand records.getIds() to async work and query the records there.
  • Call out from a Queueable. Give the job Database.AllowsCallouts and make the callout in execute.
  • No unit of work. DML here runs at once and is not merged. Change records from a Writer.
  • Runs before the commit. A Publish Immediately event sent here reaches subscribers even if the restore fails later.
  • Writer wins. A class that also implements AfterUndelete.Writer runs only as a Writer.

Test

apex
@IsTest
static void dispatchOnAfterUndeleteEnqueuesOneJob() {
    // Setup
    Contact restoredContact = new Contact(Id = new TriggerHandler.RandomIdGenerator().get(Contact.SObjectType));
    List<TriggerHandler.TriggerRecord> qualified = new List<TriggerHandler.TriggerRecord>{ new TriggerHandler.TriggerRecord(restoredContact, null) };

    // Test
    new ContactDispatcher().dispatchOnAfterUndelete(new TriggerHandler.UndeleteTriggerRecords(qualified));

    // Verify
    Assert.areEqual(1, Limits.getQueueableJobs(), 'One job should be enqueued.');
}