造个轮子任务调度执行小框架任务清单执行恢复实现

2023年 8月 13日 67.6k 0

前言

okey,通过前面的两篇文章,关于这个任务执行这一块,我想应该是明白了。但是这里的话,还是不够的。我们希望对于任务还可以做到执行失败的重试执行,关于这个意外宕机的一个状态恢复。

当然这里要说的是,由于完整的实现,就是按照那种牛逼的标准来实现的话,这个实现确实很复杂,要考虑的情况也非常多,这个是没有办法的事情。所以这里只能实现一个简单的。

这里的话又不得不提到我们一开始,对于这个任务清单和任务清单项的一个类型的处理了:

我们主要有这几个类型:

package com.huterox.todoscheduler.core.enumType;

import java.io.Serializable;

/**
 * TodoItem类型,是必须要坚持执行,还是非必须
 * */
public enum TodoItemElementType implements Serializable {
    /**
     * 是不是必须要执行,也就是说,如果当前这个item执行失败,整个
     * 清单任务执行失败
     * */
    MUSTITEM("MUSTITEM"),
    /**
     * 执行失败可以跳过,注意,这个时候,重启的时候是不会管这个的
     * */
    CONTINUTEITEM("CONTINUTEITEM");
    private String elementCode;
    TodoItemElementType(String s) {
        this.elementCode = s;
    }
    public String getElementCode() {
        return elementCode;
    }
    public void setElementCode(String elementCode) {
        this.elementCode = elementCode;
    }

}

package com.huterox.todoscheduler.core.enumType;

import java.io.Serializable;

/**
 * 任务清单对应的类型
 * */
public enum TodoListElementType implements Serializable {

    /**
     * 宕机之后重启先执行修复函数然后继续执行没有完成的任务的模式
     * */
    StrongConsistency("StrongConsistency"),
    /**
     * 宕机之后重启执行修复,但是不继续执行任务
     * */
    WeakConsistency("WeakConsistency"),
    /**
     * 宕机之后重启不执行任何操作
     * */
    NothingConsistency("NothingConsistency");

    private String elementCode;

    TodoListElementType(String s) {
        this.elementCode = s;
    }

    public String getElementCode() {
        return elementCode;
    }

    public void setElementCode(String elementCode) {
        this.elementCode = elementCode;
    }
}

所以我们此时还涉及到这个。

恢复执行流程

那么在这里的话,我们就需要先聊到这个恢复的执行流程。

这里的话主要先看到这个接口:
在这里插入图片描述

package com.huterox.todoscheduler.core.scheduler;

/**
 * 定制任务执行器,在这块的话,主要是扫描失败任务
 * 让后尝试恢复任务,以及服务器宕机之后对任务的恢复
 * */
public interface SchedulerEx {

    //恢复任务
    void repairTask();

    //重新执行失败的任务
    void againTask();

    //定时扫描失败的进程你
    void DaemonScheduling();
}

所以看到这个我估计你应该是明白了它的一个操作:

失败任务执行

首先,在这里我们先来看到对于失败任务的执行。在这里的话,注意看到这个东西:

我们的话在这些方法执行的时候的话,会保存状态,这个状态的保存的话,还是通过这个JDK的一个Serilizable接口来做。这里的话,不存在传输的问题,直接存,然后解析即可。

package com.huterox.todoscheduler.common;

import java.io.File;

import java.io.*;

public class SerializationUtils implements Serializable {

    private static final String DEFAULT_DIRECTORY = "src/main/resources";

    public static void serializeObject(Object object, String fileName) {
        serializeObject(object, DEFAULT_DIRECTORY, fileName);
    }

    public static Object deserializeObject(String fileName) {
        return deserializeObject(DEFAULT_DIRECTORY, fileName);
    }

    public static void serializeObject(Object object, String directory, String fileName) {
        try {
            // 创建目录
            File dir = new File(directory);
            if (!dir.exists()) {
                if (dir.mkdirs()) {
                    System.out.println("目录已创建: " + directory);
                } else {
                    System.out.println("无法创建目录: " + directory);
                    return;
                }
            }

            // 序列化对象
            FileOutputStream fileOut = new FileOutputStream(directory + "/" + fileName);
            ObjectOutputStream out = new ObjectOutputStream(fileOut);
            out.writeObject(object);
            out.close();
            fileOut.close();
            System.out.println("对象已序列化并保存到文件: " + directory + "/" + fileName);

        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    public static Object deserializeObject(String directory, String fileName) {
        Object object = null;
        try {
            // 反序列化对象
            FileInputStream fileIn = new FileInputStream(directory + "/" + fileName);
            ObjectInputStream in = new ObjectInputStream(fileIn);
            object = in.readObject();
            in.close();
            fileIn.close();
            System.out.println("从文件中反序列化出对象: " + directory + "/" + fileName);

        } catch (Exception e) {
            e.printStackTrace();
        }
        return object;
    }

    public static void deleteSerializedObject(String directory, String fileName) {
        try {
            File file = new File(directory + "/" + fileName);
            if (file.exists()) {
                if (file.delete()) {
                    System.out.println("文件删除成功: " + directory + "/" + fileName);
                } else {
                    System.out.println("无法删除文件: " + directory + "/" + fileName);
                }
            } else {
                System.out.println("文件不存在: " + directory + "/" + fileName);
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}

然后在执行的时候,我们把失败的任务放在这里:

在这里插入图片描述

package com.huterox.todoscheduler.core.global;

import com.huterox.todoscheduler.common.SerializationUtils;
import com.huterox.todoscheduler.core.execute.proxy.TodoListExBean;

import java.io.Serializable;
import java.util.List;
import java.util.concurrent.CopyOnWriteArrayList;

/**
 * 执行失败的清单对象列表
 * 冷知识:CopyOnWriteArrayList 支持直接迭代删除
 * */
public class TodoListFailedList implements Serializable {

    private static volatile List list;

    private TodoListFailedList() {}

    public static List getInstance() {
        if (list == null) {
            synchronized (TodoListFailedList.class) {
                if (list == null) {
                    list = new CopyOnWriteArrayList();
                }
            }
        }
        return list;
    }

    public static List addFailedWithSerializable(TodoListExBean todoListExBean) {
        if (list == null) {
            synchronized (TodoListFailedList.class) {
                if (list == null) {
                    list = new CopyOnWriteArrayList();
                }
            }
        }
        list.add(todoListExBean);
        //把这个list进行备份,这里面存放了失败的执行清单,所以这个时候要注意恢复
        SerializationUtils.serializeObject(list,"failedCatalogue","catalogue.ser");
        return list;
    }

    public static List addFailed(TodoListExBean todoListExBean) {
        if (list == null) {
            synchronized (TodoListFailedList.class) {
                if (list == null) {
                    list = new CopyOnWriteArrayList();
                }
            }
        }
        list.add(todoListExBean);
        return list;
    }

}

所以的话,你可以直接找到这个东西,然后在对应目录去找到,然后实例化,然后去执行:

   public void againTask() {
//重新执行失败任务

Object deserializeObject = SerializationUtils
.deserializeObject("failedCatalogue", "catalogue.ser");
if (deserializeObject!=null){
CopyOnWriteArrayList failedCatalogue = (CopyOnWriteArrayList) deserializeObject;

for(TodoListExBean todoListExBean:failedCatalogue){
if(todoListExBean.getExTimes()

相关文章

JavaScript2024新功能:Object.groupBy、正则表达式v标志
PHP trim 函数对多字节字符的使用和限制
新函数 json_validate() 、randomizer 类扩展…20 个PHP 8.3 新特性全面解析
使用HTMX为WordPress增效:如何在不使用复杂框架的情况下增强平台功能
为React 19做准备:WordPress 6.6用户指南
如何删除WordPress中的所有评论

发布评论