Add restore and revert actions dependent on diff change tracking
Opened this issue · 9 comments
RFC: For snapshot change tracking, add restore and reverts actions which would require a full diff and snapshot.
Normal validations and policies would apply to the source version
Change tracking would require a full diff:
Proposed structure for an update change with snapshot:
{
subject: { from: "subject", to: "new subject" },
body: { unchanged: "body" }
embedded_author: {
first_name: { unchanged: "Jane" },
last_name: { from: "Doh", to: "Doe" }
}
embedded_tags: {
"tag-3": {
op: "create",
changes: { tag: { to: "ash" } }
index: { to: 0 }
},
"tag-1": {
op: "update",
changes: { tag: { unchanged: "phoenix" } },
index: { from: 0, to: 1 }
},
"tag-2": {
op: "destroy",
changes: { tag: { unchanged: "nerves" } },
index: { from: 1}
}
}
}
Same changes but changes only:
{
subject: { from: "subject", to: "new subject" },
// body is unchanged
embedded_author: {
last_name: { from: "Doh", to: "Doe" }
}
embedded_tags: {
"tag-3": {
op: "create",
changes: { tag: { to: "ash" } }
index: { to: 0 }
},
"tag-1": {
op: "update",
// no changes, only moved index
index: { from: 0, to: 1 }
},
"tag-2": {
op: "destroy",
index: { from: 1}
}
}
}
This will take some time to get right. One of the difficulties is that we're building a schema here that could ultimately need to change in the future which would be problematic. I'd also suggest potentially only storing the to
here. The benefit of doing it this way is that any "stale" updates (i.e a an update action that uses an old version of a record that doesn't lock the record) won't affect the integrity of your log. We're going to be adding features to make stale updates not really an issue, but its something to keep in mind.
Yeah, that make sense. It will be more expensive, it would need to go back until it gets values for each field, or if its backed by ecto like AshPostgres maybe use a fancy query.
The issue about storing from
is that it's only valid if you lock the record on all updates. If you don't, you could get interleaved versions where neither has the correct from
.
👍 Something we could also do is add a change to lock records on all updates automatically, and explain that in the docs. In your case if they aren't written to frequently, that should be okay.
Breaking this into three issues:
- add a
change_tracking_mode :full_diff
that works like above - add an
undo_changes_action :undo
option to create an action that will undo only the changes made in that version. The actual Change will be a module that can be manually added to a an action via a mixin. - add an
restore_changes_action :restore
option to create an action that will restore all fields in the changes hash to their state at the time of versioning. The Change can also just be manually added to an action via a mixin. - add a
lock_on_update: true
option to ensure integrating of the changes map if desired.