Skip to content

feat(offline): replace aggregate intent chains atomically - #65

Merged
rdlabo merged 1 commit into
mainfrom
feat/offline-aggregate-replacement
Aug 12, 2026
Merged

feat(offline): replace aggregate intent chains atomically#65
rdlabo merged 1 commit into
mainfrom
feat/offline-aggregate-replacement

Conversation

@rdlabo

@rdlabo rdlabo commented Aug 12, 2026

Copy link
Copy Markdown
Contributor

Summary

  • add a serialized aggregate-chain replacement primitive for conflict recovery
  • preserve FIFO intent count, aggregate identity, companion footprint, and createdAt ordering
  • commit the fully prepared replacement chain and remove the old chain in one replica transaction
  • retain the original chain on preparation or validation failure

Verification

  • offline sync focused: 120/120
  • kit lint
  • git diff --check

Open in Devin Review

@netlify

netlify Bot commented Aug 12, 2026

Copy link
Copy Markdown

Deploy Preview for rdlabo-ionic-angular-library ready!

Name Link
🔨 Latest commit 52dfbd5
🔍 Latest deploy log https://app.netlify.com/projects/rdlabo-ionic-angular-library/deploys/6a7c63e589a6f900084607f8
😎 Deploy Preview https://deploy-preview-65--rdlabo-ionic-angular-library.netlify.app
📱 Preview on mobile
Toggle QR Code...

QR Code

Use your smartphone camera to open QR code link.

To edit notification comments on pull requests, go to your Netlify project configuration.

@rdlabo
rdlabo force-pushed the feat/offline-aggregate-replacement branch from 154ecef to 10c6aab Compare August 12, 2026 12:12

@devin-ai-integration devin-ai-integration Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Devin Review found 1 potential issue.

View 1 additional finding in Devin Review.

Open in Devin Review

);
}
const retained = knownCommands.filter((command) => !replaced.some((item) => item.commandId === command.commandId));
this.#assertDistinctBatchFootprints(materializations, retained, true);

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🟡 連鎖置換で一度消してから作り直したはずの関連データが消えたままになる

集約チェーンの置換をまとめて書き込む際、後続intentが復活させたはずの関連行が先行intentの削除指示によって上書き削除されます(#commitMaterializedEnqueuesremoveRows 生成、projects/kit/offline/src/lib/offline-sync.service.ts:660)。
Impact: 置換後に本来残るはずのローカルデータが消え、画面表示や後続同期が実際の意図と食い違います。

putRows→removeRows の適用順とチェーン内重複キー許可の組み合わせ

replacePreparedAggregate#assertDistinctBatchFootprints(materializations, retained, true)projects/kit/offline/src/lib/offline-sync.service.ts:354)で allowOneAggregate = true を渡すため、チェーン内の同一 replica キー重複チェック(同ファイル 622-625 行)が無効化されます。その結果、entry0 の companion が after = null(削除)、entry1 の同じ companion が after = row(再作成)というチェーンが許容されます。

しかし #commitMaterializedEnqueues は全 entry の put を putRows に、全 entry の削除を removeRows にフラットに集約します(同ファイル 656-660 行)。両リポジトリ実装とも putRows を全件適用した後に removeRows を適用するため(projects/kit/offline/src/lib/offline-repository.ts:686-698projects/kit/offline/src/lib/sqlite-offline-repository.ts:411-420)、entry1 が書いた行が entry0 の削除で消え、チェーン最終状態と一致しません。ベース行は putRows のみなので順序勝ちで正しく、影響は companion 行に限られます。

enqueuePreparedBatch 経路では重複 footprint が例外になるため、この経路は本 PR で新規に生じたものです。

Prompt for agents
replacePreparedAggregate では #assertDistinctBatchFootprints に allowOneAggregate=true を渡してチェーン内の replica footprint 重複チェックを無効化しているため、同一 companion キーに対して先行 intent が削除、後続 intent が再作成という組み合わせが通ってしまいます。一方 #commitMaterializedEnqueues は全 entry の put/remove をまとめて渡し、両リポジトリ実装(offline-repository.ts の #applyReplicaTransaction、sqlite-offline-repository.ts の transactReplica)は putRows を全て適用した後に removeRows を適用するため、最終状態がチェーンの意図と食い違い、本来残るべき companion 行が削除されます。対策としては、コミット前にチェーン内で同一 replica キーの最終状態(最後の entry の after)だけを put/remove に畳み込む、もしくは同一キーに対する削除と再作成が混在するチェーンを検証時に拒否することが考えられます。
Open in Devin Review

Was this helpful? React with 👍 or 👎 to provide feedback.

@rdlabo
rdlabo force-pushed the feat/offline-aggregate-replacement branch from 10c6aab to 52dfbd5 Compare August 12, 2026 12:15
@rdlabo
rdlabo merged commit 90e1f7e into main Aug 12, 2026
11 of 12 checks passed
@rdlabo
rdlabo deleted the feat/offline-aggregate-replacement branch August 12, 2026 12:16
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant