✨ 定时清理未使用的 tag.
This commit is contained in:
@@ -3,6 +3,9 @@ package com.orion.ops.module.infra.dao;
|
|||||||
import com.orion.ops.framework.mybatis.core.mapper.IMapper;
|
import com.orion.ops.framework.mybatis.core.mapper.IMapper;
|
||||||
import com.orion.ops.module.infra.entity.domain.TagDO;
|
import com.orion.ops.module.infra.entity.domain.TagDO;
|
||||||
import org.apache.ibatis.annotations.Mapper;
|
import org.apache.ibatis.annotations.Mapper;
|
||||||
|
import org.apache.ibatis.annotations.Param;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 标签枚举 Mapper 接口
|
* 标签枚举 Mapper 接口
|
||||||
@@ -14,4 +17,12 @@ import org.apache.ibatis.annotations.Mapper;
|
|||||||
@Mapper
|
@Mapper
|
||||||
public interface TagDAO extends IMapper<TagDO> {
|
public interface TagDAO extends IMapper<TagDO> {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获取未使用的标签
|
||||||
|
*
|
||||||
|
* @param days days
|
||||||
|
* @return tagId
|
||||||
|
*/
|
||||||
|
List<TagDO> selectUnusedTag(@Param("days") Integer days);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -46,4 +46,9 @@ public interface TagService {
|
|||||||
*/
|
*/
|
||||||
Integer deleteTagByIdList(List<Long> idList);
|
Integer deleteTagByIdList(List<Long> idList);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 清理未使用的 tag
|
||||||
|
*/
|
||||||
|
void clearUnusedTag();
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -32,6 +32,11 @@ import java.util.stream.Collectors;
|
|||||||
@Service
|
@Service
|
||||||
public class TagServiceImpl implements TagService {
|
public class TagServiceImpl implements TagService {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 未使用的天数
|
||||||
|
*/
|
||||||
|
private static final Integer UN_USED_DAYS = 3;
|
||||||
|
|
||||||
@Resource
|
@Resource
|
||||||
private TagDAO tagDAO;
|
private TagDAO tagDAO;
|
||||||
|
|
||||||
@@ -113,4 +118,27 @@ public class TagServiceImpl implements TagService {
|
|||||||
return effect;
|
return effect;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void clearUnusedTag() {
|
||||||
|
// 查询
|
||||||
|
List<TagDO> tagList = tagDAO.selectUnusedTag(UN_USED_DAYS);
|
||||||
|
if (tagList.isEmpty()) {
|
||||||
|
log.info("TagService.clearUnusedTag isEmpty");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
// 删除数据
|
||||||
|
List<Long> tagIdList = tagList.stream()
|
||||||
|
.map(TagDO::getId)
|
||||||
|
.collect(Collectors.toList());
|
||||||
|
int effect = tagDAO.deleteBatchIds(tagIdList);
|
||||||
|
log.info("TagService.clearUnusedTag deleted count: {}, deleted: {}, tags: {}", tagIdList.size(), effect, tagIdList);
|
||||||
|
// 删除缓存
|
||||||
|
List<String> cacheKeys = tagList.stream()
|
||||||
|
.map(TagDO::getType)
|
||||||
|
.distinct()
|
||||||
|
.map(TagCacheKeyDefine.TAG_NAME::format)
|
||||||
|
.collect(Collectors.toList());
|
||||||
|
RedisLists.delete(cacheKeys);
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,58 @@
|
|||||||
|
package com.orion.ops.module.infra.task;
|
||||||
|
|
||||||
|
import com.orion.ops.module.infra.service.TagService;
|
||||||
|
import lombok.extern.slf4j.Slf4j;
|
||||||
|
import org.redisson.api.RLock;
|
||||||
|
import org.redisson.api.RedissonClient;
|
||||||
|
import org.springframework.scheduling.annotation.Scheduled;
|
||||||
|
import org.springframework.stereotype.Component;
|
||||||
|
|
||||||
|
import javax.annotation.Resource;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* tag 定时清理任务
|
||||||
|
*
|
||||||
|
* @author Jiahang Li
|
||||||
|
* @version 1.0.0
|
||||||
|
* @since 2024/4/15 23:50
|
||||||
|
*/
|
||||||
|
@Slf4j
|
||||||
|
@Component
|
||||||
|
public class TagAutoClearTask {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 分布式锁名称
|
||||||
|
*/
|
||||||
|
private static final String LOCK_KEY = "tag:clear:lock";
|
||||||
|
|
||||||
|
@Resource
|
||||||
|
private RedissonClient redissonClient;
|
||||||
|
|
||||||
|
@Resource
|
||||||
|
private TagService tagService;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 定时清理未引用的 tag
|
||||||
|
*/
|
||||||
|
@Scheduled(cron = "0 0 2 * * ?")
|
||||||
|
public void clear() {
|
||||||
|
log.info("TagAutoClearTask.clear start");
|
||||||
|
// 获取锁
|
||||||
|
RLock lock = redissonClient.getLock(LOCK_KEY);
|
||||||
|
// 未获取到直接返回
|
||||||
|
if (!lock.tryLock()) {
|
||||||
|
log.info("TagAutoClearTask.clear locked end");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
try {
|
||||||
|
// 清理
|
||||||
|
tagService.clearUnusedTag();
|
||||||
|
log.info("TagAutoClearTask.clear finish");
|
||||||
|
} catch (Exception e) {
|
||||||
|
log.error("TagAutoClearTask.clear error", e);
|
||||||
|
} finally {
|
||||||
|
lock.unlock();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@@ -19,4 +19,14 @@
|
|||||||
id, name, type, create_time, update_time, creator, updater, deleted
|
id, name, type, create_time, update_time, creator, updater, deleted
|
||||||
</sql>
|
</sql>
|
||||||
|
|
||||||
|
<select id="selectUnusedTag" resultMap="BaseResultMap">
|
||||||
|
SELECT t.id, t.type
|
||||||
|
FROM tag t
|
||||||
|
LEFT JOIN tag_rel tr ON t.id = tr.tag_id AND tr.deleted = 0
|
||||||
|
WHERE t.create_time <![CDATA[ < ]]> DATE_SUB(NOW(), INTERVAL #{days} DAY)
|
||||||
|
AND tr.tag_id IS NULL
|
||||||
|
AND t.deleted = 0
|
||||||
|
GROUP BY t.id
|
||||||
|
</select>
|
||||||
|
|
||||||
</mapper>
|
</mapper>
|
||||||
|
|||||||
@@ -46,7 +46,6 @@
|
|||||||
const logViewRef = ref();
|
const logViewRef = ref();
|
||||||
const currentHostExecId = ref();
|
const currentHostExecId = ref();
|
||||||
const statusIntervalId = ref();
|
const statusIntervalId = ref();
|
||||||
const finishIntervalId = ref();
|
|
||||||
const execLog = ref<ExecLogQueryResponse>();
|
const execLog = ref<ExecLogQueryResponse>();
|
||||||
const appender = ref<ILogAppender>();
|
const appender = ref<ILogAppender>();
|
||||||
|
|
||||||
@@ -60,8 +59,6 @@
|
|||||||
record.status === execStatus.RUNNING) {
|
record.status === execStatus.RUNNING) {
|
||||||
// 注册状态轮询
|
// 注册状态轮询
|
||||||
statusIntervalId.value = setInterval(fetchTaskStatus, 5000);
|
statusIntervalId.value = setInterval(fetchTaskStatus, 5000);
|
||||||
// 注册完成时间轮询
|
|
||||||
finishIntervalId.value = setInterval(setTaskFinishTime, 1000);
|
|
||||||
}
|
}
|
||||||
// 打开日志
|
// 打开日志
|
||||||
nextTick(() => {
|
nextTick(() => {
|
||||||
@@ -95,9 +92,8 @@
|
|||||||
if (hostStatus) {
|
if (hostStatus) {
|
||||||
host.status = hostStatus.status;
|
host.status = hostStatus.status;
|
||||||
host.startTime = hostStatus.startTime;
|
host.startTime = hostStatus.startTime;
|
||||||
if (hostStatus.finishTime) {
|
// 使用时间
|
||||||
host.finishTime = hostStatus.finishTime;
|
host.finishTime = host.finishTime || Date.now();
|
||||||
}
|
|
||||||
host.exitStatus = hostStatus.exitStatus;
|
host.exitStatus = hostStatus.exitStatus;
|
||||||
host.errorMessage = hostStatus.errorMessage;
|
host.errorMessage = hostStatus.errorMessage;
|
||||||
}
|
}
|
||||||
@@ -154,8 +150,6 @@
|
|||||||
const clearAllInterval = () => {
|
const clearAllInterval = () => {
|
||||||
// 关闭状态轮询
|
// 关闭状态轮询
|
||||||
clearInterval(statusIntervalId.value);
|
clearInterval(statusIntervalId.value);
|
||||||
// 关闭使用时间轮询
|
|
||||||
clearInterval(finishIntervalId.value);
|
|
||||||
};
|
};
|
||||||
|
|
||||||
// 加载字典值
|
// 加载字典值
|
||||||
|
|||||||
@@ -23,7 +23,9 @@
|
|||||||
<span class="tag-value">{{ host.exitStatus }}</span>
|
<span class="tag-value">{{ host.exitStatus }}</span>
|
||||||
</a-tag>
|
</a-tag>
|
||||||
<!-- 持续时间 -->
|
<!-- 持续时间 -->
|
||||||
<a-tag color="arcoblue" title="持续时间">
|
<a-tag v-if="host.startTime"
|
||||||
|
color="arcoblue"
|
||||||
|
title="持续时间">
|
||||||
<template #icon>
|
<template #icon>
|
||||||
<icon-loading v-if="host.status === execHostStatus.WAITING || host.status === execHostStatus.RUNNING" />
|
<icon-loading v-if="host.status === execHostStatus.WAITING || host.status === execHostStatus.RUNNING" />
|
||||||
<icon-clock-circle v-else />
|
<icon-clock-circle v-else />
|
||||||
|
|||||||
Reference in New Issue
Block a user