|
|
@@ -2,7 +2,6 @@ package com.fs.live.task;
|
|
|
|
|
|
import com.alibaba.fastjson.JSONObject;
|
|
|
import com.fs.common.core.domain.R;
|
|
|
-import com.fs.common.core.redis.RedisCache;
|
|
|
import com.fs.common.utils.StringUtils;
|
|
|
import com.fs.live.domain.Live;
|
|
|
import com.fs.live.domain.LiveCompletionPointsRecord;
|
|
|
@@ -26,8 +25,6 @@ import java.util.HashSet;
|
|
|
import java.util.List;
|
|
|
import java.util.Set;
|
|
|
|
|
|
-import static com.fs.live.websocket.service.WebSocketServer.USER_ENTRY_TIME_KEY;
|
|
|
-
|
|
|
/**
|
|
|
* 直播完课奖励定时任务(积分 / 优惠券)
|
|
|
*/
|
|
|
@@ -35,9 +32,6 @@ import static com.fs.live.websocket.service.WebSocketServer.USER_ENTRY_TIME_KEY;
|
|
|
@Component
|
|
|
public class LiveCompletionPointsTask {
|
|
|
|
|
|
- @Autowired
|
|
|
- private RedisCache redisCache;
|
|
|
-
|
|
|
@Autowired
|
|
|
private ILiveWatchUserService liveWatchUserService;
|
|
|
|
|
|
@@ -141,13 +135,31 @@ public class LiveCompletionPointsTask {
|
|
|
/**
|
|
|
* 完课优惠券弹窗:与定时任务一致,先写留存再推送 WebSocket
|
|
|
*/
|
|
|
+ /**
|
|
|
+ * 尝试推送完课优惠券弹窗(定时任务 / WebSocket 心跳共用)
|
|
|
+ * @return 是否推送成功
|
|
|
+ */
|
|
|
+ public boolean tryDispatchCompletionCouponNotify(Long liveId, Long userId, Long watchDuration) {
|
|
|
+ return dispatchCompletionCouponNotify(liveId, userId, watchDuration, false) != null;
|
|
|
+ }
|
|
|
+
|
|
|
private LiveConsoleOpLog dispatchCompletionCouponNotify(Long liveId, Long userId, Long watchDuration, boolean forcePush) {
|
|
|
LiveCompletionCouponNotifyResult notifyResult =
|
|
|
completionCouponService.prepareCompletionCouponNotify(liveId, userId, watchDuration, forcePush);
|
|
|
if (notifyResult == null || !notifyResult.isShouldNotify()) {
|
|
|
+ if (notifyResult != null && notifyResult.isEligible()) {
|
|
|
+ log.info("[完课优惠券] 观看已达标但未推送弹窗, liveId={}, userId={}, " +
|
|
|
+ "可能原因: 未配置今日问题 / 今日已推送 / 今日已领券",
|
|
|
+ liveId, userId);
|
|
|
+ }
|
|
|
return null;
|
|
|
}
|
|
|
- return saveAndPushCompletionCouponNotify(liveId, userId, notifyResult);
|
|
|
+ LiveConsoleOpLog opLog = saveAndPushCompletionCouponNotify(liveId, userId, notifyResult);
|
|
|
+ if (opLog == null) {
|
|
|
+ log.warn("[完课优惠券] 满足推送条件但 WebSocket 发送失败(用户未在线或连接已断开), liveId={}, userId={}",
|
|
|
+ liveId, userId);
|
|
|
+ }
|
|
|
+ return opLog;
|
|
|
}
|
|
|
|
|
|
private LiveConsoleOpLog saveAndPushCompletionCouponNotify(Long liveId, Long userId,
|
|
|
@@ -226,20 +238,11 @@ public class LiveCompletionPointsTask {
|
|
|
}
|
|
|
|
|
|
/**
|
|
|
- * 与 scanLiveWatchUserStatus 一致:DB 累计时长 + 当前在线会话未落库部分
|
|
|
+ * DB 累计时长 + Redis 当前会话 + hash 缓存,与 ILiveWatchUserService.getUserWatchDuration 一致
|
|
|
*/
|
|
|
private long resolveEffectiveWatchDuration(Long liveId, Long userId) {
|
|
|
- Long total = liveWatchUserService.getTotalWatchDuration(liveId, userId);
|
|
|
- long duration = total != null ? total : 0L;
|
|
|
- String entryTimeKey = String.format(USER_ENTRY_TIME_KEY, liveId, userId);
|
|
|
- Long entryTime = redisCache.getCacheObject(entryTimeKey);
|
|
|
- if (entryTime != null) {
|
|
|
- long sessionSeconds = (System.currentTimeMillis() - entryTime) / 1000;
|
|
|
- duration += sessionSeconds;
|
|
|
- log.debug("[完课定时] 累加Redis在线时长, liveId={}, userId={}, dbDuration={}s, redisSession={}s, total={}s",
|
|
|
- liveId, userId, total, sessionSeconds, duration);
|
|
|
- }
|
|
|
- return duration;
|
|
|
+ Long duration = liveWatchUserService.getUserWatchDuration(liveId, userId);
|
|
|
+ return duration != null ? duration : 0L;
|
|
|
}
|
|
|
|
|
|
@FunctionalInterface
|