1、Stream API背景
某些重要数据,需要实时监控是否有变化,或者某些数据在其他的平台有集成。
如果有变化,不刷新页面或者做其他trigger等操作便可以收到相关更改的推送通知(不管是salesforce平台还是其他外部服务,比如java端等,可以通过此种方式进行实时同步),告诉当前的需要监控的记录已经发生了变化。这种场景往往更会出现在数据不止存储在salesforce端,还有其他平台有数据的存储或者访问。这种情况下可以使用Streaming API。
2、Stream API简单介绍
在Salesforce中,Stream API是一种用于处理事件流(Event Streams)的工具。它允许开发人员通过订阅事件流来实时获取关于Salesforce平台上发生的各种操作和事件的信息。
具体来说,Stream API允许开发人员订阅特定的事件主题(如数据更改、记录创建、记录更新等),并实时接收有关这些事件的通知。这些事件可以是来自Salesforce对象的更改,也可以是与工作流、流程触发器、批量处理等相关的活动。
通过Stream API,开发人员可以创建一个持续的连接,监听Salesforce平台上的事件流,并在事件发生时立即采取相应的操作。这使得开发人员能够实现实时的数据同步、事件监控和响应,从而更好地管理和分析Salesforce中的数据。
总的来说,Stream API为开发人员提供了一种灵活且强大的方式来处理Salesforce平台上的事件流,从而实现实时数据处理和应用程序集成。
Streaming API提供了两种功能
基于Salesforce数据改变,对订阅的客户端进行通知推送
另一种是不基于Salesforce数据改变,对订阅的客户端进行通知推送
接下来大部分内容基于Salesforce数据改变后,对订阅的客户端进行推送。通知推送不止可以应用于salesforce系统,其他系统等也可以通过oauth等连接后接收到通知推送
Streaming API用于制定一套你想要接收的数据的条件,并且指定哪些事件(create/update/delete/undelete)情况下符合的数据推送一条通知到客户端,一条通知就是事件触发的结果发送到渠道的消息。通知的格式为JSON的格式。使用Streaming API可以减少不必要的API请求。
Streaming API使用的推送技术,即服务器端会主动给订阅的客户端发送通知信息,而不是客户端去调用服务器端返回消息,使用Bayeux协议和CometD用于长轮询。
- 如果想使用Streaming API,需要enable api的权限以及streaming api的权限
- 想要接受通知(notifications),当前登录的user必须针对StreamingChannel表拥有read权限
- 想要创建和管理通知,当前登录的user必须对StreamingChannel拥有Create权限
3、Streaming API事件类型
Streaming API 使用推送技术支持事件流,并提供近实时接收事件的订阅机制。Streaming API订阅机制支持多种类型的事件,包括PushTopic事件、通用事件(generic events)、平台事件(platform events)和Change Data Capture事件。
3.1、PushTopic事件
3.1.1、创建PushTopic
PushTopic是一个标准的sObject,封装了以下的字段:
ApiVersion:用于指定查询的SQL的版本,37以后系统可以存储24小时以内的事件,必填字段;
Description:PushTopic的描述信息,限定在400个字符以内;
ID:指定一条记录的全局唯一的标识;
isActive:是否可用,关系到PushTopic的限制计数(系统对PushTopic有limitation size);
IsDeleted:指定此PushTopic是否移动到回收站;
Name:PushTopic的名字,定义了渠道的名字,并且此名称必须是唯一的,后期订阅者订阅时,使用的就是这个名字;
NotifyForFields:指定哪些字段被评估生成通知;
NotifyForOperations:指定数据哪种事件操作会生成通知,在api version 29以后,此字段为只读字段;
NotifyForOperationCreate:Create操作是否会生成通知,api29以后可用;
NotifyForOperationDelete:Delete操作是否会生成通知,api29以后可用;
NotifyForOperationUndelete:UnDelete操作是否会生成通知,api29以后可用;
NotifyForOperationUpdate:Update操作是否会生成通知,api29以后可用;
Query:SOQL语句决定了哪些数据符合触发的事件后会发送到渠道。定义了哪些数据可以满足条件进行推送。Query语法和SOQL基本相同
3.1.2、登录Workbench,创建PushTopic,并点击Subscribe,则目前已经模拟订阅了此PushTopic
3.1.3、修改一条Account数据,则会在Streaming Push Topic 显示具体的修改信息推送消息了。
3.2、平台事件(Platform Event)
平台事件简化了传达更改和响应事件的过程。发布者和订阅者通过事件相互通信。一个或多个订阅者可以监听同一事件并执行操作。
通过事件驱动的架构,每个服务每当更新或创建数据时都会发布一个事件。其他服务可以订阅事件。它使应用程序能够在多个服务之间维护数据一致性,而无需使用分布式事务。
Platform Event是基于发布订阅模式,即salesforce发布了消息以后,所有他的订阅者理论上都有权力去订阅到发布的数据。如果有新增的订阅者,我们只需要配置相关的订阅端即可。需要了解的是,使用Platform Event不仅可以和内部系统进行发布订阅,也可以和外部系统进行集成。Platform Event有几个名词需要了解。
Event:在业务流程中有意义的状态更改,比如account change owner
Event message:Event发生时需要发送的消息。通常我们需要创建 PlatForm Event来进行对应,这个后期讲
Event producer:消息的发布者
Event channel:消息发布者发布消息的渠道,这里我们用到的就是Event Bus
Event consumer:从渠道中接受消息的订阅者。
3.2.1、创建平台事件
3.2.2、发布/订阅平台事件
3.2.2.1、发布平台事件
如上图,发布平台事件有四种方式:
使用 APEX 发布事件消息传递
流(Flow)构建器(Platform Event Trigger flow)
进程(Process Builder)构建器
使用来自外部应用程序的 Salesforce API 进行事件消息传递
模拟需求外部系统有备份salesforce的Account数据,当Account的行业(Industry)变化以后,会发一个Task告诉Owner,同时将变化的数据告诉外部连携系统。Publish Platform可以有很多种方式,可以通过apex / process builder / flow / rest api(通常demo中会使用workbench来操作)。
这里介绍使用 APEX 发布事件消息传递:
trigger中一个核心的语句是EventBus.publish,和Datebase.insert一样,可以传递一个list或者一个item。以下的代码便可以实现一个Platform Event的发布广播操作。
trigger AccountTrigger on Account(after update) {
List<AccountEvent__e> needPublishAccountList = new List<AccountEvent__e>();
for(Account accountItem : (List<Account>)Trigger.new) {
Account oldAccount = Trigger.oldMap.get(accountItem.Id);
if(oldAccount != null && oldAccount.Industry != accountItem.Industry) {
AccountEvent__e accountPublishItem = new AccountEvent__e();
accountPublishItem.Account_Id__c = accountItem.Id;
accountPublishItem.After_Industry__c = accountItem.Industry;
accountPublishItem.Before_Industry__c = oldAccount.Industry;
needPublishAccountList.add(accountPublishItem);
}
}
if(!needPublishAccountList.isEmpty()) {
List<Database.SaveResult> results = EventBus.publish(needPublishAccountList);
for (Database.SaveResult sr : results) {
if (sr.isSuccess()) {
System.debug('Successfully published event.');
} else {
for(Database.Error err : sr.getErrors()) {
System.debug('Error returned: ' + err.getStatusCode() + ' - ' + err.getMessage());
}
}
}
}
}
3.2.2.2、订阅平台事件
平台事件已经发布,我们需要知道代码是否正确,订阅者是否可以收到信息。通过SOQL没法搜索到Platform Event的信息,订阅平台事件的四种方式:
Apex Trigger
在Lightning组件中订阅平台事件通知(LWC/Aura)
在外部应用程序中
流(Flow)构建器/进程(Process Builder)构建器
使用哪种方式的订阅要取决于我们项目的需要,如果订阅在内部系统执行,作为公用操作可以使用trigger。如果我们需要在程序中监听,可以使用lightning aura或者lwc去监听,并进行页面实时变更操作。如果外部连携,可以考虑使用CometD进行连携。
这里使用Trigger来订阅平台事件:
只能使用after insert,用于广播以后针对owner创建一个task信息。
trigger AccountEventTrigger on AccountEvent__e (after insert) {
List<Task> taskList = new List<Task>();
for (AccountEvent__e accountEvent : Trigger.New) {
Task taskItem = new Task();
taskItem.Subject = 'Industry change reminder';
taskItem.Description = '描述信息: ' + 'old industry : ' + accountEvent.Before_Industry__c + ' new industry : ' + accountEvent.After_Industry__c;
taskItem.ActivityDate = System.today();
taskItem.Priority = 'Medium';
taskItem.OwnerId = UserInfo.getUserId();
taskList.add(taskItem);
}
insert taskList;
}
3.3、更改数据捕获(Change Data Capture)
3.3.1、关于CDC
Salesforce中的Change Data Capture(CDC)是一种用于捕获Salesforce对象数据更改的机制。它允许开发人员实时监视和捕获Salesforce中记录的创建、更新、删除等操作,并在这些操作发生时获取相关的变更信息。
下面是Change Data Capture的一些关键特性和工作原理:
实时事件捕获:Change Data Capture能够实时捕获对象记录的更改,无需轮询或定期检查。这意味着你可以立即获取到数据更改的通知,而无需等待或消耗额外的资源。
异步处理:CDC是异步处理的,它通过事件流的方式将数据更改的通知发送给订阅者。这意味着你可以将数据更改的处理逻辑与主要的业务逻辑解耦,从而提高系统的可扩展性和可维护性。
支持标准和自定义对象:Change Data Capture支持捕获标准对象和自定义对象的数据更改。你可以选择对哪些对象启用CDC,以及监视哪些字段的更改。
可靠性和安全性:CDC提供了可靠的事件传递机制,确保即使在系统故障或网络中断的情况下,数据更改的通知也不会丢失。此外,CDC还提供了安全性控制机制,以确保只有授权的用户才能访问和订阅数据更改事件。
支持广泛的用例:CDC可用于许多用例,包括实时数据同步、业务流程自动化、数据集成和分析等。例如,你可以使用CDC将Salesforce中的数据同步到外部系统,或者根据数据更改触发自动化的业务流程。
总的来说,Change Data Capture为开发人员提供了一种简单而强大的方式来捕获和处理Salesforce中的数据更改。它可以帮助你构建实时、可靠和安全的数据集成和应用程序集成解决方案,从而提高业务的效率和灵活性。
Change Data Capture(CDC) 功能是从 Winter ’19 版本开始正式启用的功能。
它是基于“发布-订阅”模式设计,可以将 Salesforce 中记录的改变自动推送给订阅者所在的系统,比如 Salesforce 内部的功能模块或外部的数据库(保持Salesforce与内部功能模块或外部系统数据一致)。
在 Lightning 框架中,lightning:empApi 组件可以实现“订阅者”的角色。
3.3.1.1、何时使用更改数据捕获
整组数据的初始副本已位于外部系统中。
现在,希望将新数据和更新数据持续同步到外部系统。
两个系统之间重复数据的协调。
它发布 Salesforce 数据的增量,无论是新记录还是更改记录。
它忽略共享设置并发送所有记录的更改事件,但它遵循字段级安全性。
如果 salesforce 记录字段使用 Shield Platform Encryption 进行加密,则加密字段值的更改会生成更改事件。
3.3.1.2、不适用于使用CDC的场景
根据记录和字段更改执行审核跟踪。
更改数据捕获旨在保持下游系统的同步,而不是单个用户。如果许多用户订阅了CometD客户机,那么并发客户机限制可能会达到。
3.3.2、使用更改数据捕获(CDC)
3.3.2.1、启用CDC功能,选择要追踪的对象
设定哪些对象的更新会被记录:
3.3.2.2、订阅更改数据捕获(Change Data Capture Events)或者 ChangeEvent考察点
订阅更改数据捕获四种方式:
Asynchronous Trigger(异步触发器)
Lightning Component
Lightning Web Component
EMP Connector(EMP 连接器)
Asynchronous Trigger(异步触发器)订阅更改数据捕获
如果我们使用 PushTopic方式订阅,如果下游系统真的没收到数据是一个很麻烦的事情,我们没法去和他们解释到底是salesforce没有广播这条数据,还是订阅端问题,会有适当的扯皮操作
但是使用CDC完全不会有这个疑问,因为当发布出去以后,我们可以通过trigger去实现订阅从而实现tracking。不是所有的表都支持CDC,所以我们可以去查看一下官方文档来确定一下。
针对支持的表,trigger的写法和 ApexTrigger很相似,区别就是监控的表为 [Object]ChangeEvent。如果是标准表,则直接使用名称,比如 AccountChangeEvent。如果是自定义表,则中间需要加上两个下划线,比如 CustomObject__ChangeEvent。并且只允许 after insert使用。下面的例子是针对 OpportunityChangeEvent进行监听,如果是Stage为Close Won情况下,创建一个Task。通过这个trigger,我们也可以打印出来实际的这个结构。
- 创建Trigger
trigger OpportunityChangeTrigger on OpportunityChangeEvent (after insert) {
system.debug('更改数据捕获');
List<Task> tasks = new List<Task>();
// Iterate through each event message.
for (OpportunityChangeEvent event : Trigger.New) {
// Get some event header fields
EventBus.ChangeEventHeader header = event.ChangeEventHeader;
system.debug('更改数据捕获==>event : ' + JSON.serialize(event));
if (header.changetype == 'UPDATE') {
System.debug('更改数据捕获==>List of all changed fields:');
for (String field : header.changedFields) {
if (null == event.get(field)) {
System.debug('更改数据捕获==>Deleted field value (set to null): ' + field);
} else {
System.debug('更改数据捕获==>Changed field value: ' + field + '. New Value: ' + event.get(field));
}
}
}
if ((header.changetype=='UPDATE') && (event.isWon==true)) {
// Create a task
Task tk = new Task();
tk.Subject = '更改数据捕获==>Follow up on won opportunities: ' + header.recordIds;
tk.OwnerId = header.CommitUser;
tasks.add(tk);
}
}
// Insert all tasks in bulk.
if (tasks.size() > 0) {
insert tasks;
}
}
- 更改调试日志的【已跟踪实体类型】为自动过程
- 创建一条业务机会,并查看Debug Log
{
"attributes": {
"type": "OpportunityChangeEvent",
"url": "/services/data/v59.0/sobjects/OpportunityChangeEvent/10892240"
},
"LastModifiedDate": "2023-11-10T08:07:38.000+0000",
"HasOpportunityLineItem": false,
"Discount_Percent__c": 3.0,
"StageName": "Qualification",
"Probability": 10,
"ForecastCategory": "Pipeline",
"IsClosed": false,
"CloseDate": "2023-11-15",
"Name": "更改数据捕获2",
"IsExcludedFromTerritory2Filter": false,
"CreatedById": "0057F000000YKbXQAW",
"OwnerId": "0057F000000YKbXQAW",
"ReplayId": "10892240",
"IsWon": false,
"ChangeEventHeader": {
"changeOrigin": "com/salesforce/api/soap/59.0;client=SfdcInternalAPI/",
"changeType": "CREATE",
"changedFields": [],
"commitNumber": 11473260822797,
"commitTimestamp": 1699603658000,
"commitUser": "0057F000000YKbXQAW",
"diffFields": [],
"entityName": "Opportunity",
"nulledFields": [],
"recordIds": [
"0067F00001DvQePQAV"
],
"sequenceNumber": 1,
"transactionKey": "0002023b-3b3f-58a5-8662-361aff06623b"
},
"CreatedDate": "2023-11-10T08:07:38.000+0000",
"IsSplit": false,
"Id": "1CExx000000jhZIGAY",
"ForecastCategoryName": "Pipeline",
"IsPrivate": false,
"LastModifiedById": "0057F000000YKbXQAW"
}
- 更新这条业务机会,并查看Debug Log
{
"attributes": {
"type": "OpportunityChangeEvent",
"url": "/services/data/v59.0/sobjects/OpportunityChangeEvent/10892573"
},
"LastModifiedDate": "2023-11-10T08:54:58.000+0000",
"HasOpportunityLineItem": false,
"Description": "用于更新业务机会,验证CDC结果",
"IsExcludedFromTerritory2Filter": false,
"LeadSource": "Web",
"ReplayId": "10892573",
"IsWon": false,
"ChangeEventHeader": {
"changeOrigin": "com/salesforce/api/soap/59.0;client=SfdcInternalAPI/",
"changeType": "UPDATE",
"changedFields": [
"Description",
"LeadSource",
"LastModifiedDate",
"PartnerAccountId"
],
"commitNumber": 11473276022230,
"commitTimestamp": 1699606498000,
"commitUser": "0057F000000YKbXQAW",
"diffFields": [],
"entityName": "Opportunity",
"nulledFields": [
"PartnerAccountId"
],
"recordIds": [
"0067F00001DvQePQAV"
],
"sequenceNumber": 1,
"transactionKey": "000204d0-6008-eead-b5d1-437ef0e961ef"
},
"IsSplit": false,
"Id": "1CExx000000jhefGAA",
"IsClosed": false,
"IsPrivate": false
}
3.4、PushTopic事件与平台事件(platform events)和更改数据捕获事件(CDC)区别:
特征 | 主题推送事件 | 更改数据捕获事件 | 平台事件 |
将自定义架构定义为强类型字段 | N/A | N/A | √ |
包括用户定义的有效负载 | N/A | N/A | √ |
通过一个或多个 API 发布自定义事件 | N/A | N/A | √ |
通过 Apex 发布事件 | N/A | N/A | √ |
使用 Process Builder 和 Flow Builder 以声明方式发布 | N/A | N/A | √ |
发布给特定用户 | N/A | N/A | × |
使用 JavaScript、Java 和其他语言通过 CometD 订阅 | √ | √ | √ |
通过 Apex 触发器订阅 | × | √ | √ |
过滤订阅 | √ | × | × |
接收 Salesforce 记录更改的自动发布事件通知 | √ | √ | N/A |
选择要包含在 Salesforce 记录更改的事件通知中的字段 | √ | × | N/A |
接收版本化事件架构 | × | √ | √ |
获得现场级安全性 | √ | √ | × |
获得记录共享支持 | √ | × | N/A |
使用 Shield Platform Encryption 加密现场数据 | × | √ | √ |
重播保留的事件通知 | √ | √ | √ |
事件保留期限 | 1天 | 3天 | 1 天或 3 天* |
Copyright © 乔木船长
个人主页:乔木船长
欢迎转发点评和指正!