@dxos/echo-pipeline 0.8.1 → 0.8.2-main.10c050d
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/dist/lib/browser/{chunk-32WDI3LB.mjs → chunk-3XSXS5EX.mjs} +15 -21
- package/dist/lib/browser/chunk-3XSXS5EX.mjs.map +7 -0
- package/dist/lib/browser/chunk-CGS2ULMK.mjs +11 -0
- package/dist/lib/browser/chunk-CGS2ULMK.mjs.map +7 -0
- package/dist/lib/browser/chunk-TQJTKNMS.mjs +126 -0
- package/dist/lib/browser/chunk-TQJTKNMS.mjs.map +7 -0
- package/dist/lib/browser/filter/index.mjs +11 -0
- package/dist/lib/browser/filter/index.mjs.map +7 -0
- package/dist/lib/browser/index.mjs +1380 -516
- package/dist/lib/browser/index.mjs.map +4 -4
- package/dist/lib/browser/meta.json +1 -1
- package/dist/lib/browser/testing/index.mjs +202 -22
- package/dist/lib/browser/testing/index.mjs.map +4 -4
- package/dist/lib/node/chunk-HOPOFWAL.cjs +147 -0
- package/dist/lib/node/chunk-HOPOFWAL.cjs.map +7 -0
- package/dist/lib/node/chunk-Q7SFCCGT.cjs +33 -0
- package/dist/lib/node/chunk-Q7SFCCGT.cjs.map +7 -0
- package/dist/lib/node/{chunk-TC2PRBEU.cjs → chunk-SG2PL5RH.cjs} +18 -24
- package/dist/lib/node/chunk-SG2PL5RH.cjs.map +7 -0
- package/dist/lib/node/filter/index.cjs +32 -0
- package/dist/lib/node/filter/index.cjs.map +7 -0
- package/dist/lib/node/index.cjs +1381 -525
- package/dist/lib/node/index.cjs.map +4 -4
- package/dist/lib/node/meta.json +1 -1
- package/dist/lib/node/testing/index.cjs +207 -31
- package/dist/lib/node/testing/index.cjs.map +4 -4
- package/dist/lib/node-esm/{chunk-UKOLB3LW.mjs → chunk-3BZP75TJ.mjs} +15 -21
- package/dist/lib/node-esm/chunk-3BZP75TJ.mjs.map +7 -0
- package/dist/lib/node-esm/chunk-HSLMI22Q.mjs +11 -0
- package/dist/lib/node-esm/chunk-HSLMI22Q.mjs.map +7 -0
- package/dist/lib/node-esm/chunk-RVK35BS7.mjs +126 -0
- package/dist/lib/node-esm/chunk-RVK35BS7.mjs.map +7 -0
- package/dist/lib/node-esm/filter/index.mjs +11 -0
- package/dist/lib/node-esm/filter/index.mjs.map +7 -0
- package/dist/lib/node-esm/index.mjs +1380 -516
- package/dist/lib/node-esm/index.mjs.map +4 -4
- package/dist/lib/node-esm/meta.json +1 -1
- package/dist/lib/node-esm/testing/index.mjs +202 -22
- package/dist/lib/node-esm/testing/index.mjs.map +4 -4
- package/dist/types/src/automerge/automerge-host.d.ts +6 -4
- package/dist/types/src/automerge/automerge-host.d.ts.map +1 -1
- package/dist/types/src/automerge/collection-synchronizer.d.ts +1 -1
- package/dist/types/src/automerge/collection-synchronizer.d.ts.map +1 -1
- package/dist/types/src/automerge/echo-data-monitor.d.ts +6 -6
- package/dist/types/src/automerge/echo-data-monitor.d.ts.map +1 -1
- package/dist/types/src/automerge/echo-network-adapter.d.ts +4 -1
- package/dist/types/src/automerge/echo-network-adapter.d.ts.map +1 -1
- package/dist/types/src/automerge/heads-store.d.ts +2 -2
- package/dist/types/src/automerge/heads-store.d.ts.map +1 -1
- package/dist/types/src/automerge/leveldb-storage-adapter.d.ts +1 -1
- package/dist/types/src/automerge/leveldb-storage-adapter.d.ts.map +1 -1
- package/dist/types/src/automerge/mesh-echo-replicator-connection.d.ts.map +1 -1
- package/dist/types/src/automerge/mesh-echo-replicator.d.ts.map +1 -1
- package/dist/types/src/automerge/network-protocol.d.ts +1 -1
- package/dist/types/src/automerge/network-protocol.d.ts.map +1 -1
- package/dist/types/src/automerge/space-collection.d.ts +1 -1
- package/dist/types/src/automerge/space-collection.d.ts.map +1 -1
- package/dist/types/src/common/feeds.d.ts.map +1 -1
- package/dist/types/src/common/space-id.d.ts.map +1 -1
- package/dist/types/src/db-host/automerge-metrics.d.ts +1 -1
- package/dist/types/src/db-host/automerge-metrics.d.ts.map +1 -1
- package/dist/types/src/db-host/data-service.d.ts.map +1 -1
- package/dist/types/src/db-host/database-root.d.ts +7 -7
- package/dist/types/src/db-host/database-root.d.ts.map +1 -1
- package/dist/types/src/db-host/documents-iterator.d.ts +1 -1
- package/dist/types/src/db-host/documents-iterator.d.ts.map +1 -1
- package/dist/types/src/db-host/documents-synchronizer.d.ts +4 -4
- package/dist/types/src/db-host/documents-synchronizer.d.ts.map +1 -1
- package/dist/types/src/db-host/echo-host.d.ts +13 -2
- package/dist/types/src/db-host/echo-host.d.ts.map +1 -1
- package/dist/types/src/db-host/index.d.ts +0 -1
- package/dist/types/src/db-host/index.d.ts.map +1 -1
- package/dist/types/src/db-host/query-service.d.ts +2 -0
- package/dist/types/src/db-host/query-service.d.ts.map +1 -1
- package/dist/types/src/db-host/space-state-manager.d.ts +4 -3
- package/dist/types/src/db-host/space-state-manager.d.ts.map +1 -1
- package/dist/types/src/edge/echo-edge-replicator.d.ts.map +1 -1
- package/dist/types/src/edge/inflight-request-limiter.d.ts.map +1 -1
- package/dist/types/src/filter/filter-match.d.ts +13 -0
- package/dist/types/src/filter/filter-match.d.ts.map +1 -0
- package/dist/types/src/filter/filter-match.test.d.ts +2 -0
- package/dist/types/src/filter/filter-match.test.d.ts.map +1 -0
- package/dist/types/src/filter/index.d.ts +2 -0
- package/dist/types/src/filter/index.d.ts.map +1 -0
- package/dist/types/src/index.d.ts +1 -0
- package/dist/types/src/index.d.ts.map +1 -1
- package/dist/types/src/metadata/metadata-store.d.ts.map +1 -1
- package/dist/types/src/pipeline/message-selector.d.ts.map +1 -1
- package/dist/types/src/pipeline/pipeline.d.ts.map +1 -1
- package/dist/types/src/pipeline/timeframe-clock.d.ts.map +1 -1
- package/dist/types/src/query/errors.d.ts +23 -0
- package/dist/types/src/query/errors.d.ts.map +1 -0
- package/dist/types/src/query/index.d.ts +5 -0
- package/dist/types/src/query/index.d.ts.map +1 -0
- package/dist/types/src/query/plan.d.ts +132 -0
- package/dist/types/src/query/plan.d.ts.map +1 -0
- package/dist/types/src/query/query-executor.d.ts +83 -0
- package/dist/types/src/query/query-executor.d.ts.map +1 -0
- package/dist/types/src/query/query-planner.d.ts +33 -0
- package/dist/types/src/query/query-planner.d.ts.map +1 -0
- package/dist/types/src/query/query-planner.test.d.ts +2 -0
- package/dist/types/src/query/query-planner.test.d.ts.map +1 -0
- package/dist/types/src/space/admission-discovery-extension.d.ts.map +1 -1
- package/dist/types/src/space/control-pipeline.d.ts.map +1 -1
- package/dist/types/src/space/space-manager.d.ts.map +1 -1
- package/dist/types/src/space/space-protocol.d.ts.map +1 -1
- package/dist/types/src/space/space.d.ts.map +1 -1
- package/dist/types/src/testing/change-metadata.d.ts.map +1 -1
- package/dist/types/src/testing/index.d.ts +2 -0
- package/dist/types/src/testing/index.d.ts.map +1 -1
- package/dist/types/src/testing/test-agent-builder.d.ts.map +1 -1
- package/dist/types/src/testing/test-data.d.ts +18 -0
- package/dist/types/src/testing/test-data.d.ts.map +1 -0
- package/dist/types/src/testing/test-network-adapter.d.ts +3 -2
- package/dist/types/src/testing/test-network-adapter.d.ts.map +1 -1
- package/dist/types/src/testing/test-schema.d.ts +39 -0
- package/dist/types/src/testing/test-schema.d.ts.map +1 -0
- package/dist/types/src/util.d.ts +2 -2
- package/dist/types/src/util.d.ts.map +1 -1
- package/dist/types/tsconfig.tsbuildinfo +1 -1
- package/package.json +43 -34
- package/src/automerge/automerge-host.test.ts +7 -7
- package/src/automerge/automerge-host.ts +58 -60
- package/src/automerge/automerge-repo.test.ts +65 -65
- package/src/automerge/collection-synchronizer.test.ts +1 -1
- package/src/automerge/collection-synchronizer.ts +11 -10
- package/src/automerge/echo-data-monitor.ts +21 -20
- package/src/automerge/echo-network-adapter.test.ts +1 -1
- package/src/automerge/echo-network-adapter.ts +25 -18
- package/src/automerge/heads-store.ts +4 -3
- package/src/automerge/leveldb-storage-adapter.ts +1 -1
- package/src/automerge/mesh-echo-replicator-connection.ts +6 -5
- package/src/automerge/mesh-echo-replicator.ts +2 -2
- package/src/automerge/network-protocol.ts +2 -1
- package/src/automerge/space-collection.ts +2 -1
- package/src/db-host/automerge-metrics.ts +2 -1
- package/src/db-host/data-service.ts +4 -3
- package/src/db-host/database-root.ts +17 -22
- package/src/db-host/documents-iterator.ts +9 -8
- package/src/db-host/documents-synchronizer.test.ts +2 -2
- package/src/db-host/documents-synchronizer.ts +20 -18
- package/src/db-host/echo-host.ts +44 -15
- package/src/db-host/index.ts +0 -1
- package/src/db-host/query-service.ts +43 -37
- package/src/db-host/space-state-manager.ts +14 -4
- package/src/edge/echo-edge-replicator.test.ts +3 -3
- package/src/edge/echo-edge-replicator.ts +9 -8
- package/src/edge/inflight-request-limiter.ts +4 -4
- package/src/filter/filter-match.test.ts +101 -0
- package/src/filter/filter-match.ts +174 -0
- package/src/filter/index.ts +5 -0
- package/src/index.ts +1 -0
- package/src/metadata/metadata-store.ts +13 -13
- package/src/pipeline/pipeline-stress.test.ts +9 -9
- package/src/pipeline/pipeline.ts +13 -13
- package/src/pipeline/timeframe-clock.ts +5 -5
- package/src/query/errors.ts +7 -0
- package/src/query/index.ts +8 -0
- package/src/query/plan.ts +179 -0
- package/src/query/query-executor.ts +648 -0
- package/src/query/query-planner.test.ts +613 -0
- package/src/query/query-planner.ts +470 -0
- package/src/space/admission-discovery-extension.ts +2 -2
- package/src/space/control-pipeline.ts +8 -8
- package/src/space/space-manager.ts +5 -4
- package/src/space/space-protocol.browser.test.ts +1 -0
- package/src/space/space-protocol.test.ts +1 -0
- package/src/space/space-protocol.ts +4 -4
- package/src/space/space.ts +5 -5
- package/src/testing/index.ts +2 -0
- package/src/testing/test-agent-builder.ts +6 -6
- package/src/testing/test-data.ts +127 -0
- package/src/testing/test-network-adapter.ts +15 -12
- package/src/testing/test-replicator.ts +2 -2
- package/src/testing/test-schema.ts +53 -0
- package/src/util.ts +7 -3
- package/dist/lib/browser/chunk-32WDI3LB.mjs.map +0 -7
- package/dist/lib/node/chunk-TC2PRBEU.cjs.map +0 -7
- package/dist/lib/node-esm/chunk-UKOLB3LW.mjs.map +0 -7
- package/dist/types/src/db-host/query-state.d.ts +0 -41
- package/dist/types/src/db-host/query-state.d.ts.map +0 -1
- package/src/db-host/query-state.ts +0 -217
|
@@ -2,9 +2,6 @@
|
|
|
2
2
|
// Copyright 2024 DXOS.org
|
|
3
3
|
//
|
|
4
4
|
|
|
5
|
-
import { onTestFinished, describe, expect, test } from 'vitest';
|
|
6
|
-
|
|
7
|
-
import { asyncTimeout, sleep } from '@dxos/async';
|
|
8
5
|
import {
|
|
9
6
|
change,
|
|
10
7
|
clone,
|
|
@@ -16,7 +13,7 @@ import {
|
|
|
16
13
|
next as A,
|
|
17
14
|
save,
|
|
18
15
|
saveSince,
|
|
19
|
-
} from '@
|
|
16
|
+
} from '@automerge/automerge';
|
|
20
17
|
import {
|
|
21
18
|
type AutomergeUrl,
|
|
22
19
|
type DocHandle,
|
|
@@ -28,7 +25,10 @@ import {
|
|
|
28
25
|
type PeerId,
|
|
29
26
|
Repo,
|
|
30
27
|
type SharePolicy,
|
|
31
|
-
} from '@
|
|
28
|
+
} from '@automerge/automerge-repo';
|
|
29
|
+
import { onTestFinished, describe, expect, test } from 'vitest';
|
|
30
|
+
|
|
31
|
+
import { asyncTimeout, sleep } from '@dxos/async';
|
|
32
32
|
import { randomBytes } from '@dxos/crypto';
|
|
33
33
|
import { PublicKey } from '@dxos/keys';
|
|
34
34
|
import { createTestLevel } from '@dxos/kv-store/testing';
|
|
@@ -36,6 +36,7 @@ import { TestBuilder as TeleportBuilder, TestPeer as TeleportPeer } from '@dxos/
|
|
|
36
36
|
import { openAndClose } from '@dxos/test-utils';
|
|
37
37
|
import { isNonNullable, range } from '@dxos/util';
|
|
38
38
|
|
|
39
|
+
import { FIND_PARAMS } from './automerge-host';
|
|
39
40
|
import { EchoNetworkAdapter } from './echo-network-adapter';
|
|
40
41
|
import { LevelDBStorageAdapter } from './leveldb-storage-adapter';
|
|
41
42
|
import { MeshEchoReplicator } from './mesh-echo-replicator';
|
|
@@ -51,7 +52,7 @@ describe('AutomergeRepo', () => {
|
|
|
51
52
|
let valueDuringChange: string | undefined;
|
|
52
53
|
|
|
53
54
|
handle.addListener('change', (doc) => {
|
|
54
|
-
valueDuringChange = handle.
|
|
55
|
+
valueDuringChange = handle.doc()!.field;
|
|
55
56
|
});
|
|
56
57
|
|
|
57
58
|
handle.change((doc: any) => {
|
|
@@ -115,7 +116,7 @@ describe('AutomergeRepo', () => {
|
|
|
115
116
|
const [host] = repos;
|
|
116
117
|
await connectAdapters(adapters);
|
|
117
118
|
const url = 'automerge:3JN8F3Z4dUWEEKKFN7WE9gEGvVUT';
|
|
118
|
-
const handle = host.find(url as AutomergeUrl);
|
|
119
|
+
const handle = await host.find(url as AutomergeUrl, FIND_PARAMS);
|
|
119
120
|
await handle.whenReady(['requesting']);
|
|
120
121
|
});
|
|
121
122
|
|
|
@@ -132,7 +133,7 @@ describe('AutomergeRepo', () => {
|
|
|
132
133
|
|
|
133
134
|
{
|
|
134
135
|
const repo = new Repo({ network: [], storage });
|
|
135
|
-
const handle = repo.find(url as AutomergeUrl);
|
|
136
|
+
const handle = await repo.find(url as AutomergeUrl);
|
|
136
137
|
|
|
137
138
|
let requestingState = false;
|
|
138
139
|
queueMicrotask(async () => {
|
|
@@ -157,8 +158,7 @@ describe('AutomergeRepo', () => {
|
|
|
157
158
|
doc.text = text;
|
|
158
159
|
});
|
|
159
160
|
|
|
160
|
-
|
|
161
|
-
expect((await asyncTimeout(docOnClient.doc(), 1000))!.text).to.equal(text);
|
|
161
|
+
expect((await asyncTimeout(client.find<any>(handle.url), 1000))!.doc().text).to.equal(text);
|
|
162
162
|
});
|
|
163
163
|
|
|
164
164
|
test('share policy gets enabled afterwards', async () => {
|
|
@@ -177,16 +177,13 @@ describe('AutomergeRepo', () => {
|
|
|
177
177
|
});
|
|
178
178
|
|
|
179
179
|
{
|
|
180
|
-
|
|
181
|
-
await asyncTimeout(docOnClient.whenReady(['unavailable']), 1000);
|
|
180
|
+
await client.find(handle.url, { allowableStates: ['unavailable'] });
|
|
182
181
|
}
|
|
183
182
|
|
|
184
183
|
sharePolicy = true;
|
|
185
184
|
|
|
186
185
|
{
|
|
187
|
-
|
|
188
|
-
// TODO(mykola): We expect the document to be available here, but it's not.
|
|
189
|
-
await asyncTimeout(docOnClient.whenReady(['unavailable']), 1000);
|
|
186
|
+
await client.find(handle.url, { allowableStates: ['unavailable'] });
|
|
190
187
|
}
|
|
191
188
|
});
|
|
192
189
|
|
|
@@ -206,26 +203,26 @@ describe('AutomergeRepo', () => {
|
|
|
206
203
|
|
|
207
204
|
const firstHandle = host.create();
|
|
208
205
|
firstHandle.change((doc: any) => (doc.text = 'Hello world'));
|
|
209
|
-
await host.find(firstHandle.url)
|
|
206
|
+
await host.find(firstHandle.url);
|
|
210
207
|
allowedDocs.push(firstHandle.documentId);
|
|
211
208
|
|
|
212
209
|
await connectAdapters(adapters);
|
|
213
210
|
|
|
214
211
|
{
|
|
215
|
-
const firstDocOnClient = client.find<any>(firstHandle.url);
|
|
212
|
+
const firstDocOnClient = await client.find<any>(firstHandle.url);
|
|
216
213
|
await asyncTimeout(firstDocOnClient.whenReady(), 1000);
|
|
217
|
-
expect(firstDocOnClient.
|
|
214
|
+
expect(firstDocOnClient.doc()!.text).to.equal('Hello world');
|
|
218
215
|
}
|
|
219
216
|
|
|
220
217
|
const secondHandle = host.create();
|
|
221
218
|
secondHandle.change((doc: any) => (doc.text = 'Hello world'));
|
|
222
|
-
await host.find(secondHandle.url)
|
|
219
|
+
await host.find(secondHandle.url);
|
|
223
220
|
allowedDocs.push(secondHandle.documentId);
|
|
224
221
|
|
|
225
222
|
{
|
|
226
|
-
const secondDocOnClient = client.find<any>(secondHandle.url);
|
|
223
|
+
const secondDocOnClient = await client.find<any>(secondHandle.url);
|
|
227
224
|
await asyncTimeout(secondDocOnClient.whenReady(), 1000);
|
|
228
|
-
expect(secondDocOnClient.
|
|
225
|
+
expect(secondDocOnClient.doc()!.text).to.equal('Hello world');
|
|
229
226
|
}
|
|
230
227
|
});
|
|
231
228
|
|
|
@@ -239,14 +236,15 @@ describe('AutomergeRepo', () => {
|
|
|
239
236
|
await connectAdapters(adapters);
|
|
240
237
|
|
|
241
238
|
const handle = host.create();
|
|
242
|
-
const docOnClient = client.find<any>(handle.url);
|
|
239
|
+
const docOnClient = await client.find<any>(handle.url, FIND_PARAMS);
|
|
243
240
|
{
|
|
244
241
|
const sanityText = 'Hello world';
|
|
245
242
|
handle.change((doc: any) => {
|
|
246
243
|
doc.sanityText = sanityText;
|
|
247
244
|
});
|
|
245
|
+
await asyncTimeout(docOnClient.whenReady(), 1000);
|
|
248
246
|
|
|
249
|
-
expect(
|
|
247
|
+
expect(docOnClient.doc().sanityText).to.equal(sanityText);
|
|
250
248
|
}
|
|
251
249
|
|
|
252
250
|
// Disrupt connection.
|
|
@@ -259,7 +257,8 @@ describe('AutomergeRepo', () => {
|
|
|
259
257
|
});
|
|
260
258
|
|
|
261
259
|
await sleep(100);
|
|
262
|
-
|
|
260
|
+
await asyncTimeout(docOnClient.whenReady(), 1000);
|
|
261
|
+
expect(docOnClient.doc().offlineText).to.be.undefined;
|
|
263
262
|
}
|
|
264
263
|
|
|
265
264
|
// Re-establish connection.
|
|
@@ -272,8 +271,9 @@ describe('AutomergeRepo', () => {
|
|
|
272
271
|
doc.onlineText = onlineText;
|
|
273
272
|
});
|
|
274
273
|
await sleep(100);
|
|
275
|
-
|
|
276
|
-
expect(
|
|
274
|
+
await asyncTimeout(docOnClient.whenReady(), 1000);
|
|
275
|
+
expect(docOnClient.doc().onlineText).to.equal(onlineText);
|
|
276
|
+
expect(docOnClient.doc().offlineText).to.equal(offlineText);
|
|
277
277
|
}
|
|
278
278
|
});
|
|
279
279
|
|
|
@@ -297,9 +297,9 @@ describe('AutomergeRepo', () => {
|
|
|
297
297
|
|
|
298
298
|
// If we wait here for replication to finish naturally, the test will pass.
|
|
299
299
|
|
|
300
|
-
const docD = repoD.find(docA.url);
|
|
300
|
+
const docD = await repoD.find(docA.url);
|
|
301
301
|
|
|
302
|
-
await docD.whenReady();
|
|
302
|
+
await asyncTimeout(docD.whenReady(), 1000);
|
|
303
303
|
});
|
|
304
304
|
|
|
305
305
|
test('replication though a 3 peer chain', async () => {
|
|
@@ -319,9 +319,9 @@ describe('AutomergeRepo', () => {
|
|
|
319
319
|
doc.text = 'Hello world';
|
|
320
320
|
});
|
|
321
321
|
|
|
322
|
-
const _ = repoB.find(docA.url);
|
|
323
|
-
const docC = repoC.find(docA.url);
|
|
324
|
-
await docC.whenReady();
|
|
322
|
+
const _ = repoB.find(docA.url, FIND_PARAMS);
|
|
323
|
+
const docC = await repoC.find(docA.url, FIND_PARAMS);
|
|
324
|
+
await asyncTimeout(docC.whenReady(), 1000);
|
|
325
325
|
});
|
|
326
326
|
|
|
327
327
|
test('replicate document after request', async () => {
|
|
@@ -338,7 +338,7 @@ describe('AutomergeRepo', () => {
|
|
|
338
338
|
doc.text = 'Hello world';
|
|
339
339
|
});
|
|
340
340
|
|
|
341
|
-
const docB = client.find(docA.url);
|
|
341
|
+
const docB = await client.find(docA.url, { allowableStates: ['unavailable'] });
|
|
342
342
|
|
|
343
343
|
// Request document from repoB.
|
|
344
344
|
await asyncTimeout(docB.whenReady([unavailable]), 1_000);
|
|
@@ -373,11 +373,12 @@ describe('AutomergeRepo', () => {
|
|
|
373
373
|
await connectAdapters(adapters);
|
|
374
374
|
|
|
375
375
|
// Load doc on peer1
|
|
376
|
-
const hostHandle = peer1.find<any>(url as AutomergeUrl);
|
|
376
|
+
const hostHandle = await peer1.find<any>(url as AutomergeUrl);
|
|
377
377
|
|
|
378
378
|
// Doc should be pushed to peer2
|
|
379
|
-
await
|
|
380
|
-
await expect.poll(() =>
|
|
379
|
+
await hostHandle.whenReady();
|
|
380
|
+
await expect.poll(() => hostHandle.doc()!.text).not.toBeUndefined();
|
|
381
|
+
await expect.poll(() => peer2.handles[hostHandle.documentId].doc()).toEqual(hostHandle.doc());
|
|
381
382
|
});
|
|
382
383
|
|
|
383
384
|
test('client cold-starts and syncs doc from a Repo', async () => {
|
|
@@ -390,8 +391,8 @@ describe('AutomergeRepo', () => {
|
|
|
390
391
|
};
|
|
391
392
|
|
|
392
393
|
// Sync handshake.
|
|
393
|
-
let syncedHeads = getHeads(serverHandle.
|
|
394
|
-
receiveByClient(save(serverHandle.
|
|
394
|
+
let syncedHeads = getHeads(serverHandle.doc()!);
|
|
395
|
+
receiveByClient(save(serverHandle.doc()!));
|
|
395
396
|
|
|
396
397
|
serverHandle.on('change', ({ doc }) => {
|
|
397
398
|
// Note: This is mock of a sync protocol between client and server.
|
|
@@ -420,7 +421,7 @@ describe('AutomergeRepo', () => {
|
|
|
420
421
|
test('client creates doc and syncs with a Repo', async () => {
|
|
421
422
|
const repo = new Repo({ network: [] });
|
|
422
423
|
const receiveByServer = async (blob: Uint8Array, docId: DocumentId) => {
|
|
423
|
-
const serverHandle = repo.find(docId);
|
|
424
|
+
const serverHandle = await repo.find(docId, FIND_PARAMS);
|
|
424
425
|
serverHandle.update((doc) => {
|
|
425
426
|
return A.loadIncremental(doc, blob);
|
|
426
427
|
});
|
|
@@ -445,8 +446,8 @@ describe('AutomergeRepo', () => {
|
|
|
445
446
|
});
|
|
446
447
|
await sendDoc(clientDoc);
|
|
447
448
|
|
|
448
|
-
await repo.find(documentId)
|
|
449
|
-
expect(
|
|
449
|
+
const serverHandle = await repo.find<any>(documentId);
|
|
450
|
+
expect(serverHandle.doc()!.field).to.deep.equal(value);
|
|
450
451
|
}
|
|
451
452
|
});
|
|
452
453
|
|
|
@@ -456,7 +457,7 @@ describe('AutomergeRepo', () => {
|
|
|
456
457
|
await connectAdapters(adapters);
|
|
457
458
|
|
|
458
459
|
const handleA = repoA.create<any>();
|
|
459
|
-
const handleB = repoB.find<any>(handleA.url);
|
|
460
|
+
const handleB = await repoB.find<any>(handleA.url);
|
|
460
461
|
|
|
461
462
|
const text = 'Hello world';
|
|
462
463
|
handleA.update((doc: any) => {
|
|
@@ -465,10 +466,11 @@ describe('AutomergeRepo', () => {
|
|
|
465
466
|
});
|
|
466
467
|
});
|
|
467
468
|
|
|
468
|
-
expect(handleA.
|
|
469
|
+
expect(handleA.doc()!.text).to.equal(text);
|
|
469
470
|
|
|
471
|
+
await sleep(100);
|
|
470
472
|
await asyncTimeout(handleB.whenReady(), 1000);
|
|
471
|
-
expect(handleB.
|
|
473
|
+
expect(handleB.doc()!.text).to.equal(text);
|
|
472
474
|
});
|
|
473
475
|
});
|
|
474
476
|
|
|
@@ -493,11 +495,10 @@ describe('AutomergeRepo', () => {
|
|
|
493
495
|
await expect
|
|
494
496
|
.poll(
|
|
495
497
|
async () => {
|
|
496
|
-
const docOnPeer2 = peer2.repo.find<any>(handle.url);
|
|
497
|
-
|
|
498
|
-
return doc!.text;
|
|
498
|
+
const docOnPeer2 = await peer2.repo.find<any>(handle.url);
|
|
499
|
+
return docOnPeer2.doc()!.text;
|
|
499
500
|
},
|
|
500
|
-
{ timeout:
|
|
501
|
+
{ timeout: 5_000 },
|
|
501
502
|
)
|
|
502
503
|
.toEqual(text);
|
|
503
504
|
}
|
|
@@ -510,17 +511,18 @@ describe('AutomergeRepo', () => {
|
|
|
510
511
|
handle.change((doc: any) => {
|
|
511
512
|
doc.offlineText = offlineText;
|
|
512
513
|
});
|
|
513
|
-
const docOnPeer2 = peer2.repo.find<any>(handle.url);
|
|
514
|
+
const docOnPeer2 = await peer2.repo.find<any>(handle.url);
|
|
514
515
|
await sleep(100);
|
|
515
|
-
|
|
516
|
+
await asyncTimeout(docOnPeer2.whenReady(), 1000);
|
|
517
|
+
expect(docOnPeer2.doc()!.offlineText).to.be.undefined;
|
|
516
518
|
}
|
|
517
519
|
|
|
518
520
|
{
|
|
519
521
|
// Wait for offline changes to be synced after reconnect.
|
|
520
|
-
const docOnPeer2 = peer2.repo.find<any>(handle.url);
|
|
522
|
+
const docOnPeer2 = await peer2.repo.find<any>(handle.url);
|
|
521
523
|
await docChangeAfterAction(docOnPeer2, () => connectPeers(spaceKey, teleportBuilder, peer1, peer2));
|
|
522
524
|
await docOnPeer2.whenReady();
|
|
523
|
-
expect(
|
|
525
|
+
expect(docOnPeer2.doc()!.offlineText).to.eq(offlineText);
|
|
524
526
|
|
|
525
527
|
// Test connection.
|
|
526
528
|
const onlineText = 'This has been written after the connection was re-established';
|
|
@@ -530,7 +532,7 @@ describe('AutomergeRepo', () => {
|
|
|
530
532
|
});
|
|
531
533
|
});
|
|
532
534
|
await docOnPeer2.whenReady();
|
|
533
|
-
expect(
|
|
535
|
+
expect(docOnPeer2.doc()!.onlineText).to.eq(onlineText);
|
|
534
536
|
}
|
|
535
537
|
});
|
|
536
538
|
|
|
@@ -556,11 +558,11 @@ describe('AutomergeRepo', () => {
|
|
|
556
558
|
});
|
|
557
559
|
await connectPeers(spaceKey, teleportBuilder, peerWithDocs.peer, peer2);
|
|
558
560
|
|
|
559
|
-
const shouldNotFindDoc = peer2.repo.find(docNotInRemoteCollection.url);
|
|
560
|
-
const shouldFindDoc = peer2.repo.find(docInRemoteCollection.url);
|
|
561
|
+
const shouldNotFindDoc = await peer2.repo.find(docNotInRemoteCollection.url, FIND_PARAMS);
|
|
562
|
+
const shouldFindDoc = await peer2.repo.find(docInRemoteCollection.url, FIND_PARAMS);
|
|
561
563
|
await shouldFindDoc.whenReady();
|
|
562
|
-
expect(shouldFindDoc.
|
|
563
|
-
await shouldNotFindDoc.whenReady(['unavailable']);
|
|
564
|
+
expect(shouldFindDoc.doc()).to.deep.eq(docInRemoteCollection.doc());
|
|
565
|
+
await asyncTimeout(shouldNotFindDoc.whenReady(['unavailable']), 1000);
|
|
564
566
|
});
|
|
565
567
|
|
|
566
568
|
/**
|
|
@@ -590,12 +592,12 @@ describe('AutomergeRepo', () => {
|
|
|
590
592
|
await connectPeers(spaceKey, teleportBuilder, peerWithDocs.peer, peer2);
|
|
591
593
|
await connectPeers(anotherSpaceKey, teleportBuilder, peer2, peerFromAnotherSpace);
|
|
592
594
|
|
|
593
|
-
const loadedDocument = peer2.repo.find(document.url);
|
|
594
|
-
await loadedDocument.whenReady();
|
|
595
|
+
const loadedDocument = await peer2.repo.find(document.url, FIND_PARAMS);
|
|
596
|
+
await asyncTimeout(loadedDocument.whenReady(), 1000);
|
|
595
597
|
|
|
596
598
|
await sleep(200);
|
|
597
|
-
const doc = peerFromAnotherSpace.repo.find(document.url);
|
|
598
|
-
await doc.whenReady(['unavailable']);
|
|
599
|
+
const doc = await peerFromAnotherSpace.repo.find(document.url, { allowableStates: ['unavailable'] });
|
|
600
|
+
await asyncTimeout(doc.whenReady(['unavailable']), 1000);
|
|
599
601
|
});
|
|
600
602
|
|
|
601
603
|
test('collection-sync with chain of peers', async () => {
|
|
@@ -624,12 +626,12 @@ describe('AutomergeRepo', () => {
|
|
|
624
626
|
await connectPeers(spaceKey, teleportBuilder, peerWithDocs.peer, peer2);
|
|
625
627
|
await connectPeers(spaceKey, teleportBuilder, peer2, peer3);
|
|
626
628
|
|
|
627
|
-
const loadedDocument = peer2.repo.find(document.url);
|
|
629
|
+
const loadedDocument = await peer2.repo.find(document.url, FIND_PARAMS);
|
|
628
630
|
await loadedDocument.whenReady();
|
|
629
631
|
|
|
630
|
-
const doc = peer3.repo.find(document.url);
|
|
632
|
+
const doc = await peer3.repo.find(document.url, FIND_PARAMS);
|
|
631
633
|
await doc.whenReady();
|
|
632
|
-
expect(doc.
|
|
634
|
+
expect(doc.doc()).to.deep.eq(document.doc());
|
|
633
635
|
});
|
|
634
636
|
});
|
|
635
637
|
|
|
@@ -692,8 +694,6 @@ const createRepoTopology = async <Peers extends string[], Peer extends string =
|
|
|
692
694
|
|
|
693
695
|
const connectAdapters = async (pairs: [TestAdapter, TestAdapter][], options?: { noEmitPeerCandidate?: boolean }) => {
|
|
694
696
|
for (const pair of pairs) {
|
|
695
|
-
pair[0].ready();
|
|
696
|
-
pair[1].ready();
|
|
697
697
|
await pair[0].onConnect.wait();
|
|
698
698
|
await pair[1].onConnect.wait();
|
|
699
699
|
if (!options?.noEmitPeerCandidate) {
|
|
@@ -2,10 +2,10 @@
|
|
|
2
2
|
// Copyright 2024 DXOS.org
|
|
3
3
|
//
|
|
4
4
|
|
|
5
|
+
import type { PeerId } from '@automerge/automerge-repo';
|
|
5
6
|
import { onTestFinished, describe, expect, test } from 'vitest';
|
|
6
7
|
|
|
7
8
|
import { sleep } from '@dxos/async';
|
|
8
|
-
import type { PeerId } from '@dxos/automerge/automerge-repo';
|
|
9
9
|
|
|
10
10
|
import { CollectionSynchronizer, diffCollectionState, type CollectionState } from './collection-synchronizer';
|
|
11
11
|
|
|
@@ -2,9 +2,10 @@
|
|
|
2
2
|
// Copyright 2024 DXOS.org
|
|
3
3
|
//
|
|
4
4
|
|
|
5
|
+
import { next as am } from '@automerge/automerge';
|
|
6
|
+
import type { DocumentId, PeerId } from '@automerge/automerge-repo';
|
|
7
|
+
|
|
5
8
|
import { asyncReturn, Event, scheduleTask, scheduleTaskInterval } from '@dxos/async';
|
|
6
|
-
import { next as am } from '@dxos/automerge/automerge';
|
|
7
|
-
import type { DocumentId, PeerId } from '@dxos/automerge/automerge-repo';
|
|
8
9
|
import { Resource, type Context } from '@dxos/context';
|
|
9
10
|
import { log } from '@dxos/log';
|
|
10
11
|
import { trace } from '@dxos/tracing';
|
|
@@ -69,7 +70,7 @@ export class CollectionSynchronizer extends Resource {
|
|
|
69
70
|
return this._perCollectionStates.get(collectionId)?.localState;
|
|
70
71
|
}
|
|
71
72
|
|
|
72
|
-
setLocalCollectionState(collectionId: string, state: CollectionState) {
|
|
73
|
+
setLocalCollectionState(collectionId: string, state: CollectionState): void {
|
|
73
74
|
this._activeCollections.add(collectionId);
|
|
74
75
|
|
|
75
76
|
log('setLocalCollectionState', { collectionId, state });
|
|
@@ -83,7 +84,7 @@ export class CollectionSynchronizer extends Resource {
|
|
|
83
84
|
});
|
|
84
85
|
}
|
|
85
86
|
|
|
86
|
-
clearLocalCollectionState(collectionId: string) {
|
|
87
|
+
clearLocalCollectionState(collectionId: string): void {
|
|
87
88
|
this._activeCollections.delete(collectionId);
|
|
88
89
|
this._perCollectionStates.delete(collectionId);
|
|
89
90
|
log('clearLocalCollectionState', { collectionId });
|
|
@@ -93,7 +94,7 @@ export class CollectionSynchronizer extends Resource {
|
|
|
93
94
|
return this._getOrCreatePerCollectionState(collectionId).remoteStates;
|
|
94
95
|
}
|
|
95
96
|
|
|
96
|
-
refreshCollection(collectionId: string) {
|
|
97
|
+
refreshCollection(collectionId: string): void {
|
|
97
98
|
let scheduleAnotherRefresh = false;
|
|
98
99
|
const state = this._getOrCreatePerCollectionState(collectionId);
|
|
99
100
|
for (const peerId of this._connectedPeers) {
|
|
@@ -115,7 +116,7 @@ export class CollectionSynchronizer extends Resource {
|
|
|
115
116
|
/**
|
|
116
117
|
* Callback when a connection to a peer is established.
|
|
117
118
|
*/
|
|
118
|
-
onConnectionOpen(peerId: PeerId) {
|
|
119
|
+
onConnectionOpen(peerId: PeerId): void {
|
|
119
120
|
const spanId = getSpanName(peerId);
|
|
120
121
|
trace.spanStart({
|
|
121
122
|
id: spanId,
|
|
@@ -144,7 +145,7 @@ export class CollectionSynchronizer extends Resource {
|
|
|
144
145
|
/**
|
|
145
146
|
* Callback when a connection to a peer is closed.
|
|
146
147
|
*/
|
|
147
|
-
onConnectionClosed(peerId: PeerId) {
|
|
148
|
+
onConnectionClosed(peerId: PeerId): void {
|
|
148
149
|
this._connectedPeers.delete(peerId);
|
|
149
150
|
|
|
150
151
|
for (const perCollectionState of this._perCollectionStates.values()) {
|
|
@@ -155,7 +156,7 @@ export class CollectionSynchronizer extends Resource {
|
|
|
155
156
|
/**
|
|
156
157
|
* Callback when a peer queries the state of a collection.
|
|
157
158
|
*/
|
|
158
|
-
onCollectionStateQueried(collectionId: string, peerId: PeerId) {
|
|
159
|
+
onCollectionStateQueried(collectionId: string, peerId: PeerId): void {
|
|
159
160
|
const perCollectionState = this._getOrCreatePerCollectionState(collectionId);
|
|
160
161
|
|
|
161
162
|
if (perCollectionState.localState) {
|
|
@@ -166,7 +167,7 @@ export class CollectionSynchronizer extends Resource {
|
|
|
166
167
|
/**
|
|
167
168
|
* Callback when a peer sends the state of a collection.
|
|
168
169
|
*/
|
|
169
|
-
onRemoteStateReceived(collectionId: string, peerId: PeerId, state: CollectionState) {
|
|
170
|
+
onRemoteStateReceived(collectionId: string, peerId: PeerId, state: CollectionState): void {
|
|
170
171
|
log('onRemoteStateReceived', { collectionId, peerId, state });
|
|
171
172
|
validateCollectionState(state);
|
|
172
173
|
const perCollectionState = this._getOrCreatePerCollectionState(collectionId);
|
|
@@ -200,7 +201,7 @@ export class CollectionSynchronizer extends Resource {
|
|
|
200
201
|
}));
|
|
201
202
|
}
|
|
202
203
|
|
|
203
|
-
private _refreshInterestedPeers(collectionId: string) {
|
|
204
|
+
private _refreshInterestedPeers(collectionId: string): void {
|
|
204
205
|
for (const peerId of this._connectedPeers) {
|
|
205
206
|
if (this._shouldSyncCollection(collectionId, peerId)) {
|
|
206
207
|
this._getOrCreatePerCollectionState(collectionId).interestedPeers.add(peerId);
|
|
@@ -2,7 +2,8 @@
|
|
|
2
2
|
// Copyright 2024 DXOS.org
|
|
3
3
|
//
|
|
4
4
|
|
|
5
|
-
import { type Message } from '@
|
|
5
|
+
import { type Message } from '@automerge/automerge-repo';
|
|
6
|
+
|
|
6
7
|
import { type TimeAware, trace } from '@dxos/tracing';
|
|
7
8
|
import { CircularBuffer, mapValues, SlidingWindowSummary, type SlidingWindowSummaryConfig } from '@dxos/util';
|
|
8
9
|
|
|
@@ -26,7 +27,7 @@ export class EchoDataMonitor implements StorageAdapterDataMonitor, NetworkDataMo
|
|
|
26
27
|
private readonly _localTimeSeries = createLocalTimeSeries();
|
|
27
28
|
private readonly _storageAverages = createStorageAverages();
|
|
28
29
|
private readonly _replicationAverages = createNetworkAverages();
|
|
29
|
-
private readonly
|
|
30
|
+
private readonly _sizeByMessage: { [type: string]: SlidingWindowSummary } = {};
|
|
30
31
|
private readonly _lastReceivedMessages = new CircularBuffer<StoredMessage>(100);
|
|
31
32
|
private readonly _lastSentMessages = new CircularBuffer<StoredMessage>(100);
|
|
32
33
|
|
|
@@ -34,7 +35,7 @@ export class EchoDataMonitor implements StorageAdapterDataMonitor, NetworkDataMo
|
|
|
34
35
|
|
|
35
36
|
constructor(private readonly _params: EchoDataMonitorOptions = { timeSeriesLength: 30 }) {}
|
|
36
37
|
|
|
37
|
-
public tick(timeMs: number) {
|
|
38
|
+
public tick(timeMs: number): void {
|
|
38
39
|
this._advanceTimeWindow(timeMs - this._lastTick);
|
|
39
40
|
this._lastTick = timeMs;
|
|
40
41
|
}
|
|
@@ -68,8 +69,8 @@ export class EchoDataMonitor implements StorageAdapterDataMonitor, NetworkDataMo
|
|
|
68
69
|
countPerSecond: this._replicationAverages.sentPerSecond.average(),
|
|
69
70
|
failedPerSecond: this._replicationAverages.sendsFailedPerSecond.average(),
|
|
70
71
|
},
|
|
71
|
-
|
|
72
|
-
|
|
72
|
+
countByMessage: this._computeMessageHistogram('type'),
|
|
73
|
+
avgSizeByMessage: mapValues(this._sizeByMessage, (summary) => summary.average()),
|
|
73
74
|
},
|
|
74
75
|
};
|
|
75
76
|
}
|
|
@@ -99,7 +100,7 @@ export class EchoDataMonitor implements StorageAdapterDataMonitor, NetworkDataMo
|
|
|
99
100
|
return this._computeMessageHistogram('peerId');
|
|
100
101
|
}
|
|
101
102
|
|
|
102
|
-
private _advanceTimeWindow(millisPassed: number) {
|
|
103
|
+
private _advanceTimeWindow(millisPassed: number): void {
|
|
103
104
|
const oldMetrics = Object.freeze(this._activeCounters);
|
|
104
105
|
this._activeCounters = createLocalCounters();
|
|
105
106
|
this._lastCompleteCounters = oldMetrics;
|
|
@@ -114,7 +115,7 @@ export class EchoDataMonitor implements StorageAdapterDataMonitor, NetworkDataMo
|
|
|
114
115
|
}
|
|
115
116
|
}
|
|
116
117
|
|
|
117
|
-
private _addToTimeSeries<T extends object>(values: T, timeSeries: TimeSeries<T>) {
|
|
118
|
+
private _addToTimeSeries<T extends object>(values: T, timeSeries: TimeSeries<T>): void {
|
|
118
119
|
for (const [key, value] of Object.entries(values)) {
|
|
119
120
|
const values: (typeof value)[] = (timeSeries as any)[key];
|
|
120
121
|
values.push(value);
|
|
@@ -124,7 +125,7 @@ export class EchoDataMonitor implements StorageAdapterDataMonitor, NetworkDataMo
|
|
|
124
125
|
}
|
|
125
126
|
}
|
|
126
127
|
|
|
127
|
-
private _reportPerSecondRate(metrics: LocalCounters) {
|
|
128
|
+
private _reportPerSecondRate(metrics: LocalCounters): void {
|
|
128
129
|
const toReport: [string, number, SlidingWindowSummary][] = [
|
|
129
130
|
['storage.load', metrics.storage.loadedChunks, this._storageAverages.loadsPerSecond],
|
|
130
131
|
['storage.store', metrics.storage.storedChunks, this._storageAverages.storesPerSecond],
|
|
@@ -143,17 +144,17 @@ export class EchoDataMonitor implements StorageAdapterDataMonitor, NetworkDataMo
|
|
|
143
144
|
this._replicationAverages.sendsFailedPerSecond.record(metrics.replication.failed);
|
|
144
145
|
}
|
|
145
146
|
|
|
146
|
-
public recordPeerConnected(peerId: string) {
|
|
147
|
+
public recordPeerConnected(peerId: string): void {
|
|
147
148
|
this._activeCounters.byPeerId[peerId] = createMessageCounter();
|
|
148
149
|
this._connectionsCount++;
|
|
149
150
|
}
|
|
150
151
|
|
|
151
|
-
public recordPeerDisconnected(peerId: string) {
|
|
152
|
+
public recordPeerDisconnected(peerId: string): void {
|
|
152
153
|
this._connectionsCount--;
|
|
153
154
|
delete this._activeCounters.byPeerId[peerId];
|
|
154
155
|
}
|
|
155
156
|
|
|
156
|
-
public recordBytesStored(count: number) {
|
|
157
|
+
public recordBytesStored(count: number): void {
|
|
157
158
|
this._activeCounters.storage.storedChunks++;
|
|
158
159
|
this._activeCounters.storage.storedBytes += count;
|
|
159
160
|
this._storageAverages.storedChunkSize.record(count);
|
|
@@ -168,14 +169,14 @@ export class EchoDataMonitor implements StorageAdapterDataMonitor, NetworkDataMo
|
|
|
168
169
|
this._storageAverages.storeDuration.record(durationMs);
|
|
169
170
|
}
|
|
170
171
|
|
|
171
|
-
public recordBytesLoaded(count: number) {
|
|
172
|
+
public recordBytesLoaded(count: number): void {
|
|
172
173
|
this._activeCounters.storage.loadedChunks++;
|
|
173
174
|
this._activeCounters.storage.loadedBytes += count;
|
|
174
175
|
this._storageAverages.loadedChunkSize.record(count);
|
|
175
176
|
trace.metrics.distribution('dxos.echo.storage.bytes-loaded', count, { unit: 'bytes' });
|
|
176
177
|
}
|
|
177
178
|
|
|
178
|
-
public recordMessageSent(message: Message, duration: number) {
|
|
179
|
+
public recordMessageSent(message: Message, duration: number): void {
|
|
179
180
|
let metricsGroupName;
|
|
180
181
|
const bytes = getByteCount(message);
|
|
181
182
|
const tags = { type: message.type };
|
|
@@ -196,7 +197,7 @@ export class EchoDataMonitor implements StorageAdapterDataMonitor, NetworkDataMo
|
|
|
196
197
|
this._lastSentMessages.push({ type: message.type, peerId: message.targetId });
|
|
197
198
|
}
|
|
198
199
|
|
|
199
|
-
public recordMessageReceived(message: Message) {
|
|
200
|
+
public recordMessageReceived(message: Message): void {
|
|
200
201
|
const bytes = getByteCount(message);
|
|
201
202
|
const tags = { type: message.type };
|
|
202
203
|
if (isAutomergeProtocolMessage(message)) {
|
|
@@ -212,7 +213,7 @@ export class EchoDataMonitor implements StorageAdapterDataMonitor, NetworkDataMo
|
|
|
212
213
|
this._lastReceivedMessages.push({ type: message.type, peerId: message.senderId });
|
|
213
214
|
}
|
|
214
215
|
|
|
215
|
-
public recordMessageSendingFailed(message: Message) {
|
|
216
|
+
public recordMessageSendingFailed(message: Message): void {
|
|
216
217
|
const tags = { type: message.type, success: false };
|
|
217
218
|
if (isAutomergeProtocolMessage(message)) {
|
|
218
219
|
this._activeCounters.replication.failed++;
|
|
@@ -224,8 +225,8 @@ export class EchoDataMonitor implements StorageAdapterDataMonitor, NetworkDataMo
|
|
|
224
225
|
messageCounts.failed++;
|
|
225
226
|
}
|
|
226
227
|
|
|
227
|
-
private _getStatsForType(message: Message) {
|
|
228
|
-
const messageSize = (this.
|
|
228
|
+
private _getStatsForType(message: Message): { messageCounts: MessageCounts; messageSize: SlidingWindowSummary } {
|
|
229
|
+
const messageSize = (this._sizeByMessage[message.type] ??= createSlidingWindow());
|
|
229
230
|
const messageCounts = (this._activeCounters.byType[message.type] ??= createMessageCounter());
|
|
230
231
|
return { messageCounts, messageSize };
|
|
231
232
|
}
|
|
@@ -269,7 +270,7 @@ type MessageCounts = {
|
|
|
269
270
|
type MessageCountTimeSeries = TimeSeries<MessageCounts>;
|
|
270
271
|
|
|
271
272
|
type MessageAttributeHistogram = {
|
|
272
|
-
[
|
|
273
|
+
[Message: string]: {
|
|
273
274
|
received: number;
|
|
274
275
|
sent: number;
|
|
275
276
|
};
|
|
@@ -287,8 +288,8 @@ export type EchoDataStats = {
|
|
|
287
288
|
connections: number;
|
|
288
289
|
receivedMessages: BaseDataOpStats;
|
|
289
290
|
sentMessages: TimedDataOpStats & { failedPerSecond: number };
|
|
290
|
-
|
|
291
|
-
|
|
291
|
+
avgSizeByMessage: { [Message: string]: number };
|
|
292
|
+
countByMessage: MessageAttributeHistogram;
|
|
292
293
|
};
|
|
293
294
|
};
|
|
294
295
|
|
|
@@ -2,10 +2,10 @@
|
|
|
2
2
|
// Copyright 2024 DXOS.org
|
|
3
3
|
//
|
|
4
4
|
|
|
5
|
+
import { cbor, type PeerId } from '@automerge/automerge-repo';
|
|
5
6
|
import { onTestFinished, describe, expect, test } from 'vitest';
|
|
6
7
|
|
|
7
8
|
import { sleep, Trigger, waitForCondition } from '@dxos/async';
|
|
8
|
-
import { cbor, type PeerId } from '@dxos/automerge/automerge-repo';
|
|
9
9
|
import { invariant } from '@dxos/invariant';
|
|
10
10
|
import { PublicKey } from '@dxos/keys';
|
|
11
11
|
import { type SyncMessage } from '@dxos/protocols/proto/dxos/mesh/teleport/automerge';
|