You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
{{ message }}
Repository navigation
Sync: an 'unchanged' import rebuilds asset_refs from plan-time rows and can drop a concurrent edit's row #196
Found while verifying RFC-0045 (#193). Pre-existing on main.
packages/core-ts/src/sync-plan.ts (the import batch builder, around lines 295–310) skips the node delete and insert when the import is planned unchanged. It still always pushes refsRebuild(siteId, changes.rows):
if(!changes.unchanged&&!changes.conflict){/* delete + insert nodes */}// The derived reference index follows the node set in the same batch (RFC-0004 §4.4).batch.push(...refsRebuild(siteId,changes.rows));
changes.rows was read at plan time. When nothing else in the batch writes the node set, the rebuild has no CAS anchor. Here is the race:
A no-op cloudhal push (or pull, or import) of site S plans unchanged.
Concurrently, an editor saves an entry that newly uses asset A. That write inserts an asset_refs row for A.
The import batch runs. Its refsRebuild deletes S's asset_refs and re-inserts them from the plan-time rows, which do not include A's new use.
From then on, A is in use but has no asset_refs row. deleteAsset's NOT EXISTS asset_refs guard (assets.ts) allows deleting it, and the media "unused" filter lists it. A published page can lose its image. The window is small (a no-op import racing an edit), but the result is silent data loss.
Fix: run refsRebuild only when the same batch also writes the node set (!changes.unchanged && !changes.conflict). An unchanged import has nothing to rebuild. Add a shared-suite case: an unchanged import racing an asset-adding edit keeps the edit's row.
RFC-0045 step 0 (asset_refs scoping) should fold this in, and RFC-0045's entry_refs rebuild follows the same rule.
Activity
docs(rfc): accept RFC-0045 (collections stage 4)
fix(core-ts): read field assets through a running rename's fromKey (#196
Merge pull request #200 from cloudhal-dev/claude/practical-lichterman…