@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 = 64 * 1024;
1853
- var SYNC_FRAGMENT_CHUNK_SIZE = 64 * 1024;
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
- sendBytesMaybeFragmented(channel, bytes) {
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.emit("message", message);
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.dispatchMessage(fromPeerId, reassembled);
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=51457A626E5A2F2B64756E2164756E21
3005
+ //# debugId=18409B674B254AA864756E2164756E21