@automerge/automerge-repo 2.0.0-collectionsync-alpha.1 → 2.0.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +8 -8
- package/dist/AutomergeUrl.d.ts +17 -5
- package/dist/AutomergeUrl.d.ts.map +1 -1
- package/dist/AutomergeUrl.js +71 -24
- package/dist/DocHandle.d.ts +33 -41
- package/dist/DocHandle.d.ts.map +1 -1
- package/dist/DocHandle.js +105 -66
- package/dist/FindProgress.d.ts +30 -0
- package/dist/FindProgress.d.ts.map +1 -0
- package/dist/FindProgress.js +1 -0
- package/dist/RemoteHeadsSubscriptions.d.ts +4 -5
- package/dist/RemoteHeadsSubscriptions.d.ts.map +1 -1
- package/dist/RemoteHeadsSubscriptions.js +4 -1
- package/dist/Repo.d.ts +24 -5
- package/dist/Repo.d.ts.map +1 -1
- package/dist/Repo.js +355 -169
- package/dist/helpers/abortable.d.ts +36 -0
- package/dist/helpers/abortable.d.ts.map +1 -0
- package/dist/helpers/abortable.js +47 -0
- package/dist/helpers/arraysAreEqual.d.ts.map +1 -1
- package/dist/helpers/bufferFromHex.d.ts +3 -0
- package/dist/helpers/bufferFromHex.d.ts.map +1 -0
- package/dist/helpers/bufferFromHex.js +13 -0
- package/dist/helpers/debounce.d.ts.map +1 -1
- package/dist/helpers/eventPromise.d.ts.map +1 -1
- package/dist/helpers/headsAreSame.d.ts +2 -2
- package/dist/helpers/headsAreSame.d.ts.map +1 -1
- package/dist/helpers/mergeArrays.d.ts +1 -1
- package/dist/helpers/mergeArrays.d.ts.map +1 -1
- package/dist/helpers/pause.d.ts.map +1 -1
- package/dist/helpers/tests/network-adapter-tests.d.ts.map +1 -1
- package/dist/helpers/tests/network-adapter-tests.js +13 -13
- package/dist/helpers/tests/storage-adapter-tests.d.ts.map +1 -1
- package/dist/helpers/tests/storage-adapter-tests.js +6 -9
- package/dist/helpers/throttle.d.ts.map +1 -1
- package/dist/helpers/withTimeout.d.ts.map +1 -1
- package/dist/index.d.ts +35 -7
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +37 -6
- package/dist/network/NetworkSubsystem.d.ts +0 -1
- package/dist/network/NetworkSubsystem.d.ts.map +1 -1
- package/dist/network/NetworkSubsystem.js +0 -3
- package/dist/network/messages.d.ts +1 -7
- package/dist/network/messages.d.ts.map +1 -1
- package/dist/network/messages.js +1 -2
- package/dist/storage/StorageAdapter.d.ts +0 -9
- package/dist/storage/StorageAdapter.d.ts.map +1 -1
- package/dist/storage/StorageAdapter.js +0 -33
- package/dist/storage/StorageSubsystem.d.ts +6 -2
- package/dist/storage/StorageSubsystem.d.ts.map +1 -1
- package/dist/storage/StorageSubsystem.js +131 -37
- package/dist/storage/keyHash.d.ts +1 -1
- package/dist/storage/keyHash.d.ts.map +1 -1
- package/dist/synchronizer/CollectionSynchronizer.d.ts +3 -4
- package/dist/synchronizer/CollectionSynchronizer.d.ts.map +1 -1
- package/dist/synchronizer/CollectionSynchronizer.js +32 -26
- package/dist/synchronizer/DocSynchronizer.d.ts +8 -8
- package/dist/synchronizer/DocSynchronizer.d.ts.map +1 -1
- package/dist/synchronizer/DocSynchronizer.js +205 -79
- package/dist/types.d.ts +4 -1
- package/dist/types.d.ts.map +1 -1
- package/fuzz/fuzz.ts +3 -3
- package/package.json +4 -5
- package/src/AutomergeUrl.ts +101 -26
- package/src/DocHandle.ts +158 -77
- package/src/FindProgress.ts +48 -0
- package/src/RemoteHeadsSubscriptions.ts +11 -9
- package/src/Repo.ts +465 -180
- package/src/helpers/abortable.ts +62 -0
- package/src/helpers/bufferFromHex.ts +14 -0
- package/src/helpers/headsAreSame.ts +2 -2
- package/src/helpers/tests/network-adapter-tests.ts +14 -13
- package/src/helpers/tests/storage-adapter-tests.ts +13 -24
- package/src/index.ts +57 -38
- package/src/network/NetworkSubsystem.ts +0 -4
- package/src/network/messages.ts +2 -11
- package/src/storage/StorageAdapter.ts +0 -42
- package/src/storage/StorageSubsystem.ts +155 -45
- package/src/storage/keyHash.ts +1 -1
- package/src/synchronizer/CollectionSynchronizer.ts +42 -29
- package/src/synchronizer/DocSynchronizer.ts +263 -89
- package/src/types.ts +4 -1
- package/test/AutomergeUrl.test.ts +130 -0
- package/test/CollectionSynchronizer.test.ts +6 -8
- package/test/DocHandle.test.ts +161 -77
- package/test/DocSynchronizer.test.ts +11 -9
- package/test/RemoteHeadsSubscriptions.test.ts +1 -1
- package/test/Repo.test.ts +406 -341
- package/test/StorageSubsystem.test.ts +95 -20
- package/test/remoteHeads.test.ts +28 -13
- package/dist/CollectionHandle.d.ts +0 -14
- package/dist/CollectionHandle.d.ts.map +0 -1
- package/dist/CollectionHandle.js +0 -37
- package/dist/DocUrl.d.ts +0 -47
- package/dist/DocUrl.d.ts.map +0 -1
- package/dist/DocUrl.js +0 -72
- package/dist/EphemeralData.d.ts +0 -20
- package/dist/EphemeralData.d.ts.map +0 -1
- package/dist/EphemeralData.js +0 -1
- package/dist/ferigan.d.ts +0 -51
- package/dist/ferigan.d.ts.map +0 -1
- package/dist/ferigan.js +0 -98
- package/dist/src/DocHandle.d.ts +0 -182
- package/dist/src/DocHandle.d.ts.map +0 -1
- package/dist/src/DocHandle.js +0 -405
- package/dist/src/DocUrl.d.ts +0 -49
- package/dist/src/DocUrl.d.ts.map +0 -1
- package/dist/src/DocUrl.js +0 -72
- package/dist/src/EphemeralData.d.ts +0 -19
- package/dist/src/EphemeralData.d.ts.map +0 -1
- package/dist/src/EphemeralData.js +0 -1
- package/dist/src/Repo.d.ts +0 -74
- package/dist/src/Repo.d.ts.map +0 -1
- package/dist/src/Repo.js +0 -208
- package/dist/src/helpers/arraysAreEqual.d.ts +0 -2
- package/dist/src/helpers/arraysAreEqual.d.ts.map +0 -1
- package/dist/src/helpers/arraysAreEqual.js +0 -2
- package/dist/src/helpers/cbor.d.ts +0 -4
- package/dist/src/helpers/cbor.d.ts.map +0 -1
- package/dist/src/helpers/cbor.js +0 -8
- package/dist/src/helpers/eventPromise.d.ts +0 -11
- package/dist/src/helpers/eventPromise.d.ts.map +0 -1
- package/dist/src/helpers/eventPromise.js +0 -7
- package/dist/src/helpers/headsAreSame.d.ts +0 -2
- package/dist/src/helpers/headsAreSame.d.ts.map +0 -1
- package/dist/src/helpers/headsAreSame.js +0 -4
- package/dist/src/helpers/mergeArrays.d.ts +0 -2
- package/dist/src/helpers/mergeArrays.d.ts.map +0 -1
- package/dist/src/helpers/mergeArrays.js +0 -15
- package/dist/src/helpers/pause.d.ts +0 -6
- package/dist/src/helpers/pause.d.ts.map +0 -1
- package/dist/src/helpers/pause.js +0 -10
- package/dist/src/helpers/tests/network-adapter-tests.d.ts +0 -21
- package/dist/src/helpers/tests/network-adapter-tests.d.ts.map +0 -1
- package/dist/src/helpers/tests/network-adapter-tests.js +0 -122
- package/dist/src/helpers/withTimeout.d.ts +0 -12
- package/dist/src/helpers/withTimeout.d.ts.map +0 -1
- package/dist/src/helpers/withTimeout.js +0 -24
- package/dist/src/index.d.ts +0 -53
- package/dist/src/index.d.ts.map +0 -1
- package/dist/src/index.js +0 -40
- package/dist/src/network/NetworkAdapter.d.ts +0 -26
- package/dist/src/network/NetworkAdapter.d.ts.map +0 -1
- package/dist/src/network/NetworkAdapter.js +0 -4
- package/dist/src/network/NetworkSubsystem.d.ts +0 -23
- package/dist/src/network/NetworkSubsystem.d.ts.map +0 -1
- package/dist/src/network/NetworkSubsystem.js +0 -120
- package/dist/src/network/messages.d.ts +0 -85
- package/dist/src/network/messages.d.ts.map +0 -1
- package/dist/src/network/messages.js +0 -23
- package/dist/src/storage/StorageAdapter.d.ts +0 -14
- package/dist/src/storage/StorageAdapter.d.ts.map +0 -1
- package/dist/src/storage/StorageAdapter.js +0 -1
- package/dist/src/storage/StorageSubsystem.d.ts +0 -12
- package/dist/src/storage/StorageSubsystem.d.ts.map +0 -1
- package/dist/src/storage/StorageSubsystem.js +0 -145
- package/dist/src/synchronizer/CollectionSynchronizer.d.ts +0 -25
- package/dist/src/synchronizer/CollectionSynchronizer.d.ts.map +0 -1
- package/dist/src/synchronizer/CollectionSynchronizer.js +0 -106
- package/dist/src/synchronizer/DocSynchronizer.d.ts +0 -29
- package/dist/src/synchronizer/DocSynchronizer.d.ts.map +0 -1
- package/dist/src/synchronizer/DocSynchronizer.js +0 -263
- package/dist/src/synchronizer/Synchronizer.d.ts +0 -9
- package/dist/src/synchronizer/Synchronizer.d.ts.map +0 -1
- package/dist/src/synchronizer/Synchronizer.js +0 -2
- package/dist/src/types.d.ts +0 -16
- package/dist/src/types.d.ts.map +0 -1
- package/dist/src/types.js +0 -1
- package/dist/test/CollectionSynchronizer.test.d.ts +0 -2
- package/dist/test/CollectionSynchronizer.test.d.ts.map +0 -1
- package/dist/test/CollectionSynchronizer.test.js +0 -57
- package/dist/test/DocHandle.test.d.ts +0 -2
- package/dist/test/DocHandle.test.d.ts.map +0 -1
- package/dist/test/DocHandle.test.js +0 -238
- package/dist/test/DocSynchronizer.test.d.ts +0 -2
- package/dist/test/DocSynchronizer.test.d.ts.map +0 -1
- package/dist/test/DocSynchronizer.test.js +0 -111
- package/dist/test/Network.test.d.ts +0 -2
- package/dist/test/Network.test.d.ts.map +0 -1
- package/dist/test/Network.test.js +0 -11
- package/dist/test/Repo.test.d.ts +0 -2
- package/dist/test/Repo.test.d.ts.map +0 -1
- package/dist/test/Repo.test.js +0 -568
- package/dist/test/StorageSubsystem.test.d.ts +0 -2
- package/dist/test/StorageSubsystem.test.d.ts.map +0 -1
- package/dist/test/StorageSubsystem.test.js +0 -56
- package/dist/test/helpers/DummyNetworkAdapter.d.ts +0 -9
- package/dist/test/helpers/DummyNetworkAdapter.d.ts.map +0 -1
- package/dist/test/helpers/DummyNetworkAdapter.js +0 -15
- package/dist/test/helpers/DummyStorageAdapter.d.ts +0 -16
- package/dist/test/helpers/DummyStorageAdapter.d.ts.map +0 -1
- package/dist/test/helpers/DummyStorageAdapter.js +0 -33
- package/dist/test/helpers/generate-large-object.d.ts +0 -5
- package/dist/test/helpers/generate-large-object.d.ts.map +0 -1
- package/dist/test/helpers/generate-large-object.js +0 -9
- package/dist/test/helpers/getRandomItem.d.ts +0 -2
- package/dist/test/helpers/getRandomItem.d.ts.map +0 -1
- package/dist/test/helpers/getRandomItem.js +0 -4
- package/dist/test/types.d.ts +0 -4
- package/dist/test/types.d.ts.map +0 -1
- package/dist/test/types.js +0 -1
- package/src/CollectionHandle.ts +0 -54
- package/src/ferigan.ts +0 -184
package/test/DocHandle.test.ts
CHANGED
|
@@ -1,13 +1,16 @@
|
|
|
1
|
-
import
|
|
1
|
+
import { next as A } from "@automerge/automerge"
|
|
2
2
|
import assert from "assert"
|
|
3
3
|
import { decode } from "cbor-x"
|
|
4
|
-
import { describe, it, vi } from "vitest"
|
|
5
|
-
import {
|
|
4
|
+
import { describe, expect, it, vi } from "vitest"
|
|
5
|
+
import {
|
|
6
|
+
encodeHeads,
|
|
7
|
+
generateAutomergeUrl,
|
|
8
|
+
parseAutomergeUrl,
|
|
9
|
+
} from "../src/AutomergeUrl.js"
|
|
6
10
|
import { eventPromise } from "../src/helpers/eventPromise.js"
|
|
7
11
|
import { pause } from "../src/helpers/pause.js"
|
|
8
12
|
import { DocHandle, DocHandleChangePayload } from "../src/index.js"
|
|
9
13
|
import { TestDoc } from "./types.js"
|
|
10
|
-
import { UNLOADED } from "../src/DocHandle.js"
|
|
11
14
|
|
|
12
15
|
describe("DocHandle", () => {
|
|
13
16
|
const TEST_ID = parseAutomergeUrl(generateAutomergeUrl()).documentId
|
|
@@ -35,7 +38,7 @@ describe("DocHandle", () => {
|
|
|
35
38
|
handle.update(doc => docFromMockStorage(doc))
|
|
36
39
|
|
|
37
40
|
assert.equal(handle.isReady(), true)
|
|
38
|
-
const doc =
|
|
41
|
+
const doc = handle.doc()
|
|
39
42
|
assert.equal(doc?.foo, "bar")
|
|
40
43
|
})
|
|
41
44
|
|
|
@@ -47,13 +50,13 @@ describe("DocHandle", () => {
|
|
|
47
50
|
handle.update(doc => docFromMockStorage(doc))
|
|
48
51
|
|
|
49
52
|
assert.equal(handle.isReady(), true)
|
|
50
|
-
const doc =
|
|
51
|
-
assert.deepEqual(doc, handle.
|
|
53
|
+
const doc = handle.doc()
|
|
54
|
+
assert.deepEqual(doc, handle.doc())
|
|
52
55
|
})
|
|
53
56
|
|
|
54
|
-
it("should
|
|
57
|
+
it("should throw an exception if we access the doc before ready", async () => {
|
|
55
58
|
const handle = new DocHandle<TestDoc>(TEST_ID)
|
|
56
|
-
assert.
|
|
59
|
+
assert.throws(() => handle.doc())
|
|
57
60
|
})
|
|
58
61
|
|
|
59
62
|
it("should not return a doc until ready", async () => {
|
|
@@ -63,7 +66,7 @@ describe("DocHandle", () => {
|
|
|
63
66
|
// simulate loading from storage
|
|
64
67
|
handle.update(doc => docFromMockStorage(doc))
|
|
65
68
|
|
|
66
|
-
const doc =
|
|
69
|
+
const doc = handle.doc()
|
|
67
70
|
|
|
68
71
|
assert.equal(handle.isReady(), true)
|
|
69
72
|
assert.equal(doc?.foo, "bar")
|
|
@@ -83,15 +86,15 @@ describe("DocHandle", () => {
|
|
|
83
86
|
handle.change(d => (d.foo = "bar"))
|
|
84
87
|
assert.equal(handle.isReady(), true)
|
|
85
88
|
|
|
86
|
-
const heads = A.getHeads(handle.
|
|
89
|
+
const heads = encodeHeads(A.getHeads(handle.doc()))
|
|
87
90
|
assert.notDeepEqual(handle.heads(), [])
|
|
88
91
|
assert.deepEqual(heads, handle.heads())
|
|
89
92
|
})
|
|
90
93
|
|
|
91
|
-
it("should
|
|
94
|
+
it("should throw an if the heads aren't loaded", async () => {
|
|
92
95
|
const handle = new DocHandle<TestDoc>(TEST_ID)
|
|
93
96
|
assert.equal(handle.isReady(), false)
|
|
94
|
-
|
|
97
|
+
expect(() => handle.heads()).toThrow("DocHandle is not ready")
|
|
95
98
|
})
|
|
96
99
|
|
|
97
100
|
it("should return the history when requested", async () => {
|
|
@@ -113,8 +116,45 @@ describe("DocHandle", () => {
|
|
|
113
116
|
assert.equal(handle.isReady(), true)
|
|
114
117
|
|
|
115
118
|
const history = handle.history()
|
|
116
|
-
const
|
|
117
|
-
assert.deepEqual(
|
|
119
|
+
const viewHandle = handle.view(history[1])
|
|
120
|
+
assert.deepEqual(await viewHandle.doc(), { foo: "one" })
|
|
121
|
+
})
|
|
122
|
+
|
|
123
|
+
it("should support fixed heads from construction", async () => {
|
|
124
|
+
const handle = setup()
|
|
125
|
+
handle.change(d => (d.foo = "zero"))
|
|
126
|
+
handle.change(d => (d.foo = "one"))
|
|
127
|
+
|
|
128
|
+
const history = handle.history()
|
|
129
|
+
const viewHandle = new DocHandle<TestDoc>(TEST_ID, { heads: history[0] })
|
|
130
|
+
viewHandle.update(() => A.clone(handle.doc()!))
|
|
131
|
+
viewHandle.doneLoading()
|
|
132
|
+
|
|
133
|
+
assert.deepEqual(await viewHandle.doc(), { foo: "zero" })
|
|
134
|
+
})
|
|
135
|
+
|
|
136
|
+
it("should prevent changes on fixed-heads handles", async () => {
|
|
137
|
+
const handle = setup()
|
|
138
|
+
handle.change(d => (d.foo = "zero"))
|
|
139
|
+
const viewHandle = handle.view(handle.heads()!)
|
|
140
|
+
|
|
141
|
+
assert.throws(() => viewHandle.change(d => (d.foo = "one")))
|
|
142
|
+
assert.throws(() =>
|
|
143
|
+
viewHandle.changeAt(handle.heads()!, d => (d.foo = "one"))
|
|
144
|
+
)
|
|
145
|
+
assert.throws(() => viewHandle.merge(handle))
|
|
146
|
+
})
|
|
147
|
+
|
|
148
|
+
it("should return fixed heads from heads()", async () => {
|
|
149
|
+
const handle = setup()
|
|
150
|
+
handle.change(d => (d.foo = "zero"))
|
|
151
|
+
const originalHeads = handle.heads()!
|
|
152
|
+
|
|
153
|
+
handle.change(d => (d.foo = "one"))
|
|
154
|
+
const viewHandle = handle.view(originalHeads)
|
|
155
|
+
|
|
156
|
+
assert.deepEqual(viewHandle.heads(), originalHeads)
|
|
157
|
+
assert.notDeepEqual(viewHandle.heads(), handle.heads())
|
|
118
158
|
})
|
|
119
159
|
|
|
120
160
|
it("should return diffs", async () => {
|
|
@@ -154,6 +194,31 @@ describe("DocHandle", () => {
|
|
|
154
194
|
])
|
|
155
195
|
})
|
|
156
196
|
|
|
197
|
+
it("should support diffing against another handle", async () => {
|
|
198
|
+
const handle = setup()
|
|
199
|
+
handle.change(d => (d.foo = "zero"))
|
|
200
|
+
const viewHandle = handle.view(handle.heads()!)
|
|
201
|
+
|
|
202
|
+
handle.change(d => (d.foo = "one"))
|
|
203
|
+
|
|
204
|
+
const patches = viewHandle.diff(handle)
|
|
205
|
+
assert.deepEqual(patches, [
|
|
206
|
+
{ action: "put", path: ["foo"], value: "" },
|
|
207
|
+
{ action: "splice", path: ["foo", 0], value: "one" },
|
|
208
|
+
])
|
|
209
|
+
})
|
|
210
|
+
|
|
211
|
+
// TODO: alexg -- should i remove this test? should this fail or no?
|
|
212
|
+
it.skip("should fail diffing against unrelated handles", async () => {
|
|
213
|
+
const handle1 = setup()
|
|
214
|
+
const handle2 = setup()
|
|
215
|
+
|
|
216
|
+
handle1.change(d => (d.foo = "zero"))
|
|
217
|
+
handle2.change(d => (d.foo = "one"))
|
|
218
|
+
|
|
219
|
+
assert.throws(() => handle1.diff(handle2))
|
|
220
|
+
})
|
|
221
|
+
|
|
157
222
|
it("should allow direct access to decoded changes", async () => {
|
|
158
223
|
const handle = setup()
|
|
159
224
|
const time = Date.now()
|
|
@@ -194,8 +259,6 @@ describe("DocHandle", () => {
|
|
|
194
259
|
const handle = new DocHandle<TestDoc>(TEST_ID)
|
|
195
260
|
assert.equal(handle.isReady(), false)
|
|
196
261
|
|
|
197
|
-
handle.doc()
|
|
198
|
-
|
|
199
262
|
assert(vi.getTimerCount() > timerCount)
|
|
200
263
|
|
|
201
264
|
// simulate loading from storage
|
|
@@ -220,7 +283,7 @@ describe("DocHandle", () => {
|
|
|
220
283
|
assert.equal(handle.isReady(), true)
|
|
221
284
|
handle.change(d => (d.foo = "pizza"))
|
|
222
285
|
|
|
223
|
-
const doc =
|
|
286
|
+
const doc = handle.doc()
|
|
224
287
|
assert.equal(doc?.foo, "pizza")
|
|
225
288
|
})
|
|
226
289
|
|
|
@@ -230,7 +293,9 @@ describe("DocHandle", () => {
|
|
|
230
293
|
// we don't have it in storage, so we request it from the network
|
|
231
294
|
handle.request()
|
|
232
295
|
|
|
233
|
-
|
|
296
|
+
await expect(() => {
|
|
297
|
+
handle.doc()
|
|
298
|
+
}).toThrowError("DocHandle is not ready")
|
|
234
299
|
assert.equal(handle.isReady(), false)
|
|
235
300
|
assert.throws(() => handle.change(_ => {}))
|
|
236
301
|
})
|
|
@@ -246,7 +311,7 @@ describe("DocHandle", () => {
|
|
|
246
311
|
return A.change(doc, d => (d.foo = "bar"))
|
|
247
312
|
})
|
|
248
313
|
|
|
249
|
-
const doc =
|
|
314
|
+
const doc = handle.doc()
|
|
250
315
|
assert.equal(handle.isReady(), true)
|
|
251
316
|
assert.equal(doc?.foo, "bar")
|
|
252
317
|
})
|
|
@@ -262,7 +327,7 @@ describe("DocHandle", () => {
|
|
|
262
327
|
doc.foo = "bar"
|
|
263
328
|
})
|
|
264
329
|
|
|
265
|
-
const doc =
|
|
330
|
+
const doc = handle.doc()
|
|
266
331
|
assert.equal(doc?.foo, "bar")
|
|
267
332
|
|
|
268
333
|
const changePayload = await p
|
|
@@ -287,7 +352,7 @@ describe("DocHandle", () => {
|
|
|
287
352
|
|
|
288
353
|
const p = new Promise<void>(resolve =>
|
|
289
354
|
handle.once("change", ({ handle, doc }) => {
|
|
290
|
-
assert.equal(handle.
|
|
355
|
+
assert.equal(handle.doc()?.foo, doc.foo)
|
|
291
356
|
|
|
292
357
|
resolve()
|
|
293
358
|
})
|
|
@@ -324,7 +389,7 @@ describe("DocHandle", () => {
|
|
|
324
389
|
doc.foo = "baz"
|
|
325
390
|
})
|
|
326
391
|
|
|
327
|
-
const doc =
|
|
392
|
+
const doc = handle.doc()
|
|
328
393
|
assert.equal(doc?.foo, "baz")
|
|
329
394
|
|
|
330
395
|
return p
|
|
@@ -339,7 +404,7 @@ describe("DocHandle", () => {
|
|
|
339
404
|
})
|
|
340
405
|
|
|
341
406
|
await p
|
|
342
|
-
const doc =
|
|
407
|
+
const doc = handle.doc()
|
|
343
408
|
assert.equal(doc?.foo, "bar")
|
|
344
409
|
})
|
|
345
410
|
|
|
@@ -359,11 +424,7 @@ describe("DocHandle", () => {
|
|
|
359
424
|
// set docHandle time out after 5 ms
|
|
360
425
|
const handle = new DocHandle<TestDoc>(TEST_ID, { timeoutDelay: 5 })
|
|
361
426
|
|
|
362
|
-
|
|
363
|
-
|
|
364
|
-
assert.equal(doc, undefined)
|
|
365
|
-
|
|
366
|
-
assert.equal(handle.state, "unavailable")
|
|
427
|
+
expect(() => handle.doc()).toThrowError("DocHandle is not ready")
|
|
367
428
|
})
|
|
368
429
|
|
|
369
430
|
it("should not time out if the document is loaded in time", async () => {
|
|
@@ -374,11 +435,11 @@ describe("DocHandle", () => {
|
|
|
374
435
|
handle.update(doc => docFromMockStorage(doc))
|
|
375
436
|
|
|
376
437
|
// now it should not time out
|
|
377
|
-
const doc =
|
|
438
|
+
const doc = handle.doc()
|
|
378
439
|
assert.equal(doc?.foo, "bar")
|
|
379
440
|
})
|
|
380
441
|
|
|
381
|
-
it("should
|
|
442
|
+
it("should throw an exception if loading from the network times out", async () => {
|
|
382
443
|
// set docHandle time out after 5 ms
|
|
383
444
|
const handle = new DocHandle<TestDoc>(TEST_ID, { timeoutDelay: 5 })
|
|
384
445
|
|
|
@@ -388,8 +449,7 @@ describe("DocHandle", () => {
|
|
|
388
449
|
// there's no update
|
|
389
450
|
await pause(10)
|
|
390
451
|
|
|
391
|
-
|
|
392
|
-
assert.equal(doc, undefined)
|
|
452
|
+
expect(() => handle.doc()).toThrowError("DocHandle is not ready")
|
|
393
453
|
})
|
|
394
454
|
|
|
395
455
|
it("should not time out if the document is updated in time", async () => {
|
|
@@ -407,7 +467,7 @@ describe("DocHandle", () => {
|
|
|
407
467
|
// now it should not time out
|
|
408
468
|
await pause(5)
|
|
409
469
|
|
|
410
|
-
const doc =
|
|
470
|
+
const doc = handle.doc()
|
|
411
471
|
assert.equal(doc?.foo, "bar")
|
|
412
472
|
})
|
|
413
473
|
|
|
@@ -423,49 +483,6 @@ describe("DocHandle", () => {
|
|
|
423
483
|
assert.equal(handle.isDeleted(), true)
|
|
424
484
|
})
|
|
425
485
|
|
|
426
|
-
it("should clear document reference when unloaded", async () => {
|
|
427
|
-
const handle = setup()
|
|
428
|
-
|
|
429
|
-
handle.change(doc => {
|
|
430
|
-
doc.foo = "bar"
|
|
431
|
-
})
|
|
432
|
-
const doc = await handle.doc()
|
|
433
|
-
assert.equal(doc?.foo, "bar")
|
|
434
|
-
|
|
435
|
-
handle.unload()
|
|
436
|
-
assert.equal(handle.isUnloaded(), true)
|
|
437
|
-
|
|
438
|
-
const clearedDoc = await handle.doc([UNLOADED])
|
|
439
|
-
assert.notEqual(clearedDoc?.foo, "bar")
|
|
440
|
-
})
|
|
441
|
-
|
|
442
|
-
it("should allow reloading after unloading", async () => {
|
|
443
|
-
const handle = setup()
|
|
444
|
-
|
|
445
|
-
handle.change(doc => {
|
|
446
|
-
doc.foo = "bar"
|
|
447
|
-
})
|
|
448
|
-
const doc = await handle.doc()
|
|
449
|
-
assert.equal(doc?.foo, "bar")
|
|
450
|
-
|
|
451
|
-
handle.unload()
|
|
452
|
-
|
|
453
|
-
// reload to transition from unloaded to loading
|
|
454
|
-
handle.reload()
|
|
455
|
-
|
|
456
|
-
// simulate requesting from the network
|
|
457
|
-
handle.request()
|
|
458
|
-
|
|
459
|
-
// simulate updating from the network
|
|
460
|
-
handle.update(doc => {
|
|
461
|
-
return A.change(doc, d => (d.foo = "bar"))
|
|
462
|
-
})
|
|
463
|
-
|
|
464
|
-
const reloadedDoc = await handle.doc()
|
|
465
|
-
assert.equal(handle.isReady(), true)
|
|
466
|
-
assert.equal(reloadedDoc?.foo, "bar")
|
|
467
|
-
})
|
|
468
|
-
|
|
469
486
|
it("should allow changing at old heads", async () => {
|
|
470
487
|
const handle = setup()
|
|
471
488
|
|
|
@@ -503,4 +520,71 @@ describe("DocHandle", () => {
|
|
|
503
520
|
assert.deepStrictEqual(decode(data), message)
|
|
504
521
|
})
|
|
505
522
|
})
|
|
523
|
+
|
|
524
|
+
it("should cache view handles based on heads", async () => {
|
|
525
|
+
// Create and setup a document with some data
|
|
526
|
+
const handle = setup()
|
|
527
|
+
handle.change(doc => {
|
|
528
|
+
doc.foo = "Hello"
|
|
529
|
+
})
|
|
530
|
+
const heads1 = handle.heads()
|
|
531
|
+
|
|
532
|
+
// Make another change to get a different set of heads
|
|
533
|
+
handle.change(doc => {
|
|
534
|
+
doc.foo = "Hello, World!"
|
|
535
|
+
})
|
|
536
|
+
|
|
537
|
+
// Create a view at the first set of heads
|
|
538
|
+
const view1 = handle.view(heads1)
|
|
539
|
+
|
|
540
|
+
// Request the same view again
|
|
541
|
+
const view2 = handle.view(heads1)
|
|
542
|
+
|
|
543
|
+
// Verify we got the same handle instance back (cached version)
|
|
544
|
+
expect(view1).toBe(view2)
|
|
545
|
+
|
|
546
|
+
// Verify the contents are correct
|
|
547
|
+
expect(view1.doc().foo).toBe("Hello")
|
|
548
|
+
|
|
549
|
+
// Test with a different set of heads
|
|
550
|
+
const view3 = handle.view(handle.heads())
|
|
551
|
+
expect(view3).not.toBe(view1)
|
|
552
|
+
expect(view3.doc().foo).toBe("Hello, World!")
|
|
553
|
+
})
|
|
554
|
+
|
|
555
|
+
it("should improve performance when requesting the same view multiple times", () => {
|
|
556
|
+
// Create and setup a document with some data
|
|
557
|
+
const handle = setup()
|
|
558
|
+
handle.change(doc => {
|
|
559
|
+
doc.foo = "Hello"
|
|
560
|
+
})
|
|
561
|
+
const heads = handle.heads()
|
|
562
|
+
|
|
563
|
+
// First, measure time without cache (first access)
|
|
564
|
+
const startTimeNoCached = performance.now()
|
|
565
|
+
const firstView = handle.view(heads)
|
|
566
|
+
const endTimeNoCached = performance.now()
|
|
567
|
+
|
|
568
|
+
// Now measure with cache (subsequent accesses)
|
|
569
|
+
const startTimeCached = performance.now()
|
|
570
|
+
for (let i = 0; i < 100; i++) {
|
|
571
|
+
handle.view(heads)
|
|
572
|
+
}
|
|
573
|
+
const endTimeCached = performance.now()
|
|
574
|
+
|
|
575
|
+
// Assert that all views are the same instance
|
|
576
|
+
for (let i = 0; i < 10; i++) {
|
|
577
|
+
expect(handle.view(heads)).toBe(firstView)
|
|
578
|
+
}
|
|
579
|
+
|
|
580
|
+
// Calculate average times
|
|
581
|
+
const timeForFirstAccess = endTimeNoCached - startTimeNoCached
|
|
582
|
+
const timeForCachedAccesses = (endTimeCached - startTimeCached) / 100
|
|
583
|
+
|
|
584
|
+
console.log(`Time for first view (no cache): ${timeForFirstAccess}ms`)
|
|
585
|
+
console.log(`Average time per cached view: ${timeForCachedAccesses}ms`)
|
|
586
|
+
|
|
587
|
+
// Cached access should be significantly faster
|
|
588
|
+
expect(timeForCachedAccesses).toBeLessThan(timeForFirstAccess / 10)
|
|
589
|
+
})
|
|
506
590
|
})
|
|
@@ -1,7 +1,11 @@
|
|
|
1
1
|
import assert from "assert"
|
|
2
2
|
import { describe, it } from "vitest"
|
|
3
3
|
import { next as Automerge } from "@automerge/automerge"
|
|
4
|
-
import {
|
|
4
|
+
import {
|
|
5
|
+
encodeHeads,
|
|
6
|
+
generateAutomergeUrl,
|
|
7
|
+
parseAutomergeUrl,
|
|
8
|
+
} from "../src/AutomergeUrl.js"
|
|
5
9
|
import { DocHandle } from "../src/DocHandle.js"
|
|
6
10
|
import { eventPromise } from "../src/helpers/eventPromise.js"
|
|
7
11
|
import {
|
|
@@ -16,10 +20,9 @@ const alice = "alice" as PeerId
|
|
|
16
20
|
const bob = "bob" as PeerId
|
|
17
21
|
const charlie = "charlie" as PeerId
|
|
18
22
|
|
|
19
|
-
describe
|
|
23
|
+
describe("DocSynchronizer", () => {
|
|
20
24
|
let handle: DocHandle<TestDoc>
|
|
21
25
|
let docSynchronizer: DocSynchronizer
|
|
22
|
-
let beelay: Automerge.beelay.Beelay
|
|
23
26
|
|
|
24
27
|
const setup = () => {
|
|
25
28
|
const docId = parseAutomergeUrl(generateAutomergeUrl()).documentId
|
|
@@ -27,7 +30,6 @@ describe.skip("DocSynchronizer", () => {
|
|
|
27
30
|
handle.doneLoading()
|
|
28
31
|
|
|
29
32
|
docSynchronizer = new DocSynchronizer({
|
|
30
|
-
beelay,
|
|
31
33
|
handle: handle as DocHandle<unknown>,
|
|
32
34
|
})
|
|
33
35
|
|
|
@@ -69,11 +71,14 @@ describe.skip("DocSynchronizer", () => {
|
|
|
69
71
|
|
|
70
72
|
assert.equal(message1.peerId, "alice")
|
|
71
73
|
assert.equal(message1.documentId, handle.documentId)
|
|
72
|
-
assert.
|
|
74
|
+
assert.deepStrictEqual(message1.syncState.lastSentHeads, [])
|
|
73
75
|
|
|
74
76
|
assert.equal(message2.peerId, "alice")
|
|
75
77
|
assert.equal(message2.documentId, handle.documentId)
|
|
76
|
-
assert.
|
|
78
|
+
assert.deepStrictEqual(
|
|
79
|
+
encodeHeads(message2.syncState.lastSentHeads),
|
|
80
|
+
handle.heads()
|
|
81
|
+
)
|
|
77
82
|
})
|
|
78
83
|
|
|
79
84
|
it("still syncs with a peer after it disconnects and reconnects", async () => {
|
|
@@ -108,7 +113,6 @@ describe.skip("DocSynchronizer", () => {
|
|
|
108
113
|
|
|
109
114
|
const handle = new DocHandle<TestDoc>(docId, { isNew: false })
|
|
110
115
|
docSynchronizer = new DocSynchronizer({
|
|
111
|
-
beelay,
|
|
112
116
|
handle: handle as DocHandle<unknown>,
|
|
113
117
|
})
|
|
114
118
|
docSynchronizer.beginSync([alice])
|
|
@@ -123,7 +127,6 @@ describe.skip("DocSynchronizer", () => {
|
|
|
123
127
|
|
|
124
128
|
const bobHandle = new DocHandle<TestDoc>(docId, { isNew: false })
|
|
125
129
|
const bobDocSynchronizer = new DocSynchronizer({
|
|
126
|
-
beelay,
|
|
127
130
|
handle: bobHandle as DocHandle<unknown>,
|
|
128
131
|
})
|
|
129
132
|
bobDocSynchronizer.beginSync([alice])
|
|
@@ -133,7 +136,6 @@ describe.skip("DocSynchronizer", () => {
|
|
|
133
136
|
const aliceHandle = new DocHandle<TestDoc>(docId, { isNew: false })
|
|
134
137
|
const aliceDocSynchronizer = new DocSynchronizer({
|
|
135
138
|
handle: aliceHandle as DocHandle<unknown>,
|
|
136
|
-
beelay,
|
|
137
139
|
})
|
|
138
140
|
aliceHandle.request()
|
|
139
141
|
|
|
@@ -10,7 +10,7 @@ import {
|
|
|
10
10
|
} from "../src/network/messages.js"
|
|
11
11
|
import { collectMessages } from "./helpers/collectMessages.js"
|
|
12
12
|
|
|
13
|
-
describe
|
|
13
|
+
describe("RepoHeadsSubscriptions", () => {
|
|
14
14
|
const storageA = "remote-a" as StorageId
|
|
15
15
|
const storageB = "remote-b" as StorageId
|
|
16
16
|
const storageC = "remote-c" as StorageId
|