AfterDelete.Finalizer
Runs once after a Writer or Dispatcher has seen every record in the chunk, with the records that qualified. Use it for one aggregate query or one write per former parent.
Interface
apex
public class AfterDelete {
public interface Finalizer {
void finalizeAfterDelete(TriggerHandler.DeleteRecords records);
}
}finalizeAfterDelete(records): called once per chunk, after this handler’s records, only if at least one record qualified; after the dispatch for a Dispatcher. It receives only the qualified records.
Example
apex
public with sharing class ContactWriter implements AfterDelete.Writer, AfterDelete.Finalizer {
private TriggerHandler.UnitOfWork unitOfWork;
public Boolean writeOnAfterDeleteWhen(TriggerHandler.DeleteRecord record) {
return record.isNotNull(Contact.AccountId);
}
public void writeOnAfterDelete(TriggerHandler.DeleteRecord record, TriggerHandler.UnitOfWork unitOfWork) {
this.unitOfWork = unitOfWork;
unitOfWork.toInsert(new Task(WhatId = ((Contact) record.getOldSObject()).AccountId, Subject = 'Review contact'));
}
public void finalizeAfterDelete(TriggerHandler.DeleteRecords records) {
for (Id accountId : records.getIdsOf(Contact.AccountId)) {
this.unitOfWork.toUpdate(new Account(Id = accountId, Description = 'Contacts changed'));
}
}
}Good to Know
- Not an end-of-statement hook. A delete of 1,000 records runs it once per chunk of up to 200.
- Keep the unit in a field. The Finalizer gets no unit of work. Store the one from
writeOnAfterDelete, as the Skeleton does. Its writes commit with the rest. - Aggregate over what remains. The deleted rows are gone from SOQL, so a query over the former parents' children counts only the survivors.
- A throw discards a ContinueOnError Writer's writes. Its private unit commits after the Finalizer, so a swallowed exception skips that commit.
- A Dispatcher's job is already enqueued. Its Finalizer runs after the dispatch, so a throw here does not undo the job.
