背景
#70 は同期時の operation と DAG ノードの対応付けを、timestamp 近傍マッチから 位置(N番目同士) に変えた。一直線の履歴ではバージョン喪失と再送時の cycle detected を止める。
その対応付けが成立するのは履歴が一直線のときだけである。#70 は長さ不一致をエラーにして誤 stamp を拒否するが、分岐したコンテンツの同期 success path は閉じたままになる。#70 の範囲外として切り出す。
問題
get_operations_with_index は genesis 配下の全 operation を返し、linear_history は分岐点で子を1つしか選ばない。件数がずれると get_operations は失敗する。
失敗した同期 round は再試行されるが、同じ拒否が返るだけである。auto-merge 後も側枝の operation は残るため、長さは二度と一致しない。
G → v2 → v3 → A ─┐
→ B ─┴→ Merge → New
- operations: 7(A と B の両方 + Merge + New)
- linear_history: 6(分岐点で A か B の一方)
両枝を持ったノードは Fetch / Push できず、クラスタ全体が両枝を飲み込むと、その genesis を配れるノードがなくなる。
いつ起きるか
可用性のために member が2台以上あるとき。
- 同じコンテンツを持つ member が2台以上
- 2回の書き込みが、違う member のローカル CRDT に載る
- 2回目の時点で、その member が1回目の最新をまだ持っていない
genesis を持つノードはローカル commit する。ゲートウェイ / ALB が PUT を振り分けると、短い間隔の連続保存や、content update と token 無効化(同じ DAG 上の policy 更新)の競合で再現しうる。
一度起きると自己回復しない。ユーザーからは「保存は成功したが他ノードに届かない」「そのコンテンツの同期だけ失敗し続ける」に見える。
関連して、#70 の「誤 CID レプリカは通常同期で治る」も get_history 一致までしか見ていない。誤 CID ノードは head として残り、次のローカル update がゴーストとマージすると、上と同じ同期不能になる。
あるべき修正
位置で組まない。operation が作ったノードを identity で探す。
- commit 時に
op.id → node CID または node_timestamp を operation へ書き戻す
- あるいは
parents + payload で DAG 上のノードを引く
拒否は「ノードが読めない」など本当に stamp できない場合に限定する。分岐・マージ後も get_operations が全 operation を正しい stamp 付きで返せることをテストする。heal 後にローカル update しても他レプリカと履歴が一致することもカバーする。
関連
背景
#70 は同期時の operation と DAG ノードの対応付けを、timestamp 近傍マッチから 位置(N番目同士) に変えた。一直線の履歴ではバージョン喪失と再送時の
cycle detectedを止める。その対応付けが成立するのは履歴が一直線のときだけである。#70 は長さ不一致をエラーにして誤 stamp を拒否するが、分岐したコンテンツの同期 success path は閉じたままになる。#70 の範囲外として切り出す。
問題
get_operations_with_indexは genesis 配下の全 operation を返し、linear_historyは分岐点で子を1つしか選ばない。件数がずれるとget_operationsは失敗する。失敗した同期 round は再試行されるが、同じ拒否が返るだけである。auto-merge 後も側枝の operation は残るため、長さは二度と一致しない。
両枝を持ったノードは Fetch / Push できず、クラスタ全体が両枝を飲み込むと、その genesis を配れるノードがなくなる。
いつ起きるか
可用性のために member が2台以上あるとき。
genesis を持つノードはローカル commit する。ゲートウェイ / ALB が PUT を振り分けると、短い間隔の連続保存や、content update と token 無効化(同じ DAG 上の policy 更新)の競合で再現しうる。
一度起きると自己回復しない。ユーザーからは「保存は成功したが他ノードに届かない」「そのコンテンツの同期だけ失敗し続ける」に見える。
関連して、#70 の「誤 CID レプリカは通常同期で治る」も
get_history一致までしか見ていない。誤 CID ノードは head として残り、次のローカル update がゴーストとマージすると、上と同じ同期不能になる。あるべき修正
位置で組まない。operation が作ったノードを identity で探す。
op.id → node CIDまたはnode_timestampを operation へ書き戻すparents+ payload で DAG 上のノードを引く拒否は「ノードが読めない」など本当に stamp できない場合に限定する。分岐・マージ後も
get_operationsが全 operation を正しい stamp 付きで返せることをテストする。heal 後にローカル update しても他レプリカと履歴が一致することもカバーする。関連