Mindmap Node Save Sequence Diagram
This document describes how mindmap nodes are saved from the Studio component through IndexedDB to the Python backend.
Overview
The persistence architecture follows a local-first pattern:
- User edits are immediately persisted to IndexedDB (offline-capable)
- Changes are queued in
syncQueuefor backend sync SyncManagerperiodically flushes the queue to the server- Backend processes changes and commits to PostgreSQL
Sequence Diagram
Key Components
| Component | File | Responsibility |
|---|---|---|
| Studio | Studio.tsx | React component with useReducer for state; useEffect detects changes |
| Persistence | persistence.ts | Async functions to save nodes/deltas to IndexedDB |
| db (KemmaDB) | db.ts | IndexedDB wrapper with nodes, maps, syncQueue stores |
| SyncManager | sync-manager.ts | Background sync loop, queue compression, retry logic |
| API Client | client.ts | Axios wrapper for HTTP calls to backend |
| Backend | routes/nodes.py | FastAPI endpoint processing batch updates |
Data Flow Details
1. Auto-Save Effect (Studio.tsx)
typescript
useEffect(() => {
const changes: NodeChange[] = []
// Compare currentNodes vs prevNodes.current
// Collect creates, updates, deletes
if (changes.length > 0) {
mindmapPersistence.persistNodeChanges(changes)
}
prevNodes.current = currentNodes
}, [nodes])2. IndexedDB Schema (db.ts)
Three object stores:
nodes- Cached node data (indexed byuserId,mapId)maps- Mindmap metadatasyncQueue- Pending changes for backend sync
3. Sync Queue Compression (sync-manager.ts)
Multiple updates to the same node are coalesced:
NODE_UPDATE(id=1, text="A") + NODE_MOVE(id=1, x=10)
→ NODE_COALESCED_UPDATE(id=1, { text: "A", x: 10 })4. Backend Processing (nodes.py)
python
@router.post("/nodes/batch")
async def batch_update_nodes(batch: SyncBatchRequest, ...):
for item in batch.changes:
match record.type:
case "NODE_CREATE": db.add(new_node)
case "NODE_DELETE": await db.delete(node)
case "NODE_COALESCED_UPDATE": # update fields
await db.commit()Error Handling
- Offline: Changes queue locally; sync resumes when online
- Network errors: Exponential backoff retry (1s, 2s, 4s)
- 409 Conflict: Ignored (idempotent creates)
- beforeunload: Triggers sync to prevent data loss