@fairfox/polly 0.63.0 → 0.65.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.d.ts +1 -1
- package/dist/src/mesh.js +244 -35
- package/dist/src/mesh.js.map +6 -6
- package/dist/src/peer.js +88 -20
- package/dist/src/peer.js.map +3 -3
- package/dist/src/shared/lib/crdt-state.d.ts +14 -0
- package/dist/src/shared/lib/mesh-state.d.ts +37 -1
- package/dist/src/shared/lib/mesh-webrtc-adapter.d.ts +89 -1
- package/package.json +1 -1
package/dist/src/mesh.d.ts
CHANGED
|
@@ -28,7 +28,7 @@ export { DEFAULT_MESH_KEY_ID, MeshNetworkAdapter, } from "./shared/lib/mesh-netw
|
|
|
28
28
|
export type { MeshSignalingClientOptions, SignalingMessage as MeshSignalingMessage, } from "./shared/lib/mesh-signaling-client";
|
|
29
29
|
export { MeshSignalingClient } from "./shared/lib/mesh-signaling-client";
|
|
30
30
|
export type { DocIdResolver, LazyWrapperExitReason, MeshStateLazyWrapperRecord, MeshStateLoadedRejectionBreadcrumb, MeshStateOptions, MeshStateStorageOpenError, } from "./shared/lib/mesh-state";
|
|
31
|
-
export { $meshCounter, $meshList, $meshState, $meshText, configureMeshState, deriveDocumentId, getDocIdResolver, getLastConfiguredRepoPeerId, getLastLoadedRejection, getLazyInvocations, getLazyReachedRepo, getLazyWrappers, getMeshStateModuleId, getStorageOpenError, isMeshStateConfigured, MESH_STATE_MODULE_ID, registerDocIdResolver, resetMeshState, resolveDocumentId, wasMeshStateResolved, } from "./shared/lib/mesh-state";
|
|
31
|
+
export { $meshCounter, $meshList, $meshState, $meshText, configureMeshState, deriveDocumentId, getDocIdResolver, getLastConfiguredRepoPeerId, getLastLoadedRejection, getLazyInvocations, getLazyReachedRepo, getLazyWrappers, getMeshStateModuleId, getRedirectDetector, getStorageOpenError, isMeshStateConfigured, MESH_STATE_MODULE_ID, registerDocIdResolver, registerRedirectDetector, resetMeshState, resolveDocumentId, wasMeshStateResolved, } from "./shared/lib/mesh-state";
|
|
32
32
|
export type { HandleSyncSnapshot, InFlightSyncSnapshot, MeshWebRTCAdapterOptions, SlotInitiationDecision, SlotInitiationRejectionReason, SweepSnapshot, SyncHandshakeAttemptSnapshot, SyncProgressEvent, TransportSnapshot, } from "./shared/lib/mesh-webrtc-adapter";
|
|
33
33
|
export { DEFAULT_ICE_SERVERS, MeshWebRTCAdapter } from "./shared/lib/mesh-webrtc-adapter";
|
|
34
34
|
export type { CreatePairingTokenOptions, PairingToken, } from "./shared/lib/pairing";
|
package/dist/src/mesh.js
CHANGED
|
@@ -1729,25 +1729,10 @@ function $crdtState(options) {
|
|
|
1729
1729
|
const inner = signal2(options.initialValue);
|
|
1730
1730
|
let updating = false;
|
|
1731
1731
|
let currentHandle;
|
|
1732
|
-
|
|
1733
|
-
|
|
1734
|
-
|
|
1735
|
-
|
|
1736
|
-
if (options.schemaVersion !== undefined) {
|
|
1737
|
-
const targetVersion = options.schemaVersion;
|
|
1738
|
-
const migrations = options.migrations ?? {};
|
|
1739
|
-
handle.change((doc) => {
|
|
1740
|
-
runMigrations(doc, targetVersion, migrations);
|
|
1741
|
-
setDocVersion(doc, targetVersion);
|
|
1742
|
-
});
|
|
1743
|
-
}
|
|
1744
|
-
updating = true;
|
|
1745
|
-
try {
|
|
1746
|
-
inner.value = cloneDoc(handle.doc());
|
|
1747
|
-
} finally {
|
|
1748
|
-
updating = false;
|
|
1749
|
-
}
|
|
1750
|
-
handle.on("change", (payload) => {
|
|
1732
|
+
let detachChangeListener;
|
|
1733
|
+
let swapping = false;
|
|
1734
|
+
function attachChangeListener(handle) {
|
|
1735
|
+
const listener = (payload) => {
|
|
1751
1736
|
if (updating)
|
|
1752
1737
|
return;
|
|
1753
1738
|
updating = true;
|
|
@@ -1756,7 +1741,75 @@ function $crdtState(options) {
|
|
|
1756
1741
|
} finally {
|
|
1757
1742
|
updating = false;
|
|
1758
1743
|
}
|
|
1744
|
+
if (options.resolveRedirect && !swapping) {
|
|
1745
|
+
maybeRebind(handle, payload.doc);
|
|
1746
|
+
}
|
|
1747
|
+
};
|
|
1748
|
+
handle.on("change", listener);
|
|
1749
|
+
detachChangeListener = () => {
|
|
1750
|
+
handle.off("change", listener);
|
|
1751
|
+
};
|
|
1752
|
+
}
|
|
1753
|
+
async function maybeRebind(fromHandle, doc) {
|
|
1754
|
+
if (!options.resolveRedirect)
|
|
1755
|
+
return;
|
|
1756
|
+
if (swapping)
|
|
1757
|
+
return;
|
|
1758
|
+
swapping = true;
|
|
1759
|
+
try {
|
|
1760
|
+
const next = await options.resolveRedirect(fromHandle, doc);
|
|
1761
|
+
if (!next)
|
|
1762
|
+
return;
|
|
1763
|
+
if (next === currentHandle)
|
|
1764
|
+
return;
|
|
1765
|
+
if (next.documentId === fromHandle.documentId)
|
|
1766
|
+
return;
|
|
1767
|
+
detachChangeListener?.();
|
|
1768
|
+
detachChangeListener = undefined;
|
|
1769
|
+
currentHandle = next;
|
|
1770
|
+
attachChangeListener(next);
|
|
1771
|
+
updating = true;
|
|
1772
|
+
try {
|
|
1773
|
+
inner.value = cloneDoc(next.doc());
|
|
1774
|
+
} finally {
|
|
1775
|
+
updating = false;
|
|
1776
|
+
}
|
|
1777
|
+
} finally {
|
|
1778
|
+
swapping = false;
|
|
1779
|
+
}
|
|
1780
|
+
}
|
|
1781
|
+
async function followInitialRedirects(start) {
|
|
1782
|
+
if (!options.resolveRedirect)
|
|
1783
|
+
return start;
|
|
1784
|
+
let handle = start;
|
|
1785
|
+
const seen = new Set([handle.documentId]);
|
|
1786
|
+
for (;; ) {
|
|
1787
|
+
const doc = handle.doc();
|
|
1788
|
+
if (!doc)
|
|
1789
|
+
break;
|
|
1790
|
+
const next = await options.resolveRedirect(handle, doc);
|
|
1791
|
+
if (!next || next === handle)
|
|
1792
|
+
break;
|
|
1793
|
+
const nextIdString = next.documentId;
|
|
1794
|
+
if (seen.has(nextIdString))
|
|
1795
|
+
break;
|
|
1796
|
+
seen.add(nextIdString);
|
|
1797
|
+
handle = next;
|
|
1798
|
+
await handle.whenReady();
|
|
1799
|
+
}
|
|
1800
|
+
return handle;
|
|
1801
|
+
}
|
|
1802
|
+
function applyPendingMigrations(handle) {
|
|
1803
|
+
if (options.schemaVersion === undefined)
|
|
1804
|
+
return;
|
|
1805
|
+
const targetVersion = options.schemaVersion;
|
|
1806
|
+
const migrations = options.migrations ?? {};
|
|
1807
|
+
handle.change((doc) => {
|
|
1808
|
+
runMigrations(doc, targetVersion, migrations);
|
|
1809
|
+
setDocVersion(doc, targetVersion);
|
|
1759
1810
|
});
|
|
1811
|
+
}
|
|
1812
|
+
function bindSignalToHandle() {
|
|
1760
1813
|
effect2(() => {
|
|
1761
1814
|
const value = inner.value;
|
|
1762
1815
|
if (updating)
|
|
@@ -1772,6 +1825,21 @@ function $crdtState(options) {
|
|
|
1772
1825
|
updating = false;
|
|
1773
1826
|
}
|
|
1774
1827
|
});
|
|
1828
|
+
}
|
|
1829
|
+
const loaded = (async () => {
|
|
1830
|
+
const initialHandle = await options.getHandle();
|
|
1831
|
+
await initialHandle.whenReady();
|
|
1832
|
+
const handle = await followInitialRedirects(initialHandle);
|
|
1833
|
+
currentHandle = handle;
|
|
1834
|
+
applyPendingMigrations(handle);
|
|
1835
|
+
updating = true;
|
|
1836
|
+
try {
|
|
1837
|
+
inner.value = cloneDoc(handle.doc());
|
|
1838
|
+
} finally {
|
|
1839
|
+
updating = false;
|
|
1840
|
+
}
|
|
1841
|
+
attachChangeListener(handle);
|
|
1842
|
+
bindSignalToHandle();
|
|
1775
1843
|
})();
|
|
1776
1844
|
return {
|
|
1777
1845
|
key: options.key,
|
|
@@ -1951,6 +2019,13 @@ function getDocIdResolver() {
|
|
|
1951
2019
|
function resolveDocumentId(key) {
|
|
1952
2020
|
return docIdResolver?.(key) ?? deriveDocumentId(key);
|
|
1953
2021
|
}
|
|
2022
|
+
var redirectDetector;
|
|
2023
|
+
function registerRedirectDetector(detector) {
|
|
2024
|
+
redirectDetector = detector;
|
|
2025
|
+
}
|
|
2026
|
+
function getRedirectDetector() {
|
|
2027
|
+
return redirectDetector;
|
|
2028
|
+
}
|
|
1954
2029
|
function buildHandleFactory(repo, key, initialDoc) {
|
|
1955
2030
|
const documentId = resolveDocumentId(key);
|
|
1956
2031
|
return async () => {
|
|
@@ -1961,23 +2036,22 @@ function buildHandleFactory(repo, key, initialDoc) {
|
|
|
1961
2036
|
const cached = repo.handles[documentId];
|
|
1962
2037
|
lazyReachedRepo++;
|
|
1963
2038
|
const docIdString = documentId;
|
|
2039
|
+
let handle;
|
|
1964
2040
|
if (cached) {
|
|
1965
2041
|
await withStorageTimeout("whenReady", docIdString, cached.whenReady(["ready", "unavailable"]));
|
|
1966
2042
|
if (cached.state === "ready") {
|
|
1967
2043
|
exitReason = "returned-cached";
|
|
1968
|
-
|
|
2044
|
+
handle = cached;
|
|
2045
|
+
} else {
|
|
2046
|
+
handle = await loadOrSeed(repo, documentId, initialDoc, docIdString, (r) => {
|
|
2047
|
+
exitReason = r;
|
|
2048
|
+
});
|
|
1969
2049
|
}
|
|
2050
|
+
} else {
|
|
2051
|
+
handle = await loadOrSeed(repo, documentId, initialDoc, docIdString, (r) => {
|
|
2052
|
+
exitReason = r;
|
|
2053
|
+
});
|
|
1970
2054
|
}
|
|
1971
|
-
const loadPromise = repo.storageSubsystem?.loadDoc(documentId);
|
|
1972
|
-
const stored = loadPromise ? await withStorageTimeout("loadDoc", docIdString, loadPromise) : undefined;
|
|
1973
|
-
if (stored) {
|
|
1974
|
-
exitReason = "loaded-from-storage";
|
|
1975
|
-
return repo.find(documentId, { allowableStates: ["ready"] });
|
|
1976
|
-
}
|
|
1977
|
-
const seeded = Automerge.save(Automerge.from(initialDoc));
|
|
1978
|
-
const handle = repo.import(seeded, { docId: documentId });
|
|
1979
|
-
handle.doneLoading();
|
|
1980
|
-
exitReason = "seeded-and-imported";
|
|
1981
2055
|
return handle;
|
|
1982
2056
|
} catch (err) {
|
|
1983
2057
|
errorMessage = err instanceof Error ? err.message : String(err);
|
|
@@ -1997,6 +2071,19 @@ function buildHandleFactory(repo, key, initialDoc) {
|
|
|
1997
2071
|
}
|
|
1998
2072
|
};
|
|
1999
2073
|
}
|
|
2074
|
+
async function loadOrSeed(repo, documentId, initialDoc, docIdString, setExitReason) {
|
|
2075
|
+
const loadPromise = repo.storageSubsystem?.loadDoc(documentId);
|
|
2076
|
+
const stored = loadPromise ? await withStorageTimeout("loadDoc", docIdString, loadPromise) : undefined;
|
|
2077
|
+
if (stored) {
|
|
2078
|
+
setExitReason("loaded-from-storage");
|
|
2079
|
+
return repo.find(documentId, { allowableStates: ["ready"] });
|
|
2080
|
+
}
|
|
2081
|
+
const seeded = Automerge.save(Automerge.from(initialDoc));
|
|
2082
|
+
const handle = repo.import(seeded, { docId: documentId });
|
|
2083
|
+
handle.doneLoading();
|
|
2084
|
+
setExitReason("seeded-and-imported");
|
|
2085
|
+
return handle;
|
|
2086
|
+
}
|
|
2000
2087
|
function attachLoadedRejectionSink(primitive) {
|
|
2001
2088
|
primitive.loaded.catch((err) => {
|
|
2002
2089
|
recordLoadedRejection(err);
|
|
@@ -2010,11 +2097,35 @@ function $meshState(key, initialValue, options = {}) {
|
|
|
2010
2097
|
primitive: "meshState",
|
|
2011
2098
|
initialValue,
|
|
2012
2099
|
getHandle: buildHandleFactory(repo, key, initialValue),
|
|
2100
|
+
resolveRedirect: buildRedirectResolver(repo),
|
|
2013
2101
|
schemaVersion: options.schemaVersion,
|
|
2014
2102
|
migrations: options.migrations,
|
|
2015
2103
|
access: options.access
|
|
2016
2104
|
}));
|
|
2017
2105
|
}
|
|
2106
|
+
function buildRedirectResolver(repo) {
|
|
2107
|
+
if (!redirectDetector) {}
|
|
2108
|
+
return async (_handle, doc) => {
|
|
2109
|
+
const detector = redirectDetector;
|
|
2110
|
+
if (!detector)
|
|
2111
|
+
return;
|
|
2112
|
+
let nextId;
|
|
2113
|
+
try {
|
|
2114
|
+
nextId = detector(doc);
|
|
2115
|
+
} catch {
|
|
2116
|
+
return;
|
|
2117
|
+
}
|
|
2118
|
+
if (!nextId)
|
|
2119
|
+
return;
|
|
2120
|
+
try {
|
|
2121
|
+
return await repo.find(nextId, {
|
|
2122
|
+
allowableStates: ["ready", "unavailable"]
|
|
2123
|
+
});
|
|
2124
|
+
} catch {
|
|
2125
|
+
return;
|
|
2126
|
+
}
|
|
2127
|
+
};
|
|
2128
|
+
}
|
|
2018
2129
|
function $meshText(key, initialValue, options = {}) {
|
|
2019
2130
|
const repo = resolveRepo(options.repo);
|
|
2020
2131
|
return attachLoadedRejectionSink($crdtText(key, initialValue, {
|
|
@@ -2253,7 +2364,9 @@ function serialiseSlotView(slot) {
|
|
|
2253
2364
|
selectedCandidatePair: slot.transport.selectedCandidatePair ? { ...slot.transport.selectedCandidatePair } : undefined
|
|
2254
2365
|
} : undefined,
|
|
2255
2366
|
lastSyncHandshakeAttempt: { ...slot.lastSyncHandshakeAttempt },
|
|
2256
|
-
handles
|
|
2367
|
+
handles,
|
|
2368
|
+
createdAt: slot.createdAt,
|
|
2369
|
+
lastInboundAt: slot.lastInboundAt
|
|
2257
2370
|
};
|
|
2258
2371
|
}
|
|
2259
2372
|
function emptySyncHandshakeAttempt() {
|
|
@@ -2280,6 +2393,9 @@ var DEFAULT_ICE_SERVERS = [
|
|
|
2280
2393
|
{ urls: "stun:stun.l.google.com:19302" },
|
|
2281
2394
|
{ urls: "stun:stun1.l.google.com:19302" }
|
|
2282
2395
|
];
|
|
2396
|
+
var SLOT_NEVER_CONNECTED_TIMEOUT_MS = 30000;
|
|
2397
|
+
var SLOT_IDLE_TIMEOUT_MS = 120000;
|
|
2398
|
+
var SLOT_WATCHDOG_INTERVAL_MS = 5000;
|
|
2283
2399
|
function emptyHandleSyncSnapshot() {
|
|
2284
2400
|
return {
|
|
2285
2401
|
lastSyncMessageOutAt: undefined,
|
|
@@ -2310,6 +2426,10 @@ class MeshWebRTCAdapter extends NetworkAdapter2 {
|
|
|
2310
2426
|
lastSlotInitiationDecisions = new Map;
|
|
2311
2427
|
sweepRunCount = 0;
|
|
2312
2428
|
lastSweepAt;
|
|
2429
|
+
slotWatchdogTimer;
|
|
2430
|
+
slotNeverConnectedTimeoutMs;
|
|
2431
|
+
slotIdleTimeoutMs;
|
|
2432
|
+
slotWatchdogIntervalMs;
|
|
2313
2433
|
get knownPeerIds() {
|
|
2314
2434
|
if (this.keyringSource !== undefined) {
|
|
2315
2435
|
return [...this.keyringSource().knownPeers.keys()].filter((id) => id !== this.localPeerId);
|
|
@@ -2335,6 +2455,9 @@ class MeshWebRTCAdapter extends NetworkAdapter2 {
|
|
|
2335
2455
|
this.knownPeersRefreshIntervalMs = options.knownPeersRefreshIntervalMs ?? 2000;
|
|
2336
2456
|
this.syncYieldEnabled = options.syncYieldEnabled ?? true;
|
|
2337
2457
|
this.syncFragmentChunkSize = options.syncFragmentChunkSizeOverride ?? SYNC_FRAGMENT_CHUNK_SIZE;
|
|
2458
|
+
this.slotNeverConnectedTimeoutMs = options.slotNeverConnectedTimeoutMs ?? SLOT_NEVER_CONNECTED_TIMEOUT_MS;
|
|
2459
|
+
this.slotIdleTimeoutMs = options.slotIdleTimeoutMs ?? SLOT_IDLE_TIMEOUT_MS;
|
|
2460
|
+
this.slotWatchdogIntervalMs = options.slotWatchdogIntervalMs ?? SLOT_WATCHDOG_INTERVAL_MS;
|
|
2338
2461
|
this.localPeerId = options.peerId;
|
|
2339
2462
|
const PC = options.RTCPeerConnection ?? globalThis.RTCPeerConnection;
|
|
2340
2463
|
if (typeof PC !== "function") {
|
|
@@ -2492,9 +2615,11 @@ class MeshWebRTCAdapter extends NetworkAdapter2 {
|
|
|
2492
2615
|
this.ready = true;
|
|
2493
2616
|
this.readyResolver?.();
|
|
2494
2617
|
this.startKnownPeersSweep();
|
|
2618
|
+
this.startSlotWatchdog();
|
|
2495
2619
|
}
|
|
2496
2620
|
disconnect() {
|
|
2497
2621
|
this.stopKnownPeersSweep();
|
|
2622
|
+
this.stopSlotWatchdog();
|
|
2498
2623
|
for (const slot of this.slots.values()) {
|
|
2499
2624
|
slot.channel?.close();
|
|
2500
2625
|
slot.connection.close();
|
|
@@ -2525,6 +2650,70 @@ class MeshWebRTCAdapter extends NetworkAdapter2 {
|
|
|
2525
2650
|
clearInterval(this.knownPeersRefreshTimer);
|
|
2526
2651
|
this.knownPeersRefreshTimer = undefined;
|
|
2527
2652
|
}
|
|
2653
|
+
tearDownWedgedSlot(peerId) {
|
|
2654
|
+
const slot = this.slots.get(peerId);
|
|
2655
|
+
if (!slot)
|
|
2656
|
+
return;
|
|
2657
|
+
this.slots.delete(peerId);
|
|
2658
|
+
try {
|
|
2659
|
+
slot.channel?.close();
|
|
2660
|
+
} catch {}
|
|
2661
|
+
try {
|
|
2662
|
+
slot.connection.close();
|
|
2663
|
+
} catch {}
|
|
2664
|
+
this.emit("peer-disconnected", { peerId });
|
|
2665
|
+
}
|
|
2666
|
+
startSlotWatchdog() {
|
|
2667
|
+
if (this.slotWatchdogIntervalMs <= 0)
|
|
2668
|
+
return;
|
|
2669
|
+
if (this.slotWatchdogTimer !== undefined)
|
|
2670
|
+
return;
|
|
2671
|
+
this.slotWatchdogTimer = setInterval(() => {
|
|
2672
|
+
try {
|
|
2673
|
+
this.sweepWedgedSlots();
|
|
2674
|
+
} catch {}
|
|
2675
|
+
}, this.slotWatchdogIntervalMs);
|
|
2676
|
+
}
|
|
2677
|
+
stopSlotWatchdog() {
|
|
2678
|
+
if (this.slotWatchdogTimer === undefined)
|
|
2679
|
+
return;
|
|
2680
|
+
clearInterval(this.slotWatchdogTimer);
|
|
2681
|
+
this.slotWatchdogTimer = undefined;
|
|
2682
|
+
}
|
|
2683
|
+
sweepWedgedSlots() {
|
|
2684
|
+
const now = performance.now();
|
|
2685
|
+
const peerIds = [...this.slots.keys()];
|
|
2686
|
+
for (const peerId of peerIds) {
|
|
2687
|
+
const slot = this.slots.get(peerId);
|
|
2688
|
+
if (!slot)
|
|
2689
|
+
continue;
|
|
2690
|
+
const reason = this.classifyWedgedSlot(slot, now);
|
|
2691
|
+
if (!reason)
|
|
2692
|
+
continue;
|
|
2693
|
+
this.lastSlotInitiationDecisions.set(peerId, {
|
|
2694
|
+
decision: "rejected",
|
|
2695
|
+
reason: "fatal-error",
|
|
2696
|
+
error: reason,
|
|
2697
|
+
at: now
|
|
2698
|
+
});
|
|
2699
|
+
this.tearDownWedgedSlot(peerId);
|
|
2700
|
+
}
|
|
2701
|
+
}
|
|
2702
|
+
classifyWedgedSlot(slot, now) {
|
|
2703
|
+
const state = slot.connection.connectionState;
|
|
2704
|
+
const ageMs = now - slot.createdAt;
|
|
2705
|
+
if (this.slotNeverConnectedTimeoutMs > 0 && (state === "new" || state === "connecting") && ageMs > this.slotNeverConnectedTimeoutMs) {
|
|
2706
|
+
return `slot never reached connected (state=${state}) after ${Math.round(ageMs)}ms`;
|
|
2707
|
+
}
|
|
2708
|
+
if (this.slotIdleTimeoutMs > 0 && state === "connected" && slot.channel?.readyState === "open") {
|
|
2709
|
+
const lastInbound = slot.lastInboundAt ?? slot.createdAt;
|
|
2710
|
+
const idleMs = now - lastInbound;
|
|
2711
|
+
if (idleMs > this.slotIdleTimeoutMs) {
|
|
2712
|
+
return `slot idle: no inbound bytes for ${Math.round(idleMs)}ms (state=connected, dc=open)`;
|
|
2713
|
+
}
|
|
2714
|
+
}
|
|
2715
|
+
return;
|
|
2716
|
+
}
|
|
2528
2717
|
send(message) {
|
|
2529
2718
|
const targetId = message.targetId;
|
|
2530
2719
|
const bytes = this.serialiseMessage(message);
|
|
@@ -2660,12 +2849,23 @@ class MeshWebRTCAdapter extends NetworkAdapter2 {
|
|
|
2660
2849
|
transport: undefined,
|
|
2661
2850
|
lastDataChannelError: undefined,
|
|
2662
2851
|
lastSyncHandshakeAttempt: emptySyncHandshakeAttempt(),
|
|
2663
|
-
handles: new Map
|
|
2852
|
+
handles: new Map,
|
|
2853
|
+
createdAt: performance.now(),
|
|
2854
|
+
lastInboundAt: undefined
|
|
2664
2855
|
};
|
|
2665
2856
|
this.slots.set(targetId, slot);
|
|
2666
2857
|
this.wireConnection(targetId, connection);
|
|
2667
2858
|
this.wireDataChannel(targetId, channel);
|
|
2668
|
-
this.initiateOffer(targetId, connection)
|
|
2859
|
+
this.initiateOffer(targetId, connection).catch((err) => {
|
|
2860
|
+
const message = err instanceof Error ? err.message : String(err);
|
|
2861
|
+
this.lastSlotInitiationDecisions.set(targetId, {
|
|
2862
|
+
decision: "rejected",
|
|
2863
|
+
reason: "fatal-error",
|
|
2864
|
+
error: message,
|
|
2865
|
+
at: performance.now()
|
|
2866
|
+
});
|
|
2867
|
+
this.tearDownWedgedSlot(targetId);
|
|
2868
|
+
});
|
|
2669
2869
|
return slot;
|
|
2670
2870
|
}
|
|
2671
2871
|
async initiateOffer(targetId, connection) {
|
|
@@ -2703,7 +2903,9 @@ class MeshWebRTCAdapter extends NetworkAdapter2 {
|
|
|
2703
2903
|
transport: undefined,
|
|
2704
2904
|
lastDataChannelError: undefined,
|
|
2705
2905
|
lastSyncHandshakeAttempt: emptySyncHandshakeAttempt(),
|
|
2706
|
-
handles: new Map
|
|
2906
|
+
handles: new Map,
|
|
2907
|
+
createdAt: performance.now(),
|
|
2908
|
+
lastInboundAt: undefined
|
|
2707
2909
|
};
|
|
2708
2910
|
this.slots.set(fromPeerId, slot);
|
|
2709
2911
|
this.wireConnection(fromPeerId, connection);
|
|
@@ -2775,6 +2977,8 @@ class MeshWebRTCAdapter extends NetworkAdapter2 {
|
|
|
2775
2977
|
if (state === "connected") {
|
|
2776
2978
|
this.emitPeerCandidateOnce(peerId);
|
|
2777
2979
|
} else if (state === "disconnected" || state === "failed" || state === "closed") {
|
|
2980
|
+
if (!this.slots.has(peerId))
|
|
2981
|
+
return;
|
|
2778
2982
|
this.slots.delete(peerId);
|
|
2779
2983
|
this.emit("peer-disconnected", { peerId });
|
|
2780
2984
|
}
|
|
@@ -2805,6 +3009,9 @@ class MeshWebRTCAdapter extends NetworkAdapter2 {
|
|
|
2805
3009
|
slot.pendingSends = [];
|
|
2806
3010
|
};
|
|
2807
3011
|
channel.onmessage = (event) => {
|
|
3012
|
+
const liveSlot = this.slots.get(peerId);
|
|
3013
|
+
if (liveSlot)
|
|
3014
|
+
liveSlot.lastInboundAt = performance.now();
|
|
2808
3015
|
const data = event.data;
|
|
2809
3016
|
if (data instanceof ArrayBuffer) {
|
|
2810
3017
|
this.dispatchMessage(peerId, new Uint8Array(data));
|
|
@@ -3630,6 +3837,7 @@ export {
|
|
|
3630
3837
|
revokePeerLocally,
|
|
3631
3838
|
resolveDocumentId,
|
|
3632
3839
|
resetMeshState,
|
|
3840
|
+
registerRedirectDetector,
|
|
3633
3841
|
registerDocIdResolver,
|
|
3634
3842
|
parsePairingToken,
|
|
3635
3843
|
memoryKeyringStorage,
|
|
@@ -3637,6 +3845,7 @@ export {
|
|
|
3637
3845
|
isMeshStateConfigured,
|
|
3638
3846
|
isBlobRef,
|
|
3639
3847
|
getStorageOpenError,
|
|
3848
|
+
getRedirectDetector,
|
|
3640
3849
|
getMeshStateModuleId,
|
|
3641
3850
|
getLazyWrappers,
|
|
3642
3851
|
getLazyReachedRepo,
|
|
@@ -3694,4 +3903,4 @@ export {
|
|
|
3694
3903
|
$meshCounter
|
|
3695
3904
|
};
|
|
3696
3905
|
|
|
3697
|
-
//# debugId=
|
|
3906
|
+
//# debugId=9FE5660EB3793A1964756E2164756E21
|