Skip to content

Commit 76140d5

Browse files
authored
fix: websocket reconnection loop (#3805)
* wip: add reproduction logs * skip reconnection if reconnection in progress * wip * reset to baseline * add reconnect lock * remove logs * remove reproduction environment * Create lazy-turkeys-burn.md * self-review
1 parent 87a7aa5 commit 76140d5

File tree

2 files changed

+28
-25
lines changed

2 files changed

+28
-25
lines changed

.changeset/lazy-turkeys-burn.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
---
2+
"viem": patch
3+
---
4+
5+
Fixed reconnection logic for WebSocket clients.

src/utils/rpc/socket.ts

Lines changed: 23 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -132,6 +132,27 @@ export async function getSocketRpcClient<socket extends {}>(
132132
let socket: Socket<{}>
133133
let keepAliveTimer: ReturnType<typeof setInterval> | undefined
134134

135+
let reconnectInProgress = false
136+
function attemptReconnect() {
137+
// Attempt to reconnect.
138+
if (reconnect && reconnectCount < attempts) {
139+
if (reconnectInProgress) return
140+
reconnectInProgress = true
141+
reconnectCount++
142+
// Make sure the previous socket is definitely closed.
143+
socket?.close()
144+
setTimeout(async () => {
145+
await setup().catch(console.error)
146+
reconnectInProgress = false
147+
}, delay)
148+
}
149+
// Otherwise, clear all requests and subscriptions.
150+
else {
151+
requests.clear()
152+
subscriptions.clear()
153+
}
154+
}
155+
135156
// Set up socket implementation.
136157
async function setup() {
137158
const result = await getSocket({
@@ -142,17 +163,7 @@ export async function getSocketRpcClient<socket extends {}>(
142163
for (const subscription of subscriptions.values())
143164
subscription.onError?.(new SocketClosedError({ url }))
144165

145-
// Attempt to reconnect.
146-
if (reconnect && reconnectCount < attempts)
147-
setTimeout(async () => {
148-
reconnectCount++
149-
await setup().catch(console.error)
150-
}, delay)
151-
// Otherwise, clear all requests and subscriptions.
152-
else {
153-
requests.clear()
154-
subscriptions.clear()
155-
}
166+
attemptReconnect()
156167
},
157168
onError(error_) {
158169
error = error_
@@ -162,20 +173,7 @@ export async function getSocketRpcClient<socket extends {}>(
162173
for (const subscription of subscriptions.values())
163174
subscription.onError?.(error)
164175

165-
// Make sure socket is definitely closed.
166-
socketClient?.close()
167-
168-
// Attempt to reconnect.
169-
if (reconnect && reconnectCount < attempts)
170-
setTimeout(async () => {
171-
reconnectCount++
172-
await setup().catch(console.error)
173-
}, delay)
174-
// Otherwise, clear all requests and subscriptions.
175-
else {
176-
requests.clear()
177-
subscriptions.clear()
178-
}
176+
attemptReconnect()
179177
},
180178
onOpen() {
181179
error = undefined

0 commit comments

Comments
 (0)