perf:动态调度数据库保存

This commit is contained in:
xiang
2025-07-27 23:46:31 +08:00
parent 6e0154bfe9
commit 4787e03535
11 changed files with 148 additions and 12 deletions

View File

@@ -8,6 +8,7 @@
<artifactId>xservice-basic</artifactId>
<version>1.0-SNAPSHOT</version>
</parent>
<version>1.0.2-SNAPSHOT</version>
<artifactId>xservice-common</artifactId>

View File

@@ -0,0 +1,65 @@
package com.xiang.xservice.basic.utils;
public class PrimaryKeyUtils {
/**
* 自定义起始时间戳,例如 2025-01-01
*/
private static final long START_TIMESTAMP = 1735660800000L;
private static final long DATA_CENTER_ID_BITS = 5L;
private static final long WORKER_ID_BITS = 5L;
private static final long SEQUENCE_BITS = 12L;
private static final long MAX_DATA_CENTER_ID = ~(-1L << DATA_CENTER_ID_BITS);
private static final long MAX_WORKER_ID = ~(-1L << WORKER_ID_BITS);
private static final long WORKER_ID_SHIFT = SEQUENCE_BITS;
private static final long DATA_CENTER_ID_SHIFT = SEQUENCE_BITS + WORKER_ID_BITS;
private static final long TIMESTAMP_LEFT_SHIFT = SEQUENCE_BITS + WORKER_ID_BITS + DATA_CENTER_ID_BITS;
private static final long SEQUENCE_MASK = ~(-1L << SEQUENCE_BITS);
// 可通过配置设置
private static final long DATA_CENTER_ID = 1L;
private static final long WORKER_ID = 1L;
private static long sequence = 0L;
private static long lastTimestamp = -1L;
// 分布式下可使用分布式锁替代 synchronized
public static synchronized long snowflakeId() {
long timestamp = currentTimestamp();
if (timestamp < lastTimestamp) {
throw new RuntimeException("Clock moved backwards. Refusing to generate id");
}
if (timestamp == lastTimestamp) {
sequence = (sequence + 1) & SEQUENCE_MASK;
if (sequence == 0) {
timestamp = waitNextMillis(timestamp);
}
} else {
sequence = 0L;
}
lastTimestamp = timestamp;
return ((timestamp - START_TIMESTAMP) << TIMESTAMP_LEFT_SHIFT)
| (DATA_CENTER_ID << DATA_CENTER_ID_SHIFT)
| (WORKER_ID << WORKER_ID_SHIFT)
| sequence;
}
private static long waitNextMillis(long currentTimestamp) {
long timestamp = currentTimestamp();
while (timestamp <= currentTimestamp) {
timestamp = currentTimestamp();
}
return timestamp;
}
private static long currentTimestamp() {
return System.currentTimeMillis();
}
}

View File

@@ -18,4 +18,12 @@
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
</properties>
<dependencies>
<dependency>
<groupId>com.xiang</groupId>
<artifactId>xservice-common</artifactId>
<version>1.0-SNAPSHOT</version>
</dependency>
</dependencies>
</project>

View File

@@ -1,14 +1,14 @@
package com.xiang.xservice.schedule.config;
import com.xiang.xservice.schedule.core.DynamicTaskScheduler;
import com.xiang.xservice.schedule.core.TaskRegistry;
import com.xiang.xservice.schedule.service.IDynamicTaskSchedulerService;
import org.mybatis.spring.annotation.MapperScan;
import org.springframework.boot.autoconfigure.AutoConfiguration;
import org.springframework.context.annotation.Import;
@AutoConfiguration
@MapperScan("com.xiang.xservice.schedule.mapper")
@Import({DynamicTaskSchedulerConfig.class, IDynamicTaskSchedulerService.class, TaskRegistry.class})
@Import({DynamicTaskSchedulerConfig.class, DynamicTaskScheduler.class, TaskRegistry.class})
public class DynamicSchedulerAutoConfiguration {
}

View File

@@ -5,6 +5,7 @@ import lombok.RequiredArgsConstructor;
import org.springframework.scheduling.concurrent.ThreadPoolTaskScheduler;
import org.springframework.stereotype.Component;
import javax.annotation.PostConstruct;
import java.time.LocalDateTime;
import java.time.ZoneId;
import java.util.Date;
@@ -30,7 +31,6 @@ public class DynamicTaskScheduler {
taskMap.remove(config.getTaskId());
}
}, Date.from(time.atZone(ZoneId.systemDefault()).toInstant()));
taskMap.put(config.getTaskId(), future);
}
@@ -38,7 +38,6 @@ public class DynamicTaskScheduler {
ScheduledFuture<?> future = taskMap.get(taskId);
if (future != null) {
future.cancel(true);
taskMap.remove(taskId);
}
}

View File

@@ -5,6 +5,7 @@ import lombok.Data;
import lombok.NoArgsConstructor;
import java.time.LocalDateTime;
import java.util.Map;
@Data
@AllArgsConstructor
@@ -12,5 +13,7 @@ import java.time.LocalDateTime;
public class TaskConfig {
private Long taskId;
private String taskName;
private String taskGroup;
private LocalDateTime executionTime;
private Map<String, Object> parameters;
}

View File

@@ -0,0 +1,20 @@
package com.xiang.xservice.schedule.enums;
import lombok.Getter;
@Getter
public enum TaskStatusEnum {
UN_START(1, "未开始"),
PROCEED(2, "进行中"),
FINISHED(3, "已完成"),
CANCELED(4, "取消")
;
private final Integer code;
private final String desc;
TaskStatusEnum(Integer code, String desc) {
this.code = code;
this.desc = desc;
}
}

View File

@@ -13,5 +13,5 @@ public interface ScheduledTaskMapper {
int update(ScheduledTaskEntity entity);
ScheduledTaskEntity getTask(@Param("id") String taskId);
ScheduledTaskEntity getTask(@Param("id") Long taskId);
}

View File

@@ -1,10 +1,14 @@
package com.xiang.xservice.schedule.service;
import com.xiang.xservice.schedule.entity.ScheduledTaskEntity;
import com.xiang.xservice.schedule.enums.TaskStatusEnum;
import com.xiang.xservice.schedule.mapper.ScheduledTaskMapper;
import lombok.RequiredArgsConstructor;
import org.springframework.stereotype.Service;
import java.time.LocalDateTime;
import java.util.Objects;
@Service
@RequiredArgsConstructor
public class DynamicTaskSchedulerServiceImpl implements IDynamicTaskSchedulerService{
@@ -22,7 +26,40 @@ public class DynamicTaskSchedulerServiceImpl implements IDynamicTaskSchedulerSer
}
@Override
public ScheduledTaskEntity getTask(String taskId) {
public ScheduledTaskEntity getTask(Long taskId) {
return scheduledTaskMapper.getTask(taskId);
}
@Override
public Boolean updateProcess(Long taskId) {
ScheduledTaskEntity task = scheduledTaskMapper.getTask(taskId);
if (Objects.nonNull(task)) {
task.setStatus(TaskStatusEnum.PROCEED.getCode());
task.setUpdatedTime(LocalDateTime.now());
return scheduledTaskMapper.update(task) > 0;
}
return Boolean.FALSE;
}
@Override
public Boolean cancelTask(Long taskId) {
ScheduledTaskEntity task = scheduledTaskMapper.getTask(taskId);
if (Objects.nonNull(task)) {
task.setStatus(TaskStatusEnum.CANCELED.getCode());
task.setUpdatedTime(LocalDateTime.now());
return scheduledTaskMapper.update(task) > 0;
}
return Boolean.FALSE;
}
@Override
public Boolean finishTask(Long taskId) {
ScheduledTaskEntity task = scheduledTaskMapper.getTask(taskId);
if (Objects.nonNull(task)) {
task.setStatus(TaskStatusEnum.FINISHED.getCode());
task.setUpdatedTime(LocalDateTime.now());
return scheduledTaskMapper.update(task) > 0;
}
return Boolean.FALSE;
}
}

View File

@@ -6,5 +6,8 @@ import com.xiang.xservice.schedule.entity.ScheduledTaskEntity;
public interface IDynamicTaskSchedulerService {
Boolean saveTask(ScheduledTaskEntity entity);
Boolean updateTask(ScheduledTaskEntity entity);
ScheduledTaskEntity getTask(String taskId);
ScheduledTaskEntity getTask(Long taskId);
Boolean updateProcess(Long taskId);
Boolean cancelTask(Long taskId);
Boolean finishTask(Long taskId);
}

View File

@@ -19,13 +19,13 @@
</sql>
<!-- 插入一条任务 -->
<insert id="insertTask" useGeneratedKeys="true" keyProperty="id">
INSERT INTO script_schedule_task (task_name, task_group, run_time, status, parameters, create_time, update_time)
VALUES (#{taskName}, #{taskGroup}, #{runTime}, #{status}, #{parameters}, #{createdTime}, #{updatedTime})
<insert id="save" useGeneratedKeys="true" keyProperty="id" parameterType="com.xiang.xservice.schedule.entity.ScheduledTaskEntity">
INSERT INTO script_schedule_task (id, task_name, task_group, run_time, status, parameters, create_time, update_time)
VALUES (#{id}, #{taskName}, #{taskGroup}, #{runTime}, #{status}, #{parameters}, #{createdTime}, #{updatedTime})
</insert>
<!-- 更新任务 -->
<update id="updateTask">
<update id="update" parameterType="com.xiang.xservice.schedule.entity.ScheduledTaskEntity">
UPDATE script_schedule_task
SET task_name = #{taskName},
task_group = #{taskGroup},
@@ -37,7 +37,7 @@
WHERE id = #{id}
</update>
<select id="getTask" resultMap="BaseResultMap">
<select id="getTask" resultMap="BaseResultMap" parameterType="java.lang.Long">
select <include refid="Base_Column_List"/>
from script_schedule_task where id = #{id}
</select>