@chromahq/react 1.0.36 → 1.0.40
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/index.d.ts +8 -1
- package/dist/index.js +44 -20
- package/package.json +1 -1
package/dist/index.d.ts
CHANGED
|
@@ -32,8 +32,15 @@ interface BridgeProviderProps {
|
|
|
32
32
|
pingInterval?: number;
|
|
33
33
|
/** How long to wait before resetting retry count in ms. Default: 30000 */
|
|
34
34
|
maxRetryCooldown?: number;
|
|
35
|
-
/** Default timeout for messages in ms. Default:
|
|
35
|
+
/** Default timeout for messages in ms. Default: 30000 */
|
|
36
36
|
defaultTimeout?: number;
|
|
37
|
+
/**
|
|
38
|
+
* Timeout threshold for counting failures toward reconnection.
|
|
39
|
+
* Only requests with timeouts <= this value are counted as potential SW issues.
|
|
40
|
+
* Requests with longer timeouts (intentional slow operations) won't trigger reconnection.
|
|
41
|
+
* Default: 15000 (15s)
|
|
42
|
+
*/
|
|
43
|
+
timeoutFailureThreshold?: number;
|
|
37
44
|
/** Callback when connection status changes */
|
|
38
45
|
onConnectionChange?: (status: ConnectionStatus) => void;
|
|
39
46
|
/** Callback when an error occurs */
|
package/dist/index.js
CHANGED
|
@@ -5,22 +5,26 @@ const BRIDGE_ENABLE_LOGS = true;
|
|
|
5
5
|
const CONFIG = {
|
|
6
6
|
RETRY_AFTER: 1e3,
|
|
7
7
|
MAX_RETRIES: 10,
|
|
8
|
-
PING_INTERVAL:
|
|
9
|
-
// Check every
|
|
8
|
+
PING_INTERVAL: 5e3,
|
|
9
|
+
// Check every 5s (reduced frequency to avoid false positives during heavy operations)
|
|
10
10
|
MAX_RETRY_COOLDOWN: 3e4,
|
|
11
|
-
DEFAULT_TIMEOUT:
|
|
11
|
+
DEFAULT_TIMEOUT: 3e4,
|
|
12
|
+
// Increased from 20s to 30s for slow operations
|
|
12
13
|
MAX_RETRY_DELAY: 3e4,
|
|
13
|
-
PING_TIMEOUT:
|
|
14
|
-
// Give SW
|
|
14
|
+
PING_TIMEOUT: 1e4,
|
|
15
|
+
// Give SW 10s to respond (handles busy periods like large storage reads)
|
|
15
16
|
ERROR_CHECK_INTERVAL: 100,
|
|
16
17
|
MAX_ERROR_CHECKS: 10,
|
|
17
|
-
CONSECUTIVE_FAILURE_THRESHOLD:
|
|
18
|
-
// Require
|
|
18
|
+
CONSECUTIVE_FAILURE_THRESHOLD: 5,
|
|
19
|
+
// Require 5 consecutive failures (25s total) before reconnecting
|
|
19
20
|
RECONNECT_DELAY: 100,
|
|
20
21
|
PORT_NAME: "chroma-bridge",
|
|
21
22
|
// Service worker restart retry settings (indefinite retries)
|
|
22
23
|
SW_RESTART_RETRY_DELAY: 500,
|
|
23
|
-
SW_RESTART_MAX_DELAY: 5e3
|
|
24
|
+
SW_RESTART_MAX_DELAY: 5e3,
|
|
25
|
+
// Threshold for counting timeouts toward reconnection (only count fast timeouts as failures)
|
|
26
|
+
TIMEOUT_FAILURE_THRESHOLD_MS: 15e3
|
|
27
|
+
// Only count timeouts < 15s as potential SW issues
|
|
24
28
|
};
|
|
25
29
|
const calculateBackoffDelay = (attempt, baseDelay, maxDelay) => Math.min(baseDelay * Math.pow(2, attempt - 1), maxDelay);
|
|
26
30
|
const clearTimeoutSafe = (ref) => {
|
|
@@ -52,14 +56,17 @@ function createBridgeInstance(deps) {
|
|
|
52
56
|
reconnectionGracePeriodRef,
|
|
53
57
|
healthPausedUntilRef,
|
|
54
58
|
defaultTimeout,
|
|
59
|
+
timeoutFailureThreshold,
|
|
55
60
|
onReconnectNeeded
|
|
56
61
|
} = deps;
|
|
57
62
|
const rejectAllPending = (message) => {
|
|
58
|
-
pendingRequestsRef.current.forEach(({ reject, timeout }) => {
|
|
59
|
-
|
|
60
|
-
|
|
63
|
+
pendingRequestsRef.current.forEach(({ reject, timeout, timeoutDuration }, id) => {
|
|
64
|
+
if (timeoutDuration <= timeoutFailureThreshold) {
|
|
65
|
+
clearTimeout(timeout);
|
|
66
|
+
reject(new Error(message));
|
|
67
|
+
pendingRequestsRef.current.delete(id);
|
|
68
|
+
}
|
|
61
69
|
});
|
|
62
|
-
pendingRequestsRef.current.clear();
|
|
63
70
|
};
|
|
64
71
|
const send = (key, payload, timeoutDuration = defaultTimeout) => {
|
|
65
72
|
return new Promise((resolve, reject) => {
|
|
@@ -71,15 +78,16 @@ function createBridgeInstance(deps) {
|
|
|
71
78
|
const timeout = setTimeout(() => {
|
|
72
79
|
if (!pendingRequestsRef.current.has(id)) return;
|
|
73
80
|
pendingRequestsRef.current.delete(id);
|
|
74
|
-
|
|
81
|
+
const isShortTimeout = timeoutDuration <= timeoutFailureThreshold;
|
|
82
|
+
if (!reconnectionGracePeriodRef.current && isShortTimeout) {
|
|
75
83
|
consecutiveTimeoutsRef.current++;
|
|
76
84
|
}
|
|
77
85
|
{
|
|
78
86
|
console.warn(
|
|
79
|
-
`[Bridge] Request timed out: ${key} (${timeoutDuration}ms)${reconnectionGracePeriodRef.current ? " [grace period]" : ""}`
|
|
87
|
+
`[Bridge] Request timed out: ${key} (${timeoutDuration}ms)${reconnectionGracePeriodRef.current ? " [grace period]" : ""}${!isShortTimeout ? " [long operation, not counted toward reconnect]" : ""}`
|
|
80
88
|
);
|
|
81
89
|
}
|
|
82
|
-
if (!reconnectionGracePeriodRef.current && consecutiveTimeoutsRef.current >= CONFIG.CONSECUTIVE_FAILURE_THRESHOLD) {
|
|
90
|
+
if (!reconnectionGracePeriodRef.current && isShortTimeout && consecutiveTimeoutsRef.current >= CONFIG.CONSECUTIVE_FAILURE_THRESHOLD) {
|
|
83
91
|
{
|
|
84
92
|
console.warn(
|
|
85
93
|
`[Bridge] ${consecutiveTimeoutsRef.current} consecutive timeouts, reconnecting...`
|
|
@@ -94,7 +102,8 @@ function createBridgeInstance(deps) {
|
|
|
94
102
|
pendingRequestsRef.current.set(id, {
|
|
95
103
|
resolve,
|
|
96
104
|
reject,
|
|
97
|
-
timeout
|
|
105
|
+
timeout,
|
|
106
|
+
timeoutDuration
|
|
98
107
|
});
|
|
99
108
|
try {
|
|
100
109
|
portRef.current.postMessage({ id, key, payload });
|
|
@@ -248,6 +257,7 @@ const BridgeProvider = ({
|
|
|
248
257
|
pingInterval = CONFIG.PING_INTERVAL,
|
|
249
258
|
maxRetryCooldown = CONFIG.MAX_RETRY_COOLDOWN,
|
|
250
259
|
defaultTimeout = CONFIG.DEFAULT_TIMEOUT,
|
|
260
|
+
timeoutFailureThreshold = CONFIG.TIMEOUT_FAILURE_THRESHOLD_MS,
|
|
251
261
|
onConnectionChange,
|
|
252
262
|
onError
|
|
253
263
|
}) => {
|
|
@@ -331,6 +341,9 @@ const BridgeProvider = ({
|
|
|
331
341
|
reject(new Error("Bridge disconnected"));
|
|
332
342
|
});
|
|
333
343
|
pendingRequestsRef.current.clear();
|
|
344
|
+
if (!emitDisconnect) {
|
|
345
|
+
eventListenersRef.current.clear();
|
|
346
|
+
}
|
|
334
347
|
setIsServiceWorkerAlive(false);
|
|
335
348
|
setBridge(null);
|
|
336
349
|
isConnectingRef.current = false;
|
|
@@ -359,6 +372,10 @@ const BridgeProvider = ({
|
|
|
359
372
|
}
|
|
360
373
|
}
|
|
361
374
|
});
|
|
375
|
+
return;
|
|
376
|
+
}
|
|
377
|
+
if (message.id && BRIDGE_ENABLE_LOGS) {
|
|
378
|
+
console.warn("[Bridge] Received response for unknown/expired request:", message.id);
|
|
362
379
|
}
|
|
363
380
|
}, []);
|
|
364
381
|
const scheduleReconnect = useCallback(
|
|
@@ -524,6 +541,7 @@ const BridgeProvider = ({
|
|
|
524
541
|
reconnectionGracePeriodRef,
|
|
525
542
|
healthPausedUntilRef,
|
|
526
543
|
defaultTimeout,
|
|
544
|
+
timeoutFailureThreshold,
|
|
527
545
|
onReconnectNeeded: triggerReconnect
|
|
528
546
|
});
|
|
529
547
|
setBridge(bridgeInstance);
|
|
@@ -552,11 +570,13 @@ const BridgeProvider = ({
|
|
|
552
570
|
}
|
|
553
571
|
});
|
|
554
572
|
const rejectAllPendingRequests = (message) => {
|
|
555
|
-
pendingRequestsRef.current.forEach(({ reject, timeout }) => {
|
|
556
|
-
|
|
557
|
-
|
|
573
|
+
pendingRequestsRef.current.forEach(({ reject, timeout, timeoutDuration }, id) => {
|
|
574
|
+
if (timeoutDuration <= timeoutFailureThreshold) {
|
|
575
|
+
clearTimeout(timeout);
|
|
576
|
+
reject(new Error(message));
|
|
577
|
+
pendingRequestsRef.current.delete(id);
|
|
578
|
+
}
|
|
558
579
|
});
|
|
559
|
-
pendingRequestsRef.current.clear();
|
|
560
580
|
consecutiveTimeoutsRef.current = 0;
|
|
561
581
|
};
|
|
562
582
|
startHealthMonitor({
|
|
@@ -614,17 +634,21 @@ const BridgeProvider = ({
|
|
|
614
634
|
isConnectingRef.current = false;
|
|
615
635
|
connect();
|
|
616
636
|
} else if (currentStatus === "connected" && currentBridge) {
|
|
637
|
+
if (isConnectingRef.current) return;
|
|
617
638
|
currentBridge.ping().then((alive) => {
|
|
618
639
|
if (!isMountedRef.current) return;
|
|
640
|
+
if (isConnectingRef.current) return;
|
|
619
641
|
if (!alive) {
|
|
620
642
|
{
|
|
621
643
|
console.warn("[Bridge] Tab visible but unresponsive, reconnecting...");
|
|
622
644
|
}
|
|
623
645
|
retryCountRef.current = 0;
|
|
646
|
+
swRestartRetryCountRef.current = 0;
|
|
624
647
|
isConnectingRef.current = false;
|
|
625
648
|
cleanup();
|
|
626
649
|
connect();
|
|
627
650
|
}
|
|
651
|
+
}).catch(() => {
|
|
628
652
|
});
|
|
629
653
|
}
|
|
630
654
|
};
|