forked from molecule-ai/molecule-core
Closes #2069. removeSubtree dropped a parent + descendants locally after DELETE returned 200, but a GET /workspaces request that was IN-FLIGHT before the DELETE completed could land AFTER and hydrate the store with a stale snapshot — re-introducing the deleted nodes on the canvas until the next 10s fallback poll corrected it. New module canvas/src/store/deleteTombstones.ts holds a transient process-lifetime Map<id, deletedAt>. removeSubtree calls markDeleted(removedIds); hydrate calls wasRecentlyDeleted(id) to filter the incoming workspaces. TTL is 10s — matches the WS-fallback poll cadence so a single round-trip is covered, after which a legitimately re-imported id flows through normally. GC happens lazily at every read AND at write time so the map stays bounded — no separate timer / interval / unmount plumbing. Tests: - canvas/src/store/__tests__/deleteTombstones.test.ts: 7 cases covering immediate flag, never-marked, TTL boundary (9999ms vs 10001ms), GC-on-read, GC-on-write, re-mark resets timestamp, iterable input. - canvas/src/store/__tests__/canvas.test.ts: end-to-end "hydrate cannot resurrect ids that removeSubtree just dropped (#2069)" exercises the full chain at the store level. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> |
||
|---|---|---|
| .. | ||
| e2e | ||
| public | ||
| src | ||
| .env.example | ||
| .gitignore | ||
| components.json | ||
| Dockerfile | ||
| next.config.ts | ||
| package-lock.json | ||
| package.json | ||
| playwright.config.ts | ||
| playwright.staging.config.ts | ||
| postcss.config.js | ||
| tailwind.config.ts | ||
| tsconfig.json | ||
| vitest.config.ts | ||