mirror of
https://github.com/Memo-2023/mana-monorepo.git
synced 2026-05-14 18:41:08 +02:00
chore(dexie): v55 — sweep orphan updatedAt field from existing rows (F3 cleanup)
After F3 of the sync field-meta overhaul, every read of "last modified" goes through `deriveUpdatedAt(record)` over `__fieldMeta`. The legacy `updatedAt` field on existing IndexedDB rows was deliberately left in place by v53 (its comment explicitly defers the row-rewrite to a later cleanup) so the cut-over could proceed without a full DB rewrite. This v55 upgrade walks every sync-relevant table (`Object.keys(TABLE_TO_APP)`) and `delete row.updatedAt`. Idempotent (rows without the field are a no-op), best-effort (try/catch per table guards against a registry entry that doesn't yet have a Dexie store row). Local-only tables (_pendingChanges, _activity, _clientIdentity, _aiDebugLog) never carried `updatedAt`, so they stay out of the sweep. Plan: docs/plans/sync-field-meta-overhaul.md (F3-fu row in Shipping Log). Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
parent
da50da8964
commit
53fecbf4a7
3 changed files with 39 additions and 2 deletions
|
|
@ -185,7 +185,7 @@ Logout / Tab-Close → MemoryKeyProvider.setKey(null) → Cyphertext bleibt
|
|||
### Eckdaten
|
||||
|
||||
- **120+ Collections** in einer einzigen IndexedDB
|
||||
- **Schema-Versionen** 1–54 (v53 ersetzte `updatedAt`-Indizes durch `_updatedAtIndex`, v54 fügte `_clientIdentity` für stabile Client-IDs hinzu)
|
||||
- **Schema-Versionen** 1–55 (v53 ersetzte `updatedAt`-Indizes durch `_updatedAtIndex`, v54 fügte `_clientIdentity` für stabile Client-IDs hinzu, v55 löscht den Orphan-`updatedAt`-Wert aus existing rows nach F3-Cutover)
|
||||
- **Eager Apps**: mana, todo, calendar, contacts, tags, links — syncen beim Start
|
||||
- **Lazy Apps**: starten Sync erst beim ersten Modul-Besuch via `ensureAppSynced()`
|
||||
- **Conflict Resolution**: ✅ Origin-gated Field-Level LWW via `__fieldMeta` (siehe Sync Field-Meta Overhaul unten)
|
||||
|
|
@ -205,6 +205,7 @@ Sieben Phasen, die vier strukturelle Bugs in der Conflict-Detection abgeräumt h
|
|||
- **F5** (`d78f57c04`) `userContextStore.ensureDoc()` Public-API entfernt. Internal `getOrCreateLocalDoc()` bleibt als Fallback für brand-new clients deren First-Pull noch nicht durch ist. UI mountet ohne ensureDoc-Race.
|
||||
- **F6** (`a031493fe`) Stable `client_id` in Dexie-Tabelle `_clientIdentity`. `restoreClientIdFromDexie()` läuft im (app)-Layout vor `createUnifiedSync` und reconciliated Dexie ↔ localStorage. Dexie ist canonical, localStorage ist fast-read-cache. Survives clear-site-data und incognito flush.
|
||||
- **F7** (`2a8e8ff98`) `repair-silent-twin.ts` + `legacy-avatar.ts` Migrationen ersatzlos gelöscht — pre-live, keine Live-Daten brauchen sie. Orphan-localStorage-Flags-Sweep im Boot (`migrations-cleanup.ts`, `119cd2cf8`) räumt die zugehörigen Flags auf.
|
||||
- **F3-fu (v55 cleanup)** (_pending_) Dexie v55 row-rewrite: löscht den Orphan-`updatedAt`-Wert aus jedem Row in `Object.keys(TABLE_TO_APP)`. v53 hatte ihn bewusst stehengelassen (Comment "next-version upgrade can drop it"); nach F3+F5 liest niemand mehr `row.updatedAt`, also pure waste. Idempotent — rows ohne das Feld sind ein no-op.
|
||||
|
||||
Die vier Bug-Wurzeln (siehe ursprüngliche Diagnose 2026-04-26):
|
||||
|
||||
|
|
|
|||
|
|
@ -1369,6 +1369,41 @@ db.version(54).stores({
|
|||
_clientIdentity: 'id',
|
||||
});
|
||||
|
||||
// v55 — Sync Field-Meta Overhaul F3 cleanup.
|
||||
// The v53 upgrade kept the legacy `updatedAt` field on existing rows so
|
||||
// nothing read it during the cut-over (the F3 sweep migrated 121 store
|
||||
// files + 43 Local-* types in one pass; v53's comment explicitly
|
||||
// deferred the row-rewrite). All reads now go through
|
||||
// `deriveUpdatedAt(record)` from `__fieldMeta`, so the orphan field is
|
||||
// pure waste — bytes per row, encrypted-blob noise on the encrypted
|
||||
// tables, and a confusing artifact in the IndexedDB inspector.
|
||||
//
|
||||
// Walk every sync-relevant table (the `TABLE_TO_APP` registry) and
|
||||
// delete `updatedAt` from each row. Idempotent: rows without the field
|
||||
// are a no-op. Local-only tables (_pendingChanges, _activity,
|
||||
// _clientIdentity, _aiDebugLog, …) never carried `updatedAt` so they
|
||||
// stay out of the sweep.
|
||||
db.version(55).upgrade(async (tx) => {
|
||||
const tables = Object.keys(TABLE_TO_APP);
|
||||
for (const tableName of tables) {
|
||||
try {
|
||||
await tx
|
||||
.table(tableName)
|
||||
.toCollection()
|
||||
.modify((row: Record<string, unknown>) => {
|
||||
if ('updatedAt' in row) {
|
||||
delete row.updatedAt;
|
||||
}
|
||||
});
|
||||
} catch {
|
||||
// A table may exist in the registry but not in this Dexie
|
||||
// version (e.g. a future addition with no upgrade row yet).
|
||||
// The sweep is best-effort cleanup, not load-bearing — skip
|
||||
// missing tables silently.
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
// ─── Sync Routing ──────────────────────────────────────────
|
||||
// SYNC_APP_MAP, TABLE_TO_SYNC_NAME, TABLE_TO_APP, SYNC_NAME_TO_TABLE,
|
||||
// toSyncName() and fromSyncName() are now derived from per-module
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue