Skip to content

Commit e9c3fe0

Browse files
committed
feat: 🎸 use one path for updates and creates
1 parent 8061945 commit e9c3fe0

File tree

4 files changed

+34
-51
lines changed

4 files changed

+34
-51
lines changed

src/__tests__/json-crdt-server/block.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -141,7 +141,7 @@ export const runBlockTests = (_setup: ApiTestSetup, params: {staticOnly?: true}
141141
stop();
142142
});
143143

144-
test('throws BLOCK_NOT_FOUND when "create" flag missing', async () => {
144+
test('throws NOT_FOUND when "create" flag missing', async () => {
145145
const {call, stop} = await setup();
146146
const id = getId();
147147
const model = Model.withLogicalClock();

src/json-crdt-repo/local/server-crud/ServerCrudLocalHistorySync.ts

Lines changed: 20 additions & 50 deletions
Original file line numberDiff line numberDiff line change
@@ -50,12 +50,27 @@ export class ServerCrudLocalHistorySync {
5050
const core = this.core;
5151
if (!core.connected$.getValue()) return false;
5252
const meta = await this.getMeta(collection, id);
53-
const isNewBlock = meta.time < 1;
54-
if (isNewBlock) {
55-
await this.pushNewBlock(collection, id);
56-
} else {
57-
await this.pushExistingBlock(collection, id, meta.time);
53+
const blob = await core.read(collection, id);
54+
const {history} = core.decoder.decode(blob, {format: 'seq.cbor', history: true});
55+
const patches: RemoteBlockPatch[] = [];
56+
let time = 0;
57+
// TODO: perf: use a binary search to find the first patch to sync.
58+
history!.patches.forEach(({v: patch}) => {
59+
const id = patch.getId();
60+
if (!id) return;
61+
// TODO: also filter in SESSION.GLOBAL patches.
62+
if (id.sid === core.sid && id.time > meta.time) {
63+
patches.push({blob: patch.toBinary()});
64+
time = id.time;
65+
}
66+
});
67+
if (!patches.length) {
68+
await this.putMeta(collection, id, {time, ts: Date.now()});
69+
return true;
5870
}
71+
const remoteId = [...collection, id].join('/');
72+
await this.core.remote.update(remoteId, patches);
73+
await this.putMeta(collection, id, {time, ts: Date.now()});
5974
await this.markTidy(collection, id);
6075
return true;
6176
});
@@ -66,51 +81,6 @@ export class ServerCrudLocalHistorySync {
6681
});
6782
}
6883

69-
private async pushNewBlock(collection: string[], id: string): Promise<void> {
70-
const core = this.core;
71-
const blob = await core.read(collection, id);
72-
const {history} = core.decoder.decode(blob, {format: 'seq.cbor', history: true});
73-
const patches: RemoteBlockPatch[] = [];
74-
let time = 0;
75-
history!.patches.forEach(({v: patch}) => {
76-
const id = patch.getId();
77-
if (!id) return;
78-
if (id.sid === core.sid) {
79-
patches.push({blob: patch.toBinary()});
80-
time = id.time;
81-
}
82-
});
83-
if (!patches.length) return;
84-
const remoteId = [...collection, id].join('/');
85-
await this.core.remote.create(remoteId, patches);
86-
await this.putMeta(collection, id, {time, ts: Date.now()});
87-
}
88-
89-
/**
90-
* @todo Unify this with `pushNewBlock`.
91-
*/
92-
private async pushExistingBlock(collection: string[], id: string, syncedTime: number): Promise<void> {
93-
const core = this.core;
94-
const blob = await core.read(collection, id);
95-
const {history} = core.decoder.decode(blob, {format: 'seq.cbor', history: true});
96-
const patches: RemoteBlockPatch[] = [];
97-
let time = 0;
98-
// TODO: perf: use a binary search to find the first patch to sync.
99-
history!.patches.forEach(({v: patch}) => {
100-
const id = patch.getId();
101-
if (!id) return;
102-
// TODO: also filter in SESSION.GLOBAL patches.
103-
if (id.sid === core.sid && id.time > syncedTime) {
104-
patches.push({blob: patch.toBinary()});
105-
time = id.time;
106-
}
107-
});
108-
if (!patches.length) return;
109-
const remoteId = [...collection, id].join('/');
110-
await this.core.remote.update(remoteId, patches);
111-
await this.putMeta(collection, id, {time, ts: Date.now()});
112-
}
113-
11484
public async lock<T>(
11585
{
11686
collection,

src/json-crdt-repo/local/server-crud/__tests__/ServerCrudLocalHistory.spec.ts

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -157,6 +157,10 @@ describe('.create()', () => {
157157
await tick(15);
158158
throw new Error('Remote call failed');
159159
};
160+
remote.remote.update = async (...args) => {
161+
await tick(15);
162+
throw new Error('Remote call failed');
163+
};
160164
return setup({remote});
161165
};
162166

@@ -218,6 +222,10 @@ describe('.create()', () => {
218222
await tick(500);
219223
throw new Error('something went wrong');
220224
};
225+
remote.remote.update = async (...args) => {
226+
await tick(500);
227+
throw new Error('something went wrong');
228+
};
221229
return setup({
222230
remote,
223231
local: {
@@ -286,6 +294,10 @@ describe('.create()', () => {
286294
await tick(200);
287295
return create(...args);
288296
};
297+
remote.remote.update = async (...args) => {
298+
await tick(200);
299+
return create(...args);
300+
};
289301
return setup({
290302
remote,
291303
local: {

src/json-crdt-repo/remote/DemoServerRemoteHistory.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -78,6 +78,7 @@ export class DemoServerRemoteHistory
7878
patches: Pick<DemoServerPatch, 'blob'>[],
7979
): Promise<{patches: Omit<DemoServerPatch, 'blob'>[]}> {
8080
const res = await this.client.call('block.upd', {
81+
create: true,
8182
id,
8283
patches: patches.map((patch) => ({
8384
blob: patch.blob,

0 commit comments

Comments
 (0)