Azure Data Factroy にて Salesforce コネクターを利用した際における同時 API 要求数の制限の検証

## 概要

Azure Data Factory で Salesforce コネクター（Bulk API 2.0）を使用した際に、Salesforce の同時 API 要求数の制限によるエラーが発生するかどうかを検証しました。その結果、Azure Data Factory で Salesforce からデータを 160 並列で読み込むとエラーが発生することが確認されました。メモ程度ですが、記録として残しておきます。

> [{"message":"ConcurrentRequests (Concurrent API Requests) Limit exceeded.","errorCode":"REQUEST_LIMIT_EXCEEDED"}]

Salesforce の同時 API 要求数の制限については、Salesforce のドキュメントに記載されています。今回の検証結果では、80 並列の実行は正常に終了し、160 並列の実行でエラーが発生しました。このことから、並列実行数が制限を超えた場合でも、即座にエラーが発生するとは限らないことがわかりました。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/24031/9283277c-68e8-fe9a-d93c-973cd3bb5f6e.png)

## 事前準備

### 1. データの準備

[Snowfakery](https://snowfakery.readthedocs.io/en/latest/)というライブラリにて、検証用のデータを生成しました。データについては、 Databricks というサービス上で作成しています。

```sql
- var: count
  value: 99999

# - include_file: user.yml
# - include_file: Product2_PricebookEntry.yml
# - include_file: account_contact_lead_opportunity_order.yml

- object: case
  count: ${{count}}
  fields:
    IsDeleted: False
    MasterRecordId: null
    CaseNumber: ${{fake.random_int(min=40000, max=50000)}}
    ContactId: null
    AssetId: null
    ParentId: null
    SuppliedName: ${{fake.name}}
    SuppliedEmail: ${{fake.email}}
    SuppliedPhone: ${{fake.phone_number}}
    SuppliedCompany: ${{fake.company}}
    Type: 
      random_choice: 
        問い合わせ: 80%
        クレーム: 20%
    Status: 
      random_choice: 
        新規: 25%
        処理中: 25%
        完了: 25%
        クローズ: 25%
    Priority: 
      random_choice: 
        高: 33%
        中: 34%
        低: 33%
    Origin: 
      random_choice: 
        Web: 20%
        Email: 20%
        Phone: 20%
        Social: 20%
        Other: 20%
    Subject: ${{fake.sentence(nb_words=6)}}
    Description: "${{fake.text}}"
    IsClosed: ${{fake.boolean}}
    ClosedDate: ${{fake.date_this_year}}
    CreatedDate: ${{fake.date_this_year}}
    CreatedById: ${{fake.uuid4}}
    LastModifiedDate: ${{fake.date_this_year}}
    LastModifiedById: ${{fake.uuid4}}
    SystemModstamp: ${{fake.date_this_year}}
    LastViewedDate: null
    LastReferencedDate: null
    Reason: Null
    IsEscalated: Null
    ContactPhone: Null
    ContactMobile: Null
    ContactEmail: Null
    ContactFax: Null
    Comments: Null
```

```python
%sh
snowfakery data_config/acc.yml --output-format CSV --output-folder sample_data_01
```

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/24031/2899aa5a-ccbb-2986-1082-5e039eeac873.png)

### 2. Azure Data Factory にて Salesforce へデータを書き込み

Snowfakery にて作成して同一データを Azure Data Factory から何度か実行して Saleforce へ書き込みました。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/24031/760f22c5-d264-c235-b3e4-3afe00aac803.png)

### 3. Azure Data Factory にて Saleforce からデータの読み込み

Salesforce からデータの読み込みが実施できることを確認しました。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/24031/6038c860-d9b8-ae72-9844-f98961df0818.png)


## 検証

### 1. Azure Data Factory にて Saleforce からデータの読み込みを 80 並列で実行

Azure Data Factory にて Saleforce からデータの読み込み処理を 80 回呼び出すプログラムを実行したところ、正常終了しました。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/24031/52d6fb14-f479-fb44-b5d2-b1537911701b.png)

### 2. Azure Data Factory にて Saleforce からデータの読み込みを 31 並列で実行

Azure Data Factory にて Salesforce へデータを書き込む処理を 31 回呼び出すプログラムを実行したところ、正常終了しました。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/24031/1fb35543-130c-5726-81a3-777606b15971.png)

### 3. Azure Data Factory にて Saleforce からデータの読み込みとAzure Data Factory にて Saleforce からデータの読み込みを 80 並列で実行

Azure Data Factory にて Saleforce からデータの読み込みとAzure Data Factory にて Saleforce からデータの読み込みを 80 並列で実行したところ、エラーとなりました。

> Failure happened on 'Source' side. ErrorCode=SalesforceHttpResponseNotSuccessCodeException,'Type=Microsoft.DataTransfer.Common.Shared.HybridDeliveryException,Message=The API request to Salesforce failed. Request Url: https://xxx.my.salesforce.com//services/data/v61.0/query/0r8xx3G81RNFPM8ASP-1000, Status Code: Forbidden, Error message: [{"message":"ConcurrentRequests (Concurrent API Requests) Limit exceeded.","errorCode":"REQUEST_LIMIT_EXCEEDED"}],Source=Microsoft.Connectors.Salesforce,'

> Failure happened on 'Sink' side. ErrorCode=SalesforceHttpResponseNotSuccessCodeException,'Type=Microsoft.DataTransfer.Common.Shared.HybridDeliveryException,Message=The API request to Salesforce failed. Request Url: https://xxx.my.salesforce.com/services/data/v61.0/jobs/ingest/750IT00000dSex6YAC, Status Code: Forbidden, Error message: [{"message":"ConcurrentRequests (Concurrent API Requests) Limit exceeded.","errorCode":"REQUEST_LIMIT_EXCEEDED"}],Source=Microsoft.Connectors.Salesforce,'

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/24031/a90a09a0-6a36-2592-9843-d22a60a4baa5.png)

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/24031/3a316900-8ce0-d284-37ee-f4e4df70a948.png)

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/24031/37427580-89e9-9a9b-529f-4abe7d5c8f66.png)

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/24031/e91ad425-dec6-a402-540c-1cbabc2676cc.png)

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/24031/11802746-12bb-cac6-589b-0cf70de01e7b.png)