Change Data Capture - Asynchronous Trigger Processing
In Salesforce there are multiple ways of processing data Asynchronously using "Batch Apex", "Schedule Apex", "Queueable Apex", and "Future Method". In Summer '19 release, there is another feature available called "Asynchronous Apex Triggers" that can process data Asynchronously with the help "Change Data Capture".
With Change Data Capture enabled for any specific object (Custom and Standard) in Salesforce, it begins publishing events every time when a record is created or updated or deleted or undeleted. Change Data Capture supports all custom objects and for list of supported standard object, here is the Link.
Change Data Capture Setup:
In order to enable Objects for receiving change notifications, navigate to Setup-->Integrations-->Change Data Capture, select object to add and click Save.
Asynchronous Apex Trigger:
Once Change Data Capture is enabled on an object, events are published and those events can be processed Asynchronously using Asynchronous Apex Trigger which is an "after-insert" context and this is also one of the subscription modal apart from CometD.
Every change event has a below standard message structure which include both Header and Body Fields and the list of fields that included in the body will very based on event type!
To get the specifics on each Event Header and Body Fields, go through below Salesforce documentation link's.
Change Event Header Fields
Change Event Body Fields
Let's go ahead and subscribe to the change events using Asynchronous Apex Trigger, before that we need to setup a debug log with "Automated Process" for trace entity type!
My Scenario: I have two custom object's (Tournament and Contestant) and here Contestant object has a lookup relationship to Tournament object. Now I have below Asynchronous Apex Trigger on Contestant_ChangeEvent object that will handle change events to update parent record fields and to send some test email every time there is an CREATE or UPDATE event happens.
Reference Resource
Change Data Capture Developer Guide
Thank you!
With Change Data Capture enabled for any specific object (Custom and Standard) in Salesforce, it begins publishing events every time when a record is created or updated or deleted or undeleted. Change Data Capture supports all custom objects and for list of supported standard object, here is the Link.
Change Data Capture Setup:
In order to enable Objects for receiving change notifications, navigate to Setup-->Integrations-->Change Data Capture, select object to add and click Save.
Asynchronous Apex Trigger:
Once Change Data Capture is enabled on an object, events are published and those events can be processed Asynchronously using Asynchronous Apex Trigger which is an "after-insert" context and this is also one of the subscription modal apart from CometD.
Every change event has a below standard message structure which include both Header and Body Fields and the list of fields that included in the body will very based on event type!
{
"data": {
"schema": "<schema_ID>",
"payload": {
"ChangeEventHeader": {
"entityName" : "...",
"recordIds" : "...",
"changeType" : "...",
"changeOrigin" : "...",
"transactionKey" : "...",
"sequenceNumber" : "...",
"commitTimestamp" : "...",
"commitUser" : "...",
"commitNumber" : "..."
},
"field1":"...",
"field2":"...",
. . .
},
"event": {
"replayId": <replayID>
}
},
"channel": "/data/<channel>"
}
To get the specifics on each Event Header and Body Fields, go through below Salesforce documentation link's.
Let's go ahead and subscribe to the change events using Asynchronous Apex Trigger, before that we need to setup a debug log with "Automated Process" for trace entity type!
My Scenario: I have two custom object's (Tournament and Contestant) and here Contestant object has a lookup relationship to Tournament object. Now I have below Asynchronous Apex Trigger on Contestant_ChangeEvent object that will handle change events to update parent record fields and to send some test email every time there is an CREATE or UPDATE event happens.
/* * @Purpose : Change Event Trigger on "Contestant__C" Object * * @Developer : SFDC_DEV * * @Description : New Change Event Trigger * * @Modified Date : Jun-19-2019 */ trigger ContestantChangeTrigger on reddydev2018__Contestant__ChangeEvent (after insert) { List<Tournament__c> lstUpdt = new List<Tournament__c>(); Set<String> rcdIds = new Set<String>(); List<Messaging.SingleEmailMessage> lstMail = new List<Messaging.SingleEmailMessage>(); for (reddydev2018__Contestant__ChangeEvent iter: Trigger.New) { List<String> recordIds = iter.ChangeEventHeader.getRecordIds(); // add record id's the set rcdIds.addAll(recordIds); // get header details from eventbus EventBus.ChangeEventHeader header = iter.ChangeEventHeader; System.debug('************ChangeEventHeader: ' + header); // create a new email Messaging.SingleEmailMessage mail = new Messaging.SingleEmailMessage(); List<String> sendTo = new List<String>(); sendTo.add('reddydev2018@gmail.com'); mail.setToAddresses(sendTo); mail.setSenderDisplayName('ContestantChangeTrigger'); // check if the changetype is CREATE or UPDATE if (header.changeType == 'CREATE') { System.debug('************Create_Event************'); mail.setSubject('Hi - ContestantChangeTrigger CREATE got executed!'); mail.setHtmlBody('Hello - Here is the change event occured on Entitiy: ' + header.changeType + ' and CommitUserId: ' + header.commitUser); lstMail.add(mail); } else if (header.changeType == 'UPDATE') { System.debug('************Update_Event************'); mail.setSubject('Hi - ContestantChangeTrigger UPDATE got executed!'); mail.setHtmlBody('Hello - Here is the change event occured on Entitiy: ' + header.changeType + ' and CommitUserId: ' + header.commitUser); lstMail.add(mail); } } System.debug('************' + rcdIds); if (rcdIds.size() > 0) { // query Contestant records with matching record ids for (reddydev2018__Contestant__c iter: [Select Id, reddydev2018__Contestant_Name__c, reddydev2018__Contestant_Email__c, reddydev2018__Tournament__c, reddydev2018__Tournament__r.reddydev2018__Winner_Name__c, reddydev2018__Tournament__r.reddydev2018__Winner_Email__c From reddydev2018__Contestant__c Where Id IN: rcdIds]) { // check if lookup Tournament record has same values if (iter.reddydev2018__Tournament__c != null && (iter.reddydev2018__Contestant_Name__c != iter.reddydev2018__Tournament__r.reddydev2018__Winner_Name__c || iter.reddydev2018__Contestant_Email__c != iter.reddydev2018__Tournament__r.reddydev2018__Winner_Email__c)) { // assign name and email values to the lookup record iter.reddydev2018__Tournament__r.reddydev2018__Winner_Name__c = iter.reddydev2018__Contestant_Name__c; iter.reddydev2018__Tournament__r.reddydev2018__Winner_Email__c = iter.reddydev2018__Contestant_Email__c; // add record to the list lstUpdt.add(iter.reddydev2018__Tournament__r); } } // update qualifying records if (lstUpdt.size() > 0) { update lstUpdt; } // send email if (lstMail.size() > 0) { Messaging.sendEmail(lstMail); } } }
Reference Resource
Thank you!


Nice blog has been shared by you. it will be really helpful to many peoples who are all working under the technology.thank you for sharing this blog.
ReplyDeleteElectronic Signature Software