@adventurelabs/scout-core 1.0.55 → 1.0.56
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/hooks/useScoutDbListener.js +69 -19
- package/package.json +1 -1
|
@@ -6,6 +6,11 @@ export function useScoutDbListener(scoutSupabase) {
|
|
|
6
6
|
const supabase = useRef(null);
|
|
7
7
|
const channels = useRef([]);
|
|
8
8
|
const dispatch = useAppDispatch();
|
|
9
|
+
const reconnectTimeoutRef = useRef(null);
|
|
10
|
+
const reconnectAttemptsRef = useRef(0);
|
|
11
|
+
const maxReconnectAttempts = 10;
|
|
12
|
+
const baseDelay = 1000; // 1 second
|
|
13
|
+
const maxDelay = 5000; // 5 seconds
|
|
9
14
|
function handleTagInserts(payload) {
|
|
10
15
|
console.log("[DB Listener] Tag INSERT received:", payload.new);
|
|
11
16
|
dispatch(addTag(payload.new));
|
|
@@ -71,15 +76,20 @@ export function useScoutDbListener(scoutSupabase) {
|
|
|
71
76
|
function handleConnectivityUpdates(payload) {
|
|
72
77
|
console.log("[DB Listener] Connectivity UPDATE received:", payload.new);
|
|
73
78
|
}
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
79
|
+
// Clean up all channels
|
|
80
|
+
const cleanupChannels = () => {
|
|
81
|
+
channels.current.forEach((channel) => {
|
|
82
|
+
if (channel) {
|
|
83
|
+
scoutSupabase.removeChannel(channel);
|
|
84
|
+
}
|
|
85
|
+
});
|
|
86
|
+
channels.current = [];
|
|
87
|
+
};
|
|
88
|
+
// Setup channel with event handlers
|
|
89
|
+
const setupChannel = () => {
|
|
90
|
+
if (!scoutSupabase)
|
|
91
|
+
return null;
|
|
92
|
+
const mainChannel = scoutSupabase.channel("schema_db_changes");
|
|
83
93
|
// Subscribe to all events
|
|
84
94
|
mainChannel
|
|
85
95
|
.on("postgres_changes", { event: "INSERT", schema: "public", table: "plans" }, handlePlanInserts)
|
|
@@ -101,27 +111,67 @@ export function useScoutDbListener(scoutSupabase) {
|
|
|
101
111
|
console.log("[DB Listener] Subscription status:", status);
|
|
102
112
|
if (status === "SUBSCRIBED") {
|
|
103
113
|
console.log("[DB Listener] ✅ Successfully subscribed to real-time updates");
|
|
114
|
+
reconnectAttemptsRef.current = 0; // Reset reconnect attempts on successful connection
|
|
104
115
|
}
|
|
105
116
|
else if (status === "CHANNEL_ERROR") {
|
|
106
|
-
console.error("[DB Listener] ❌ Channel error occurred");
|
|
117
|
+
console.error("[DB Listener] ❌ Channel error occurred. Reconnecting...");
|
|
118
|
+
handleReconnect();
|
|
107
119
|
}
|
|
108
120
|
else if (status === "TIMED_OUT") {
|
|
109
|
-
console.error("[DB Listener] ⏰ Subscription timed out");
|
|
121
|
+
console.error("[DB Listener] ⏰ Subscription timed out. Reconnecting...");
|
|
122
|
+
handleReconnect();
|
|
110
123
|
}
|
|
111
124
|
else if (status === "CLOSED") {
|
|
112
|
-
console.log("[DB Listener] 🔒 Channel closed");
|
|
125
|
+
console.log("[DB Listener] 🔒 Channel closed. Reconnecting...");
|
|
126
|
+
handleReconnect();
|
|
113
127
|
}
|
|
114
128
|
});
|
|
115
|
-
|
|
129
|
+
return mainChannel;
|
|
130
|
+
};
|
|
131
|
+
// Handle reconnection with exponential backoff
|
|
132
|
+
const handleReconnect = () => {
|
|
133
|
+
if (reconnectAttemptsRef.current >= maxReconnectAttempts) {
|
|
134
|
+
console.error("[DB Listener] 🚫 Max reconnection attempts reached");
|
|
135
|
+
return;
|
|
136
|
+
}
|
|
137
|
+
// Clear any existing timeout
|
|
138
|
+
if (reconnectTimeoutRef.current) {
|
|
139
|
+
clearTimeout(reconnectTimeoutRef.current);
|
|
140
|
+
}
|
|
141
|
+
const delay = Math.min(baseDelay * (reconnectAttemptsRef.current + 1), maxDelay);
|
|
142
|
+
console.log(`[DB Listener] 🔄 Attempting reconnection in ${delay}ms (attempt ${reconnectAttemptsRef.current + 1}/${maxReconnectAttempts})`);
|
|
143
|
+
reconnectTimeoutRef.current = setTimeout(() => {
|
|
144
|
+
reconnectAttemptsRef.current++;
|
|
145
|
+
cleanupChannels();
|
|
146
|
+
const newChannel = setupChannel();
|
|
147
|
+
if (newChannel) {
|
|
148
|
+
channels.current.push(newChannel);
|
|
149
|
+
}
|
|
150
|
+
}, delay);
|
|
151
|
+
};
|
|
152
|
+
useEffect(() => {
|
|
153
|
+
if (!scoutSupabase) {
|
|
154
|
+
console.error("[DB Listener] No Supabase client available");
|
|
155
|
+
return;
|
|
156
|
+
}
|
|
157
|
+
supabase.current = scoutSupabase;
|
|
158
|
+
// Initial channel setup
|
|
159
|
+
const mainChannel = setupChannel();
|
|
160
|
+
if (mainChannel) {
|
|
161
|
+
channels.current.push(mainChannel);
|
|
162
|
+
}
|
|
116
163
|
// Cleanup function
|
|
117
164
|
return () => {
|
|
118
165
|
console.log("[DB Listener] 🧹 Cleaning up channels");
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
}
|
|
124
|
-
|
|
166
|
+
// Clear any pending reconnection attempts
|
|
167
|
+
if (reconnectTimeoutRef.current) {
|
|
168
|
+
clearTimeout(reconnectTimeoutRef.current);
|
|
169
|
+
reconnectTimeoutRef.current = null;
|
|
170
|
+
}
|
|
171
|
+
// Reset reconnect attempts
|
|
172
|
+
reconnectAttemptsRef.current = 0;
|
|
173
|
+
// Clean up channels
|
|
174
|
+
cleanupChannels();
|
|
125
175
|
};
|
|
126
176
|
}, [scoutSupabase, dispatch]);
|
|
127
177
|
}
|