|
|
@@ -73,6 +73,10 @@ public class Task {
|
|
|
private ILiveCouponIssueService liveCouponIssueService;
|
|
|
@Autowired
|
|
|
private ILiveVideoService liveVideoService;
|
|
|
+ @Autowired
|
|
|
+ private ILiveWatchLogService liveWatchLogService;
|
|
|
+ @Autowired
|
|
|
+ private ILiveUserFirstEntryService liveUserFirstEntryService;
|
|
|
|
|
|
@Autowired
|
|
|
public FsJstAftersalePushService fsJstAftersalePushService;
|
|
|
@@ -161,8 +165,8 @@ public class Task {
|
|
|
collect.forEach(liveAutoTask -> {
|
|
|
liveAutoTask.setCreateTime(null);
|
|
|
liveAutoTask.setUpdateTime(null);
|
|
|
- redisCache.redisTemplate.opsForZSet().add(key + live.getLiveId(), JSON.toJSONString(liveAutoTask),liveAutoTask.getAbsValue().getTime());
|
|
|
- redisCache.redisTemplate.expire(key+live.getLiveId(), 1, TimeUnit.DAYS);
|
|
|
+ redisCache.zSetAdd(key + live.getLiveId(), JSON.toJSONString(liveAutoTask),liveAutoTask.getAbsValue().getTime());
|
|
|
+ redisCache.expire(key+live.getLiveId(), 1, TimeUnit.DAYS);
|
|
|
});
|
|
|
}
|
|
|
|
|
|
@@ -205,7 +209,7 @@ public class Task {
|
|
|
webSocketServer.broadcastMessage(live.getLiveId(), JSONObject.toJSONString(R.ok().put("data",sendMsgVo)));
|
|
|
List<LiveAutoTask> collect = liveAutoTasks.stream().filter(liveAutoTask -> liveAutoTask.getLiveId().equals(live.getLiveId())).collect(Collectors.toList());
|
|
|
if (!collect.isEmpty()) {
|
|
|
- redisCache.redisTemplate.delete(key + live.getLiveId());
|
|
|
+ redisCache.deleteObject(key + live.getLiveId());
|
|
|
collect.forEach(liveAutoTask -> {
|
|
|
liveAutoTask.setCreateTime(null);
|
|
|
liveAutoTask.setUpdateTime(null);
|
|
|
@@ -627,6 +631,7 @@ public class Task {
|
|
|
@DistributeLock(key = "scanLiveTagMark", scene = "task")
|
|
|
public void scanLiveTagMark() {
|
|
|
try {
|
|
|
+
|
|
|
// 获取所有打标签缓存的key
|
|
|
String pattern = String.format(LiveKeysConstant.LIVE_TAG_MARK_CACHE, "*");
|
|
|
Set<String> keys = redisCache.redisTemplate.keys(pattern);
|
|
|
@@ -636,8 +641,9 @@ public class Task {
|
|
|
}
|
|
|
|
|
|
long currentTimeMillis = System.currentTimeMillis();
|
|
|
+ LocalDateTime now = LocalDateTime.now();
|
|
|
List<Long> processedLiveIds = new ArrayList<>();
|
|
|
-
|
|
|
+ Date nowDate = new Date();
|
|
|
for (String key : keys) {
|
|
|
try {
|
|
|
// 从Redis获取直播间信息
|
|
|
@@ -658,21 +664,114 @@ public class Task {
|
|
|
continue;
|
|
|
}
|
|
|
|
|
|
+ // 查询直播间信息
|
|
|
+ Live live = liveService.selectLiveDbByLiveId(liveId);
|
|
|
+ if (live == null || live.getStartTime() == null) {
|
|
|
+ continue;
|
|
|
+ }
|
|
|
// 计算结束时间:开始时间 + 视频时长(秒转毫秒)
|
|
|
long endTimeMillis = startTimeMillis + (videoDuration * 1000);
|
|
|
-
|
|
|
+
|
|
|
// 如果当前时间已经超过了结束时间,执行打标签操作
|
|
|
if (currentTimeMillis >= endTimeMillis) {
|
|
|
- log.info("直播间视频播放完成,开始打标签: liveId={}, startTime={}, videoDuration={}, endTime={}, currentTime={}",
|
|
|
- liveId, startTimeMillis, videoDuration, endTimeMillis, currentTimeMillis);
|
|
|
+ // 查询当前直播间的在线用户(liveFlag = 1, replayFlag = 0)
|
|
|
+ LiveWatchUser queryUser = new LiveWatchUser();
|
|
|
+ queryUser.setLiveId(liveId);
|
|
|
+ queryUser.setLiveFlag(1);
|
|
|
+ queryUser.setReplayFlag(0);
|
|
|
+ List<LiveWatchUser> liveUsers = liveWatchUserService.selectLiveWatchUserList(queryUser);
|
|
|
+
|
|
|
+ if (liveUsers != null && !liveUsers.isEmpty()) {
|
|
|
+
|
|
|
+ List<LiveWatchUser> updateLiveUsers = new ArrayList<>(); // 需要更新的直播用户
|
|
|
+ List<LiveWatchUser> replayUsers = new ArrayList<>(); // 回放用户数据
|
|
|
+
|
|
|
+ for (LiveWatchUser liveUser : liveUsers) {
|
|
|
+ Long userId = liveUser.getUserId();
|
|
|
+ if (userId == null) {
|
|
|
+ continue;
|
|
|
+ }
|
|
|
+
|
|
|
+ // 1. 计算并更新直播用户的在线时长
|
|
|
+ // 优先从 Redis 获取进入时间
|
|
|
+ String entryTimeKey = String.format("live:user:entry:time:%s:%s", liveId, userId);
|
|
|
+ Long entryTime = redisCache.getCacheObject(entryTimeKey);
|
|
|
+
|
|
|
+ // 如果没有 Redis 记录,使用数据库中的 updateTime
|
|
|
+ if (entryTime == null) {
|
|
|
+ if (liveUser.getUpdateTime() != null) {
|
|
|
+ entryTime = liveUser.getUpdateTime().getTime();
|
|
|
+ } else if (liveUser.getCreateTime() != null) {
|
|
|
+ entryTime = liveUser.getCreateTime().getTime();
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ // 计算当前观看时长(秒)
|
|
|
+ long currentWatchDuration = 0L;
|
|
|
+ if (entryTime != null) {
|
|
|
+ currentWatchDuration = (currentTimeMillis - entryTime) / 1000;
|
|
|
+ if (currentWatchDuration < 0) {
|
|
|
+ currentWatchDuration = 0L;
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ // 加上历史在线时长
|
|
|
+ Long historyOnlineSeconds = liveUser.getOnlineSeconds();
|
|
|
+ if (historyOnlineSeconds == null) {
|
|
|
+ historyOnlineSeconds = 0L;
|
|
|
+ }
|
|
|
+ long totalOnlineSeconds = historyOnlineSeconds + currentWatchDuration;
|
|
|
+
|
|
|
+ // 更新直播用户的在线时长
|
|
|
+ liveUser.setOnlineSeconds(totalOnlineSeconds);
|
|
|
+ liveUser.setUpdateTime(nowDate);
|
|
|
+ updateLiveUsers.add(liveUser);
|
|
|
+
|
|
|
+ // 2. 生成回放用户数据(liveFlag = 0, replayFlag = 1),在线时长从0开始
|
|
|
+ LiveWatchUser replayUser = new LiveWatchUser();
|
|
|
+ replayUser.setLiveId(liveUser.getLiveId());
|
|
|
+ replayUser.setUserId(liveUser.getUserId());
|
|
|
+ replayUser.setMsgStatus(liveUser.getMsgStatus());
|
|
|
+ replayUser.setOnline(liveUser.getOnline());
|
|
|
+ replayUser.setOnlineSeconds(0L); // 回放观看时长从0开始,重新计时
|
|
|
+ replayUser.setGlobalVisible(liveUser.getGlobalVisible());
|
|
|
+ replayUser.setSingleVisible(liveUser.getSingleVisible());
|
|
|
+ replayUser.setLiveFlag(0); // 回放标记
|
|
|
+ replayUser.setReplayFlag(1); // 回放标记
|
|
|
+ replayUser.setLocation(liveUser.getLocation());
|
|
|
+ replayUser.setCreateTime(nowDate);
|
|
|
+ replayUser.setUpdateTime(nowDate);
|
|
|
+ replayUsers.add(replayUser);
|
|
|
+ }
|
|
|
+
|
|
|
+ // 批量更新直播用户的在线时长
|
|
|
+ if (!updateLiveUsers.isEmpty()) {
|
|
|
+ int batchSize = 500;
|
|
|
+ for (int i = 0; i < updateLiveUsers.size(); i += batchSize) {
|
|
|
+ int end = Math.min(i + batchSize, updateLiveUsers.size());
|
|
|
+ List<LiveWatchUser> batch = updateLiveUsers.subList(i, end);
|
|
|
+ liveWatchUserService.batchUpdateLiveWatchUser(batch);
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ // 批量插入回放用户数据
|
|
|
+ if (!replayUsers.isEmpty()) {
|
|
|
+ int batchSize = 500;
|
|
|
+ for (int i = 0; i < replayUsers.size(); i += batchSize) {
|
|
|
+ int end = Math.min(i + batchSize, replayUsers.size());
|
|
|
+ List<LiveWatchUser> batch = replayUsers.subList(i, end);
|
|
|
+ liveWatchUserService.batchInsertLiveWatchUser(batch);
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ // 清理直播间状态缓存
|
|
|
+ liveWatchUserService.clearLiveFlagCache(liveId);
|
|
|
+ }
|
|
|
|
|
|
// 标记为已处理,稍后删除缓存
|
|
|
processedLiveIds.add(liveId);
|
|
|
-
|
|
|
// 调用打标签方法
|
|
|
liveWatchUserService.qwTagMarkByLiveWatchLog(liveId);
|
|
|
-
|
|
|
-
|
|
|
}
|
|
|
} catch (Exception e) {
|
|
|
log.error("处理直播间打标签缓存异常: key={}, error={}", key, e.getMessage(), e);
|
|
|
@@ -684,7 +783,6 @@ public class Task {
|
|
|
try {
|
|
|
String tagMarkKey = String.format(LiveKeysConstant.LIVE_TAG_MARK_CACHE, liveId);
|
|
|
redisCache.deleteObject(tagMarkKey);
|
|
|
- log.info("已删除已处理的直播间打标签缓存: liveId={}", liveId);
|
|
|
} catch (Exception e) {
|
|
|
log.error("删除直播间打标签缓存失败: liveId={}, error={}", liveId, e.getMessage(), e);
|
|
|
}
|
|
|
@@ -695,73 +793,230 @@ public class Task {
|
|
|
}
|
|
|
|
|
|
/**
|
|
|
- * 批量同步Redis中的观看时长到数据库
|
|
|
- * 每2分钟执行一次,减少数据库压力
|
|
|
+ * 实时扫描用户直播数据,根据用户的直播在线时长更新观看记录状态
|
|
|
+ * 每30秒执行一次
|
|
|
*/
|
|
|
- @Scheduled(cron = "0 0/2 * * * ?")
|
|
|
- @DistributeLock(key = "batchSyncWatchDuration", scene = "task")
|
|
|
- public void batchSyncWatchDuration() {
|
|
|
+ @Scheduled(cron = "0/30 * * * * ?")
|
|
|
+ @DistributeLock(key = "scanLiveWatchUserStatus", scene = "task")
|
|
|
+ public void scanLiveWatchUserStatus() {
|
|
|
try {
|
|
|
- log.info("开始批量同步观看时长到数据库");
|
|
|
-
|
|
|
- // 优化:从所有直播间的Hash中批量获取数据
|
|
|
+ // 查询所有正在直播的直播间
|
|
|
List<Live> activeLives = liveService.selectNoEndLiveList();
|
|
|
-
|
|
|
if (activeLives == null || activeLives.isEmpty()) {
|
|
|
- log.debug("当前没有活跃的直播间");
|
|
|
return;
|
|
|
}
|
|
|
-
|
|
|
- int totalCount = 0;
|
|
|
- int successCount = 0;
|
|
|
- int failCount = 0;
|
|
|
-
|
|
|
- // 逐个直播间处理
|
|
|
+
|
|
|
for (Live live : activeLives) {
|
|
|
try {
|
|
|
Long liveId = live.getLiveId();
|
|
|
-
|
|
|
- // 使用Hash结构存储每个直播间的观看时长
|
|
|
- String hashKey = "live:watch:duration:hash:" + liveId;
|
|
|
- Map<Object, Object> userDurations = redisCache.hashEntries(hashKey);
|
|
|
-
|
|
|
- if (userDurations == null || userDurations.isEmpty()) {
|
|
|
+ if (liveId == null) {
|
|
|
continue;
|
|
|
}
|
|
|
-
|
|
|
- // 获取直播/回放标记(一次查询,所有用户复用)
|
|
|
+ // 获取直播间的直播/回放状态
|
|
|
Map<String, Integer> flagMap = liveWatchUserService.getLiveFlagWithCache(liveId);
|
|
|
Integer liveFlag = flagMap.get("liveFlag");
|
|
|
- Integer replayFlag = flagMap.get("replayFlag");
|
|
|
-
|
|
|
- // 批量处理该直播间的所有用户
|
|
|
- for (Map.Entry<Object, Object> entry : userDurations.entrySet()) {
|
|
|
+ // 只处理直播状态的用户(liveFlag = 1)
|
|
|
+ if (liveFlag == null || liveFlag != 1) {
|
|
|
+ continue;
|
|
|
+ }
|
|
|
+ // 查询该直播间的在线用户(liveFlag = 1, replayFlag = 0)
|
|
|
+ LiveWatchUser queryUser = new LiveWatchUser();
|
|
|
+ queryUser.setLiveId(liveId);
|
|
|
+ queryUser.setLiveFlag(1);
|
|
|
+ queryUser.setReplayFlag(0);
|
|
|
+ queryUser.setOnline(0); // 在线用户
|
|
|
+ List<LiveWatchUser> onlineUsers = liveWatchUserService.selectLiveWatchUserList(queryUser);
|
|
|
+ if (onlineUsers == null || onlineUsers.isEmpty()) {
|
|
|
+ continue;
|
|
|
+ }
|
|
|
+ // 获取直播视频总时长
|
|
|
+ List<LiveVideo> videos = liveVideoService.listByLiveIdWithCache(liveId, 1);
|
|
|
+ long totalVideoDuration = 0L;
|
|
|
+ if (videos != null && !videos.isEmpty()) {
|
|
|
+ totalVideoDuration = videos.stream()
|
|
|
+ .filter(v -> v.getDuration() != null)
|
|
|
+ .mapToLong(LiveVideo::getDuration)
|
|
|
+ .sum();
|
|
|
+ }
|
|
|
+
|
|
|
+ // 处理每个在线用户
|
|
|
+ for (LiveWatchUser user : onlineUsers) {
|
|
|
try {
|
|
|
- Long userId = Long.parseLong(entry.getKey().toString());
|
|
|
- Long duration = Long.parseLong(entry.getValue().toString());
|
|
|
+ Long userId = user.getUserId();
|
|
|
+ if (userId == null) {
|
|
|
+ continue;
|
|
|
+ }
|
|
|
+
|
|
|
+ // 获取用户的在线观看时长
|
|
|
+ Long onlineSeconds = user.getOnlineSeconds();
|
|
|
+ if (onlineSeconds == null || onlineSeconds <= 0) {
|
|
|
+ continue;
|
|
|
+ }
|
|
|
|
|
|
- totalCount++;
|
|
|
+ // 获取用户的 companyId 和 companyUserId
|
|
|
+ LiveUserFirstEntry liveUserFirstEntry =
|
|
|
+ liveUserFirstEntryService.selectEntityByLiveIdUserIdWithCache(liveId, userId);
|
|
|
+ if (liveUserFirstEntry == null) {
|
|
|
+ continue;
|
|
|
+ }
|
|
|
|
|
|
- // 异步更新数据库
|
|
|
- liveWatchUserService.updateWatchDuration(liveId, userId, liveFlag, replayFlag, duration);
|
|
|
- successCount++;
|
|
|
+ Long qwUserId = liveUserFirstEntry.getQwUserId();
|
|
|
+ Long externalContactId = liveUserFirstEntry.getExternalContactId();
|
|
|
+
|
|
|
+ if (qwUserId == null || qwUserId <= 0 || externalContactId == null || externalContactId <= 0) {
|
|
|
+ continue;
|
|
|
+ }
|
|
|
+
|
|
|
+ // 使用 updateLiveWatchLogTypeByDuration 的逻辑更新观看记录状态
|
|
|
+ updateLiveWatchLogTypeByDuration(liveId, userId, qwUserId, externalContactId,
|
|
|
+ onlineSeconds, totalVideoDuration);
|
|
|
|
|
|
} catch (Exception e) {
|
|
|
- failCount++;
|
|
|
- log.error("同步用户观看时长失败: liveId={}, userId={}, error={}",
|
|
|
- liveId, entry.getKey(), e.getMessage());
|
|
|
+ log.error("处理用户观看记录状态异常: liveId={}, userId={}, error={}",
|
|
|
+ liveId, user.getUserId(), e.getMessage(), e);
|
|
|
}
|
|
|
}
|
|
|
|
|
|
} catch (Exception e) {
|
|
|
- log.error("处理直播间观看时长失败: liveId={}, error={}", live.getLiveId(), e.getMessage());
|
|
|
+ log.error("处理直播间观看记录状态异常: liveId={}, error={}",
|
|
|
+ live.getLiveId(), e.getMessage(), e);
|
|
|
}
|
|
|
}
|
|
|
-
|
|
|
- log.info("批量同步观看时长完成: 总数={}, 成功={}, 失败={}", totalCount, successCount, failCount);
|
|
|
-
|
|
|
} catch (Exception e) {
|
|
|
- log.error("批量同步观看时长任务异常", e);
|
|
|
+ log.error("实时扫描用户直播数据任务异常: error={}", e.getMessage(), e);
|
|
|
}
|
|
|
}
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 根据在线时长更新 LiveWatchLog 的 logType(复用 WebSocketServer 中的逻辑)
|
|
|
+ * @param liveId 直播间ID
|
|
|
+ * @param userId 用户ID
|
|
|
+ * @param qwUserId 邀请人id
|
|
|
+ * @param exId 外部人id
|
|
|
+ * @param onlineSeconds 在线时长(秒)
|
|
|
+ * @param totalVideoDuration 视频总时长(秒)
|
|
|
+ */
|
|
|
+ private void updateLiveWatchLogTypeByDuration(Long liveId, Long userId, Long qwUserId,
|
|
|
+ Long exId, Long onlineSeconds, long totalVideoDuration) {
|
|
|
+ try {
|
|
|
+ // 查询 LiveWatchLog
|
|
|
+ LiveWatchLog queryLog = new LiveWatchLog();
|
|
|
+ queryLog.setLiveId(liveId);
|
|
|
+ queryLog.setUserId(userId);
|
|
|
+ queryLog.setQwUserId(String.valueOf(qwUserId));
|
|
|
+ queryLog.setExternalContactId(exId);
|
|
|
+
|
|
|
+ List<LiveWatchLog> logs = liveWatchLogService.selectLiveWatchLogList(queryLog);
|
|
|
+ if (logs == null || logs.isEmpty()) {
|
|
|
+ return;
|
|
|
+ }
|
|
|
+
|
|
|
+ Date now = new Date();
|
|
|
+ for (LiveWatchLog log : logs) {
|
|
|
+ if (log.getLogType() != null && log.getLogType() == 2) {
|
|
|
+ continue;
|
|
|
+ }
|
|
|
+ boolean needUpdate = false;
|
|
|
+ Integer newLogType = log.getLogType();
|
|
|
+
|
|
|
+ // ① 如果在线时长 <= 3分钟,修改 logType 为 4(看课中断)
|
|
|
+ if (onlineSeconds <= 180) { // 3分钟 = 180秒
|
|
|
+ newLogType = 4;
|
|
|
+ needUpdate = true;
|
|
|
+ }
|
|
|
+ // ③ 如果直播视频 >= 40分钟,在线时长 >= 30分钟,logType 设置为 2(完课)
|
|
|
+ else if (totalVideoDuration >= 2400 && onlineSeconds >= 1800) { // 40分钟 = 2400秒,30分钟 = 1800秒
|
|
|
+ newLogType = 2;
|
|
|
+ log.setFinishTime(now);
|
|
|
+ needUpdate = true;
|
|
|
+ }
|
|
|
+ // 如果直播视频 >= 20分钟且 < 40分钟,在线时长 >= 20分钟,logType 设置为 2(完课)
|
|
|
+ else if (totalVideoDuration >= 1200 && totalVideoDuration < 2400 && onlineSeconds >= 1200) { // 20分钟 = 1200秒
|
|
|
+ newLogType = 2;
|
|
|
+ log.setFinishTime(now);
|
|
|
+ needUpdate = true;
|
|
|
+ }
|
|
|
+
|
|
|
+ // 如果 logType 已经是 2(完课),不再更新
|
|
|
+ if (needUpdate) {
|
|
|
+ log.setLogType(newLogType);
|
|
|
+ liveWatchLogService.updateLiveWatchLog(log);
|
|
|
+ }
|
|
|
+ }
|
|
|
+ } catch (Exception e) {
|
|
|
+ log.error("根据在线时长更新 LiveWatchLog logType 异常:liveId={}, userId={}, error={}",
|
|
|
+ liveId, userId, e.getMessage(), e);
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 批量同步Redis中的观看时长到数据库
|
|
|
+ * 每2分钟执行一次,减少数据库压力
|
|
|
+ */
|
|
|
+// @Scheduled(cron = "0 0/2 * * * ?")
|
|
|
+// @DistributeLock(key = "batchSyncWatchDuration", scene = "task")
|
|
|
+// public void batchSyncWatchDuration() {
|
|
|
+// try {
|
|
|
+// log.info("开始批量同步观看时长到数据库");
|
|
|
+//
|
|
|
+// // 优化:从所有直播间的Hash中批量获取数据
|
|
|
+// List<Live> activeLives = liveService.selectNoEndLiveList();
|
|
|
+//
|
|
|
+// if (activeLives == null || activeLives.isEmpty()) {
|
|
|
+// log.debug("当前没有活跃的直播间");
|
|
|
+// return;
|
|
|
+// }
|
|
|
+//
|
|
|
+// int totalCount = 0;
|
|
|
+// int successCount = 0;
|
|
|
+// int failCount = 0;
|
|
|
+//
|
|
|
+// // 逐个直播间处理
|
|
|
+// for (Live live : activeLives) {
|
|
|
+// try {
|
|
|
+// Long liveId = live.getLiveId();
|
|
|
+//
|
|
|
+// // 使用Hash结构存储每个直播间的观看时长
|
|
|
+// String hashKey = "live:watch:duration:hash:" + liveId;
|
|
|
+// Map<Object, Object> userDurations = redisCache.redisTemplate.opsForHash().entries(hashKey);
|
|
|
+//
|
|
|
+// if (userDurations == null || userDurations.isEmpty()) {
|
|
|
+// continue;
|
|
|
+// }
|
|
|
+//
|
|
|
+// // 获取直播/回放标记(一次查询,所有用户复用)
|
|
|
+// Map<String, Integer> flagMap = liveWatchUserService.getLiveFlagWithCache(liveId);
|
|
|
+// Integer liveFlag = flagMap.get("liveFlag");
|
|
|
+// Integer replayFlag = flagMap.get("replayFlag");
|
|
|
+//
|
|
|
+// // 批量处理该直播间的所有用户
|
|
|
+// for (Map.Entry<Object, Object> entry : userDurations.entrySet()) {
|
|
|
+// try {
|
|
|
+// Long userId = Long.parseLong(entry.getKey().toString());
|
|
|
+// Long duration = Long.parseLong(entry.getValue().toString());
|
|
|
+//
|
|
|
+// totalCount++;
|
|
|
+//
|
|
|
+// // 异步更新数据库
|
|
|
+// liveWatchUserService.updateWatchDuration(liveId, userId, liveFlag, replayFlag, duration);
|
|
|
+// successCount++;
|
|
|
+//
|
|
|
+// } catch (Exception e) {
|
|
|
+// failCount++;
|
|
|
+// log.error("同步用户观看时长失败: liveId={}, userId={}, error={}",
|
|
|
+// liveId, entry.getKey(), e.getMessage());
|
|
|
+// }
|
|
|
+// }
|
|
|
+//
|
|
|
+// } catch (Exception e) {
|
|
|
+// log.error("处理直播间观看时长失败: liveId={}, error={}", live.getLiveId(), e.getMessage());
|
|
|
+// }
|
|
|
+// }
|
|
|
+//
|
|
|
+// log.info("批量同步观看时长完成: 总数={}, 成功={}, 失败={}", totalCount, successCount, failCount);
|
|
|
+//
|
|
|
+// } catch (Exception e) {
|
|
|
+// log.error("批量同步观看时长任务异常", e);
|
|
|
+// }
|
|
|
+// }
|
|
|
}
|