优化 SSE 管理器

This commit is contained in:
jxxghp
2025-08-24 17:34:43 +08:00
parent 79e4ecfdbe
commit 1af1a06700
3 changed files with 45 additions and 11 deletions
@@ -165,8 +165,9 @@ function handleCurrentFileProgressMessage(event: MessageEvent) {
} }
// 使用优化的进度SSE连接 - 整体进度 // 使用优化的进度SSE连接 - 整体进度
const overallProgressUrl = `${import.meta.env.VITE_API_BASE_URL}system/progress/filetransfer`
const overallProgressSSE = useProgressSSE( const overallProgressSSE = useProgressSSE(
`${import.meta.env.VITE_API_BASE_URL}system/progress/filetransfer`, overallProgressUrl,
handleOverallProgressMessage, handleOverallProgressMessage,
'transfer-queue-overall-progress', 'transfer-queue-overall-progress',
progressActive, progressActive,
@@ -184,10 +185,14 @@ function startCurrentFileProgress(filePath: string) {
if (filePath) { if (filePath) {
// filePath计算md5 // filePath计算md5
const filePathMd5 = CryptoJS.MD5(filePath).toString() const filePathMd5 = CryptoJS.MD5(filePath).toString()
// 使用包含文件路径的唯一监听器ID,避免SSE管理器复用连接导致的消息串流
const uniqueListenerId = `transfer-queue-current-file-progress-${filePathMd5}`
const currentFileProgressUrl = `${import.meta.env.VITE_API_BASE_URL}system/progress/${filePathMd5}`
currentFileProgressSSE = useProgressSSE( currentFileProgressSSE = useProgressSSE(
`${import.meta.env.VITE_API_BASE_URL}system/progress/${filePathMd5}`, currentFileProgressUrl,
handleCurrentFileProgressMessage, handleCurrentFileProgressMessage,
'transfer-queue-current-file-progress', uniqueListenerId,
progressActive, progressActive,
) )
currentFileProgressSSE.start() currentFileProgressSSE.start()
+6 -3
View File
@@ -25,7 +25,8 @@ export function useBackgroundOptimization() {
connectDelay?: number // 新增:连接延迟 connectDelay?: number // 新增:连接延迟
}, },
) => { ) => {
const manager = sseManagerSingleton.getManager(url, options) // 使用独立的SSE管理器,确保每个监听器都有独立的连接
const manager = sseManagerSingleton.getIndependentManager(url, listenerId, options)
const isConnected = ref(false) const isConnected = ref(false)
onMounted(() => { onMounted(() => {
@@ -101,7 +102,8 @@ export function useBackgroundOptimization() {
delay: number = 3000, delay: number = 3000,
options?: Parameters<typeof useSSE>[3], options?: Parameters<typeof useSSE>[3],
) => { ) => {
const manager = sseManagerSingleton.getManager(url, options) // 使用独立的SSE管理器,确保每个监听器都有独立的连接
const manager = sseManagerSingleton.getIndependentManager(url, listenerId, options)
onMounted(() => { onMounted(() => {
setTimeout(() => { setTimeout(() => {
@@ -133,7 +135,8 @@ export function useBackgroundOptimization() {
listenerId: string, listenerId: string,
isActive: Ref<boolean>, isActive: Ref<boolean>,
) => { ) => {
const manager = sseManagerSingleton.getManager(url, { // 使用独立的SSE管理器,确保每个监听器都有独立的连接
const manager = sseManagerSingleton.getIndependentManager(url, listenerId, {
backgroundCloseDelay: 1000, // 进度SSE更快关闭 backgroundCloseDelay: 1000, // 进度SSE更快关闭
reconnectDelay: 1000, reconnectDelay: 1000,
maxReconnectAttempts: 5, maxReconnectAttempts: 5,
+31 -5
View File
@@ -119,11 +119,12 @@ export class SSEManager {
this.eventSource.onmessage = event => { this.eventSource.onmessage = event => {
// 分发消息给所有监听器 // 分发消息给所有监听器
this.listeners.forEach(listener => { this.listeners.forEach((listener, listenerId) => {
try { try {
// 为每个监听器提供独立的错误处理
listener(event) listener(event)
} catch (error) { } catch (error) {
console.error('SSE: 监听器错误', error) console.error(`SSE: 监听器错误 [${listenerId}]`, error)
} }
}) })
} }
@@ -245,12 +246,37 @@ class SSEManagerSingleton {
/** /**
* 获取或创建SSE管理器 * 获取或创建SSE管理器
* @param url SSE连接URL
* @param options SSE选项
* @returns SSE管理器实例
*/ */
getManager(url: string, options?: ConstructorParameters<typeof SSEManager>[1]): SSEManager { getManager(url: string, options?: ConstructorParameters<typeof SSEManager>[1]): SSEManager {
if (!this.managers.has(url)) { // 使用完整的URL作为key,确保不同路径的SSE连接不会复用
this.managers.set(url, new SSEManager(url, options)) const managerKey = url
if (!this.managers.has(managerKey)) {
this.managers.set(managerKey, new SSEManager(url, options))
} }
return this.managers.get(url)! return this.managers.get(managerKey)!
}
/**
* 获取或创建独立的SSE管理器(为每个监听器创建独立连接)
* @param url SSE连接URL
* @param listenerId 监听器ID
* @param options SSE选项
* @returns SSE管理器实例
*/
getIndependentManager(
url: string,
listenerId: string,
options?: ConstructorParameters<typeof SSEManager>[1],
): SSEManager {
// 使用URL + 监听器ID作为key,确保每个监听器都有独立的连接
const managerKey = `${url}::${listenerId}`
if (!this.managers.has(managerKey)) {
this.managers.set(managerKey, new SSEManager(url, options))
}
return this.managers.get(managerKey)!
} }
/** /**