Heroku Connect の書き込みエラー
この記事の英語版に更新があります。ご覧の翻訳には含まれていない変更点があるかもしれません。
最終更新日 2022年11月21日(月)
Table of Contents
計画的なメンテナンス期間などのさまざまな理由で、Salesforce への書き込みが失敗することがあります。Salesforce が利用できない場合、再び利用可能になるまで Connect は書き込みをキューに入れます。それ以外のすべてのケースでは、エラーを解決するためにユーザーの介入が必要です。 ログエラーについての詳細は、「Heroku Connect のログメッセージと一般的なエラー」を参照してください。
書き込みエラーの詳細の表示
書き込みエラーの詳細は、[Explorer (エクスプローラー)] タブでレコードを参照すると確認できます。heroku pg:psql
を使用して、データベースの _trigger_log
テーブルでそれらを確認することもできます。
SELECT table_name, record_id, action, sf_message
FROM salesforce._trigger_log
WHERE state = 'FAILED';
ユーザーの介入が必要なエラーが発生すると、通知の受信を選択したすべてのユーザーに Heroku Connect から通知が送信されます。詳細は、「関連付けられた通知に関するエラー」 を参照してください。
一般的な書き込みエラー
Permission Denied (アクセス拒否)
Salesforce のオブジェクトまたはフィールドへの書き込みアクセスが統合のユーザーに許可されていないことを示す一般的なエラーです。Salesforce で適切なアクセス許可を付与して、書き込み更新を再処理します。
duplicate value found (重複した値の検出)
Heroku Connect でレコードを Salesforce にプッシュしようとしましたが、Salesforce でレコードを保存できませんでした。
たとえば、duplicate value found: Contact_External_ID__c duplicates value on record with id: a006..
とします。このエラーは、Contact_External_ID__c
という値がすでに存在し、一意である必要があることを示します。
場合によっては、Heroku Connect での競合状態がこのエラーの原因である可能性があります。このエラーが発生しないよう、レコードをデータベースに挿入するときは常に外部 ID を追加してください。
外部 ID が設定されている場合、このエラーの原因として可能性が高いのは、すでにコミットされているレコードを Connect で再処理したことです。コミットが成功しても成功の報告が Connect に返されないことがあるため、この場合はこのエラーを無視してもかまいません。
entity is deleted (削除されたエンティティ)
Heroku Connect でレコードを Salesforce に同期しようとしましたが、Salesforce 側でレコードが削除済みであることが Salesforce から報告されます。
owner is inactive, cannot reparent record (所有者が非アクティブで親レコードが見つからない)
Heroku Connect で、別のオブジェクトを指している関係フィールドとレコードを同期しようとしましたが、その親オブジェクトがアクティブではなくなっています。
Id not specified in an update call (更新呼び出しで ID 未指定)
このエラーは、順序付き書き込みアルゴリズムの使用中に挿入に失敗した後、レコードに対して後続の更新が行われると発生します。
「順序付き書き込みアルゴリズム使用時の再試行」のいずれかの方法を使用して、最初の挿入エラーを解決し、後続の更新を再送信してください。
Salesforce API ドキュメントには、エラーコードとその説明の完全なリストが含まれています。
書き込みエラー解決後の再試行
エラーの原因を調査した後、Connect で更新を再処理します。再試行の方法は、使用している書き込みアルゴリズムによって異なります。
マージ書き込みアルゴリズム使用時の再試行
トリガーログの state
フィールドを NEW
にリセットすることによって、更新の再処理を Heroku Connect に指示します。または、INSERT が失敗した場合は、書き込みが失敗したレコードの列を UPDATE します。この変更により、変更を Salesforce に INSERT として送信するトリガーログエントリが作成されます。
たとえば、Contact
という名前のマッピングで失敗したすべてのエントリを再試行するには、次のクエリを使用します。
UPDATE salesforce._trigger_log SET state = 'NEW'
WHERE state = 'FAILED' AND table_name = 'contact';
この例では、デフォルトの Postgres スキーマ名 salesforce
を使用しています。別のスキーマを使用している場合は、名前を変更します。_trigger_log
テーブルの table_name
フィールドにはスキーマ名が含まれていません。
24 時間以上が経過したトリガーログエントリは _trigger_log_archive
テーブルに移動します。アーカイブされたエントリを再送信するには、それらのエントリを _trigger_log
テーブルに再度コピーする必要があります。
-- Set the records you want to retry to a state of 'REQUEUE'
UPDATE salesforce._trigger_log_archive SET state='REQUEUE'
WHERE state='NEW'; -- or some other criteria like state='FAILED' and table_name = 'account' and sf_message like '%my error message%'
-- Copy them to the trigger log table
INSERT INTO salesforce._trigger_log (created_at, updated_at, state, txid, table_name, action, record_id, values, old, sfid)
SELECT now(), now(), 'NEW', txid, table_name, action, record_id, values, old, sfid
FROM salesforce._trigger_log_archive where state='REQUEUE';
-- Update the records still in the archive
UPDATE salesforce._trigger_log_archive SET state='REQUEUED'
WHERE state='REQUEUE';
変更が NEW
状態にリセットされたことを Connect が検出するまで、最大で 20 分ほどかかる場合があります。
順序付き書き込みアルゴリズム使用時の再試行
Postgresql では有効な INSERT または UPDATE が、Salesforce に送信すると無効になる場合があります。参照整合性またはデータ形式に関する追加の規則が Salesforce で適用されることがあります。トリガーベースの検証またはロックの問題が原因で変更が失敗する可能性もあります。
トリガーログテーブルから失敗を抽出して、Salesforce に送信された変更のステータスを定期的に確認します。
SELECT created_at, table_name, record_id, sfid, sf_message
FROM salesforce._trigger_log WHERE state='FAILED';
単純なエラーの訂正は、レコードの値を更新するだけで十分な場合があります。より複雑な変更に関しては、データベースで利用可能な修復関数のいずれかを使用することが必要な場合があります。
Heroku Connect では、Salesforce への書き込みが失敗したときに変更を再トリガーするための 2 つの PL/PGSQL 署名を提供しています。
hc_capture_insert_from_row
: INSERT の再トリガーhc_capture_update_from_row
: UPDATE の再トリガー
INSERT と UPDATE の両方での書き込みエラーの解決については、以下のユースケースの例を参照してください。
INSERT の失敗
INSERT の失敗には、次の PL/PGSQL 署名を持つ挿入修復関数を使用します。
hc_capture_insert_from_row(
source_row hstore,
table_name varchar,
excluded_cols text[] = ARRAY[]::text[]
)
excluded_cols
パラメータはオプションです。設定されていない場合、関数はどのフィールドも除外しません。
たとえば、次のようにしてレコードを再送信できます。
SELECT salesforce.hc_capture_insert_from_row(hstore(salesforce.account.*), 'account')
FROM salesforce.account WHERE id = 1234;
このステートメントは、_trigger_log
の values
列に格納するために行全体を hstore 値に変換します。account
テーブル用であることを挿入修復関数に通知します。
注: 必要なのはテーブルの名前だけで、スキーマ名を含む完全修飾名は必要ありません。
excluded_cols
パラメータを使用して、レコードの一部を省略できます。次に例を示します。
SELECT salesforce.hc_capture_insert_from_row(
hstore(salesforce.account.*), 'account', ARRAY['parent__external_id__c'])
FROM salesforce.account where id = 1234;
このステートメントはすべての列と値を捕捉しますが、parent__external_id__c
という名前の列は除外します。
UPDATE の失敗
UPDATE の失敗の多くは、値を訂正すれば解決します。たとえば、name
列に加えられた変更が長すぎる場合は、短くした値で更新し、元の失敗した書き込みは無視します。
UPDATE salesforce.account set name='Smaller Name' where id = 1234;
値の訂正だけではエラーを解決できない場合、更新修復関数を使用します。この関数の PL/PGSQL 署名は次のとおりです。
hc_capture_update_from_row(
source_row hstore,
table_name varchar,
columns_to_include text[] = ARRAY[]::text[]
)
columns_to_include
パラメータはオプションです。設定されていない場合、関数はすべてのフィールドを含めます。
場合によっては、更新変更を再びキューに入れる必要があります。「INSERT の失敗」セクションで示した例では、挿入修復によって parent__external_id__c
が除外されました。次にその値を設定する更新を書き込む場合は、次のステートメントを使用します。
SELECT salesforce.hc_capture_update_from_row(
hstore(salesforce.account.*), 'account', ARRAY['parent__external_id__c'])
FROM salesforce.account where id = 1234;
このステートメントは、デフォルトでテーブルのすべての列と値を選択し、hstore 値に変換します。
レコードのどの部分を更新するかをフィルタリングすることもできます。特定の列のみを更新するには、columns_to_include
パラメータを使用します。