Skip to content

Commit 541a45a

Browse files
committed
core: properly handle syncing into empty target
1 parent cadb67f commit 541a45a

File tree

2 files changed

+53
-14
lines changed

2 files changed

+53
-14
lines changed

packages/core/src/sync/sync.ts

Lines changed: 35 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -55,8 +55,24 @@ class Driver {
5555
private async enter(targetLevel: number, sourceNode: Node) {
5656
if (sourceNode.level > targetLevel) {
5757
const children = await this.client.getChildren(sourceNode.level, sourceNode.key)
58-
for (const sourceChild of children) {
59-
await this.enter(targetLevel, sourceChild)
58+
if (targetLevel === 0 && sourceNode.level === 1) {
59+
const ids: Uint8Array[] = []
60+
61+
for (const { level, key, id } of children) {
62+
if (key === null) {
63+
continue
64+
}
65+
66+
assert(level === 0, "unexpected child level")
67+
assert(id !== undefined, "expected leaf nodes to have a value")
68+
ids.push(id)
69+
}
70+
71+
await this.fetch(ids)
72+
} else {
73+
for (const sourceChild of children) {
74+
await this.enter(targetLevel, sourceChild)
75+
}
6076
}
6177
} else {
6278
await this.scan(sourceNode)
@@ -76,30 +92,35 @@ class Driver {
7692
}
7793
} else if (sourceNode.level === 1) {
7894
const ids: Uint8Array[] = []
79-
for (const { key, id } of children) {
95+
for (const { level, key, id } of children) {
8096
if (key === null) {
8197
continue
8298
}
8399

84-
assert(id, "expected leaf nodes to have a value")
100+
assert(level === 0, "unexpected child level")
101+
assert(id !== undefined, "expected leaf nodes to have a value")
85102
const existingRecord = await this.txn.getMessage(id)
86103
if (existingRecord === null) {
87104
ids.push(id)
88105
}
89106
}
90107

91-
const decoder = new TextDecoder()
108+
await this.fetch(ids)
109+
}
110+
}
92111

93-
const messages = await this.client.getMessages(ids)
112+
private async fetch(ids: Uint8Array[]) {
113+
const decoder = new TextDecoder()
94114

95-
for (const [i, data] of messages.entries()) {
96-
const id = ids[i]
97-
assert(equalArrays(sha256(data), id), "message response did not match the request hash")
98-
const message = JSON.parse(decoder.decode(data))
99-
assert(messageType.is(message), "invalid message")
100-
await this.handleMessage(id, data, message)
101-
await this.txn.insertMessage(id, message)
102-
}
115+
const messages = await this.client.getMessages(ids)
116+
117+
for (const [i, data] of messages.entries()) {
118+
const id = ids[i]
119+
assert(equalArrays(sha256(data), id), "message response did not match the request hash")
120+
const message = JSON.parse(decoder.decode(data))
121+
assert(messageType.is(message), "invalid message")
122+
await this.handleMessage(id, data, message)
123+
await this.txn.insertMessage(id, message)
103124
}
104125
}
105126
}

packages/core/test/sync.test.ts

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -94,6 +94,24 @@ test("sync two tiny MSTs", async (t) => {
9494
t.deepEqual(delta, [b, c])
9595
})
9696

97+
test("sync from empty source", async (t) => {
98+
const a = await signer.sign("log", { message: "a" })
99+
const b = await signer.sign("log", { message: "b" })
100+
const c = await signer.sign("log", { message: "c" })
101+
102+
const delta = await testSync([], [a, b, c])
103+
t.deepEqual(delta, [])
104+
})
105+
106+
test("sync into empty target", async (t) => {
107+
const a = await signer.sign("log", { message: "a" })
108+
const b = await signer.sign("log", { message: "b" })
109+
const c = await signer.sign("log", { message: "c" })
110+
111+
const delta = await testSync([a, b, c], [])
112+
t.deepEqual(delta, [a, b, c])
113+
})
114+
97115
// test("sync two big MSTs", async (t) => {
98116
// const count = 1000
99117
// const index = Math.floor(Math.random() * count)

0 commit comments

Comments
 (0)