1
0
mirror of synced 2026-02-11 14:17:48 +08:00

fix: 修复会话存档SDK生命周期管理的审查问题

1. getChatRecords() 返回空列表而非 null,避免 NPE
2. downloadMediaFile() 正确传播文件写入异常
3. updateMsgAuditSdk() 确保旧 SDK 被销毁,避免资源泄漏
This commit is contained in:
Binary Wang
2026-01-16 10:28:35 +08:00
parent 1d4e08cdea
commit 048b51e3b7
3 changed files with 27 additions and 8 deletions

View File

@@ -20,6 +20,7 @@ import java.io.File;
import java.io.FileOutputStream;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.LinkedList;
import java.util.List;
import java.util.function.Consumer;
@@ -345,7 +346,8 @@ public class WxCpMsgAuditServiceImpl implements WxCpMsgAuditService {
throw new WxErrorException(chatDatas.toJson());
}
return chatDatas.getChatData();
List<WxCpChatDatas.WxCpChatData> chatDataList = chatDatas.getChatData();
return chatDataList != null ? chatDataList : Collections.emptyList();
} finally {
// 释放SDK引用计数原子操作
this.releaseSdk(sdk);
@@ -392,21 +394,34 @@ public class WxCpMsgAuditServiceImpl implements WxCpMsgAuditService {
throw new WxErrorException(e);
}
// 使用AtomicReference捕获Lambda中的异常以便在执行完后抛出
final java.util.concurrent.atomic.AtomicReference<Exception> exceptionHolder = new java.util.concurrent.atomic.AtomicReference<>();
try {
File targetFile = new File(targetFilePath);
if (!targetFile.getParentFile().exists()) {
targetFile.getParentFile().mkdirs();
}
this.getMediaFile(sdk, sdkfileid, proxy, passwd, timeout, i -> {
// 如果之前已经发生异常,不再继续处理
if (exceptionHolder.get() != null) {
return;
}
try {
// 大于512k的文件会分片拉取此处需要使用追加写避免后面的分片覆盖之前的数据。
FileOutputStream outputStream = new FileOutputStream(targetFile, true);
outputStream.write(i);
outputStream.close();
} catch (Exception e) {
e.printStackTrace();
exceptionHolder.set(e);
}
});
// 检查是否发生异常,如果有则抛出
Exception caughtException = exceptionHolder.get();
if (caughtException != null) {
throw new WxErrorException(caughtException);
}
} finally {
// 释放SDK引用计数原子操作
this.releaseSdk(sdk);

View File

@@ -475,14 +475,16 @@ public class WxCpDefaultConfigImpl implements WxCpConfigStorage, Serializable {
@Override
public synchronized void updateMsgAuditSdk(long sdk, int expiresInSeconds) {
// 如果有旧的SDK且引用计数为0销毁旧的SDK
if (this.msgAuditSdk > 0 && this.msgAuditSdk != sdk && this.msgAuditSdkRefCount == 0) {
// 如果有旧的SDK且不同于新的SDK需要销毁旧的SDK
if (this.msgAuditSdk > 0 && this.msgAuditSdk != sdk) {
// 无论旧SDK是否仍有引用都需要销毁它以避免资源泄漏
// 如果有飞行中的请求使用旧SDK这些请求可能会失败但这比资源泄漏更安全
Finance.DestroySdk(this.msgAuditSdk);
}
this.msgAuditSdk = sdk;
// 预留200秒的时间
this.msgAuditSdkExpiresTime = System.currentTimeMillis() + (expiresInSeconds - 200) * 1000L;
// 重置引用计数
// 重置引用计数因为这是一个全新的SDK
this.msgAuditSdkRefCount = 0;
}

View File

@@ -493,14 +493,16 @@ public class WxCpRedisConfigImpl implements WxCpConfigStorage {
@Override
public synchronized void updateMsgAuditSdk(long sdk, int expiresInSeconds) {
// 如果有旧的SDK且引用计数为0销毁旧的SDK
if (this.msgAuditSdk > 0 && this.msgAuditSdk != sdk && this.msgAuditSdkRefCount == 0) {
// 如果有旧的SDK且不同于新的SDK需要销毁旧的SDK
if (this.msgAuditSdk > 0 && this.msgAuditSdk != sdk) {
// 无论旧SDK是否仍有引用都需要销毁它以避免资源泄漏
// 如果有飞行中的请求使用旧SDK这些请求可能会失败但这比资源泄漏更安全
Finance.DestroySdk(this.msgAuditSdk);
}
this.msgAuditSdk = sdk;
// 预留200秒的时间
this.msgAuditSdkExpiresTime = System.currentTimeMillis() + (expiresInSeconds - 200) * 1000L;
// 重置引用计数
// 重置引用计数因为这是一个全新的SDK
this.msgAuditSdkRefCount = 0;
}