feat: support automatic cleaning recycled posts. #1031 (#1114)

pull/1130/head
Wh1te 2020-10-25 21:23:14 +08:00 committed by GitHub
parent b5f742582c
commit ff734ed153
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
4 changed files with 137 additions and 1 deletions

View File

@ -7,6 +7,7 @@ import org.springframework.boot.builder.SpringApplicationBuilder;
import org.springframework.boot.web.servlet.support.SpringBootServletInitializer; import org.springframework.boot.web.servlet.support.SpringBootServletInitializer;
import org.springframework.data.jpa.repository.config.EnableJpaRepositories; import org.springframework.data.jpa.repository.config.EnableJpaRepositories;
import org.springframework.scheduling.annotation.EnableAsync; import org.springframework.scheduling.annotation.EnableAsync;
import org.springframework.scheduling.annotation.EnableScheduling;
import run.halo.app.repository.base.BaseRepositoryImpl; import run.halo.app.repository.base.BaseRepositoryImpl;
/** /**
@ -17,6 +18,7 @@ import run.halo.app.repository.base.BaseRepositoryImpl;
*/ */
@SpringBootApplication(exclude = { MultipartAutoConfiguration.class }) @SpringBootApplication(exclude = { MultipartAutoConfiguration.class })
@EnableAsync @EnableAsync
@EnableScheduling
@EnableJpaRepositories(basePackages = "run.halo.app.repository", repositoryBaseClass = BaseRepositoryImpl.class) @EnableJpaRepositories(basePackages = "run.halo.app.repository", repositoryBaseClass = BaseRepositoryImpl.class)
public class Application extends SpringBootServletInitializer { public class Application extends SpringBootServletInitializer {

View File

@ -0,0 +1,35 @@
package run.halo.app.model.enums;
/**
* @author Wh1te
* @date 2020-10-19
*/
public enum TimeUnit implements ValueEnum<Integer> {
/**
*
*/
DAY(0),
/**
*
*/
HOUR(1);
private final Integer value;
TimeUnit(Integer value) {
this.value = value;
}
/**
* Get enum value.
*
* @return enum value
*/
@Override
public Integer getValue() {
return value;
}
}

View File

@ -1,5 +1,7 @@
package run.halo.app.model.properties; package run.halo.app.model.properties;
import run.halo.app.model.enums.TimeUnit;
/** /**
* Post properties. * Post properties.
* *
@ -37,7 +39,22 @@ public enum PostProperties implements PropertyEnum {
/** /**
* Post index sort. * Post index sort.
*/ */
INDEX_SORT("post_index_sort", String.class, "createTime"); INDEX_SORT("post_index_sort", String.class, "createTime"),
/**
* Enable auto cleaning recycled post.
*/
RECYCLED_POST_CLEANING_ENABLED("recycled_post_cleaning_enabled", Boolean.class, "false"),
/**
* Recycled post retention time
*/
RECYCLED_POST_RETENTION_TIME("recycled_post_retention_time", Integer.class, "30"),
/**
* Recycled post retention time unit.
*/
RECYCLED_POST_RETENTION_TIMEUNIT("recycled_post_retention_timeunit", TimeUnit.class, TimeUnit.DAY.name());
private final String value; private final String value;

View File

@ -0,0 +1,82 @@
package run.halo.app.task;
import cn.hutool.core.date.DateUtil;
import lombok.extern.slf4j.Slf4j;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Component;
import org.springframework.util.CollectionUtils;
import run.halo.app.model.entity.BasePost;
import run.halo.app.model.entity.Post;
import run.halo.app.model.enums.PostStatus;
import run.halo.app.model.enums.TimeUnit;
import run.halo.app.model.properties.PostProperties;
import run.halo.app.service.OptionService;
import run.halo.app.service.PostService;
import java.time.LocalDateTime;
import java.time.temporal.ChronoUnit;
import java.util.List;
import java.util.Objects;
import java.util.stream.Collectors;
/**
* @author Wh1te
* @date 2020-10-19
*/
@Slf4j
@Component
public class RecycledPostCleaningTask {
private final OptionService optionService;
private final PostService postService;
public RecycledPostCleaningTask(OptionService optionService, PostService postService) {
this.optionService = optionService;
this.postService = postService;
}
/**
* Clean recycled posts if RECYCLED_POST_CLEANING_ENABLED is true
*/
@Scheduled(cron = "0 0 */1 * * *")
public synchronized void run() {
Boolean recycledPostCleaningEnabled = optionService.getByPropertyOrDefault(PostProperties.RECYCLED_POST_CLEANING_ENABLED, Boolean.class, false);
log.debug("{} = {}", PostProperties.RECYCLED_POST_CLEANING_ENABLED.getValue(), recycledPostCleaningEnabled);
if (!recycledPostCleaningEnabled) {
return;
}
Integer recycledPostRetentionTime = optionService.getByPropertyOrDefault(PostProperties.RECYCLED_POST_RETENTION_TIME, Integer.class, PostProperties.RECYCLED_POST_RETENTION_TIME.defaultValue(Integer.class));
TimeUnit timeUnit = optionService.getEnumByPropertyOrDefault(PostProperties.RECYCLED_POST_RETENTION_TIMEUNIT, TimeUnit.class, TimeUnit.DAY);
log.debug("{} = {}", PostProperties.RECYCLED_POST_RETENTION_TIME.getValue(), recycledPostRetentionTime);
log.debug("{} = {}", PostProperties.RECYCLED_POST_RETENTION_TIMEUNIT.getValue(), Objects.requireNonNull(timeUnit).name());
long expiredIn;
switch (timeUnit) {
case HOUR:
expiredIn = recycledPostRetentionTime;
break;
case DAY:
default:
expiredIn = recycledPostRetentionTime * 24;
break;
}
List<Post> recyclePost = postService.listAllBy(PostStatus.RECYCLE);
LocalDateTime now = LocalDateTime.now();
List<Integer> ids = recyclePost.stream().filter(post -> {
LocalDateTime updateTime = DateUtil.toLocalDateTime(post.getUpdateTime());
long until = updateTime.until(now, ChronoUnit.HOURS);
return until >= expiredIn;
}).map(BasePost::getId).collect(Collectors.toList());
if (CollectionUtils.isEmpty(ids)) {
return;
}
log.info("Start cleaning recycled posts");
List<Post> posts = postService.removeByIds(ids);
log.info("Recycled posts cleaning has been completed, {} posts has been permanently deleted", posts.size());
}
}