|
@@ -1,22 +1,39 @@
|
|
|
package com.tzld.piaoquan.recommend.server.service.flowpool;
|
|
|
|
|
|
+import com.alibaba.fastjson.JSONObject;
|
|
|
+import com.google.common.collect.Lists;
|
|
|
+import com.tzld.piaoquan.recommend.server.common.RedisKeyConstants;
|
|
|
+import com.tzld.piaoquan.recommend.server.common.ThreadPoolFactory;
|
|
|
+import com.tzld.piaoquan.recommend.server.feign.FlowPoolFeign;
|
|
|
+import com.tzld.piaoquan.recommend.server.feign.model.FlowPoolResponse;
|
|
|
+import com.tzld.piaoquan.recommend.server.feign.model.FlowPoolVideoInfo;
|
|
|
import com.tzld.piaoquan.recommend.server.model.TripleConsumer;
|
|
|
import com.tzld.piaoquan.recommend.server.model.Video;
|
|
|
-import com.tzld.piaoquan.recommend.server.common.ThreadPoolFactory;
|
|
|
+import com.tzld.piaoquan.recommend.server.repository.DouHotVideoMapping;
|
|
|
+import com.tzld.piaoquan.recommend.server.repository.DouHotVideoMappingRepository;
|
|
|
+import com.tzld.piaoquan.recommend.server.repository.DouHotVideoPortraitData;
|
|
|
+import com.tzld.piaoquan.recommend.server.repository.DouHotVideoPortraitDataRepository;
|
|
|
import lombok.extern.slf4j.Slf4j;
|
|
|
import org.apache.commons.collections4.CollectionUtils;
|
|
|
import org.apache.commons.collections4.MapUtils;
|
|
|
+import org.apache.commons.lang3.StringUtils;
|
|
|
import org.springframework.beans.factory.annotation.Autowired;
|
|
|
import org.springframework.beans.factory.annotation.Qualifier;
|
|
|
+import org.springframework.beans.factory.annotation.Value;
|
|
|
import org.springframework.data.redis.core.RedisTemplate;
|
|
|
import org.springframework.stereotype.Service;
|
|
|
|
|
|
-import java.util.*;
|
|
|
+import java.util.ArrayList;
|
|
|
+import java.util.HashMap;
|
|
|
+import java.util.List;
|
|
|
+import java.util.Map;
|
|
|
import java.util.concurrent.ExecutorService;
|
|
|
+import java.util.concurrent.TimeUnit;
|
|
|
import java.util.stream.Collectors;
|
|
|
|
|
|
import static com.tzld.piaoquan.recommend.server.common.enums.AppTypeEnum.*;
|
|
|
-import static com.tzld.piaoquan.recommend.server.service.flowpool.FlowPoolConstants.*;
|
|
|
+import static com.tzld.piaoquan.recommend.server.service.flowpool.FlowPoolConstants.KEY_WITH_LEVEL_FORMAT;
|
|
|
+import static com.tzld.piaoquan.recommend.server.service.flowpool.FlowPoolConstants.KEY_WITH_LEVEL_FORMAT_V2;
|
|
|
|
|
|
/**
|
|
|
* @author dyp
|
|
@@ -30,6 +47,17 @@ public class FlowPoolService {
|
|
|
@Autowired
|
|
|
private FlowPoolConfigService flowPoolConfigService;
|
|
|
|
|
|
+ @Autowired
|
|
|
+ private DouHotVideoMappingRepository douHotVideoMappingRepository;
|
|
|
+ @Autowired
|
|
|
+ private DouHotVideoPortraitDataRepository douHotVideoPortraitDataRepository;
|
|
|
+
|
|
|
+ @Value("${dou.hot.flow.pool.id:18}")
|
|
|
+ private Integer douHotFlowPoolId;
|
|
|
+
|
|
|
+ @Autowired
|
|
|
+ private FlowPoolFeign flowPoolFeign;
|
|
|
+
|
|
|
private final String localDistributeCountFormat = "flow:pool:local:distribute:count:%s:%s";
|
|
|
|
|
|
public final String valueFormat = "%s-%s";
|
|
@@ -124,5 +152,98 @@ public class FlowPoolService {
|
|
|
}
|
|
|
});
|
|
|
}
|
|
|
+
|
|
|
+ public void syncDouHotFlowPoolVideo() {
|
|
|
+ List<FlowPoolVideoInfo> allDouHotVideo = this.findAllDouHotVideoFromFlowPool();
|
|
|
+ log.info("[DouHot video size]: {}", allDouHotVideo.size());
|
|
|
+
|
|
|
+ List<Long> allVideoId = allDouHotVideo.stream()
|
|
|
+ .map(FlowPoolVideoInfo::getVideoId)
|
|
|
+ .collect(Collectors.toList());
|
|
|
+
|
|
|
+ // 补充省份信息
|
|
|
+ Map<Long, String> allVideoAndProvinceMap = this.findAllVideoAndProvinceMap(allVideoId);
|
|
|
+ for (FlowPoolVideoInfo flowPoolVideoInfo : allDouHotVideo) {
|
|
|
+ if (allVideoAndProvinceMap.containsKey(flowPoolVideoInfo.getVideoId())) {
|
|
|
+ flowPoolVideoInfo.setProvince(allVideoAndProvinceMap.get(flowPoolVideoInfo.getVideoId()));
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ allDouHotVideo = allDouHotVideo.stream()
|
|
|
+ .filter(i -> StringUtils.isNotBlank(i.getProvince()))
|
|
|
+ .collect(Collectors.toList());
|
|
|
+ log.info("[DouHot filter empty province after video size]: {}", allDouHotVideo.size());
|
|
|
+
|
|
|
+
|
|
|
+ Map<String, List<FlowPoolVideoInfo>> provinceAndVideoListMap = allDouHotVideo.stream()
|
|
|
+ .collect(Collectors.groupingBy(FlowPoolVideoInfo::getProvince, Collectors.toList()));
|
|
|
+
|
|
|
+ for (Map.Entry<String, List<FlowPoolVideoInfo>> entry : provinceAndVideoListMap.entrySet()) {
|
|
|
+ String province = entry.getKey();
|
|
|
+ List<String> items = entry.getValue().stream()
|
|
|
+ .map(i -> String.format("%d-%s", i.getVideoId(), i.getFlowPool()))
|
|
|
+ .collect(Collectors.toList());
|
|
|
+
|
|
|
+ log.info("[DouHot province video size]. province: {}, video size: {}", entry.getKey(), items.size());
|
|
|
+
|
|
|
+ String redisKey = String.format(RedisKeyConstants.DouHot.ITEM_REDIS_KEY_FORMAT, province, "1");
|
|
|
+ log.info("[DouHot item redis key]: {}", redisKey);
|
|
|
+ redisTemplate.delete(redisKey);
|
|
|
+ redisTemplate.opsForSet().add(redisKey, items.toArray(new String[0]));
|
|
|
+ redisTemplate.expire(redisKey, 24 * 60 * 60, TimeUnit.SECONDS);
|
|
|
+ }
|
|
|
+
|
|
|
+ }
|
|
|
+
|
|
|
+ private Map<Long, String> findAllVideoAndProvinceMap(List<Long> videoIds) {
|
|
|
+ // 获取票圈视频ID与热点宝vid的映射
|
|
|
+ List<List<Long>> videoIdPartition = Lists.partition(videoIds, 500);
|
|
|
+ Map<Long, String> videoIdAndVidMap = videoIdPartition.stream().map(douHotVideoMappingRepository::findAllByVideoIdIn)
|
|
|
+ .flatMap(List::stream)
|
|
|
+ .collect(Collectors.toMap(DouHotVideoMapping::getVideoId, DouHotVideoMapping::getVid, (o1, o2) -> o1));
|
|
|
+
|
|
|
+ // 获取热点宝vid与地域的映射
|
|
|
+ List<List<String>> vidPartition = Lists.partition(new ArrayList<>(videoIdAndVidMap.values()), 500);
|
|
|
+ Map<String, String> vidAndProvinceMap = vidPartition.stream().map(i -> douHotVideoPortraitDataRepository.findAllByVidInAndType(i, 4))
|
|
|
+ .flatMap(List::stream)
|
|
|
+ .collect(Collectors.toMap(DouHotVideoPortraitData::getVid, DouHotVideoPortraitData::getName, (o1, o2) -> o1));
|
|
|
+
|
|
|
+ Map<Long, String> resultMap = new HashMap<>(videoIdAndVidMap.size());
|
|
|
+ for (Map.Entry<Long, String> entry : videoIdAndVidMap.entrySet()) {
|
|
|
+ Long videoId = entry.getKey();
|
|
|
+ String vid = entry.getValue();
|
|
|
+ if (vidAndProvinceMap.containsKey(vid)) {
|
|
|
+ resultMap.put(videoId, vidAndProvinceMap.get(vid));
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ return resultMap;
|
|
|
+ }
|
|
|
+
|
|
|
+ private List<FlowPoolVideoInfo> findAllDouHotVideoFromFlowPool() {
|
|
|
+ List<FlowPoolVideoInfo> result = new ArrayList<>();
|
|
|
+ int pageNum = 0;
|
|
|
+ while (true) {
|
|
|
+ JSONObject paramJson = new JSONObject();
|
|
|
+ paramJson.put("flowPoolId", douHotFlowPoolId);
|
|
|
+ paramJson.put("appType", 0);
|
|
|
+ paramJson.put("pageSize", 1000);
|
|
|
+ paramJson.put("pageNum", pageNum++);
|
|
|
+
|
|
|
+ log.info("[get DouHot flow pool video] paramJson:{}", paramJson);
|
|
|
+ FlowPoolResponse<List<FlowPoolVideoInfo>> response = flowPoolFeign.getFlowPoolVideo(paramJson);
|
|
|
+ if (0 != response.getCode()) {
|
|
|
+ log.error("[get DouHot flow pool video request error] responseJson: {}", response);
|
|
|
+ break;
|
|
|
+ }
|
|
|
+
|
|
|
+ if (CollectionUtils.isEmpty(response.getData())) {
|
|
|
+ log.error("[get DouHot flow pool video data is empty] responseJson: {}", response);
|
|
|
+ break;
|
|
|
+ }
|
|
|
+ result.addAll(response.getData());
|
|
|
+ }
|
|
|
+ return result;
|
|
|
+ }
|
|
|
}
|
|
|
|