mirror of
https://github.com/clash-verge-rev/clash-verge-rev.git
synced 2026-04-16 23:40:32 +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}`,
|
buildSubscriptKey: (date) => `getClashConnection-${date}`,
|
||||||
fallbackData: initConnData,
|
fallbackData: initConnData,
|
||||||
connect: () => MihomoWebSocket.connect_connections(),
|
connect: () => MihomoWebSocket.connect_connections(),
|
||||||
|
throttleMs: 16,
|
||||||
setupHandlers: ({ next, scheduleReconnect }) => ({
|
setupHandlers: ({ next, scheduleReconnect }) => ({
|
||||||
handleMessage: (data) => {
|
handleMessage: (data) => {
|
||||||
if (data.startsWith('Websocket error')) {
|
if (data.startsWith('Websocket error')) {
|
||||||
@ -89,14 +90,9 @@ export const useConnectionData = () => {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
try {
|
next(null, (old = initConnData) =>
|
||||||
const parsed = JSON.parse(data) as IConnections
|
mergeConnectionSnapshot(JSON.parse(data) as IConnections, old),
|
||||||
next(null, (old = initConnData) =>
|
)
|
||||||
mergeConnectionSnapshot(parsed, old),
|
|
||||||
)
|
|
||||||
} catch (error) {
|
|
||||||
next(error)
|
|
||||||
}
|
|
||||||
},
|
},
|
||||||
}),
|
}),
|
||||||
})
|
})
|
||||||
|
|||||||
@ -15,6 +15,7 @@ export const useMemoryData = () => {
|
|||||||
buildSubscriptKey: (date) => `getClashMemory-${date}`,
|
buildSubscriptKey: (date) => `getClashMemory-${date}`,
|
||||||
fallbackData: FALLBACK_MEMORY_USAGE,
|
fallbackData: FALLBACK_MEMORY_USAGE,
|
||||||
connect: () => MihomoWebSocket.connect_memory(),
|
connect: () => MihomoWebSocket.connect_memory(),
|
||||||
|
throttleMs: 500,
|
||||||
setupHandlers: ({ next, scheduleReconnect }) => ({
|
setupHandlers: ({ next, scheduleReconnect }) => ({
|
||||||
handleMessage: (data) => {
|
handleMessage: (data) => {
|
||||||
if (data.startsWith('Websocket error')) {
|
if (data.startsWith('Websocket error')) {
|
||||||
|
|||||||
@ -4,7 +4,7 @@ import { mutate, type MutatorCallback } from 'swr'
|
|||||||
import useSWRSubscription from 'swr/subscription'
|
import useSWRSubscription from 'swr/subscription'
|
||||||
import { type Message, type MihomoWebSocket } from 'tauri-plugin-mihomo-api'
|
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
|
type NextFn<T> = (error?: any, data?: T | MutatorCallback<T>) => void
|
||||||
|
|
||||||
@ -26,6 +26,15 @@ interface UseMihomoWsSubscriptionOptions<T> {
|
|||||||
fallbackData: T
|
fallbackData: T
|
||||||
connect: () => Promise<MihomoWebSocket>
|
connect: () => Promise<MihomoWebSocket>
|
||||||
keepPreviousData?: boolean
|
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
|
setupHandlers: (ctx: HandlerContext<T>) => HandlerResult
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -38,6 +47,7 @@ export const useMihomoWsSubscription = <T>(
|
|||||||
fallbackData,
|
fallbackData,
|
||||||
connect,
|
connect,
|
||||||
keepPreviousData = true,
|
keepPreviousData = true,
|
||||||
|
throttleMs,
|
||||||
setupHandlers,
|
setupHandlers,
|
||||||
} = options
|
} = options
|
||||||
|
|
||||||
@ -77,18 +87,59 @@ export const useMihomoWsSubscription = <T>(
|
|||||||
timeoutRef.current = setTimeout(connectWs, RECONNECT_DELAY_MS)
|
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 {
|
const {
|
||||||
handleMessage: handleTextMessage,
|
handleMessage: handleTextMessage,
|
||||||
onConnected,
|
onConnected,
|
||||||
cleanup,
|
cleanup,
|
||||||
} = setupHandlers({
|
} = setupHandlers({
|
||||||
next,
|
next: wrappedNext,
|
||||||
scheduleReconnect,
|
scheduleReconnect,
|
||||||
isMounted: () => isMounted,
|
isMounted: () => isMounted,
|
||||||
})
|
})
|
||||||
|
|
||||||
const cleanupAll = () => {
|
const cleanupAll = () => {
|
||||||
clearReconnectTimer()
|
clearReconnectTimer()
|
||||||
|
throttleCleanup?.()
|
||||||
cleanup?.()
|
cleanup?.()
|
||||||
void closeSocket()
|
void closeSocket()
|
||||||
}
|
}
|
||||||
|
|||||||
@ -16,6 +16,7 @@ export const useTrafficData = (options?: { enabled?: boolean }) => {
|
|||||||
buildSubscriptKey: (date) => `getClashTraffic-${date}`,
|
buildSubscriptKey: (date) => `getClashTraffic-${date}`,
|
||||||
fallbackData: FALLBACK_TRAFFIC,
|
fallbackData: FALLBACK_TRAFFIC,
|
||||||
connect: () => MihomoWebSocket.connect_traffic(),
|
connect: () => MihomoWebSocket.connect_traffic(),
|
||||||
|
throttleMs: 200,
|
||||||
setupHandlers: ({ next, scheduleReconnect }) => ({
|
setupHandlers: ({ next, scheduleReconnect }) => ({
|
||||||
handleMessage: (data) => {
|
handleMessage: (data) => {
|
||||||
if (data.startsWith('Websocket error')) {
|
if (data.startsWith('Websocket error')) {
|
||||||
|
|||||||
@ -23,8 +23,8 @@ export const SWR_SLOW_POLL = {
|
|||||||
|
|
||||||
export const SWR_MIHOMO = {
|
export const SWR_MIHOMO = {
|
||||||
...SWR_NOT_SMART,
|
...SWR_NOT_SMART,
|
||||||
errorRetryInterval: 500,
|
errorRetryInterval: 2000,
|
||||||
errorRetryCount: 15,
|
errorRetryCount: 3,
|
||||||
}
|
}
|
||||||
|
|
||||||
export const SWR_EXTERNAL_API = {
|
export const SWR_EXTERNAL_API = {
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user