Skip to content

Commit 404f9cb

Browse files
committed
feat(json-crdt): 🎸 add ability to replay to specific patch
1 parent 018a907 commit 404f9cb

File tree

2 files changed

+39
-3
lines changed

2 files changed

+39
-3
lines changed

src/json-crdt/file/PatchLog.ts

Lines changed: 12 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ import {printTree} from '../../util/print/printTree';
33
import {AvlMap} from '../../util/trees/avl/AvlMap';
44
import {Model} from '../model';
55
import type {Printable} from '../../util/print/types';
6+
import {first, next} from '../../util/trees/util';
67

78
export class PatchLog implements Printable {
89
public static fromModel(model: Model<any>): PatchLog {
@@ -26,9 +27,17 @@ export class PatchLog implements Printable {
2627
}
2728

2829
public replayToEnd(): Model {
29-
const model = this.start.clone();
30-
this.patches.forEach(({v}) => model.applyPatch(v));
31-
return model;
30+
const clone = this.start.clone();
31+
for (let node = first(this.patches.root); node; node = next(node))
32+
clone.applyPatch(node.v);
33+
return clone;
34+
}
35+
36+
public replayTo(ts: ITimestampStruct): Model {
37+
const clone = this.start.clone();
38+
for (let node = first(this.patches.root); node && (compare(ts, node.k) >= 0); node = next(node))
39+
clone.applyPatch(node.v);
40+
return clone;
3241
}
3342

3443
// ---------------------------------------------------------------- Printable
Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
import {Model} from '../../model';
2+
import {File} from '../File';
3+
4+
const setup = (view: unknown) => {
5+
const model = Model.withServerClock();
6+
model.api.root(view);
7+
const file = File.fromModel(model);
8+
return {model, file};
9+
};
10+
11+
test('can replay to specific patch', () => {
12+
const {model, file} = setup({foo: 'bar'});
13+
model.api.obj([]).set({x: 1});
14+
const patch1 = model.api.flush();
15+
model.api.obj([]).set({y: 2});
16+
const patch2 = model.api.flush();
17+
file.log.push(patch1);
18+
file.log.push(patch2);
19+
const model2 = file.log.replayToEnd();
20+
const model3 = file.log.replayTo(patch1.getId()!);
21+
const model4 = file.log.replayTo(patch2.getId()!);
22+
expect(model.view()).toEqual({foo: 'bar', x: 1, y: 2});
23+
expect(file.log.start.view()).toEqual({foo: 'bar'});
24+
expect(model2.view()).toEqual({foo: 'bar', x: 1, y: 2});
25+
expect(model3.view()).toEqual({foo: 'bar', x: 1});
26+
expect(model4.view()).toEqual({foo: 'bar', x: 1, y: 2});
27+
});

0 commit comments

Comments
 (0)