変更データキャプチャと非表示ユーリティティ項目を用いてプッシュ通知を実現する


Winter '19リリースで、変更データキャプチャ(Change Data Capture)がDeveloper Previewになりました。変更データキャプチャは、指定したオブジェクトに対してレコードの作成・変更・削除をニアリアルタイムにSalesforceのイベントバスにPublishするサービスです。

イベントをSubscribeするには、これまでは独自でCometDクライアントを実装する必要がありましたが、こちらもWinter '19でlightning:empApiという便利なSubscribe用のコンポーネントAPIが登場しました。

Subscribeを実装したLightningコンポーネントを配置するにあたっては、またまたWinter '19から利用可能なlightning:backgroundUtilityItemインタフェースにより、Lightningコンポーネントを非表示のユーティリティバー項目として扱うことができます。 1

実装例

評価(Rating)項目がHotの取引先が作成された場合にトーストメッセージを表示してみましょう。

1. 変更データキャプチャの設定

[設定] - [インテグレーション] - [変更データキャプチャ] から対象のオブジェクトを選択し保存します。

2. Lightningコンポーネントの作成

StreamingUtilityItem.cmp
<aura:component implements="lightning:backgroundUtilityItem">
    <lightning:empApi aura:id="empApi"/>
    <aura:handler name="init" value="{!this}" action="{!c.doInit}" />
</aura:component>
StreamingUtilityItemController.js
({
    doInit : function(component, event, helper) {
        const empApi = component.find("empApi");
        const channel = "/data/AccountChangeEvent";
        const replayId = -1; //登録後に発生したすべての新規イベントを受信

        // イベント受信時の処理
        const onMessageCallback = (message) => {
            console.log("Received [" + message.channel +
            " : " + message.data.event.replayId + "] payload=" +
            JSON.stringify(message.data.payload));
            helper.notify(message.data.payload);
        };

        // Subscribeの開始 (valueはSubscribeしたオブジェクト)
        empApi.subscribe(channel, replayId, onMessageCallback).then((value) => {
            console.log("Subscribed to channel " + channel);
        });    

        // エラー処理
        empApi.onError((message) => {
            console.log("Received error ", message);
        });  
    }
 })
StreamingUtilityItemHelper.js
({
    notify : function(payload) {
        if(payload.ChangeEventHeader.changeType == 'CREATE' && payload.Rating == 'Hot'){
            $A.get("e.force:showToast").setParams({
                type: 'success',
                message: 'Hotな取引先 ' + payload.Name +' が作成されました!'
            }).fire();
        }
    }
})

ポイント

  • 変更データキャプチャのチャネルは標準オブジェクトの場合、/data/<sObject_Name>DataChangeとなります。カスタムオブジェクトの場合は/data/<CustomObject_Name>__ChangeEventです。
  • replayIdの設定についてはStreaming API開発者ガイド - メッセージの永続性も参照してください。
  • 変更データキャプチャでは以下のようなイベントを受信します。作成時はシステム項目および入力値のある項目が、更新時は値の変更がある項目だけがペイロードに含まれますので注意が必要です。(当たり前ではありますが)
  • {
    "data": {
    "schema": "IeRuaY6cbI_HsV8Rv1Mc5g", 
    "payload": {
      "ChangeEventHeader": {
        "entityName": "Account", 
        "recordIds": [
          "001R0000002aV0B"
        ], 
        "changeType": "CREATE", 
        "changeOrigin": "com.salesforce.core", 
        "transactionKey": "001b7375-0086-250e-e6ca-b99bc3a8b69f", 
        "sequenceNumber": 1, 
        "isTransactionEnd": true, 
        "commitTimestamp": 1501010206653, 
        "commitNumber": 92847272780, 
        "commitUser": "<User_ID>"
      }, 
      "Name": "Acme", 
      "Description": "Everyone is talking about the cloud. But what does it mean?", 
      "OwnerId": "<Owner_ID>", 
      "CreatedDate": "2017-07-25T19:16:44Z", 
      "CreatedById": "<User_ID>", 
      "LastModifiedDate": "2017-07-25T19:16:44Z", 
      "LastModifiedById": "<User_ID>"
    }, 
    "event": {
      "replayId": 6
    }
    }, 
    "channel": "/data/ChangeEvents"
    }
    
  • イベントではレコードIDが複数形(recordIds)となっていますが、試しにListをinsertしたところレコードの数だけイベントを受信しました。1イベントに複数のIdが含まれる条件をご存知の方はぜひ教えてください。

3. アプリケーションへコンポーネントの配置

アプリケーションマネージャのユーティリティ項目で作成したコンポーネントを選択し保存します。

動作確認

AccountをInsertし、別ウィンドウで通知を待ってみました。うまく動いていますね!

まとめ

変更データキャプチャ・lightning:empApi・lightning:backgroundUtilityItemを組み合わせることで、簡単に通知機能を実装できました。

変更データキャプチャはPushTopicやApexトリガ+Platform Eventよりも使いやすく、外部システムとの連携など多くの活用方法がありそうです。lightning:empApiでイベントのSubscribeが実装しやすくなりました。lightninbg:backGroundUtilityItemも通知以外の活用方法がたくさんありそうですね!Enjoy Winter '19!

参考リンク


  1. 余談ですがClassicのサービスコンソールでは設定画面でVisualforceのカスタムコンソールコンポーネントを非表示にするオプションがありました。