Skip to content

Commit 243a83c

Browse files
authored
Fix multi user undo model (#4639)
* Undo by restoring each step's exact prior state, and only this user's own steps * Split up prior variants
1 parent 006807f commit 243a83c

10 files changed

Lines changed: 619 additions & 348 deletions

File tree

‎document/graph-storage/src/attributes.rs‎

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -102,10 +102,10 @@ impl Attributes {
102102

103103
/// Lands a single-key write if it is newer than the key's value, or than the floor for a key the map lacks. A
104104
/// deletion leaves a tombstone.
105-
pub(crate) fn apply_delta(&mut self, delta: AttributeDelta, timestamp: TimeStamp, force: bool) {
105+
pub(crate) fn apply_delta(&mut self, delta: AttributeDelta, timestamp: TimeStamp) {
106106
let AttributeDelta { key, value } = delta;
107107
let decided = self.get(&key).map_or(self.floor, |existing| existing.timestamp);
108-
if !force && timestamp <= decided {
108+
if timestamp <= decided {
109109
return;
110110
}
111111
let entry = match value {

‎document/graph-storage/src/crdt.rs‎

Lines changed: 8 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,6 @@
1-
use crate::{Attributes, Implementation, InputSlot, Network, NetworkId, Node, NodeId, NodeInput, PeerId, ResourceEntry, ResourceId, Rev, SourceKey, TimeStamp, UserId, Value, attr, compute_rev};
1+
use crate::{
2+
Attributes, Implementation, InputSlot, Network, NetworkId, Node, NodeId, NodeInput, PeerId, Prior, ResourceEntry, ResourceId, Rev, SourceKey, TimeStamp, UserId, Value, attr, compute_rev,
3+
};
24
use graphene_resource::ResourceHash;
35
use serde::{Deserialize, Serialize};
46

@@ -13,7 +15,8 @@ pub struct Delta {
1315
pub author: PeerId,
1416
pub timestamp: TimeStamp,
1517
pub kind: RegistryDelta,
16-
pub reverse: RegistryDelta,
18+
/// What every slot `kind` wrote held before it, stamps included, in write order. See [`Prior`].
19+
pub reverse: Vec<Prior>,
1720
/// Local, mutable annotations on this commit (interaction-end marker, future commit messages / labels).
1821
/// Deliberately excluded from `compute_rev`: relabeling a commit must not change its content-addressed
1922
/// identity, and two peers annotating the same op differently must still dedup to one `Rev`.
@@ -26,7 +29,7 @@ pub struct Delta {
2629
}
2730

2831
impl Delta {
29-
pub fn new(parent: Option<Rev>, author: PeerId, timestamp: TimeStamp, kind: RegistryDelta, reverse: RegistryDelta) -> Self {
32+
pub fn new(parent: Option<Rev>, author: PeerId, timestamp: TimeStamp, kind: RegistryDelta, reverse: Vec<Prior>) -> Self {
3033
let id = compute_rev(parent, author, timestamp, &kind);
3134
Self {
3235
id,
@@ -54,7 +57,7 @@ impl Delta {
5457
parent,
5558
author,
5659
timestamp,
57-
reverse: kind.clone(),
60+
reverse: Vec::new(),
5861
kind,
5962
attributes: Attributes::default(),
6063
retired_at_ms: 0,
@@ -219,26 +222,13 @@ pub struct AttributeDelta {
219222
pub value: Option<Value>,
220223
}
221224

222-
pub(crate) fn reverse_attribute_delta(delta: &AttributeDelta, attributes: &Attributes) -> AttributeDelta {
223-
AttributeDelta {
224-
key: delta.key.clone(),
225-
value: attributes.get(&delta.key).filter(|previous| !previous.deleted).map(|previous| previous.value.clone()),
226-
}
227-
}
228-
229225
#[cfg(test)]
230226
mod tests {
231227
use super::*;
232228

233229
#[test]
234230
fn unrecorded_retired_at_costs_one_byte_and_round_trips() {
235-
let base = Delta::new(
236-
None,
237-
PeerId(1),
238-
TimeStamp { counter: 1, peer: PeerId(1) },
239-
RegistryDelta::Other(Value::None),
240-
RegistryDelta::Other(Value::None),
241-
);
231+
let base = Delta::new(None, PeerId(1), TimeStamp { counter: 1, peer: PeerId(1) }, RegistryDelta::Other(Value::None), Vec::new());
242232
let mut stamped = base.clone();
243233
stamped.retired_at_ms = 1_790_000_000_000;
244234

0 commit comments

Comments
 (0)