mirror of
https://github.com/clash-verge-rev/clash-verge-rev.git
synced 2026-04-13 05:20:28 +08:00
Add leading-edge throttle to useMihomoWsSubscription, reduce SWR retry aggressiveness, and increase WebSocket reconnect delay to prevent event storms when switching profiles under poor network conditions.
This commit is contained in:
parent
3714f0c4c8
commit
824bcc77eb
@ -81,6 +81,7 @@ export const useConnectionData = () => {
|
||||
buildSubscriptKey: (date) => `getClashConnection-${date}`,
|
||||
fallbackData: initConnData,
|
||||
connect: () => MihomoWebSocket.connect_connections(),
|
||||
throttleMs: 16,
|
||||
setupHandlers: ({ next, scheduleReconnect }) => ({
|
||||
handleMessage: (data) => {
|
||||
if (data.startsWith('Websocket error')) {
|
||||
@ -89,14 +90,9 @@ export const useConnectionData = () => {
|
||||
return
|
||||
}
|
||||
|
||||
try {
|
||||
const parsed = JSON.parse(data) as IConnections
|
||||
next(null, (old = initConnData) =>
|
||||
mergeConnectionSnapshot(parsed, old),
|
||||
)
|
||||
} catch (error) {
|
||||
next(error)
|
||||
}
|
||||
next(null, (old = initConnData) =>
|
||||
mergeConnectionSnapshot(JSON.parse(data) as IConnections, old),
|
||||
)
|
||||
},
|
||||
}),
|
||||
})
|
||||
|
||||
@ -15,6 +15,7 @@ export const useMemoryData = () => {
|
||||
buildSubscriptKey: (date) => `getClashMemory-${date}`,
|
||||
fallbackData: FALLBACK_MEMORY_USAGE,
|
||||
connect: () => MihomoWebSocket.connect_memory(),
|
||||
throttleMs: 500,
|
||||
setupHandlers: ({ next, scheduleReconnect }) => ({
|
||||
handleMessage: (data) => {
|
||||
if (data.startsWith('Websocket error')) {
|
||||
|
||||
@ -4,7 +4,7 @@ import { mutate, type MutatorCallback } from 'swr'
|
||||
import useSWRSubscription from 'swr/subscription'
|
||||
import { type Message, type MihomoWebSocket } from 'tauri-plugin-mihomo-api'
|
||||
|
||||
export const RECONNECT_DELAY_MS = 100
|
||||
export const RECONNECT_DELAY_MS = 1000
|
||||
|
||||
type NextFn<T> = (error?: any, data?: T | MutatorCallback<T>) => void
|
||||
|
||||
@ -26,6 +26,15 @@ interface UseMihomoWsSubscriptionOptions<T> {
|
||||
fallbackData: T
|
||||
connect: () => Promise<MihomoWebSocket>
|
||||
keepPreviousData?: boolean
|
||||
/**
|
||||
* When > 0, coalesce rapid WebSocket messages by wrapping the `next`
|
||||
* function passed to `setupHandlers`. Only the most recent value is
|
||||
* flushed, at most once per `throttleMs` milliseconds.
|
||||
*
|
||||
* Uses `setTimeout` (not `requestAnimationFrame`) so it keeps working
|
||||
* when the window is backgrounded or minimized.
|
||||
*/
|
||||
throttleMs?: number
|
||||
setupHandlers: (ctx: HandlerContext<T>) => HandlerResult
|
||||
}
|
||||
|
||||
@ -38,6 +47,7 @@ export const useMihomoWsSubscription = <T>(
|
||||
fallbackData,
|
||||
connect,
|
||||
keepPreviousData = true,
|
||||
throttleMs,
|
||||
setupHandlers,
|
||||
} = options
|
||||
|
||||
@ -77,18 +87,59 @@ export const useMihomoWsSubscription = <T>(
|
||||
timeoutRef.current = setTimeout(connectWs, RECONNECT_DELAY_MS)
|
||||
}
|
||||
|
||||
let throttleCleanup: (() => void) | undefined
|
||||
let wrappedNext: NextFn<T> = next
|
||||
|
||||
if (throttleMs && throttleMs > 0) {
|
||||
let pendingData: T | MutatorCallback<T> | undefined
|
||||
let hasPending = false
|
||||
let timerId: ReturnType<typeof setTimeout> | null = null
|
||||
|
||||
const flush = () => {
|
||||
timerId = null
|
||||
if (hasPending) {
|
||||
const data = pendingData
|
||||
pendingData = undefined
|
||||
hasPending = false
|
||||
next(undefined, data)
|
||||
}
|
||||
}
|
||||
|
||||
wrappedNext = (error?: any, data?: T | MutatorCallback<T>) => {
|
||||
if (error !== undefined && error !== null) {
|
||||
next(error, data)
|
||||
return
|
||||
}
|
||||
if (!timerId) {
|
||||
next(undefined, data)
|
||||
timerId = setTimeout(flush, throttleMs)
|
||||
} else {
|
||||
pendingData = data
|
||||
hasPending = true
|
||||
}
|
||||
}
|
||||
|
||||
throttleCleanup = () => {
|
||||
if (timerId) {
|
||||
clearTimeout(timerId)
|
||||
timerId = null
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
const {
|
||||
handleMessage: handleTextMessage,
|
||||
onConnected,
|
||||
cleanup,
|
||||
} = setupHandlers({
|
||||
next,
|
||||
next: wrappedNext,
|
||||
scheduleReconnect,
|
||||
isMounted: () => isMounted,
|
||||
})
|
||||
|
||||
const cleanupAll = () => {
|
||||
clearReconnectTimer()
|
||||
throttleCleanup?.()
|
||||
cleanup?.()
|
||||
void closeSocket()
|
||||
}
|
||||
|
||||
@ -16,6 +16,7 @@ export const useTrafficData = (options?: { enabled?: boolean }) => {
|
||||
buildSubscriptKey: (date) => `getClashTraffic-${date}`,
|
||||
fallbackData: FALLBACK_TRAFFIC,
|
||||
connect: () => MihomoWebSocket.connect_traffic(),
|
||||
throttleMs: 200,
|
||||
setupHandlers: ({ next, scheduleReconnect }) => ({
|
||||
handleMessage: (data) => {
|
||||
if (data.startsWith('Websocket error')) {
|
||||
|
||||
@ -23,8 +23,8 @@ export const SWR_SLOW_POLL = {
|
||||
|
||||
export const SWR_MIHOMO = {
|
||||
...SWR_NOT_SMART,
|
||||
errorRetryInterval: 500,
|
||||
errorRetryCount: 15,
|
||||
errorRetryInterval: 2000,
|
||||
errorRetryCount: 3,
|
||||
}
|
||||
|
||||
export const SWR_EXTERNAL_API = {
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user