|
@@ -9,6 +9,7 @@ import com.tzld.longarticle.recommend.server.util.DateUtils;
|
|
|
import lombok.extern.slf4j.Slf4j;
|
|
import lombok.extern.slf4j.Slf4j;
|
|
|
import org.springframework.beans.factory.annotation.Value;
|
|
import org.springframework.beans.factory.annotation.Value;
|
|
|
import org.springframework.stereotype.Component;
|
|
import org.springframework.stereotype.Component;
|
|
|
|
|
+import org.springframework.util.StringUtils;
|
|
|
|
|
|
|
|
import java.util.ArrayList;
|
|
import java.util.ArrayList;
|
|
|
import java.util.List;
|
|
import java.util.List;
|
|
@@ -18,12 +19,21 @@ import java.util.Objects;
|
|
|
@Slf4j
|
|
@Slf4j
|
|
|
public class OldStrategy implements FilterStrategy {
|
|
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}")
|
|
@Value("${filter.old.strategy.rootPublish.days:30}")
|
|
|
private Integer filterOldStrategyRootPublishDays;
|
|
private Integer filterOldStrategyRootPublishDays;
|
|
|
|
|
|
|
|
@Value("${filter.old.strategy.create.days:90}")
|
|
@Value("${filter.old.strategy.create.days:90}")
|
|
|
private Integer filterOldStrategyCreateDays;
|
|
private Integer filterOldStrategyCreateDays;
|
|
|
|
|
|
|
|
|
|
+ /**
|
|
|
|
|
+ * sourceId 日期过滤截止日(yyyyMMdd),未配置时不启用该过滤。
|
|
|
|
|
+ */
|
|
|
|
|
+ @Value("${filter.old.strategy.execute.date:}")
|
|
|
|
|
+ private String filterOldStrategyExecuteDate;
|
|
|
|
|
+
|
|
|
@Override
|
|
@Override
|
|
|
public FilterResult filter(FilterParam param) {
|
|
public FilterResult filter(FilterParam param) {
|
|
|
FilterResult filterResult = new FilterResult();
|
|
FilterResult filterResult = new FilterResult();
|
|
@@ -31,14 +41,27 @@ public class OldStrategy implements FilterStrategy {
|
|
|
List<Content> contents = param.getContents();
|
|
List<Content> contents = param.getContents();
|
|
|
List<Content> filterContents = new ArrayList<>();
|
|
List<Content> filterContents = new ArrayList<>();
|
|
|
int contentSize = contents.size();
|
|
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) {
|
|
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
|
|
&& contentSize - filterContents.size() > 20000
|
|
|
&& ((Objects.nonNull(content.getRootPublishTimestamp())
|
|
&& ((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())
|
|
|| (Objects.nonNull(content.getSourceAuditTimestamp())
|
|
|
- && content.getSourceAuditTimestamp() < DateUtils.getTodayStart() - filterOldStrategyCreateDays * 86400000L))) {
|
|
|
|
|
|
|
+ && content.getSourceAuditTimestamp() < createExpireTimestamp));
|
|
|
|
|
+ if (beforeExecuteDate || expiredByExistingRule) {
|
|
|
content.setFilterReason("冷启老文章过滤");
|
|
content.setFilterReason("冷启老文章过滤");
|
|
|
filterContents.add(content);
|
|
filterContents.add(content);
|
|
|
} else {
|
|
} else {
|
|
@@ -50,4 +73,41 @@ public class OldStrategy implements FilterStrategy {
|
|
|
return filterResult;
|
|
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';
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+}
|