@fairfox/polly 0.53.0 → 0.54.0
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/src/mesh.js
CHANGED
|
@@ -1849,8 +1849,8 @@ import {
|
|
|
1849
1849
|
} from "@automerge/automerge-repo/slim";
|
|
1850
1850
|
|
|
1851
1851
|
// src/shared/lib/sync-fragment.ts
|
|
1852
|
-
var SYNC_FRAGMENT_THRESHOLD =
|
|
1853
|
-
var SYNC_FRAGMENT_CHUNK_SIZE =
|
|
1852
|
+
var SYNC_FRAGMENT_THRESHOLD = 60 * 1024;
|
|
1853
|
+
var SYNC_FRAGMENT_CHUNK_SIZE = 60 * 1024;
|
|
1854
1854
|
function serialiseSyncFragment(header, data) {
|
|
1855
1855
|
const headerBytes = new TextEncoder().encode(JSON.stringify(header));
|
|
1856
1856
|
const size = 4 + headerBytes.length + data.length;
|
|
@@ -1946,6 +1946,8 @@ class MeshWebRTCAdapter extends NetworkAdapter2 {
|
|
|
1946
1946
|
keyringSource;
|
|
1947
1947
|
knownPeersRefreshTimer;
|
|
1948
1948
|
knownPeersRefreshIntervalMs;
|
|
1949
|
+
syncYieldEnabled;
|
|
1950
|
+
syncFragmentChunkSize;
|
|
1949
1951
|
presentPeers = new Set;
|
|
1950
1952
|
localPeerId;
|
|
1951
1953
|
RTCPeerConnectionCtor;
|
|
@@ -1973,6 +1975,8 @@ class MeshWebRTCAdapter extends NetworkAdapter2 {
|
|
|
1973
1975
|
this.knownPeers = new Set(options.knownPeerIds ?? []);
|
|
1974
1976
|
this.keyringSource = options.keyringSource;
|
|
1975
1977
|
this.knownPeersRefreshIntervalMs = options.knownPeersRefreshIntervalMs ?? 2000;
|
|
1978
|
+
this.syncYieldEnabled = options.syncYieldEnabled ?? true;
|
|
1979
|
+
this.syncFragmentChunkSize = options.syncFragmentChunkSizeOverride ?? SYNC_FRAGMENT_CHUNK_SIZE;
|
|
1976
1980
|
this.localPeerId = options.peerId;
|
|
1977
1981
|
const PC = options.RTCPeerConnection ?? globalThis.RTCPeerConnection;
|
|
1978
1982
|
if (typeof PC !== "function") {
|
|
@@ -2010,7 +2014,8 @@ class MeshWebRTCAdapter extends NetworkAdapter2 {
|
|
|
2010
2014
|
connectionState: slot.connection.connectionState,
|
|
2011
2015
|
dataChannelState: slot.channel?.readyState ?? "no-channel",
|
|
2012
2016
|
pendingSendCount: slot.pendingSends.length,
|
|
2013
|
-
pendingRemoteIceCount: slot.pendingRemoteIce.length
|
|
2017
|
+
pendingRemoteIceCount: slot.pendingRemoteIce.length,
|
|
2018
|
+
inFlightSync: slot.inFlightSync ? { ...slot.inFlightSync } : undefined
|
|
2014
2019
|
} : undefined
|
|
2015
2020
|
});
|
|
2016
2021
|
}
|
|
@@ -2133,15 +2138,29 @@ class MeshWebRTCAdapter extends NetworkAdapter2 {
|
|
|
2133
2138
|
slot.pendingSends.push(bytes);
|
|
2134
2139
|
}
|
|
2135
2140
|
}
|
|
2136
|
-
|
|
2141
|
+
static SEND_YIELD_EVERY_N_FRAGMENTS = 8;
|
|
2142
|
+
async sendBytesMaybeFragmented(channel, bytes) {
|
|
2137
2143
|
if (bytes.length <= SYNC_FRAGMENT_THRESHOLD) {
|
|
2138
2144
|
channel.send(bytes);
|
|
2139
2145
|
return;
|
|
2140
2146
|
}
|
|
2141
2147
|
const id = crypto.randomUUID();
|
|
2142
|
-
const fragments = chunkSyncMessage(bytes, id);
|
|
2148
|
+
const fragments = chunkSyncMessage(bytes, id, this.syncFragmentChunkSize);
|
|
2149
|
+
if (!this.syncYieldEnabled) {
|
|
2150
|
+
for (const fragment of fragments) {
|
|
2151
|
+
channel.send(fragment);
|
|
2152
|
+
}
|
|
2153
|
+
return;
|
|
2154
|
+
}
|
|
2155
|
+
let i = 0;
|
|
2143
2156
|
for (const fragment of fragments) {
|
|
2144
2157
|
channel.send(fragment);
|
|
2158
|
+
i += 1;
|
|
2159
|
+
if (i % MeshWebRTCAdapter.SEND_YIELD_EVERY_N_FRAGMENTS === 0 && i < fragments.length) {
|
|
2160
|
+
await new Promise((resolve) => {
|
|
2161
|
+
setTimeout(resolve, 0);
|
|
2162
|
+
});
|
|
2163
|
+
}
|
|
2145
2164
|
}
|
|
2146
2165
|
}
|
|
2147
2166
|
handleSignal(fromPeerId, rawPayload) {
|
|
@@ -2169,7 +2188,8 @@ class MeshWebRTCAdapter extends NetworkAdapter2 {
|
|
|
2169
2188
|
channel,
|
|
2170
2189
|
pendingSends: [],
|
|
2171
2190
|
pendingFragments: new Map,
|
|
2172
|
-
pendingRemoteIce: []
|
|
2191
|
+
pendingRemoteIce: [],
|
|
2192
|
+
inFlightSync: undefined
|
|
2173
2193
|
};
|
|
2174
2194
|
this.slots.set(targetId, slot);
|
|
2175
2195
|
this.wireConnection(targetId, connection);
|
|
@@ -2199,7 +2219,8 @@ class MeshWebRTCAdapter extends NetworkAdapter2 {
|
|
|
2199
2219
|
channel: undefined,
|
|
2200
2220
|
pendingSends: [],
|
|
2201
2221
|
pendingFragments: new Map,
|
|
2202
|
-
pendingRemoteIce: []
|
|
2222
|
+
pendingRemoteIce: [],
|
|
2223
|
+
inFlightSync: undefined
|
|
2203
2224
|
};
|
|
2204
2225
|
this.slots.set(fromPeerId, slot);
|
|
2205
2226
|
this.wireConnection(fromPeerId, connection);
|
|
@@ -2310,9 +2331,56 @@ class MeshWebRTCAdapter extends NetworkAdapter2 {
|
|
|
2310
2331
|
return;
|
|
2311
2332
|
}
|
|
2312
2333
|
const message = this.deserialiseMessage(bytes);
|
|
2313
|
-
this.
|
|
2334
|
+
this.scheduleEmitMessage(fromPeerId, message, false);
|
|
2314
2335
|
} catch {}
|
|
2315
2336
|
}
|
|
2337
|
+
scheduleEmitMessage(fromPeerId, message, viaFragmentPath) {
|
|
2338
|
+
if (!this.syncYieldEnabled) {
|
|
2339
|
+
this.emit("message", message);
|
|
2340
|
+
if (viaFragmentPath) {
|
|
2341
|
+
this.finishInFlightSyncApply(fromPeerId);
|
|
2342
|
+
}
|
|
2343
|
+
return;
|
|
2344
|
+
}
|
|
2345
|
+
if (viaFragmentPath) {
|
|
2346
|
+
const slot = this.slots.get(fromPeerId);
|
|
2347
|
+
if (slot?.inFlightSync) {
|
|
2348
|
+
slot.inFlightSync.applyBacklog += 1;
|
|
2349
|
+
}
|
|
2350
|
+
}
|
|
2351
|
+
setTimeout(() => {
|
|
2352
|
+
try {
|
|
2353
|
+
this.emit("message", message);
|
|
2354
|
+
} finally {
|
|
2355
|
+
if (viaFragmentPath) {
|
|
2356
|
+
this.finishInFlightSyncApply(fromPeerId);
|
|
2357
|
+
}
|
|
2358
|
+
}
|
|
2359
|
+
}, 0);
|
|
2360
|
+
}
|
|
2361
|
+
finishInFlightSyncApply(fromPeerId) {
|
|
2362
|
+
const slot = this.slots.get(fromPeerId);
|
|
2363
|
+
if (!slot?.inFlightSync)
|
|
2364
|
+
return;
|
|
2365
|
+
slot.inFlightSync.applyBacklog = Math.max(0, slot.inFlightSync.applyBacklog - 1);
|
|
2366
|
+
this.emitSyncProgress(fromPeerId, "dispatch-applied", 0);
|
|
2367
|
+
if (slot.inFlightSync.applyBacklog === 0 && slot.pendingFragments.size === 0) {
|
|
2368
|
+
slot.inFlightSync = undefined;
|
|
2369
|
+
}
|
|
2370
|
+
}
|
|
2371
|
+
emitSyncProgress(fromPeerId, kind, bytesDelta) {
|
|
2372
|
+
const slot = this.slots.get(fromPeerId);
|
|
2373
|
+
const inFlightSync = slot?.inFlightSync;
|
|
2374
|
+
this.emit("sync-progress", {
|
|
2375
|
+
peerId: fromPeerId,
|
|
2376
|
+
kind,
|
|
2377
|
+
bytesDelta,
|
|
2378
|
+
chunksReceived: inFlightSync?.chunksReceived ?? 0,
|
|
2379
|
+
bytesReceived: inFlightSync?.bytesReceived ?? 0,
|
|
2380
|
+
applyBacklog: inFlightSync?.applyBacklog ?? 0,
|
|
2381
|
+
at: performance.now()
|
|
2382
|
+
});
|
|
2383
|
+
}
|
|
2316
2384
|
handleSyncFragment(fromPeerId, bytes) {
|
|
2317
2385
|
const parsed = parseSyncFragment(bytes);
|
|
2318
2386
|
if (!parsed)
|
|
@@ -2327,11 +2395,46 @@ class MeshWebRTCAdapter extends NetworkAdapter2 {
|
|
|
2327
2395
|
slot.pendingFragments.set(header.id, entry);
|
|
2328
2396
|
}
|
|
2329
2397
|
entry.chunks.set(header.index, data.slice());
|
|
2398
|
+
if (!slot.inFlightSync) {
|
|
2399
|
+
slot.inFlightSync = {
|
|
2400
|
+
chunksReceived: 0,
|
|
2401
|
+
bytesReceived: 0,
|
|
2402
|
+
lastChunkAt: performance.now(),
|
|
2403
|
+
applyBacklog: 0
|
|
2404
|
+
};
|
|
2405
|
+
}
|
|
2406
|
+
slot.inFlightSync.chunksReceived += 1;
|
|
2407
|
+
slot.inFlightSync.bytesReceived += data.byteLength;
|
|
2408
|
+
slot.inFlightSync.lastChunkAt = performance.now();
|
|
2409
|
+
this.emitSyncProgress(fromPeerId, "fragment-received", data.byteLength);
|
|
2330
2410
|
if (entry.chunks.size < entry.total)
|
|
2331
2411
|
return;
|
|
2332
2412
|
slot.pendingFragments.delete(header.id);
|
|
2333
2413
|
const reassembled = reassembleSyncFragments(entry.chunks, entry.total);
|
|
2334
|
-
this.
|
|
2414
|
+
if (!this.syncYieldEnabled) {
|
|
2415
|
+
this.dispatchReassembled(fromPeerId, reassembled);
|
|
2416
|
+
return;
|
|
2417
|
+
}
|
|
2418
|
+
setTimeout(() => {
|
|
2419
|
+
this.dispatchReassembled(fromPeerId, reassembled);
|
|
2420
|
+
}, 0);
|
|
2421
|
+
}
|
|
2422
|
+
dispatchReassembled(fromPeerId, bytes) {
|
|
2423
|
+
try {
|
|
2424
|
+
if (this.onBlobMessage && isBlobMessageType(bytes)) {
|
|
2425
|
+
const view = new DataView(bytes.buffer, bytes.byteOffset, bytes.byteLength);
|
|
2426
|
+
const headerLen = view.getUint32(0, false);
|
|
2427
|
+
const header = JSON.parse(new TextDecoder().decode(bytes.subarray(4, 4 + headerLen)));
|
|
2428
|
+
const data = bytes.subarray(4 + headerLen);
|
|
2429
|
+
this.onBlobMessage(fromPeerId, header, data);
|
|
2430
|
+
this.finishInFlightSyncApply(fromPeerId);
|
|
2431
|
+
return;
|
|
2432
|
+
}
|
|
2433
|
+
const message = this.deserialiseMessage(bytes);
|
|
2434
|
+
this.scheduleEmitMessage(fromPeerId, message, true);
|
|
2435
|
+
} catch {
|
|
2436
|
+
this.finishInFlightSyncApply(fromPeerId);
|
|
2437
|
+
}
|
|
2335
2438
|
}
|
|
2336
2439
|
get connectedPeerIds() {
|
|
2337
2440
|
const ids = [];
|
|
@@ -2419,6 +2522,12 @@ async function createMeshClient(options) {
|
|
|
2419
2522
|
},
|
|
2420
2523
|
...options.rtc?.knownPeersRefreshIntervalMs !== undefined && {
|
|
2421
2524
|
knownPeersRefreshIntervalMs: options.rtc.knownPeersRefreshIntervalMs
|
|
2525
|
+
},
|
|
2526
|
+
...options.rtc?.syncYieldEnabled !== undefined && {
|
|
2527
|
+
syncYieldEnabled: options.rtc.syncYieldEnabled
|
|
2528
|
+
},
|
|
2529
|
+
...options.rtc?.syncFragmentChunkSizeOverride !== undefined && {
|
|
2530
|
+
syncFragmentChunkSizeOverride: options.rtc.syncFragmentChunkSizeOverride
|
|
2422
2531
|
}
|
|
2423
2532
|
};
|
|
2424
2533
|
let webrtcAdapter;
|
|
@@ -2893,4 +3002,4 @@ export {
|
|
|
2893
3002
|
$meshCounter
|
|
2894
3003
|
};
|
|
2895
3004
|
|
|
2896
|
-
//# debugId=
|
|
3005
|
+
//# debugId=18409B674B254AA864756E2164756E21
|