salesforce零基礎學習(一百零五)Change Data Capture

zero.zhang發表於2021-07-11

本篇參考:

https://developer.salesforce.com/docs/atlas.en-us.232.0.api_streaming.meta/api_streaming/using_streaming_api_durability.htm

https://trailhead.salesforce.com/content/learn/modules/change-data-capture

 https://developer.salesforce.com/docs/atlas.en-us.change_data_capture.meta/change_data_capture/cdc_intro.htm

https://developer.salesforce.com/blogs/2018/08/what-is-change-data-capture.html

https://developer.salesforce.com/docs/atlas.en-us.232.0.object_reference.meta/object_reference/sforce_api_associated_objects_change_event.htm

salesforce零基礎學習(九十六)Platform Event淺談

salesforce零基礎學習(八十五)streaming api 簡單使用(接近實時獲取你需要跟蹤的資料的更新訊息狀態)

我們在前面介紹過 Push Topic 以及 Platform Event這兩個 Streaming API,可以想象未來的某天肯定還會補上一篇 Change Data Capture(CDC) 集齊 Streaming API 三件套,今天這篇部落格就是對CDC進行淺入淺出。

一. CDC 概念以及什麼時候使用

提起CDC以前,還是需要先重新說一下 Streaming Event 以及 Push technology。 Streaming Event(流事件)是一個系統(釋出者)向另一個系統(訂閱者)傳送的即時通知訊息。使用推送技術,釋出者將資料推送到訂閱者,這個操作近乎實時。對Streaming API感興趣或者不瞭解的,可以檢視上文的第一個連結。Streaming Event在salesforce中主要有三種封裝好的feature: Push Topic & Platform Event & Change Data Capture.

所以什麼場景下我們推薦使用 Change Data Capture呢?使用CDC有哪些優勢,什麼場景不建議呢?

  • 使外部系統與Salesforce資料保持同步;
  • 接收Salesforce記錄更改的通知,包括建立、更新、刪除和取消刪除操作;
  • 可以通過CometD或者Apex Trigger去訂閱;
  • 捕獲所有記錄的欄位變更;
  • 無論共享規則如何,訂閱者都可以廣泛訪問所有資料;
  • 訂閱者基於Field Level Security,僅傳遞使用者有權訪問的欄位;
  • 加密 change event欄位;
  • 在事件的header中獲取有關更改的資訊,例如更改的來源等,它可以讓訂閱方更靈活的判斷運算元據;
  • 使用事務邊界執行資料更新;
  • 使用版本化的事件架構;
  • 以可擴充套件的方式訂閱大量更改;
  • 訪問保留的事件最多三天。

以下場景不適用於使用CDC。

  • 根據記錄和欄位更改執行稽核跟蹤。
  • 更改資料捕獲旨在保持下游系統的同步,而不是單個使用者。如果許多使用者訂閱了CometD客戶機,那麼併發客戶機限制可能會達到。

二. CDC的釋出,結構以及訂閱

既然我們知道哪些場景推薦使用,那麼我們應該清楚如何去釋出,以及傳送出去的結構和限制等細節知識,用來做一些評估和下游系統的對接。

釋出篇:

 setup->  change data capture 然後選擇我們需要追蹤的表即可。這裡我們選擇了 Account以及 Opportunity,則Account 以及 Opportunity有CUD情況,下游訂閱端便可以獲取到訊息資料。

 結構篇:

 那下游端訂閱需要了解一下CDC推送過去的格式是什麼樣,否則他們也沒法去進行解析操作,所以我們來看一下CDC推送的訊息資料的格式。

通過下圖我們看到一個CDC的訊息資料結構可以簡單的分成兩部分: header & body。 header用來記錄推送的表的資訊,比如表名,操作的型別(CUD/UnDelete),操作的表的ID資訊等等。body部分即為改動的欄位的資訊的鍵值隊。針對新增場景,傳送所有的非空的欄位以及系統欄位;針對更新場景,傳送所有改變了的欄位;針對刪除場景,不會有任何的欄位。細節可以檢視一下官方的API文件。

這裡來做一個引申,如果系統中有formula欄位,在新增或者更新場景並不會傳送過去,所以針對 formula欄位,如果使用了CDC需要考慮進行單獨的處理,如果前期未識別,後續會增加很多effort來對應。現在看上面這個截圖可能有點懵,等會通過trigger訂閱列印出來以後可以更好的瞭解報文內容。

訂閱篇:

salesforce針對CDC支援兩種訂閱方式: CometD以及Apex Trigger,針對 CometD不做介紹,PushTopic & Platform Event & CDC都是支援CometD訂閱方式,如果涉及到下游系統,直接根據官方文件中的demo一步一步配置,很輕鬆的就可以實現。這裡主要是介紹一下 Apex Trigger方式訂閱。

要知道,如果我們使用 PushTopic方式訂閱,如果下游系統真的沒收到資料是一個很麻煩的事情,我們沒法去和他們解釋到底是salesforce沒有廣播這條資料,還是訂閱端問題,會有適當的扯皮操作,但是使用CDC我們完全不會有這個疑問,因為當廣播出去以後,我們可以通過trigger去實現訂閱從而實現tracking。不是所有的表都支援CDC,所以我們可以去檢視一下官方文件來確定一下。針對支援的表,trigger的寫法和 ApexTrigger很相似,區別就是監控的表為 [Object]ChangeEvent。如果是標註你的表,則直接使用名稱,比如 AccountChangeEvent。如果是自定義表,則中間需要加上兩個下劃線,比如 CustomObject__ChangeEvent。並且只允許 after insert使用。下面的例子是針對 OpportunityChangeEvent進行監聽,如果是Stage為Close Won情況下,建立一個Task。通過這個trigger,我們也可以列印出來實際的這個結構。

trigger OpportunityChangeTrigger on OpportunityChangeEvent (after insert) {
    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中檢視到CDC相關的訂閱資訊,需要將 Traced Entity Type設定成 Automated Process。

 

 我們新建一條 Opportunity的情況下,以下是建立的內容。

可以看一下message 的結構,其中包括了當前的型別,以及變更的欄位以及其欄位對應的值,通過header我們可以看到這條記錄執行的是CREATE的操作。不是所有的欄位都展示在這裡,只有內容非空的才會在body中。

{
    "IsClosed": false, 
    "attributes": {
        "url": "/services/data/v52.0/sobjects/OpportunityChangeEvent/4881111", 
        "type": "OpportunityChangeEvent"
    }, 
    "IsWon": false, 
    "IsSplit": false, 
    "CloseDate": "2021-07-10", 
    "ReplayId": "4881111", 
    "ForecastCategory": "Pipeline", 
    "Name": "測試CDC 0710", 
    "IsExcludedFromTerritory2Filter": false, 
    "Probability": 10, 
    "OwnerId": "0053g000000lqx1AAA", 
    "LastModifiedDate": "2021-07-10T15:58:07.000+0000", 
    "Id": "1CExx000000KTnbGAG", 
    "HasOpportunityLineItem": false, 
    "StageName": "Prospecting", 
    "IsPrivate": false, 
    "ForecastCategoryName": "Pipeline", 
    "LastModifiedById": "0053g000000lqx1AAA", 
    "CreatedById": "0053g000000lqx1AAA", 
    "ChangeEventHeader": {
        "recordIds": [
            "0063g00000AQHUwAAP"
        ], 
        "nulledFields": [], 
        "diffFields": [], 
        "commitUser": "0053g000000lqx1AAA", 
        "entityName": "Opportunity", 
        "changeType": "CREATE", 
        "commitNumber": 11077894054001, 
        "changedFields": [], 
        "commitTimestamp": 1625932687000, 
        "changeOrigin": "com/salesforce/api/soap/52.0;client=SfdcInternalAPI/", 
        "transactionKey": "00038c39-bc36-b76b-776e-d489f264045f", 
        "sequenceNumber": 1
    }, 
    "CreatedDate": "2021-07-10T15:58:07.000+0000"
}

將這條資料進行update操作,設定amount,並且修改一下Stage Name

我們可以看一下message詳情架構如下:body中擁有了 Amount資訊以及修改的欄位的資訊。我們可以看到現在的change Type是 UPDATE。在header的changedFields區域就可以看到這次修改的哪些欄位。

{
    "IsClosed": false, 
    "attributes": {
        "url": "/services/data/v52.0/sobjects/OpportunityChangeEvent/4890418", 
        "type": "OpportunityChangeEvent"
    }, 
    "Amount": 101.0, 
    "LastModifiedDate": "2021-07-11T05:40:20.000+0000", 
    "IsSplit": false, 
    "HasOpportunityLineItem": false, 
    "LastAmountChangedHistoryId": "0083g00000KllvXAAR", 
    "IsExcludedFromTerritory2Filter": false, 
    "Id": "1CExx000000KWDiGAO", 
    "ReplayId": "4890418", 
    "StageName": "Needs Analysis", 
    "IsPrivate": false, 
    "LastStageChangeDate": "2021-07-11T05:40:20.000+0000", 
    "IsWon": false, 
    "ChangeEventHeader": {
        "recordIds": [
            "0063g00000AQHUwAAP"
        ], 
        "nulledFields": [], 
        "diffFields": [], 
        "commitUser": "0053g000000lqx1AAA", 
        "entityName": "Opportunity", 
        "changeType": "UPDATE", 
        "commitNumber": 11078205948865, 
        "changedFields": [
            "StageName", 
            "Amount", 
            "ExpectedRevenue", 
            "LastModifiedDate", 
            "LastStageChangeDate", 
            "LastAmountChangedHistoryId"
        ], 
        "commitTimestamp": 1625982020000, 
        "changeOrigin": "com/salesforce/api/soap/52.0;client=SfdcInternalAPI/", 
        "transactionKey": "0003bba5-8a9b-2ad2-c3c3-a15a295b2bb5", 
        "sequenceNumber": 1
    }, 
    "ExpectedRevenue": 20.2
}

三. CDC 、 PushTopic、Platform Event 區別

我們作為開發人員還好,可能架構選型以後,我們瞭解做了就好。但是哪天我們做到了架構,需要我們選型相關的,我們如何去選型呢?這三個有什麼區別或者優缺點,如何去取捨?下圖是我們官方的一個比較,詳情連結:https://developer.salesforce.com/docs/atlas.en-us.232.0.api_streaming.meta/api_streaming/event_comparison.htm?search_text=Platform%20Event

 

除了這種 high level的比較,一定要確定好選型以後的細節考慮。比如 PushTopic的query的長度限制,Change Data Capture formula欄位變更不會傳過去,而且超過指定的數量需要花錢等等。high level決定選型,細節決定了你的effort,缺一不可。

總結:篇中淺入淺出介紹了一下CDC的使用,至此streaming api 廣播訂閱的三個模型都已經有簡單介紹。很多細節介紹也沒有展開,比如trigger一次進入資料的資料量必須2000以內等等。如果用到了這個模型,詳細檢視官方文件進行夯實即可。篇中有錯誤歡迎指出,有不懂歡迎留言。

相關文章