本篇參考:https://developer.salesforce.com/blogs/2018/07/which-streaming-event-do-i-use.html
https://trailhead.salesforce.com/content/learn/modules/platform_events_basics
我們在之前的篇章中講過 Streaming API的使用,可以參看:salesforce零基礎學習(八十五)streaming api 簡單使用(接近實時獲取你需要跟蹤的數據的更新消息狀態)
今天講的是另外一個針對消息發布訂閱的實現,即 Platform Event。Platform Event的詳細描述可以參看上面的trailhead練習,如何選取streaming event可以參看第一個鏈接。接下來通過三步來講 Platform Event。
一. 什么是Platform Event
Platform Event是一個基於發布訂閱的消息管理架構。通過Platform Event,你可以監聽你的系統數據並且滿足某種條件下,和自己或者其他外部系統進行交流通訊。比如salesforce系統的Account數據在其他的外部系統有備份。當 Account的Owner或者Account類型有改變以后,需要外部關聯的系統同時知道當前的數據進行了改變並作出相應的處理。我們以前針對此種case可能通過callout,將我們的數據變化通過http方式發布到對端系統,然后對端系統進行處理以后返回response告訴salesforce系統處理完成。此種方式可能有以下的問題:
- 當數據量大的時候,因為salesforce有callout的各種limitation,容易有government limitation的風險;
- 當對端系統遷移或者需要增加對端系統時,可能需要有額外的effort進行處理。
Platform Event是基於發布訂閱模式,即salesforce發布了消息以后,所有他的訂閱者理論上都有權力去訂閱到發布的數據。如果有新增的訂閱者,我們只需要配置相關的訂閱端即可。需要了解的是,使用Platform Event不僅可以和內部系統進行發布訂閱,也可以和外部系統進行連攜。Platform Event有幾個名詞需要了解。
- Event:在業務流程中有意義的狀態更改,比如account change owner
- Event message:Event發生時需要發送的消息。通常我們需要創建 PlatForm Event來進行對應,這個后期講
- Event producer:消息的發布者
- Event channel:消息發布者發布消息的渠道,這里我們用到的就是Event Bus
- Event consumer:從渠道中接受消息的訂閱者。
所以我們將操作連接起來可以理解成:當salesforce某些有意義的業務數據變化以后,發布者通過Event Bus這個渠道進行了數據發布,將數據廣播出去,訂閱者通過EventBus進行數據的接收即完成了數據的發布以及訂閱。數據的發布和訂閱可以有多種方式實現,篇中的頭部URL展示了Platform Event的開發文檔,包含了全部的操作手冊,本篇只是以其中的trigger方式進行掃盲,詳情操作還請查看官方這個API文檔。
二. PlatForm發布
1)創建PlatForm Event:在Set Up處搜索platform event,在Integrations下面點擊Platform Events便可以看到系統配置的Platform Event信息,點擊New Platform Event即可新建一條我們需要的PlatForm Event
2)當我們創建以后,可以選擇Publish Behavior,salesforce提供了兩個值可供選擇: Publish After Commit / Publish Immediately。這兩種有很大的區別:
-
Publish Immediately當對一個platform event列表進行publish時,即使有一些失敗,成功的那些也會繼續進行發布,即保存時allOrNone屬性會被自動忽略;
-
Publish Immediately如果設置了此種模式, setSavePoint以及rollback不支持,即發送了就發送了,沒有某種case回滾模式;反之Publish After Commit可以有回滾操作。
Event Type選擇的值為High Volume,salesforce可以將發布的廣播數據保存三天。
3)當我們創建完以后,我們會發現API Name是__e結尾的。針對Platform Event是以這種特殊的表進行存儲,當然里面的數據不支持SOQL或者apex方式去搜索出來,訂閱者只能通過其他的方式去查詢。標准的字段區域我們發現有一個 Reply Id。這個字段是一個非常重要的字段。有什么作用呢?
每一個Event Message都會包含一個 Reply Id,當廣播傳遞給訂閱者時由系統填充,代表着當前的事件在時間流中的位置(index)。對於連續的事件,Reply Id不一定是連續的,所以不要考慮使用+1的方式去找到下一個 ReplyId.當訂閱者因為某些原因丟失了接受的訂閱的信息,可以通過Reply Id去找回,但是因為 Publish Event只保留3天,所以需要在3天以內去完成。
同時我們也可以看到,下方區域還包含Trigger以及Subscription,這意味着Publish Event可以進行trigger操作,但是只能監聽trigger.afterInsert,其他的不支持。我們也可以進行創建字段操作去創建我們需要的類型以及變量數據。
4)當我們點擊Custom Fields New按鈕以后,我們可以看到包含以下的字段類型可供選擇。按照需求選擇我們需要的字段類型創建字段即可。
如圖我們創建了三個字段,和自定義字段類似,后綴也是__c,所以很好理解。
我們的模擬需求外部系統有備份salesforce的Account數據,當Account的industry變化以后,會發一個Task告訴Owner,同時將變化的數據告訴外部連攜系統。Publish Platform可以有很多種方式,可以通過apex / process builder / flow / rest api(通常demo中會使用workbench來操作)。我們的實現為使用apex trigger來實現。
trigger中核心的一個語句就是EventBus.publish了,和Datebase.insert一樣,可以傳遞一個list或者一個item都可以。以下的代碼便可以實現了一個Platform Event的發布廣播操作。
trigger AccountTrigger on Account(after update) { List<Account__e> needPublishAccountList = new List<Account__e>(); for(Account accountItem : (List<Account>)Trigger.new) { Account oldAccount = Trigger.oldMap.get(accountItem.Id); if(oldAccount != null && oldAccount.Industry != accountItem.Industry) { Account__e accountPublishItem = new Account__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()); } } } } }
三. PlatForm Event的訂閱
既然Event已經發布了,我們需要知道我們寫的代碼是否正確,訂閱者是否可以收到信息。上面也說過通過SOQL沒法搜索到Platform Event的信息,那么我們應該如何去查詢或者操作去了解是否發布成功呢?官方提供了特別多的訂閱方式。比如我們可以通過apex trigger / lightning component / lightning web component / process builder / CometD(針對外部系統連攜可以通過輪詢去訂閱)
所以我們使用哪種方式的訂閱要取決於我們項目的需要,如果訂閱在內部系統執行,作為公用操作可以使用trigger。如果我們需要在程序中監聽,可以使用lightning aura或者lwc去監聽。並進行頁面實時變更操作。如果外部連攜,可以考慮使用CometD進行連攜。具體的使用方式可以查看上面的官方文檔鏈接,本篇demo主要通過trigger/去實現訂閱的測試。
AccountEventTrigger.trigger:只能使用after insert,用於廣播以后針對owner創建一個task信息。
trigger AccountEventTrigger on Account__e (after insert) { List<Task> taskList = new List<Task>(); for (Account__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; }
我們在訂閱處便可以看到trigger作為訂閱者實現了訂閱。
總結:Platform Event在和內部外部系統信息交互有着很好用的效果,本篇只是簡單的進行功能掃盲,詳情使用自行查看開發文檔。