[claude] Detect and recover when OpaqueChanges become applicable
メンテナーはふだん 1 日以内に返信
まだ誰も着手していません。
評価
- 難易度
- 5/5
- 見積もり時間
- 1週間以上
- 初心者へのやさしさ
- 35/100
- issue の種類
- 機能追加
- 明瞭さ
- 説明が足りない
- 活発さ
- 静か
- 技術スタック
- csharp
調査の方向性
まず CrdtRepository.AddCommits、SnapshotWorker、および既存の RegenerateSnapshots、DeleteStaleSnapshots、UpdateSnapshots の各パスを読んでください。提案されている集約トラッキングとフィンガープリントの代替案を、ここで説明されている commit-log と ChangeEntities の動作と比較してください。Done には、決定済みの検出範囲、既存データベースの扱い、そして不完全なマテリアライズド状態を暗黙的に再生成せずに報告する方法を含める必要があります。
索引モデルが issue の本文から書いたものです。
説明
[Claude, autonomous]
Problem
Since #80, a change with an unknown $type is stored and synced onward as an OpaqueChange, but SnapshotWorker skips applying it. Snapshots and projected tables are then silently missing its effect, and:
- When the app later registers the type, nothing notices. The stored JSON would now deserialize concretely, but snapshots are never re-folded, so the stale state persists forever.
- Some types will never become known (a different app writing to the same project). That's a legitimate steady state, but a client currently can't even answer "is my materialized state incomplete?", which matters for consumers that write materialized state into other systems (FwHeadless → FieldWorks).
- If the first change to an entity is opaque, no snapshot exists, so later known changes to that entity are skipped too.
Recovery itself is the easy part: the commit log is complete everywhere (opaque JSON round-trips verbatim), so RegenerateSnapshots() already repairs state once the type is registered. What's missing is detection, and ideally a cheaper replay scope than "everything".
One idea: an UnappliedChangeTypes table
One aggregate row per unknown discriminator, written at commit ingest (CrdtRepository.AddCommits, same transaction): TypeName (PK), EarliestCommitId, ChangeCount.
- Detection = intersect
TypeNames with registered discriminators at project open. Non-empty: replay from the predecessor of the earliest affected commit (the existingDeleteStaleSnapshots+UpdateSnapshotspath), then delete the recovered rows. - Never-known types never intersect; their rows sit inert and double as a cheap "this project has changes I can't apply" signal for UI or sync guards.
- Existing DBs backfill with one
json_extract(Change, '$."$type"')scan overChangeEntities.
Ingest is deliberate: the converter also runs on read paths, and the SnapshotWorker skip sites also fire for ordinary out-of-order arrivals, so ingest is the only place that sees each commit exactly once.
Alternatives
Persist nothing; fingerprint the registered type set. On growth, scan history for the new types; regenerate if found.
- Pro: zero bookkeeping, fully retroactive.
- Con: a scan every release that adds a type; "am I incomplete right now?" also costs a scan; the registered set can differ per host (e.g. conditional
AddRemoteResourceEntity), so set comparison needs care.
Per-skip rows (CommitId, ChangeIndex, TypeName, EntityId).
- Pro: exact.
- Con: unbounded in the never-known steady state; no benefit over the aggregate, since replay is scoped by earliest commit, not per change; only records skips after it ships, so it needs the backfill anyway.
Regenerate whenever the registered type set changes.
- Pro: no detection code.
- Con: full replay after nearly every release;
RegenerateSnapshotsis currently unlocked, non-transactional, and slow on big projects, so everyone pays for a rare event.
Do nothing; rely on the manual regenerate troubleshooting action.
- Pro: zero code.
- Con: staleness is silent, so nobody knows to press the button; FwHeadless would sync stale state indefinitely.
Notes
- Whichever way this goes, it should land in the same release as #80 or close behind: builds that skip changes without recording anything leave stale snapshots that later detection can't tell from a clean DB without the backfill scan.
- Auto-regeneration should wait until
RegenerateSnapshotsis locked, transactional, and fast enough. Detection plus a visible warning is already useful on its own.
Context: sillsdev/languageforge-lexbox#2482 (review discussion that prompted this).
- 主要言語
- C#
- スター
- 14
- フォーク
- 4
- 平均マージ
- 2日 16時間
- マージ済み PR(30日)
- 5
環境構築
このプロジェクトの環境構築ファイルはまだ確認していません。まず README を読み、一般的な手順ははじめてのコントリビューションガイドを参照してください。
はじめの一歩
- issue を最後まで読み、次にプロジェクトのコントリビューションガイドを読みます。
- 着手することを issue にコメントします — 二人が同じ作業をするのを防げます。
- リポジトリをフォークし、ブランチを切って変更します。
- issue 番号を参照したプルリクエストを送ります。
sillsdev/harmony のほかの issue
-
enhancement
難易度 2/5 1〜3時間 初心者へのやさしさ 84/100
メンテナーはふだん 1 日以内に返信
-
難易度 5/5 1週間以上 初心者へのやさしさ 35/100
メンテナーはふだん 1 日以内に返信
-
Data bug
難易度 4/5 3〜5日 初心者へのやさしさ 55/100
sillsdev/harmony#105 · コメント 2 件 ·
メンテナーはふだん 1 日以内に返信
-
bug
難易度 4/5 3〜5日 初心者へのやさしさ 55/100
メンテナーはふだん 1 日以内に返信
-
enhancement
難易度 3/5 1〜2日 初心者へのやさしさ 58/100
メンテナーはふだん 1 日以内に返信
sillsdev/harmony の issue をすべて見る
似ている issue
-
area-ai untriaged
難易度 2/5 1〜3時間 初心者へのやさしさ 85/100
dotnet/extensions#7790 ·
メンテナーはふだん 1 日以内に返信
-
P2 testing
難易度 1/5 1時間未満 初心者へのやさしさ 90/100
メンテナーはふだん 1 日以内に返信
-
area-Infrastructure-coreclr os-ios os-maccatalyst os-tvos untriaged
難易度 2/5 1〜3時間 初心者へのやさしさ 78/100
dotnet/runtime#134766 · コメント 3 件 ·
メンテナーはふだん 1 日以内に返信
-
0 - Backlog Bug
難易度 2/5 1〜3時間 初心者へのやさしさ 88/100
BrighterCommand/Brighter#4444 ·
メンテナーはふだん 1 日以内に返信
-
bug
難易度 2/5 1〜3時間 初心者へのやさしさ 88/100
メンテナーはふだん 1 日以内に返信