Microsoft GraphのDelta Queryが410 resyncRequiredを返したとき、差分同期を安全に作り直す

Graph Delta Queryの410をresource別の再同期契約で確認し、local独自情報や未送信変更を保全して列挙と同期位置を照合します。

AIものさし編集部

Microsoft GraphのDelta Queryで410や再同期を求めるエラーが返ったら、古いdeltaLinkを繰り返す前に、対象resourceと再列挙の指示を確認します。delta tokenはOAuth access tokenとは別です。サインインし直せたことと、欠落した変更を復旧できたことを分けて考えます。

本稿はGraph差分同期の復旧設計を扱います。driveItem、message、userなどで契約が異なるため、一つのresourceのerror codeや保持期間を全Graphへ当てはめません。実API、token更新、データ削除、再同期は実行していません。状態例は架空で、利用endpointの現行referenceと実応答を照合するための手順です。

410の対象と、失敗した同期位置を記録する

endpoint、API バージョン、tenant、対象userやdrive、同期範囲、最後の成功時刻を確認します。HTTPステータスだけでなくbodyのcode/messageとLocation headerを記録します。deltaLinkやnextLinkには状態tokenを含むため、共有logへURL全文を貼らず、保管場所と閲覧範囲を決めます。

表は横にスクロールできます

観測確認する対象別に扱う問題
delta要求が410再列挙のURLと対象resourceの契約OAuth tokenの単純な更新
401/403認証主体・scope・アクセスすぐlocal複製を全削除
429/5xx待機指示と再試行上限同期位置の勝手な変更
200だが想定外の件数ページング・範囲・変更の表現必ず全変更が欠落したと断定

成功していた別tenantのdeltaLinkや、別folderのcursorを流用していないかも確認します。エラー名が似ていても、別の同期サービスの手順を混ぜないようにします。

resourceごとの再同期契約を読む

Graph公式delta概要(新しいタブで開く)は、410と空のdeltatokenを含むLocationが返る場合、full synchronizationをやり直す必要があると説明しています。また、tokenの有効期間はresourceで異なり、すべてが固定7日ではありません。切断日数だけから期限を決めず、対象の仕様と応答を見ます。

driveItem: delta(新しいタブで開く)も、古いtokenやservice状態の変化で、410と新しい列挙を始めるLocationを返す場合を案内しています。タイトルのresyncRequiredを含め、実際に受け取ったcodeと、そのresourceの現行説明が対応するかを確認します。別resourceで同じ名前が返ると推測しません。

Location等の再開先を利用する場合も、API応答の信頼できるhost・環境に属するかを確認し、任意のURLへ認証情報を送る実装にしません。URL内のtokenを手で解析・加工して修復するのではなく、提供されたリンクの契約に従います。

local複製と、未送信の変更を分ける

再列挙が必要でも、同期DBのすべてを削除する必要があるとは限りません。remoteの複製、アプリ独自情報、まだremoteへ送っていない変更を分類します。双方向同期ではlocal変更を失うと、最新のremote一覧を取り直しても元に戻せません。

表は横にスクロールできます

保存しているもの再構築時の扱い残す識別情報
remoteから取得した複製新しい列挙と照合して更新resource ID・同期範囲
アプリ独自のメモ・担当複製の消去に巻き込まない対応するresource ID
未送信のlocal変更保全して競合を判断操作ID・変更前後・送信状態
過去の配布・通知履歴同期再実行と分離業務処理の重複防止ID

remoteを正本として読むだけのアプリと、localからも更新するアプリでは、照合後の処置が違います。再列挙の結果に合わせてremoteを自動削除・上書きする判断を、単なるエラー復旧へ含めないようにします。

新しい列挙を最後まで集める

最初の応答だけを新しい全件と扱いません。Graphのdelta処理では、途中はnextLinkをたどり、ラウンドが終わったdeltaLinkを次回の同期位置にします。元の範囲や選択条件を変えず、応答で返るリンクを利用します。queryを変えたい場合は、同じ同期の続きではなく、対象仕様に沿った新しい同期設計として分けます。

収集中はgenerationなどで作業中の複製を区別し、途中の状態を正常な最新一覧として公開しない方式を検討します。これはアプリ側の設計例で、Graphが世代切替機能を提供するという意味ではありません。最終ページの反映と新deltaLinkの保存を整合させ、失敗時は未完了として残します。

通知handlerや定期jobが並行して古いcursorを進めないかも確認します。対象単位の排他、旧jobの完了待ち、世代識別など、自分の保存方式で混在を防ぎます。

一覧とlocal状態をIDで照合する

driveItemの公式資料は、deltaが全変更の履歴ではなく最新状態を示し、同じitemが複数回現れることがあるため最後の出現を使うと説明しています。folderの名前変更がすべての子を返すとは限らず、pathだけでなくIDで追跡する必要があります。この挙動をmessageやuserへ無条件に一般化せず、対象resourceごとの削除・再出現の表現を確認します。

再列挙に現れないlocal itemは、即座にremote削除と決めません。同期範囲、アクセスの変化、列挙の完了、resourceの削除表現を調べます。自分の複製を除く判断と、remoteへ削除要求を出す判断は別です。未送信の変更があるitemは、保全した内容を踏まえて競合として扱います。

表は横にスクロールできます

照合結果の例取る判断避ける処理
同じIDで名前が変化参照を保って表示を更新path違いで別物を作る
localにだけ未送信変更競合・再送可否を確認再同期開始で破棄
対象範囲が途中で変化列挙条件を再確認不在を削除と断定
同じ変更を再取得再適用が安全か確認通知・送信を毎回再実行

差分同期へ戻った後の確認を残す

許可された検証環境で、既知の追加・更新・削除、複数ページ、途中停止、同じ変更の再出現を確認します。Graphへの変更を実行できない場合は、その制約を記録し、mockの検証と実際の同期成功を同じ結果にしません。新deltaLinkで要求が通るだけでなく、利用側の一覧や関連情報が期待どおりかを照合します。

完了記録には、元の失敗code、採用したresource別手順、再列挙の範囲と終端、local独自情報・未送信変更の扱い、新しい同期位置を残します。再構築が失敗したら、保全した旧複製を最新と偽らず、利用側へ同期失敗や古さが分かる状態を保ちます。復旧の目的はエラーを消すことだけでなく、何を同期できていて何が未確認か説明できることです。