RuntimeConfig.java 8.3 KB
package com.viontech.fanxing.task.model;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.fasterxml.jackson.databind.annotation.JsonDeserialize;
import com.fasterxml.jackson.databind.annotation.JsonSerialize;
import com.fasterxml.jackson.datatype.jsr310.deser.LocalDateTimeDeserializer;
import com.fasterxml.jackson.datatype.jsr310.ser.LocalDateTimeSerializer;
import com.viontech.fanxing.commons.model.Task;
import lombok.Getter;
import lombok.NoArgsConstructor;
import lombok.Setter;
import lombok.experimental.Accessors;
import org.apache.commons.lang3.tuple.ImmutablePair;

import java.io.Serializable;
import java.security.InvalidParameterException;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.LocalTime;
import java.time.ZoneId;
import java.time.format.DateTimeFormatter;
import java.util.Calendar;
import java.util.Date;
import java.util.HashMap;

/**
 * type
 * <li>0 每天运行,指定开始和结束的时间</li>
 * <li>1 运行一次,指定具体的开始和结束的日期时间</li>
 * <li>2 按照星期配置,指定每周某天的开始和结束的时间</li>
 * <li>3 随机运行,指定运行时长</li>
 * <li>4 全天执行,只能手动停止</li>
 *
 * @author 谢明辉
 * @date 2021/7/13
 */

@Getter
@Setter
@NoArgsConstructor
public class RuntimeConfig implements Serializable {
    private static final String[] WEEK_ARR = new String[]{"sun", "mon", "tue", "wed", "thu", "fri", "sat"};
    private static final DateTimeFormatter TIME_FORMATTER = DateTimeFormatter.ofPattern("HH:mm:ss");
    private static final DateTimeFormatter DATE_TIME_FORMATTER = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");

    private int type;

    private HashMap<Integer, Config> weekConfigMap;

    private Config singleConfig;

    public RuntimeConfig(Task task) {
        String runtimeConf = task.getRuntimeConf();
        JSONObject jsonObject = JSON.parseObject(runtimeConf);
        Integer typeT = jsonObject.getInteger("type");
        if (typeT == null) {
            throw new InvalidParameterException("运行配置中type为空");
        }
        this.type = typeT;
        JSONObject config = jsonObject.getJSONObject("config");

        switch (this.type) {
            case 0:
                String start = config.getString("start");
                String end = config.getString("end");
                this.singleConfig = new Config().setStart(LocalTime.parse(start, TIME_FORMATTER)).setEnd(LocalTime.parse(end, TIME_FORMATTER));
                break;
            case 1:
                String start1 = config.getString("start");
                String end1 = config.getString("end");
                this.singleConfig = new Config().setStartTime(LocalDateTime.parse(start1, DATE_TIME_FORMATTER)).setEndTime(LocalDateTime.parse(end1, DATE_TIME_FORMATTER));
                break;
            case 2:
                this.weekConfigMap = new HashMap<>();
                for (int i = 0; i < WEEK_ARR.length; i++) {
                    String week = WEEK_ARR[i];
                    JSONObject configMap = config.getJSONObject(week);
                    if (configMap == null) {
                        continue;
                    }
                    String weekStart = configMap.getString("start");
                    String weekEnd = configMap.getString("end");
                    Config weekConfig = new Config().setStart(LocalTime.parse(weekStart, TIME_FORMATTER)).setEnd(LocalTime.parse(weekEnd, TIME_FORMATTER));
                    this.weekConfigMap.put(i, weekConfig);
                }
                break;
            // 随机执行
            case 3:
                Long runningTime = config.getLong("runningTime");
                this.singleConfig = new Config().setRunningTime(runningTime);
                break;
            // 开始后一直执行
            case 4:
                this.singleConfig = new Config().setStartTime(LocalDateTime.now());
                break;
            default:
                throw new InvalidParameterException("错误的type");
        }

    }

    /**
     * @return org.apache.commons.lang3.tuple.ImmutablePair<Long, Long>
     * <li>left 下一次任务下发时间</li>
     * <li>right 下一次任务终止时间</li>
     */
    public ImmutablePair<Long, Long> getNextTimeOfExecutionAndTerminal() {
        Long executeTimestamp = null;
        Long terminateTimestamp = null;
        LocalDateTime now = LocalDateTime.now();
        LocalDateTime executeTime;
        LocalDateTime terminateTime;
        switch (this.type) {
            case 0:
                LocalTime start = singleConfig.getStart();
                executeTime = LocalDateTime.of(LocalDate.now(), start);
                LocalTime end = singleConfig.getEnd();
                terminateTime = LocalDateTime.of(executeTime.toLocalDate(), end);
                // 如果终止时间在现在的时间之前需要明天执行
                if (terminateTime.isBefore(now)) {
                    executeTime = executeTime.plusDays(1);
                    terminateTime = terminateTime.plusDays(1);
                }
                executeTimestamp = executeTime.atZone(ZoneId.systemDefault()).toInstant().toEpochMilli();
                terminateTimestamp = terminateTime.atZone(ZoneId.systemDefault()).toInstant().toEpochMilli();
                break;
            case 1:
                executeTime = singleConfig.getStartTime();
                terminateTime = singleConfig.getEndTime();
                if (terminateTime.isBefore(now)) {
                    return ImmutablePair.nullPair();
                }
                executeTimestamp = executeTime.atZone(ZoneId.systemDefault()).toInstant().toEpochMilli();
                terminateTimestamp = terminateTime.atZone(ZoneId.systemDefault()).toInstant().toEpochMilli();
                break;
            case 2:
                Calendar instance = Calendar.getInstance();
                instance.setTime(new Date());
                int dayOfWeek = instance.get(Calendar.DAY_OF_WEEK);
                dayOfWeek -= 1;
                LocalDate localDate = LocalDate.now();
                Config config;
                boolean success = false;
                for (int i = 0; i <= 7; i++) {
                    config = this.weekConfigMap.get(dayOfWeek);
                    if (config != null) {
                        executeTime = LocalDateTime.of(localDate, config.getStart());
                        terminateTime = LocalDateTime.of(executeTime.toLocalDate(), config.getEnd());
                        if (terminateTime.isAfter(now)) {
                            executeTimestamp = executeTime.atZone(ZoneId.systemDefault()).toInstant().toEpochMilli();
                            terminateTimestamp = terminateTime.atZone(ZoneId.systemDefault()).toInstant().toEpochMilli();
                            success = true;
                            break;
                        }
                    }
                    localDate = localDate.plusDays(1);
                    dayOfWeek = (dayOfWeek + 1) % 7;
                }
                if (!success) {
                    return ImmutablePair.nullPair();
                }
                break;
            case 3:
                // 随机执行,待完善
                break;
            case 4:
                executeTimestamp = singleConfig.getStartTime().atZone(ZoneId.systemDefault()).toInstant().toEpochMilli();
                break;
            default:
                return ImmutablePair.nullPair();
        }

        return ImmutablePair.of(executeTimestamp, terminateTimestamp);
    }

    public
    @Getter
    @Setter
    @Accessors(chain = true)
    static class Config implements Serializable {
        @JsonDeserialize(using = LocalDateTimeDeserializer.class)
        @JsonSerialize(using = LocalDateTimeSerializer.class)
        private LocalTime start;
        @JsonDeserialize(using = LocalDateTimeDeserializer.class)
        @JsonSerialize(using = LocalDateTimeSerializer.class)
        private LocalTime end;
        private Long runningTime;
        @JsonDeserialize(using = LocalDateTimeDeserializer.class)
        @JsonSerialize(using = LocalDateTimeSerializer.class)
        private LocalDateTime startTime;
        @JsonDeserialize(using = LocalDateTimeDeserializer.class)
        @JsonSerialize(using = LocalDateTimeSerializer.class)
        private LocalDateTime endTime;
    }

}