Parcourir la source

过滤指定日期前的冷启池内容

wangyunpeng il y a 1 heure
Parent
commit
d09167febc

+ 65 - 5
long-article-recommend-service/src/main/java/com/tzld/longarticle/recommend/server/service/recommend/filter/strategy/OldStrategy.java

@@ -9,6 +9,7 @@ import com.tzld.longarticle.recommend.server.util.DateUtils;
 import lombok.extern.slf4j.Slf4j;
 import org.springframework.beans.factory.annotation.Value;
 import org.springframework.stereotype.Component;
+import org.springframework.util.StringUtils;
 
 import java.util.ArrayList;
 import java.util.List;
@@ -18,12 +19,21 @@ import java.util.Objects;
 @Slf4j
 public class OldStrategy implements FilterStrategy {
 
+    private static final int SOURCE_ID_DATE_LENGTH = 8;
+    private static final long ONE_DAY_MILLIS = 86400000L;
+
     @Value("${filter.old.strategy.rootPublish.days:30}")
     private Integer filterOldStrategyRootPublishDays;
 
     @Value("${filter.old.strategy.create.days:90}")
     private Integer filterOldStrategyCreateDays;
 
+    /**
+     * sourceId 日期过滤截止日(yyyyMMdd),未配置时不启用该过滤。
+     */
+    @Value("${filter.old.strategy.execute.date:}")
+    private String filterOldStrategyExecuteDate;
+
     @Override
     public FilterResult filter(FilterParam param) {
         FilterResult filterResult = new FilterResult();
@@ -31,14 +41,27 @@ public class OldStrategy implements FilterStrategy {
         List<Content> contents = param.getContents();
         List<Content> filterContents = new ArrayList<>();
         int contentSize = contents.size();
+        boolean sourceIdDateFilterEnabled = isValidSourceIdDate(filterOldStrategyExecuteDate);
+        if (StringUtils.hasText(filterOldStrategyExecuteDate) && !sourceIdDateFilterEnabled) {
+            log.warn("invalid filter.old.strategy.execute.date: {}, expected yyyyMMdd, skip sourceId date filter",
+                    filterOldStrategyExecuteDate);
+        }
+        long todayStart = DateUtils.getTodayStart();
+        long rootPublishExpireTimestamp = todayStart - filterOldStrategyRootPublishDays * ONE_DAY_MILLIS;
+        long createExpireTimestamp = todayStart - filterOldStrategyCreateDays * ONE_DAY_MILLIS;
         for (Content content : contents) {
-            if (ContentPoolEnum.autoArticlePoolLevel4.getContentPool().equals(content.getContentPoolType())
+            boolean coldStartContent = ContentPoolEnum.autoArticlePoolLevel4.getContentPool()
+                    .equals(content.getContentPoolType());
+            boolean beforeExecuteDate = coldStartContent && sourceIdDateFilterEnabled
+                    && isSourceIdBeforeDate(content.getSourceId(), filterOldStrategyExecuteDate);
+            boolean expiredByExistingRule = coldStartContent
                     && contentSize - filterContents.size() > 20000
                     && ((Objects.nonNull(content.getRootPublishTimestamp())
-                    && content.getRootPublishTimestamp() < DateUtils.getTodayStart() - filterOldStrategyRootPublishDays * 86400000L)
-                    || content.getCreateTimestamp() < DateUtils.getTodayStart() - filterOldStrategyCreateDays * 86400000L
+                    && content.getRootPublishTimestamp() < rootPublishExpireTimestamp)
+                    || content.getCreateTimestamp() < createExpireTimestamp
                     || (Objects.nonNull(content.getSourceAuditTimestamp())
-                    && content.getSourceAuditTimestamp() < DateUtils.getTodayStart() - filterOldStrategyCreateDays * 86400000L))) {
+                    && content.getSourceAuditTimestamp() < createExpireTimestamp));
+            if (beforeExecuteDate || expiredByExistingRule) {
                 content.setFilterReason("冷启老文章过滤");
                 filterContents.add(content);
             } else {
@@ -50,4 +73,41 @@ public class OldStrategy implements FilterStrategy {
         return filterResult;
     }
 
-}
+    private boolean isValidSourceIdDate(String date) {
+        if (!StringUtils.hasText(date) || date.length() != SOURCE_ID_DATE_LENGTH) {
+            return false;
+        }
+        for (int i = 0; i < SOURCE_ID_DATE_LENGTH; i++) {
+            if (!isAsciiDigit(date.charAt(i))) {
+                return false;
+            }
+        }
+        return true;
+    }
+
+    /**
+     * 直接比较 sourceId 的前八位,避免为大量内容创建 substring 和日期对象。
+     */
+    private boolean isSourceIdBeforeDate(String sourceId, String date) {
+        if (sourceId == null || sourceId.length() < SOURCE_ID_DATE_LENGTH) {
+            return false;
+        }
+        int comparison = 0;
+        for (int i = 0; i < SOURCE_ID_DATE_LENGTH; i++) {
+            char sourceIdChar = sourceId.charAt(i);
+            if (!isAsciiDigit(sourceIdChar)) {
+                return false;
+            }
+            char dateChar = date.charAt(i);
+            if (comparison == 0 && sourceIdChar != dateChar) {
+                comparison = sourceIdChar < dateChar ? -1 : 1;
+            }
+        }
+        return comparison < 0;
+    }
+
+    private boolean isAsciiDigit(char value) {
+        return value >= '0' && value <= '9';
+    }
+
+}