Interaction Sequences
Complex user workflows involve multiple interactions that must be tracked and optimized correctly. This document covers key sequences and their resulting mutations.
Why Sequences Matter
Understanding interaction sequences is critical because:
- Command aggregation must produce correct final state
- Per-entity optimization evaluates each entity's mutation timeline independently
- Edge cases like create-then-delete must result in no-ops
Common Sequences
Create Node, Then Delete It (No-Op)
A user creates a node, potentially connects it, then deletes it before saving.
Resulting Mutations:
| Entity | Timeline | Result |
|---|---|---|
| Node A | create → delete | NO-OP (never persisted) |
| Connected Edges | create → delete | NO-OP (never persisted) |
| Existing Nodes | no change | No mutation needed |
Per-entity optimization means Node A being a no-op doesn't affect whether other entities need updates. Each entity's timeline is evaluated independently.
Node Stitching: Delete Existing, Create Replacement
User deletes an existing node and creates a new one in its place.
Steps:
- User deletes an existing node
- User creates a new node (fresh or via Copy-On-Use)
Resulting Mutations:
| Entity | Timeline | Result |
|---|---|---|
| Original Node | delete | DELETE |
| New Node | create | CREATE |
| Connected Entities | update (relationship changes) | UPDATE |
Whether the new node uses Copy-On-Use data or fresh data doesn't affect mutation tracking—it's still delete + create.
Edge Rerouting / Reconnect
User changes an edge's target, either by:
- Explicitly deleting an edge and drawing a new one
- Dragging an existing edge's handle to a different target
Resulting Mutations:
| Entity | Change | Result |
|---|---|---|
| Node B | Relationship removed | UPDATE (loses parent reference) |
| Node C | Relationship added | UPDATE (gains parent reference) |
Create Node, Update Connected, Then Delete Original
A complex sequence where an intermediate update must persist despite deletion.
Steps:
- Create new node A
- Create edge Category → A
- Update Category (e.g., change name)
- Delete node A (cascade deletes edge)
Resulting Mutations:
| Entity | Timeline | Result |
|---|---|---|
| Node A | create → update (implied) → delete | NO-OP |
| Edge | create → delete | NO-OP |
| Category | update (explicit) | UPDATE ✅ |
The Category's explicit update persists regardless of Node A's lifecycle. User-initiated edits to existing entities are never discarded due to other entities' no-ops.
Update Existing Node With Pre-existing Edges
User edits an existing node without changing any connections.
Steps:
- Flow loads with existing nodes and edges
- User updates Answer's content (no edge changes)
- User saves
Key Insight: Pre-existing edges are NOT in the command's relationshipContext (only new edges are captured there). The system must derive relationship context from current canvas edges for updates to existing nodes.
Resulting Mutations:
| Entity | Timeline | Result |
|---|---|---|
| Answer | update | UPDATE with relationship context derived from edges |
Batch Delete (Multi-Select)
User selects multiple nodes and deletes them simultaneously.
Steps:
- User selects multiple nodes (e.g., Category + all child Answers)
- User presses Delete
Behavior:
- Each selected node generates a DELETE command
- Connected edges cascade delete
- Order matters: child nodes should be deleted before parents
Position-Only Movement (Canvas-Only Change)
User drags nodes to new positions without changing data or connections.
Steps:
- User drags node(s) to new position
- No entity data or edges change
Result:
- No mutation command created
- Position stored in
canvas_datafield - Persisted via DTO's
canvas_data, not entity mutations
Aggregation Optimization Rules
When building the final DTO from commands, per-entity mutation timelines are optimized:
| First Action | Last Action | Result |
|---|---|---|
| create | delete | NO-OP (entity never persisted) |
| delete | create | DELETE + CREATE (stitching scenario) |
| create | update | CREATE with latest data |
| update | update | UPDATE with latest data |
| update | delete | DELETE only |
| (existing) | update | UPDATE |
| (existing) | delete | DELETE |
Each entity is optimized independently. A no-op on Node A does not affect whether Category or other connected nodes need updates.