Переглянути джерело

update sop未生成待执行记录优化

ct 5 днів тому
батько
коміт
c597dbafef

+ 101 - 28
fs-qw-task/src/main/java/com/fs/app/taskService/impl/SopLogsTaskServiceImpl.java

@@ -794,6 +794,11 @@ public class SopLogsTaskServiceImpl implements SopLogsTaskService {
             // 处理每个 externalContactId
             sopUserLogsInfos.forEach(contactId -> {
                 try {
+                    if (contactId.getExternalId() == null) {
+                        log.error("跳过处理: externalId为空, contact={}, sopId={}, contentType={}, courseId={}, videoId={}",
+                                contactId.getExternalContactId(), logVo.getSopId(), type, courseId, videoId);
+                        return;
+                    }
                     String externalId = contactId.getExternalId().toString();
                     String externalUserName = contactId.getExternalUserName();
                     Long fsUserId = contactId.getFsUserId();
@@ -803,7 +808,28 @@ public class SopLogsTaskServiceImpl implements SopLogsTaskService {
                             type, qwUserId, companyUserId, companyId, externalId, welcomeText, qwUserName, fsUserId, false, miniAppId,
                             null,config, miniMap, grade, sendMsgType,companies,liveId);
                 } catch (Exception e) {
-                    log.error("处理 externalContactId {} 时发生异常: {}", contactId, e.getMessage(), e);
+                    String location = resolveExceptionLocation(e);
+                    String settingContentType = null;
+                    Integer settingExpiresDays = null;
+                    if (content != null && content.getSetting() != null && !content.getSetting().isEmpty()) {
+                        QwSopTempSetting.Content.Setting firstSetting = content.getSetting().get(0);
+                        settingContentType = firstSetting.getContentType();
+                        settingExpiresDays = firstSetting.getExpiresDays();
+                    }
+                    Integer configExpireDays = null;
+                    synchronized (configLock) {
+                        if (cachedCourseConfig != null) {
+                            configExpireDays = cachedCourseConfig.getVideoLinkExpireDate();
+                        }
+                    }
+                    log.error("处理 externalContactId 异常, location={}, err={}, externalContactId={}, externalId={}, fsUserId={}, grade={}, " +
+                                    "sopId={}, msgType={}, isOfficial={}, courseId={}, videoId={}, liveId={}, settingContentType={}, " +
+                                    "settingExpiresDays={}, configVideoLinkExpireDate={}, isSampSend={}, sendType={}, sendMsgType={}",
+                            location, e.toString(),
+                            contactId.getExternalContactId(), contactId.getExternalId(), contactId.getFsUserId(), contactId.getGrade(),
+                            logVo.getSopId(), type, isOfficial, courseId, videoId, liveId, settingContentType,
+                            settingExpiresDays, configExpireDays, logVo.getIsSampSend(),
+                            ruleTimeVO != null ? ruleTimeVO.getSendType() : null, sendMsgType, e);
                 }
             });
         }
@@ -852,7 +878,7 @@ public class SopLogsTaskServiceImpl implements SopLogsTaskService {
         sopLogs.setLogType(ruleTimeVO.getType());
         sopLogs.setTakeRecords(0);
 
-        if (isOfficial != 1 && Integer.valueOf(1).equals(isDaysNotStudy)) {
+        if (!Integer.valueOf(1).equals(isOfficial) && Integer.valueOf(1).equals(isDaysNotStudy)) {
             sopLogs.setSendStatus(5L);
             sopLogs.setRemark("E级客户不发送");
         }else {
@@ -861,9 +887,9 @@ public class SopLogsTaskServiceImpl implements SopLogsTaskService {
 
         sopLogs.setReceivingStatus(0L);
 
-        if (isOfficial == 1) {
+        if (Integer.valueOf(1).equals(isOfficial)) {
 
-            if (logVo.getIsSampSend()== 1) {
+            if (Integer.valueOf(1).equals(logVo.getIsSampSend())) {
                 if (fsUserId == null || Long.valueOf(0L).equals(fsUserId)) {
                     sopLogs.setSendType(2);
                     sopLogs.setRemark("未绑定小程序用户,单链补发");
@@ -883,8 +909,14 @@ public class SopLogsTaskServiceImpl implements SopLogsTaskService {
                 }
             }
 
-        } else if (isOfficial == 0) {
-            sopLogs.setSendType(ruleTimeVO.getSendType() == 1 ? 2 : ruleTimeVO.getSendType());
+        } else if (Integer.valueOf(0).equals(isOfficial) || isOfficial == null) {
+            Integer ruleSendType = ruleTimeVO.getSendType();
+            if (ruleSendType == null) {
+                log.error("createBaseLog ruleTimeVO.sendType为空, 默认按2处理, sopId={}, externalUserId={}", logVo.getSopId(), externalContactId);
+                sopLogs.setSendType(2);
+            } else {
+                sopLogs.setSendType(Integer.valueOf(1).equals(ruleSendType) ? 2 : ruleSendType);
+            }
         } else {
             sopLogs.setSendType(ruleTimeVO.getSendType());
         }
@@ -1268,7 +1300,7 @@ public class SopLogsTaskServiceImpl implements SopLogsTaskService {
             return;
         }
         //如果是@所有人,就添加
-        if (1 == content.getIsAtAll()) {
+        if (Integer.valueOf(1).equals(content.getIsAtAll())) {
             QwSopTempSetting.Content.Setting atMsg = new QwSopTempSetting.Content.Setting();
             atMsg.setContentType("99");
             settings.add(atMsg);
@@ -1364,10 +1396,14 @@ public class SopLogsTaskServiceImpl implements SopLogsTaskService {
                         addWatchLogIfNeeded(sopLogs, videoId, courseId, sendTime, qwUserId, companyUserId, companyId, externalId,logVo,2);
                     }
 
+                    log.info("处理小程序消息(contentType=4), sopId={}, externalId={}, courseId={}, videoId={}, sendType={}, fsUserId={}, expiresDays={}, isOfficial={}",
+                            sopLogs.getSopId(), externalId, courseId, videoId, sopLogs.getSendType(), sopLogs.getFsUserId(),
+                            setting.getExpiresDays(), isOfficial);
+
                     String sortLink = createLinkByMiniApp(setting, logVo, sendTime, courseId, videoId,
                             qwUserId, companyUserId, companyId, externalId,isOfficial,sopLogs.getFsUserId(), isGroupChat ? groupChat.getChatId() : null);
 
-                    if(sopLogs.getSendType()==1){
+                    if(Integer.valueOf(1).equals(sopLogs.getSendType())){
                         setting.setMiniprogramAppid(miniAppId);
                     }else {
                         int miniType = getLevel(grade);
@@ -1403,6 +1439,16 @@ public class SopLogsTaskServiceImpl implements SopLogsTaskService {
                     QwCreateLinkByAppVO linkByApp = createLinkByApp(setting, logVo, sendTime, courseId, videoId,
                             qwUserId, companyUserId, companyId, externalId,sopLogs.getCorpId(),qwUserName);
 
+                    if (linkByApp == null || linkByApp.getSortLink() == null || linkByApp.getAppMsgLink() == null) {
+                        log.error("createLinkByApp返回空, sopId={}, externalId={}, courseId={}, videoId={}, linkByAppNull={}, sortLink={}, appMsgLink={}",
+                                sopLogs.getSopId(), externalId, courseId, videoId,
+                                linkByApp == null,
+                                linkByApp != null ? linkByApp.getSortLink() : null,
+                                linkByApp != null ? linkByApp.getAppMsgLink() : null);
+                        setSopLogsStatus(sopLogs, 5L, 0L, "生成App链接失败");
+                        break;
+                    }
+
                     setting.setLinkUrl(linkByApp.getSortLink().replaceAll("^[\\s\\u2005]+", ""));
                     setting.setAppLinkUrl(linkByApp.getAppMsgLink().replaceAll("^[\\s\\u2005]+", ""));
                     setting.setCourseUrl(setting.getLinkImageUrl());
@@ -1484,7 +1530,7 @@ public class SopLogsTaskServiceImpl implements SopLogsTaskService {
                     String linkBy = createActivityLinkByMiniApp(setting,sopLogs,sopLogs.getCorpId(),new Date(), courseId, videoId,
                             qwUserId, companyUserId, companyId,cachedCourseConfig,logVo.getChatId());
 
-                    if(sopLogs.getSendType()==1){
+                    if(Integer.valueOf(1).equals(sopLogs.getSendType())){
                         setting.setMiniprogramAppid(miniAppId);
                     }
                     else {
@@ -1521,7 +1567,7 @@ public class SopLogsTaskServiceImpl implements SopLogsTaskService {
                         sroth5link = createH5LinkByMiniApp(setting, logVo, sendTime, courseId, videoId,
                                 qwUserId, companyUserId, companyId, externalId, isOfficial, sopLogs.getFsUserId());
 
-                        if(sopLogs.getSendType()==1){
+                        if(Integer.valueOf(1).equals(sopLogs.getSendType())){
                             setting.setMiniprogramAppid(miniAppId);
                         }else {
                             int miniType = getLevel(grade);
@@ -1569,9 +1615,9 @@ public class SopLogsTaskServiceImpl implements SopLogsTaskService {
 
     private String getAppIdFromMiniMap(Map<Long, Map<Integer, List<CompanyMiniapp>>> miniMap,
                                        String companyId,
-                                       int sendMsgType,
+                                       Integer sendMsgType,
                                        Integer grade) {
-        if (miniMap.isEmpty() || sendMsgType != 1) {
+        if (miniMap == null || miniMap.isEmpty() || !Integer.valueOf(1).equals(sendMsgType)) {
             return null;
         }
 
@@ -1697,9 +1743,7 @@ public class SopLogsTaskServiceImpl implements SopLogsTaskService {
 
         link.setCreateTime(sendTime);
 
-        Integer expireDays = (setting.getExpiresDays() == null || setting.getExpiresDays() == 0)
-                ? config.getVideoLinkExpireDate()
-                : setting.getExpiresDays();
+        int expireDays = resolveExpireDays(setting.getExpiresDays(), config, "generateShortLink");
 
         // 使用 Java 8 时间 API 计算过期时间
         LocalDateTime sendDateTime = sendTime.toInstant().atZone(ZoneId.systemDefault()).toLocalDateTime();
@@ -1814,9 +1858,7 @@ public class SopLogsTaskServiceImpl implements SopLogsTaskService {
 
     private Date createUpdateTime(QwSopTempSetting.Content.Setting setting,Date sendTime,CourseConfig config){
 
-        Integer expireDays = (setting.getExpiresDays() == null || setting.getExpiresDays() == 0)
-                ? config.getVideoLinkExpireDate()
-                : setting.getExpiresDays();
+        int expireDays = resolveExpireDays(setting.getExpiresDays(), config, "createUpdateTime");
 
 //         使用 Java 8 时间 API 计算过期时间
         LocalDateTime sendDateTime = sendTime.toInstant().atZone(ZoneId.systemDefault()).toLocalDateTime();
@@ -1858,7 +1900,11 @@ public class SopLogsTaskServiceImpl implements SopLogsTaskService {
         if(StringUtils.isEmpty(chatId)){
             link.setQwExternalId(Long.parseLong(externalId));
         }
-        link.setProjectCode(cloudHostProper.getProjectCode());
+        if (cloudHostProper == null) {
+            log.error("createLinkByMiniApp cloudHostProper为空, externalId={}, courseId={}, videoId={}", externalId, courseId, videoId);
+        } else {
+            link.setProjectCode(cloudHostProper.getProjectCode());
+        }
         link.setChatId(chatId);
 
         if (StringUtil.strIsNullOrEmpty(isOfficial)){
@@ -1894,9 +1940,7 @@ public class SopLogsTaskServiceImpl implements SopLogsTaskService {
         link.setRealLink(realLinkFull);
 
 
-        Integer expireDays = (setting.getExpiresDays() == null || setting.getExpiresDays() == 0)
-                ? config.getVideoLinkExpireDate()
-                : setting.getExpiresDays();
+        int expireDays = resolveExpireDays(setting.getExpiresDays(), config, "createLinkByMiniApp");
 
         // 使用 Java 8 时间 API 计算过期时间
         LocalDateTime sendDateTime = sendTime.toInstant().atZone(ZoneId.systemDefault()).toLocalDateTime();
@@ -2783,9 +2827,7 @@ public class SopLogsTaskServiceImpl implements SopLogsTaskService {
      */
     private Date createUpdateTime(QwSopCourseFinishTempSetting.Setting setting, Date sendTime, CourseConfig config) {
 
-        Integer expireDays = (setting.getExpiresDays() == null || setting.getExpiresDays() == 0)
-                ? config.getVideoLinkExpireDate()
-                : setting.getExpiresDays();
+        int expireDays = resolveExpireDays(setting.getExpiresDays(), config, "createUpdateTime-finishTemp");
 
 //         使用 Java 8 时间 API 计算过期时间
         LocalDateTime sendDateTime = sendTime.toInstant().atZone(ZoneId.systemDefault()).toLocalDateTime();
@@ -3042,9 +3084,7 @@ public class SopLogsTaskServiceImpl implements SopLogsTaskService {
         link.setRealLink(realLinkFull);
 
 
-        Integer expireDays = (setting.getExpiresDays() == null || setting.getExpiresDays() == 0)
-                ? config.getVideoLinkExpireDate()
-                : setting.getExpiresDays();
+        int expireDays = resolveExpireDays(setting.getExpiresDays(), config, "createH5LinkByMiniApp");
 
         // 使用 Java 8 时间 API 计算过期时间
         LocalDateTime sendDateTime = sendTime.toInstant().atZone(ZoneId.systemDefault()).toLocalDateTime();
@@ -3057,4 +3097,37 @@ public class SopLogsTaskServiceImpl implements SopLogsTaskService {
         enqueueCourseLink(link);
         return link.getRealLink();
     }
+
+    /**
+     * 解析短链过期天数:优先附件 expiresDays,其次 CourseConfig.videoLinkExpireDate,最后默认 1 天,避免 Integer 拆箱 NPE。
+     */
+    private int resolveExpireDays(Integer settingExpireDays, CourseConfig config, String scene) {
+        Integer configExpireDays = config != null ? config.getVideoLinkExpireDate() : null;
+        if (settingExpireDays != null && settingExpireDays != 0) {
+            return settingExpireDays;
+        }
+        if (configExpireDays != null && configExpireDays != 0) {
+            return configExpireDays;
+        }
+        log.error("短链过期天数为空,使用默认值1天, scene={}, settingExpiresDays={}, configVideoLinkExpireDate={}, configLoaded={}",
+                scene, settingExpireDays, configExpireDays, config != null);
+        return 1;
+    }
+
+    /**
+     * 从异常堆栈中取本类首个定位点,便于日志快速定位空指针行号。
+     */
+    private String resolveExceptionLocation(Throwable e) {
+        if (e == null || e.getStackTrace() == null) {
+            return "unknown";
+        }
+        for (StackTraceElement element : e.getStackTrace()) {
+            if (element != null && element.getClassName() != null
+                    && element.getClassName().contains("SopLogsTaskServiceImpl")) {
+                return element.getClassName() + "." + element.getMethodName()
+                        + "(" + element.getFileName() + ":" + element.getLineNumber() + ")";
+            }
+        }
+        return e.getStackTrace().length > 0 ? e.getStackTrace()[0].toString() : e.toString();
+    }
 }