本篇參考: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在和內部外部系統資訊互動有著很好用的效果,本篇只是簡單的進行功能掃盲,詳情使用自行檢視開發文件。