express-post-task-scheduler
Version:
A lightweight npm package to create and manage scheduled tasks using Express middleware. Configure tasks via POST requests and execute them at specified times seamlessly.
213 lines (212 loc) • 6.91 kB
JavaScript
;
Object.defineProperty(exports, "__esModule", { value: true });
exports.DB = void 0;
const filter_1 = require("./filter");
const tasks_1 = require("../tasks");
const scheduler_1 = require("../scheduler");
const scheduleJobs_1 = require("../scheduleJobs");
const client_1 = require("@prisma/client");
/**
* CRUD tasks in the sqlite db file
*/
class DB {
/**
* Create or get exist instance of this class
*/
static init() {
if (DB.instance === undefined) {
const db = new DB();
db.conn = new client_1.PrismaClient();
DB.instance = db;
}
return DB.instance;
}
/**
* Restore unfinished tasks from database if the program was terminated
*/
async loadUnfinshedTasks() {
const unfinishedTasks = await this.conn?.taskList.findMany({
where: {
executeTime: {
gte: new Date(),
},
startTime: null,
finishTime: null,
},
});
if (unfinishedTasks && unfinishedTasks.length > 0) {
for (const task of unfinishedTasks) {
const executor = tasks_1.tasks.find((_task) => _task.taskName === task.taskName)?.executor;
if (executor) {
(0, scheduler_1.scheduleTask)(task.executeTime, JSON.parse(task.data), executor, task.id);
}
}
}
}
/**
* Write a new task info into the database
* @param taskName For example: Count
* @param taskDescription For example: Execute 3 arrow functions to print Count + index on the terminal
* @param executeTime The returned formatted datetime string from scheduleTask, for example: "2024-12-30 17:00:00"
*/
async createTask(taskName, taskDescription, executeTime, data) {
const newTask = await this.conn.taskList.create({
data: {
taskName,
taskDescription,
executeTime: new Date(executeTime),
data,
},
});
return newTask;
}
/**
* Mark a executing task as started
* @param taskId The created task's id of method createTask
*/
async startTask(taskId) {
await this.conn.taskList.update({
where: {
id: taskId,
},
data: {
startTime: new Date(),
},
});
}
/**
* Mark a executed task as finished
* @param taskId The created task's id of method createTask
*/
async finishTask(taskId) {
await this.conn.taskList.update({
where: {
id: taskId,
},
data: {
finishTime: new Date(),
},
});
}
/**
* Executing a task item successfully
* @param taskId The primary key of a task
* @param itemId The id of each item in the request body's data field
* @param itemValue The stringified value of the item
*/
async markItemSuccessful(taskId, itemId, itemValue) {
await this.conn.$executeRaw(client_1.Prisma.sql `
INSERT INTO Records (itemId, taskId, itemValue, finishTime)
VALUES (${itemId}, ${taskId}, ${itemValue}, ${Date.now()});
`);
}
/**
* Executing a task item failed
* @param taskId The primary key of a task
* @param itemId The id of each item in the request body's data field
* @param itemValue The stringified value of the item
*/
async markItemFailed(taskId, itemId, itemValue, errorMessage) {
await this.conn.$executeRaw(client_1.Prisma.sql `
INSERT INTO Records (itemId, taskId, itemValue, error, finishTime)
VALUES (${itemId}, ${taskId}, ${itemValue}, ${errorMessage}, ${Date.now()});
`);
}
/**
* To filter the task from database
* @param filter The object consist of conditions, the example below shows the tasks finished during 2025-01-02
* @example {"finish": {"after": "2025-01-02", "before": "2025-01-03"}}
*/
async getTasks(filter) {
const conditions = (0, filter_1.getTasksQueryConditions)(filter);
const rows = await this.conn.taskList.findMany({
where: {
...conditions,
},
select: {
id: true,
taskName: true,
taskDescription: true,
executeTime: true,
startTime: true,
finishTime: true,
},
});
return rows;
}
/**
* To delete the task and all related records
* @param taskId Primary key of a task record
*/
async deleteTaskById(taskId) {
return this.conn?.taskList.deleteMany({
where: {
id: taskId,
},
});
}
/**
* To reschedule waiting state task
* @param taskId Primary key of a task record
* @param executeTime The new executeTime for reschedule task
* @returns
*/
async rescheduleTask(taskId, executeTime) {
let isSuccessful = false;
const updatedTask = await this.conn.taskList.update({
where: {
id: taskId,
},
data: {
executeTime,
},
select: {
id: true,
taskName: true,
taskDescription: true,
executeTime: true,
startTime: true,
finishTime: true,
},
});
if (updatedTask) {
const jobs = scheduleJobs_1.ScheduleJobs.init();
const rescheduleJob = jobs.jobList.find((job) => job.taskId === taskId);
isSuccessful =
rescheduleJob?.jobInstance.reschedule(executeTime) === true;
}
return {
isSuccessful,
updatedTask,
};
}
/**
* To filter the records from database
* @param filter The object consist of conditions, the example below shows the records finished during 2025-01-02
* @example {"finish": {"after": "2025-01-02", "before": "2025-01-03"}}
*/
async getRecords(filter) {
const conditions = (0, filter_1.getRecordQueryConditions)(filter);
const rows = await this.conn.records.findMany({
where: {
...conditions,
},
select: {
id: true,
error: true,
finishTime: true,
itemId: true,
itemValue: true,
task: {
select: {
id: true,
taskName: true,
taskDescription: true,
},
},
},
});
return rows;
}
}
exports.DB = DB;