소스 검색

homepage recommend

丁云鹏 1 년 전
부모
커밋
aee1a51ce6
15개의 변경된 파일501개의 추가작업 그리고 17개의 파일을 삭제
  1. 1 1
      recommend-server-client/src/main/java/com/tzld/piaoquan/recommend/server/gen/recommend/Video.java
  2. 2 2
      recommend-server-service/pom.xml
  3. 169 13
      recommend-server-service/src/main/java/com/tzld/piaoquan/recommend/server/service/RecommendService.java
  4. 13 0
      recommend-server-service/src/main/java/com/tzld/piaoquan/recommend/server/service/filter/FilterParam.java
  5. 13 0
      recommend-server-service/src/main/java/com/tzld/piaoquan/recommend/server/service/filter/FilterResult.java
  6. 13 0
      recommend-server-service/src/main/java/com/tzld/piaoquan/recommend/server/service/filter/FilterService.java
  7. 8 0
      recommend-server-service/src/main/java/com/tzld/piaoquan/recommend/server/service/rank/RankService.java
  8. 17 0
      recommend-server-service/src/main/java/com/tzld/piaoquan/recommend/server/service/recall/RecallParam.java
  9. 21 0
      recommend-server-service/src/main/java/com/tzld/piaoquan/recommend/server/service/recall/RecallResult.java
  10. 11 0
      recommend-server-service/src/main/java/com/tzld/piaoquan/recommend/server/service/recall/RecallService.java
  11. 8 0
      recommend-server-service/src/main/java/com/tzld/piaoquan/recommend/server/service/recall/RecallStrategy.java
  12. 173 0
      recommend-server-service/src/main/java/com/tzld/piaoquan/recommend/server/service/recall/strategy/AbstractRegionRecallStrategy.java
  13. 30 0
      recommend-server-service/src/main/java/com/tzld/piaoquan/recommend/server/util/DateUtils.java
  14. 21 0
      recommend-server-service/src/main/java/com/tzld/piaoquan/recommend/server/util/JSONUtils.java
  15. 1 1
      recommend-server-service/src/main/resources/application.yml

+ 1 - 1
recommend-server-client/src/main/java/com/tzld/piaoquan/recommend/server/gen/recommend/Video.java

@@ -17,7 +17,7 @@ private static final long serialVersionUID = 0L;
   }
   private Video() {
     pushFrom_ = "";
-    abCode_ = "";
+    abCode_ = "";toBuilder
     sortScore_ = "";
   }
 

+ 2 - 2
recommend-server-service/pom.xml

@@ -129,8 +129,8 @@
         </dependency>
         <dependency>
             <groupId>org.apache.commons</groupId>
-            <artifactId>commons-lang3</artifactId>
-            <version>3.1</version>
+            <artifactId>commons-collections4</artifactId>
+            <version>4.1</version>
         </dependency>
     </dependencies>
 

+ 169 - 13
recommend-server-service/src/main/java/com/tzld/piaoquan/recommend/server/service/RecommendService.java

@@ -1,10 +1,20 @@
 package com.tzld.piaoquan.recommend.server.service;
 
+import com.alibaba.fastjson.JSONObject;
+import com.ctrip.framework.apollo.spring.annotation.ApolloJsonValue;
+import com.google.common.cache.CacheBuilder;
+import com.google.common.cache.CacheLoader;
+import com.google.common.cache.LoadingCache;
 import com.tzld.piaoquan.recommend.server.gen.common.Result;
 import com.tzld.piaoquan.recommend.server.gen.recommend.HomepageRecommendRequest;
 import com.tzld.piaoquan.recommend.server.gen.recommend.HomepageRecommendResponse;
 import com.tzld.piaoquan.recommend.server.gen.recommend.Video;
 import com.tzld.piaoquan.recommend.server.model.param.HomepageRecommendParam;
+import com.tzld.piaoquan.recommend.server.util.DateUtils;
+import com.tzld.piaoquan.recommend.server.util.JSONUtils;
+import lombok.extern.slf4j.Slf4j;
+import org.apache.commons.collections4.MapUtils;
+import org.apache.commons.lang3.RandomUtils;
 import org.apache.commons.lang3.StringUtils;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.data.redis.core.RedisTemplate;
@@ -16,22 +26,46 @@ import javax.annotation.PostConstruct;
 import java.text.SimpleDateFormat;
 import java.util.*;
 import java.util.concurrent.TimeUnit;
+import java.util.concurrent.atomic.AtomicInteger;
 
 /**
  * @author dyp
  */
 @Service
+@Slf4j
 public class RecommendService {
-    @Autowired
-    private MidService midService;
 
     @Autowired
     private RedisTemplate<String, String> redisTemplate;
 
-    private String abExpCode;
 
     private Map<String, String> ab_initial_config_map = new HashMap<>();
 
+    @ApolloJsonValue("ab_exp_code")
+    private Map<String, Map<String, String>> abExpCodeMap = new HashMap<>();
+
+    @ApolloJsonValue("app_ab_code")
+    private Map<String, Map<String, Map<String, String>>> appAbCodeMap = new HashMap<>();
+
+    private int[] flowPoolIdList = {7, 8, 9, 10, 11, 12, 13, 14, 15, 16};
+
+    // {"control_group": [], "experimental_flow_set_level": [10, 11, 12, 13, 14, 15, 16, 17], "experimental_flow_set_level_score": [9, 18]}
+    private LoadingCache<String, Map<String, List<Integer>>> flowPoolConfigCache = CacheBuilder.newBuilder()
+            .maximumSize(10)
+            .refreshAfterWrite(600, TimeUnit.SECONDS)
+            .expireAfterWrite(600, TimeUnit.SECONDS)
+            .expireAfterAccess(600, TimeUnit.SECONDS)
+            .build(new CacheLoader<String, Map<String, List<Integer>>>() {
+                @Override
+                public Map<String, List<Integer>> load(String key) throws Exception {
+                    String value = redisTemplate.opsForValue().get(key);
+                    if (StringUtils.isEmpty(value)) {
+                        return Collections.emptyMap();
+                    }
+                    return JSONObject.parseObject(value, Map.class);
+                }
+            });
+
     @PostConstruct
     public void init() {
         ab_initial_config_map.put("VLOG", "095");
@@ -52,12 +86,48 @@ public class RecommendService {
             return specialMidRecommend(request);
         }
 
-        HomepageRecommendParam param = genHomepageRecommendParam(request);
+        HomepageRecommendParam param = genHomepageRecommendParam(request, 0);
+        log.info("genHomepageRecommendParam : {}", JSONUtils.toJson(param));
+
+
+        List<Video> videos;
+        String ab_code = param.getAb_code();
+        if (ab_code.equals("60054") || ab_code.equals("60056") || ab_code.equals("60067")
+                || ab_code.equals("60068") || ab_code.equals("60066") || ab_code.equals("60069")
+                || ab_code.equals("60070") || ab_code.equals("60071") || ab_code.equals("60072")
+                || ab_code.equals("60073") || ab_code.equals("60074") || ab_code.equals("60075")
+                || ab_code.equals("60076") || ab_code.equals("60077") || ab_code.equals("60078")
+                || ab_code.equals("60079") || ab_code.equals("60080") || ab_code.equals("60081")
+                || ab_code.equals("60082") || ab_code.equals("60083") || ab_code.equals("60084")
+                || ab_code.equals("60085") || ab_code.equals("60086")) {
+            videos = videoRecommendOld(request, param);
+        } else {
+            videos = videoRecommendNew(request, param);
+        }
+
+        List<Video> result = new ArrayList<>();
+        int i = 0;
+        for (Video v : videos) {
+            result.add(v.toBuilder().setPosition(i++).build());
+        }
+
+        //updateCache()
+        //    update_redis_data(result=rank_result, app_type=app_type, mid=mid, top_K=top_K,
+        //                      level_weight=level_weight, flow_pool_abtest_group=flow_pool_abtest_group)
+        return null;
+    }
+
+    private List<Video> videoRecommendNew(HomepageRecommendRequest request, HomepageRecommendParam param) {
+        // TODO
         return null;
+    }
 
+    private List<Video> videoRecommendOld(HomepageRecommendRequest request, HomepageRecommendParam param) {
+        // TODO
+        return null;
     }
 
-    private HomepageRecommendParam genHomepageRecommendParam(HomepageRecommendRequest request) {
+    private HomepageRecommendParam genHomepageRecommendParam(HomepageRecommendRequest request, int recommendType) {
         HomepageRecommendParam param = new HomepageRecommendParam();
         param.setTop_K(3);
         param.setFlow_pool_P(0.3);
@@ -69,22 +139,102 @@ public class RecommendService {
                 ? ab_initial_config_map.get(request.getAppType())
                 : ab_initial_config_map.get("other");
 
+        Map<String, String> abExpCode = abExpCodeMap.get(abInitialConfig);
+        param.setAb_code(abExpCode.get("ab_code"));
+        param.setRule_key(abExpCode.get("rule_key"));
+        param.setData_key(abExpCode.get("data_key"));
+        param.setRule_key_30day(abExpCode.get("30day_rule_key"));
+        param.setShield_config("");
+        param.setRank_key_prefix("rank:score1:");
+
+        // 实验配置
+        if (StringUtils.isNotBlank(request.getAbExpInfo())) {
+            Map<String, List<Map<String, String>>> map = JSONObject.parseObject(request.getAbExpInfo(), Map.class);
+            Set<String> abExpCodes = new HashSet<>();
+            for (List<Map<String, String>> list : map.values()) {
+                list.stream().forEach(m -> abExpCodes.add(m.get("abExpCode")));
+            }
+
+            // 流量池视频分发概率
+            if (abExpCodes.contains("211")) {
+                param.setFlow_pool_P(0.9);
+            } else if (abExpCodes.contains("221")) {
+                param.setFlow_pool_P(0.7);
+            } else if (abExpCodes.contains("299")) {
+                param.setFlow_pool_P(0.5);
+            } else if (abExpCodes.contains("300")) {
+                param.setFlow_pool_P(0.4);
+            } else if (abExpCodes.contains("301")) {
+                param.setFlow_pool_P(0.6);
+            } else if (abExpCodes.contains("339")) {
+                param.setFlow_pool_P(0);
+            }
+
+            for (Map.Entry<String, Map<String, String>> entry : abExpCodeMap.entrySet()) {
+                if (abExpCodes.contains(entry.getKey())) {
+                    param.setAb_code(entry.getValue().get("ab_code"));
+                    param.setRule_key(entry.getValue().get("rule_key"));
+                    param.setData_key(entry.getValue().get("data_key"));
+                    param.setRank_key_prefix(StringUtils.isNotBlank(entry.getValue().get("rank_key_prefix"))
+                            ? entry.getValue().get("rank_key_prefix")
+                            : "rank:score1:");
+                    param.setRule_key_30day(entry.getValue().get("30day_rule_key"));
+                    param.setShield_config(entry.getValue().get("ab_code"));
+                    break;
+                }
+            }
+        }
+
+        // app实验组
+        // {"10018":{"eventId":"100182","ifAddedRootEventId":true},"10020":{"eventId":"100201","ifAddedRootEventId":true}}
+        if (StringUtils.isNotBlank(request.getAbInfoData())) {
+            Map<String, Map<String, String>> map = JSONObject.parseObject(request.getAbInfoData(), Map.class);
+            Map<String, String> abInfoAppMap = new HashMap<>();
+
+            for (Map.Entry<String, Map<String, String>> entry : map.entrySet()) {
+                if (MapUtils.isEmpty(entry.getValue())) {
+                    continue;
+                }
+                String eventId = entry.getValue().get("eventId");
+                if (StringUtils.isNotBlank(eventId)) {
+                    abInfoAppMap.put(entry.getKey(), eventId);
+                }
+            }
+
+            if (recommendType == 0) {
+                String eventId = abInfoAppMap.get("10003");
+                Map<String, Map<String, String>> appAbCode = appAbCodeMap.get("10003");
+                if (StringUtils.isNotBlank(eventId) && appAbCode.containsKey(eventId)) {
+                    param.setAb_code(appAbCode.get(eventId).get("ab_code"));
+                    param.setRule_key(appAbCode.get(eventId).get("rule_key"));
+                    param.setData_key(appAbCode.get(eventId).get("data_key"));
+                }
+            }
+
+            // 流量池分发实验组划分
+            int flowPoolIdChoice = flowPoolIdList[RandomUtils.nextInt(0, flowPoolIdList.length - 1)];
+            param.setFlow_pool_abtest_group("control_group");
+            try {
+                Map<String, List<Integer>> flowPoolConfig = flowPoolConfigCache.get("flow:pool:abtest:config");
+                for (Map.Entry<String, List<Integer>> entry : flowPoolConfig.entrySet()) {
+                    if (entry.getValue().contains(flowPoolIdChoice)) {
+                        param.setFlow_pool_abtest_group(entry.getKey());
+                    }
+                }
+            } catch (Exception e) {
+                log.error("flowPoolConfigCache get error", e);
+            }
+        }
 
         return param;
     }
 
     private HomepageRecommendResponse specialMidRecommend(HomepageRecommendRequest request) {
         String keyNamePrefix = "special:videos:item:";
-        SimpleDateFormat dateFormat = new SimpleDateFormat("yyyyMMdd");
-        Date currentDate = new Date();
-        String dateStr = dateFormat.format(currentDate);
+        String dateStr = DateUtils.getCurrentDateStr("yyyyMMdd");
         String specialKeyName = keyNamePrefix + dateStr;
         if (!redisTemplate.hasKey(specialKeyName)) {
-            Calendar calendar = Calendar.getInstance();
-            calendar.setTime(currentDate);
-            calendar.add(Calendar.DAY_OF_MONTH, -1);
-            Date previousDate = calendar.getTime();
-            dateStr = dateFormat.format(previousDate);
+            dateStr = DateUtils.getBeforeDaysDateStr("yyyyMMdd", 1);
             specialKeyName = keyNamePrefix + dateStr;
         }
 
@@ -129,4 +279,10 @@ public class RecommendService {
                 .build();
     }
 
+    public static void main(String[] args) {
+        String json = "{\"ab_test001\":[{\"ab_code\":\"1\",\"config_value\":\"v1\"},{\"ab_code\":\"2\",\"config_value\":\"v2\"}],\"ab_test002\":[{\"ab_code\":\"3\",\"config_value\":\"v3\"},{\"ab_code\":\"4\",\"config_value\":\"v4\"}]}";
+        Map<String, List<Map<String, String>>> map = JSONObject.parseObject(json, Map.class);
+        System.out.println("");
+    }
+
 }

+ 13 - 0
recommend-server-service/src/main/java/com/tzld/piaoquan/recommend/server/service/filter/FilterParam.java

@@ -0,0 +1,13 @@
+package com.tzld.piaoquan.recommend.server.service.filter;
+
+import lombok.Data;
+
+import java.util.List;
+
+/**
+ * @author dyp
+ */
+@Data
+public class FilterParam {
+    private List<Long> videoIds;
+}

+ 13 - 0
recommend-server-service/src/main/java/com/tzld/piaoquan/recommend/server/service/filter/FilterResult.java

@@ -0,0 +1,13 @@
+package com.tzld.piaoquan.recommend.server.service.filter;
+
+import lombok.Data;
+
+import java.util.List;
+
+/**
+ * @author dyp
+ */
+@Data
+public class FilterResult {
+    private List<Long> videoIds;
+}

+ 13 - 0
recommend-server-service/src/main/java/com/tzld/piaoquan/recommend/server/service/filter/FilterService.java

@@ -0,0 +1,13 @@
+package com.tzld.piaoquan.recommend.server.service.filter;
+
+import org.springframework.stereotype.Service;
+
+/**
+ * @author dyp
+ */
+@Service
+public class FilterService {
+    public FilterResult filter(FilterParam param) {
+        return null;
+    }
+}

+ 8 - 0
recommend-server-service/src/main/java/com/tzld/piaoquan/recommend/server/service/rank/RankService.java

@@ -0,0 +1,8 @@
+package com.tzld.piaoquan.recommend.server.service.rank;
+
+/**
+ * @author dyp
+ */
+public class RankService {
+    
+}

+ 17 - 0
recommend-server-service/src/main/java/com/tzld/piaoquan/recommend/server/service/recall/RecallParam.java

@@ -0,0 +1,17 @@
+package com.tzld.piaoquan.recommend.server.service.recall;
+
+import lombok.Data;
+
+/**
+ * @author dyp
+ */
+@Data
+public class RecallParam {
+    private String provinceCode;
+    private String mid;
+    private String appType;
+    private String dataKey;
+    private String ruleKey;
+    private String abCode;
+    private int size;
+}

+ 21 - 0
recommend-server-service/src/main/java/com/tzld/piaoquan/recommend/server/service/recall/RecallResult.java

@@ -0,0 +1,21 @@
+package com.tzld.piaoquan.recommend.server.service.recall;
+
+import lombok.Data;
+
+import java.util.List;
+
+/**
+ * @author dyp
+ */
+@Data
+public class RecallResult {
+    private List<RecallData> recallData;
+
+    @Data
+    public static class RecallData {
+        private long videoId;
+        private double rovScore;
+        private String pushFrom;
+        private String abCode;
+    }
+}

+ 11 - 0
recommend-server-service/src/main/java/com/tzld/piaoquan/recommend/server/service/recall/RecallService.java

@@ -0,0 +1,11 @@
+package com.tzld.piaoquan.recommend.server.service.recall;
+
+import org.springframework.stereotype.Service;
+
+/**
+ * @author dyp
+ */
+@Service
+public class RecallService {
+
+}

+ 8 - 0
recommend-server-service/src/main/java/com/tzld/piaoquan/recommend/server/service/recall/RecallStrategy.java

@@ -0,0 +1,8 @@
+package com.tzld.piaoquan.recommend.server.service.recall;
+
+/**
+ * @author dyp
+ */
+public interface RecallStrategy {
+    RecallResult recall(RecallParam param);
+}

+ 173 - 0
recommend-server-service/src/main/java/com/tzld/piaoquan/recommend/server/service/recall/strategy/AbstractRegionRecallStrategy.java

@@ -0,0 +1,173 @@
+package com.tzld.piaoquan.recommend.server.service.recall.strategy;
+
+import com.alibaba.fastjson.JSONObject;
+import com.google.common.collect.Lists;
+import com.tzld.piaoquan.recommend.server.service.filter.FilterParam;
+import com.tzld.piaoquan.recommend.server.service.filter.FilterResult;
+import com.tzld.piaoquan.recommend.server.service.filter.FilterService;
+import com.tzld.piaoquan.recommend.server.service.recall.RecallParam;
+import com.tzld.piaoquan.recommend.server.service.recall.RecallResult;
+import com.tzld.piaoquan.recommend.server.service.recall.RecallStrategy;
+import com.tzld.piaoquan.recommend.server.util.DateUtils;
+import org.apache.commons.collections4.CollectionUtils;
+import org.apache.commons.lang3.StringUtils;
+import org.apache.commons.lang3.math.NumberUtils;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.data.redis.core.RedisTemplate;
+import org.springframework.data.redis.core.ZSetOperations;
+
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+import java.util.concurrent.TimeUnit;
+import java.util.stream.Collectors;
+
+/**
+ * @author dyp
+ */
+public abstract class AbstractRegionRecallStrategy implements RecallStrategy {
+    @Autowired
+    protected RedisTemplate<String, String> redisTemplate;
+
+    @Autowired
+    protected FilterService filterService;
+
+    @Override
+    public RecallResult recall(RecallParam param) {
+
+        String recordKey = recordKey(param);
+        String lastVideoKey = lastVideoKey(param);
+        int idx = 0;
+        String poolKey;
+
+        // TODO 整段逻辑很奇怪,需要重新理解
+        if (redisTemplate.hasKey(recordKey)) {
+            String record = redisTemplate.opsForValue().get("record_key");
+            Map<String, String> recordMap = JSONObject.parseObject(record, Map.class);
+
+            String record_dt = recordMap.get("date");
+            String record_h = recordMap.get("h");
+            String now_dt = DateUtils.getCurrentDateStr("yyyyMMdd");
+            int h = DateUtils.getCurrentHour();
+            if (record_dt.equals(now_dt) && Integer.valueOf(record_h) == h) {
+                poolKey = poolKey(param, now_dt, h);
+                idx = getIdx(lastVideoKey, poolKey);
+            } else if ((record_dt.equals(now_dt) && h - Integer.valueOf(record_h) == 1)
+                    || (h == 0 && Integer.valueOf(record_h) == 23)) {
+                poolKey = poolKey(param, now_dt, h);
+                if (redisTemplate.hasKey(poolKey)) {
+                    redisTemplate.opsForValue().set(recordKey, String.format("{\"date\":%s, \"h\":%d}", now_dt, h), 2,
+                            TimeUnit.HOURS);
+                    redisTemplate.delete(lastVideoKey);
+                } else {
+                    poolKey = poolKey(param, record_dt, Integer.valueOf(record_h));
+                    idx = getIdx(lastVideoKey, poolKey);
+                }
+            } else {
+                redisTemplate.delete(lastVideoKey);
+                poolKey = updateLastVideoRecord(recordKey, param);
+            }
+        } else {
+            redisTemplate.delete(lastVideoKey);
+            poolKey = updateLastVideoRecord(recordKey, param);
+        }
+
+        if (StringUtils.isBlank(poolKey)) {
+            return null;
+        }
+
+        // 召回
+        int getSize = param.getSize() * 5;
+        int freq = 0;
+        List<RecallResult.RecallData> results = new ArrayList<>();
+        while (results.size() < param.getSize()) {
+            freq += 1;
+            if (freq > 2) {
+                break;
+            }
+            Set<ZSetOperations.TypedTuple<String>> data = redisTemplate.opsForZSet().reverseRangeWithScores(poolKey, idx,
+                    idx + getSize - 1);
+            if (CollectionUtils.isEmpty(data)) {
+                break;
+            }
+            idx += getSize;
+            Map<Long, Double> videoMap = data.stream()
+                    .filter(t -> NumberUtils.isDigits(t.getValue()))
+                    .collect(Collectors.toMap(
+                            t -> Long.getLong(t.getValue()),
+                            t -> t.getScore(),
+                            (a, b) -> b
+                    ));
+            FilterParam filterParam = new FilterParam();
+            filterParam.setVideoIds(Lists.newArrayList(videoMap.keySet()));
+            FilterResult filterResult = filterService.filter(filterParam);
+            if (filterResult != null && CollectionUtils.isNotEmpty(filterResult.getVideoIds())) {
+                filterResult.getVideoIds().stream().forEach(vid -> {
+                    RecallResult.RecallData recallData = new RecallResult.RecallData();
+                    recallData.setVideoId(vid);
+                    recallData.setAbCode(param.getAbCode());
+                    recallData.setRovScore(videoMap.get(vid));
+                    recallData.setPushFrom(pushFrom());
+                    results.add(recallData);
+                });
+            }
+        }
+
+
+//        pool_recall_result.sort(key=lambda x: x.get('rovScore', 0), reverse=True)
+//
+//        # if len(recall_data) > 0 and len(pool_recall_result) == 0 \
+//        #         and self.ab_code == config_.AB_CODE['region_rank_by_h'].get('abtest_112') and self.mid:
+//
+//        if len(recall_data) > 0 and len(pool_recall_result) == 0 and self.mid:
+//            # 召回数据不为空 & 过滤后结果为空 & 位于实验组 & mid不为空时,更新召回获取的末位视频id记录到定位的key中
+//                last_video_key = f'{last_video_key_prefix}{self.app_type}:{self.mid}'
+//        self.redis_helper.set_data_to_redis(key_name=last_video_key, value=recall_data[-1][0],
+//                expire_time=expire_time)
+
+        RecallResult result = new RecallResult();
+        result.setRecallData(results.subList(0, results.size() < param.getSize() ? results.size() : param.getSize()));
+        return result;
+    }
+
+    private int getIdx(String lastVideoKey, String poolKey) {
+        int idx = 0;
+        String lastVideo = redisTemplate.opsForValue().get(lastVideoKey);
+        if (StringUtils.isNotBlank(lastVideo)) {
+            Long idxLong = redisTemplate.opsForZSet().reverseRank(poolKey, lastVideo);
+            if (idxLong != null) {
+                idx = idxLong.intValue();
+                idx += 1;
+            }
+        }
+        return idx;
+    }
+
+    private String updateLastVideoRecord(String recordKey, RecallParam param) {
+        String currentDateStr = DateUtils.getCurrentDateStr("yyyyMMdd");
+        int h = DateUtils.getCurrentHour();
+
+        String poolKey = poolKey(param, currentDateStr, h);
+        if (!redisTemplate.hasKey(poolKey)) {
+            if (h == 0) {
+                currentDateStr = DateUtils.getBeforeDaysDateStr("yyyyMMdd", 1);
+                h = 23;
+            } else {
+                h = h - 1;
+            }
+            poolKey = poolKey(param, currentDateStr, h);
+        }
+        redisTemplate.opsForValue().set(recordKey, String.format("{\"date\":%s, \"h\":%d}", currentDateStr, h), 2,
+                TimeUnit.HOURS);
+        return poolKey;
+    }
+
+    abstract String recordKey(RecallParam param);
+
+    abstract String poolKey(RecallParam param, String now_dt, int h);
+
+    abstract String lastVideoKey(RecallParam param);
+
+    abstract String pushFrom();
+}

+ 30 - 0
recommend-server-service/src/main/java/com/tzld/piaoquan/recommend/server/util/DateUtils.java

@@ -0,0 +1,30 @@
+package com.tzld.piaoquan.recommend.server.util;
+
+import java.text.SimpleDateFormat;
+import java.util.Calendar;
+import java.util.Date;
+
+/**
+ * @author dyp
+ */
+public final class DateUtils {
+    public static String getCurrentDateStr(String format) {
+        SimpleDateFormat dateFormat = new SimpleDateFormat(format);
+        Date currentDate = new Date();
+        return dateFormat.format(currentDate);
+    }
+
+    public static int getCurrentHour() {
+        Calendar calendar = Calendar.getInstance();
+        return calendar.get(Calendar.HOUR_OF_DAY);
+    }
+
+    public static String getBeforeDaysDateStr(String format, int d) {
+        SimpleDateFormat dateFormat = new SimpleDateFormat(format);
+        Calendar calendar = Calendar.getInstance();
+        calendar.setTime(new Date());
+        calendar.add(Calendar.DAY_OF_MONTH, -d);
+        Date previousDate = calendar.getTime();
+        return dateFormat.format(previousDate);
+    }
+}

+ 21 - 0
recommend-server-service/src/main/java/com/tzld/piaoquan/recommend/server/util/JSONUtils.java

@@ -0,0 +1,21 @@
+package com.tzld.piaoquan.recommend.server.util;
+
+import com.google.gson.Gson;
+import lombok.extern.slf4j.Slf4j;
+
+@Slf4j
+public class JSONUtils {
+
+
+    public static String toJson(Object obj) {
+        if (obj == null) {
+            return "";
+        }
+        try {
+            return new Gson().toJson(obj);
+        } catch (Exception e) {
+            log.error("toJson exception", e);
+            return "";
+        }
+    }
+}

+ 1 - 1
recommend-server-service/src/main/resources/application.yml

@@ -41,7 +41,7 @@ logging:
     path: /datalog/weblog/${spring.application.name}/
 
 app:
-  id: recommend-sort
+  id: recommend-server
 apollo:
   bootstrap:
     enabled: true