📝

[Rails][restforce] Salesforce Bulk Api 使用メモ

2023/10/28に公開

割と使う機会が多くて詳細を忘れがちなのでメモとして残します。

BulkApiの使用理由

SalesforceへRESTAPIでアクセスする場合で
大量レコード更新や、同一認証ユーザで連続的な更新の場合ではBulkを使用するケースがあります。

注意点としてSFDCオブジェクトごとでしかBulkは使用できないので、
よくあるAccountオブジェクトとContactオブジェクトを同期的に更新する場合はbulkは使用できないです。

Gemインストール

gem "restforce"
gem "salesforce_bulk_api"

認証について

rest_client = Restforce.new
rest_client.authenticate!
bulk_client = SalesforceBulkApi::Api.new(rest_client)

作成・更新について

第1引数はSFDCオブジェクトの指定
第2引数はbulkパラメータの指定
第3引数はBooleanで「同期・非同期」の処理選択指定
第4引数はBooleanでSFDCオブジェクト項目にNULL値を保存するか指定

# create
bulk_client.create("Account", create_bulk_params, true, true)

# update
bulk_client.create("Account", update_bulk_params, true, true)

パラメータ例

# create
create_bulk_params = [
  { "Field1__c" => "とんこつラーメン" },
  { "Field1__c" => "鹿児島ラーメン" },
]
bulk_client.create("Account", create_bulk_params)

# update
update_bulk_params = [
  { "Id" => "1", "Field1__c" => "とんこつラーメン" },
  { "Id" => "12345678912", "Field1__c" => "鹿児島ラーメン" },
]
bulk_client.update("Account", update_bulk_params)

エラーレスポンスについて

第3引数はBooleanで「同期・非同期」処理を選択で

同期処理選んだ場合のみエラーレコードの詳細がレスポンス返却されます。
以下のような形でerrorsにエラーレスポンスが格納されています。

このレスポンスが結構使いづらいです。。。
Bulkを使う状況だとだいたい失敗したパラメータのみを結果通知したりすると思います。

ただerrorsの中には成功したパラメータも含まれているかつ
エラーになったパラメータに固有ID等がないので
どのパラメータがどのSFDCオブジェクトに失敗したか特定に手間がかかります。

具体的にはbulkパラメータから成功した分を除外し、
失敗した分のbulkパラメータ一覧から以下のerrorsの値と一致するパラメータを絞り込みするみたい感じで特定します。。。

{
  ...,
  "result" => true,
  "batches" => [
    "numberRecordsProcessed" => "100", # Bulkで実行した数
    "numberRecordsFailed" => "3" # Bulkで実行した貸す
  ]
  "errors" => [
    { "id" => ["成功したID"] },
    ...

    {
      "errors" => [
        {
          "fields" => ["Id"],
          "message" => ["取引先 ID: 不正な種別の ID 値: 12345678912"],
          "statusCode" => ["MALFORMED_ID"]
        },
      ],
      "success" => ["false"],
      "created" => ["false"]
    },
    {
      "errors" => [
        {
          "fields" => ["Field1__c"],
          "message" => [
            "SFDCラーメン名項目: データ値が大きすぎる: とんこつラーメン*1000(実際に保存しようとした値)",
          ],
          "statusCode" => ["STRING_TOO_LONG"]
        },
      ],
      "success" => ["false"],
      "created" => ["false"]
    },
  ],
}

Discussion