| | |
| | | import org.springframework.stereotype.Service; |
| | | |
| | | import java.time.LocalDateTime; |
| | | import java.util.LinkedHashMap; |
| | | import java.util.LinkedHashSet; |
| | | import java.util.List; |
| | | import java.util.Map; |
| | | import java.util.Set; |
| | | |
| | | @Service |
| | |
| | | .orderByAsc(LiveSession::getId)); |
| | | int startedCount = 0; |
| | | if (dueSessions != null && !dueSessions.isEmpty()) { |
| | | for (LiveSession dueSession : dueSessions) { |
| | | List<LiveSession> effectiveDueSessions = pickEffectiveDueSessions(dueSessions); |
| | | for (LiveSession dueSession : effectiveDueSessions) { |
| | | // 定时任务与人工开播共用同一套状态迁移逻辑,避免状态口径分叉。 |
| | | LiveSessionStatusVO statusVO = liveSessionAppService.autoStart(dueSession.getId(), now); |
| | | if (statusVO == null) { |
| | |
| | | } |
| | | |
| | | if (startedCount > 0) { |
| | | log.info("live session auto start finished, scanned={}, started={}", dueSessions.size(), startedCount); |
| | | log.info("live session auto start finished, scanned={}, effective={}, started={}", |
| | | dueSessions.size(), effectiveDueSessions.size(), startedCount); |
| | | } |
| | | } |
| | | |
| | |
| | | } |
| | | |
| | | /** |
| | | * 同一课程只挑一条最应被自动开播的场次,避免历史过期开播记录被批量拉起后又互相收敛。 |
| | | */ |
| | | private List<LiveSession> pickEffectiveDueSessions(List<LiveSession> dueSessions) { |
| | | if (dueSessions == null || dueSessions.isEmpty()) { |
| | | return dueSessions; |
| | | } |
| | | Map<Long, LiveSession> effectiveSessionMap = new LinkedHashMap<Long, LiveSession>(); |
| | | for (LiveSession dueSession : dueSessions) { |
| | | if (dueSession == null || dueSession.getLiveCourseId() == null) { |
| | | continue; |
| | | } |
| | | LiveSession current = effectiveSessionMap.get(dueSession.getLiveCourseId()); |
| | | if (current == null || compareDueSession(current, dueSession) < 0) { |
| | | effectiveSessionMap.put(dueSession.getLiveCourseId(), dueSession); |
| | | } |
| | | } |
| | | return new java.util.ArrayList<LiveSession>(effectiveSessionMap.values()); |
| | | } |
| | | |
| | | /** |
| | | * 自动开播候选按计划开播时间排序,时间更晚者优先;同时间取 ID 更大的最新记录。 |
| | | */ |
| | | private int compareDueSession(LiveSession left, LiveSession right) { |
| | | LocalDateTime leftTime = left == null ? null : left.getStartTime(); |
| | | LocalDateTime rightTime = right == null ? null : right.getStartTime(); |
| | | if (leftTime == null && rightTime == null) { |
| | | return compareSessionId(left, right); |
| | | } |
| | | if (leftTime == null) { |
| | | return -1; |
| | | } |
| | | if (rightTime == null) { |
| | | return 1; |
| | | } |
| | | int timeCompare = leftTime.compareTo(rightTime); |
| | | if (timeCompare != 0) { |
| | | return timeCompare; |
| | | } |
| | | return compareSessionId(left, right); |
| | | } |
| | | |
| | | private int compareSessionId(LiveSession left, LiveSession right) { |
| | | Long leftId = left == null ? null : left.getId(); |
| | | Long rightId = right == null ? null : right.getId(); |
| | | if (leftId == null && rightId == null) { |
| | | return 0; |
| | | } |
| | | if (leftId == null) { |
| | | return -1; |
| | | } |
| | | if (rightId == null) { |
| | | return 1; |
| | | } |
| | | return leftId.compareTo(rightId); |
| | | } |
| | | |
| | | /** |
| | | * 定时收敛历史残留的直播中场次,避免同课程出现多条或过期直播中状态。 |
| | | */ |
| | | private void reconcileLivingCourses(LocalDateTime now) { |