技術をかじる猫

適当に気になった技術や言語、思ったこと考えた事など。

Salesforce開発の基礎編8

プラットフォームイベントの基礎

trailhead.salesforce.com

イベント駆動型ソフトウェアアーキテクチャの理解

JavaScript やってるとイベントの概念は分かりやすいかもしれない。

  • イベント駆動型ソフトウェアアーキテクチャの理解
    • イベント駆動は、イベント発生側と受信側に別れ、発生側は適時イベントを垂れ流す。受信側は必要に応じてイベントを受信して処理する。そういう処理モデル
  • イベント駆動型システムのコンポーネント
    • イベント
      ビジネスプロセスにおいて意味のある状態の変化。もしくはそうしたものを扱う情報の単位。
    • イベントメッセージ
      イベントに関するデータが含まれるメッセージ。
    • イベントプロデューサ
      イベントメッセージの公開者。たとえば、発注アプリケーション
    • イベントチャンネル
      イベントを流す場所、イベントのストリーム。
    • イベントコンシューマ
      チャンネル登録者。イベントを受信する側の事。
    • イベントバス
      公開/登録モデルを使用したイベントストリーミングを可能にする通信とストレージのサービス。
  • プラットフォームイベントを使用するケースの例
    • Salesforce ←→ 外部システム のやり取り
      Salesforce 上の製品注文アプリに含まれるトリガが、発注などで発火してプラットフォームイベントを公開する。
      このイベントは イベントバスに流され、登録されてる外部システムがこのイベントを受け取って処理する。
      逆に外部サーバ何等かの通知があればイベントバスにイベントを流し込み、Salesforce 内の対応アプリがイベントバス経由でイベントを受け取る。
    • トリガを利用したイベントメッセージ
      Apex トリガからイベントを publish し、対応する Platform Event Trigger にイベントを通知することもある。
  • プラットフォームイベントの特徴
    • sObject に似てる。カスタム項目を自前で定義できる。
      ただし、これは更新/削除、イベントレコード情報表示といったことができない。
    • ネイティブおよび外部アプリケーションでのプラットフォームイベントの使用
      • イベント公開: Apex, プロセスビルダー, Flow Builder, sObject API (外部サーバ)
      • イベント受信: Apex トリガ, empApi Lightning コンポーネント, CometD (外部サーバ)
  • プラットフォームイベントと他のストリーミングイベントの違い
    他のイベントとして PushTopic イベントや汎用イベントが存在する。
    プラットフォームイベントは汎用イベントに似ているが、より強力なカスタマイズが可能
    • PushTopic イベント : Salesforce レコードの変更をメッセージ受信できる
    • 汎用イベント : 任意のメッセージコンテンツ (ペイロード) を送受信できる
  • プラットフォームイベントは次で利用
    • 事前定義されたスキーマを使用してカスタムイベントデータを送受信する
    • Apex でイベントの公開または登録を行う
    • Salesforce Platform 上かどうかに関係なく柔軟にイベントの公開と処理を行う

プラットフォームイベントの定義および公開

プラットフォームイベントの定義

f:id:white-azalea:20210615211455p:plain f:id:white-azalea:20210615211527p:plain f:id:white-azalea:20210615211629p:plain f:id:white-azalea:20210615211712p:plain f:id:white-azalea:20210615211755p:plain f:id:white-azalea:20210615212116p:plain

  • 「すぐに公開」と「コミット後公開」が選べる。
    すぐに公開は、保存に失敗しようと公開できるが、トランザクションもクソもないので取り消せない。
  • イベントの項かいには Apex からやったり、プロセスビルダーや FlowBuilder からも指定できる。

Apex だとこんな感じでできる。

// Create an instance of the event and store it in the newsEvent variable
Cloud_News__e newsEvent = new Cloud_News__e(
           Location__c='Mountain City',
           Urgent__c=true,
           News_Content__c='Lake Road is closed due to mudslides.');
// Call method to publish events
Database.SaveResult sr = EventBus.publish(newsEvent);
// Inspect publishing result
if (sr.isSuccess()) {
    System.debug('Successfully published event.');
} else {
    for(Database.Error err : sr.getErrors()) {
        System.debug('Error returned: ' +
                     err.getStatusCode() +
                     ' - ' +
                     err.getMessage());
    }
}

EventBus.publish はListで複数同時送信もできる。
Salesforce API からの場合RESTで

/services/data/v45.0/sobjects/Cloud_News__e/
{
   "Location__c" : "Mountain City",
   "Urgent__c" : true,
   "News_Content__c" : "Lake Road is closed due to mudslides."
}

をPOSTするそうな。

プラットフォームイベントの登録

Apex は普通にトリガ書けばいいらしい。
イベントは after insert のみ。

// Trigger for listening to Cloud_News events.
trigger CloudNewsTrigger on Cloud_News__e (after insert) {
    // List to hold all cases to be created.
    List<Case> cases = new List<Case>();
    // Get queue Id for case owner
    Group queue = [SELECT Id FROM Group WHERE Name='Regional Dispatch' AND Type='Queue'];
    // Iterate through each notification.
    for (Cloud_News__e event : Trigger.New) {
        if (event.Urgent__c == true) {
            // Create Case to dispatch new team.
            Case cs = new Case();
            cs.Priority = 'High';
            cs.Subject = 'News team dispatch to ' +
                event.Location__c;
            cs.OwnerId = queue.Id;
            cases.add(cs);
        }
   }
    // Insert all cases corresponding to events received.
    insert cases;
}
  • イベント処理の順序:イベントの発生順に処理される
  • 非同期トリガ実行: イベントを公開したトランザクションには含まれません。なので、遅れて動くことも十分にあり得る。
  • 自動化プロセスシステムユーザ: 実行ユーザは Process Automated 権限で実行される。

一次停止とかもできて、再開すると途中から処理できるようになる。
何かバグがあって、一時的に差し止めてもその間のイベントは再開時に処理できるという話。

ユニットテストは普通に EventBus.publish して試しなさいと。

LWC だと import { subscribe, unsubscribe, onError, setDebugFlag, isEmpEnabled } from 'lightning/empApi'; から empApi が使える。
aura の場合は <lightning:empApi aura:id="empApi"/> でやれる。

他にもプロセスビルダ、フロービルダからプラットフォームイベントを拾って処理できる。

  • CometD を使用したプラットフォームイベント通知の登録
    外部システム向けには Commit というAjax のPush技術で通知を受け取れるそうだ。

developer.salesforce.com