Harden background loops and API edge cases from code review

- crawler manager: retry transient errors inside each loop, never let
  log writes break supervision, run tasks in a TaskGroup so any escaped
  error restarts the container instead of leaving a half-dead process
- market worker: tolerate symbols deleted mid-backfill, retry task
  selection and symbol queries, run loops in a TaskGroup
- market WS: validate subscription messages and close the connection
  when either the receive or forward side ends
- news pipeline: make first insert concurrency-safe with ON CONFLICT
- market API: only proxy ticker/1s klines for added symbols, map Binance
  rate limits to 503 and upstream errors to 502 without blocking
- news API: escape LIKE wildcards in search, return 422 for bad cursors
- market page: cancel pending reconnect timer on unmount
This commit is contained in:
eezd committed 2026-10-13 13:51:00 +08:00
1 parent aabc81ba5b
commit 554d224be2
7 files changed
+259 -114

No files matched your search

+6 -1
View File
@@ -36,8 +36,12 @@ export function useMarketSocket(onKline: (k: KlineMessage) => void, onTicker: (t
let current: Subscription | undefined
let retryMs = 1000
let closed = false
let retryTimer: ReturnType<typeof setTimeout> | undefined
function connect() {
// 组件已卸载时不再建立连接
if (closed)
return
socket = new WebSocket(`${location.protocol === "https:" ? "wss" : "ws"}://${location.host}/api/market/ws`)
socket.onopen = () => {
connected.value = true
@@ -58,7 +62,7 @@ export function useMarketSocket(onKline: (k: KlineMessage) => void, onTicker: (t
connected.value = false
if (closed)
return
setTimeout(connect, retryMs)
retryTimer = setTimeout(connect, retryMs)
retryMs = Math.min(retryMs * 2, RETRY_MAX_MS)
}
}
@@ -72,6 +76,7 @@ export function useMarketSocket(onKline: (k: KlineMessage) => void, onTicker: (t
connect()
onBeforeUnmount(() => {
closed = true
clearTimeout(retryTimer)
socket?.close()
})
return { connected, subscribe }