2
0
Pārlūkot izejas kodu

✨ feat(classroom): 优化消息发送机制,提高可靠性

- 添加通用重试机制(retryOperation),默认最多重试3次,带指数退避策略
- 修改文本消息发送逻辑:并行执行数据库保存和IM发送,提高响应速度
- 修改图片消息发送逻辑:并行执行数据库保存和IM发送,提高响应速度
- 优化错误处理策略:数据库保存失败时仅记录日志,IM发送失败时才抛出错误

♻️ refactor(classroom): 重构消息发送代码结构

- 移除发送消息前的冗余注释
- 统一使用Promise.allSettled处理并行异步操作
- 分离数据库错误和IM错误的处理逻辑,提高代码可读性
yourname 6 mēneši atpakaļ
vecāks
revīzija
e23ee896d3
1 mainītis faili ar 67 papildinājumiem un 21 dzēšanām
  1. 67 21
      src/client/mobile/components/Classroom/useClassroom.ts

+ 67 - 21
src/client/mobile/components/Classroom/useClassroom.ts

@@ -177,6 +177,23 @@ export const useClassroom = ({ user }:{ user : User }) => {
     }
   };
 
+  // 重试操作函数
+  const retryOperation = async <T>(
+    operation: () => Promise<T>,
+    maxRetries = 3,
+    delay = 1000
+  ): Promise<T> => {
+    for (let i = 0; i < maxRetries; i++) {
+      try {
+        return await operation();
+      } catch (error) {
+        if (i === maxRetries - 1) throw error;
+        await new Promise(resolve => setTimeout(resolve, delay * (i + 1)));
+      }
+    }
+    throw new Error('Max retries exceeded');
+  };
+
   // 保存IM消息到数据库(直接从IM消息对象创建)
   const saveImMessageToDatabase = async (
     msg: AliVCInteraction.ImMessage, 
@@ -861,7 +878,6 @@ export const useClassroom = ({ user }:{ user : User }) => {
     }
 
     try {
-      // 先保存消息到数据库
       const message: Message = {
         type: 'text',
         content: msgText,
@@ -870,17 +886,33 @@ export const useClassroom = ({ user }:{ user : User }) => {
         senderType: user?.userType, // 添加用户类型
         timestamp: Date.now()
       };
-      await saveMessageToDatabase(message);
       
-      // 然后发送IM消息
-      await imMessageManager.current.sendGroupMessage({
-        groupId: classId,
-        data: msgText,
-        type: 88888,
-        level: NORMAL,
-      });
+      // 并行执行数据库保存和IM发送
+      const [dbResult, imResult] = await Promise.allSettled([
+        saveMessageToDatabase(message),
+        retryOperation(() => 
+          imMessageManager.current!.sendGroupMessage({
+            groupId: classId,
+            data: msgText,
+            type: 88888,
+            level: NORMAL,
+          })
+        )
+      ]);
+      
       setMsgText('');
       setErrorMessage('');
+      
+      // 如果数据库保存失败,记录日志但继续
+      if (dbResult.status === 'rejected') {
+        console.error('数据库保存失败(消息已发送):', dbResult.reason);
+      }
+      
+      // 如果IM发送失败,抛出错误
+      if (imResult.status === 'rejected') {
+        throw imResult.reason;
+      }
+      
     } catch (err: any) {
       // 检查是否为禁言错误 (错误码442)
       if (err.message?.includes('code:442') || err.message?.includes('not allowed to send message')) {
@@ -895,7 +927,7 @@ export const useClassroom = ({ user }:{ user : User }) => {
     if (!imMessageManager.current || !classId) return;
 
     try {
-      // 保存消息到数据库,保存fileId到fileId字段
+      // 保存消息到数据库,保存fileId到fileId字段
       const message: Message = {
         type: 'image',
         content: '[图片]', // 内容字段保存描述文本
@@ -905,18 +937,32 @@ export const useClassroom = ({ user }:{ user : User }) => {
         timestamp: Date.now(),
         fileId: fileId // 新增fileId字段
       };
-      await saveMessageToDatabase(message);
       
-      // 然后发送IM消息
-      await imMessageManager.current!.sendGroupMessage({
-        groupId: classId,
-        data: JSON.stringify({
-          type: 'image',
-          fileId: fileId
-        }),
-        type: 88895, // 使用单一消息类型用于图片
-        level: NORMAL,
-      });
+      // 并行执行数据库保存和IM发送
+      const [dbResult, imResult] = await Promise.allSettled([
+        saveMessageToDatabase(message),
+        retryOperation(() => 
+          imMessageManager.current!.sendGroupMessage({
+            groupId: classId,
+            data: JSON.stringify({
+              type: 'image',
+              fileId: fileId
+            }),
+            type: 88895, // 使用单一消息类型用于图片
+            level: NORMAL,
+          })
+        )
+      ]);
+      
+      // 如果数据库保存失败,记录日志但继续
+      if (dbResult.status === 'rejected') {
+        console.error('数据库保存失败(图片消息已发送):', dbResult.reason);
+      }
+      
+      // 如果IM发送失败,抛出错误
+      if (imResult.status === 'rejected') {
+        throw imResult.reason;
+      }
       
     } catch (err: any) {
       // 检查是否为禁言错误 (错误码442)