update: scheduler can now prevent selected tasks from running under high load
This commit is contained in:
parent
96b4cecaec
commit
2ce726d16c
@ -21,6 +21,7 @@
|
|||||||
"@alikia/random-key": "npm:@jsr/alikia__random-key",
|
"@alikia/random-key": "npm:@jsr/alikia__random-key",
|
||||||
"@electron/remote": "^2.1.2",
|
"@electron/remote": "^2.1.2",
|
||||||
"@hono/node-server": "^1.13.7",
|
"@hono/node-server": "^1.13.7",
|
||||||
|
"@types/node-os-utils": "^1.3.4",
|
||||||
"@unly/universal-language-detector": "^2.0.3",
|
"@unly/universal-language-detector": "^2.0.3",
|
||||||
"better-sqlite3": "^11.6.0",
|
"better-sqlite3": "^11.6.0",
|
||||||
"dayjs": "^1.11.13",
|
"dayjs": "^1.11.13",
|
||||||
@ -41,6 +42,7 @@
|
|||||||
"image-size": "^1.1.1",
|
"image-size": "^1.1.1",
|
||||||
"jotai": "^2.11.0",
|
"jotai": "^2.11.0",
|
||||||
"memory-cache": "^0.2.0",
|
"memory-cache": "^0.2.0",
|
||||||
|
"node-os-utils": "^1.3.7",
|
||||||
"pino": "^9.6.0",
|
"pino": "^9.6.0",
|
||||||
"react": "^18.3.1",
|
"react": "^18.3.1",
|
||||||
"react-dom": "^18.3.1",
|
"react-dom": "^18.3.1",
|
||||||
|
@ -1,3 +1,5 @@
|
|||||||
|
import osu from "node-os-utils";
|
||||||
|
|
||||||
type TaskId = string;
|
type TaskId = string;
|
||||||
type TaskFunction = () => void;
|
type TaskFunction = () => void;
|
||||||
|
|
||||||
@ -9,6 +11,7 @@ interface Task {
|
|||||||
nextRun?: number;
|
nextRun?: number;
|
||||||
isPaused: boolean;
|
isPaused: boolean;
|
||||||
delayUntil?: number;
|
delayUntil?: number;
|
||||||
|
requiredSystemState: SystemState;
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface TaskStatus {
|
export interface TaskStatus {
|
||||||
@ -17,15 +20,27 @@ export interface TaskStatus {
|
|||||||
nextRun?: string;
|
nextRun?: string;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
type SystemState = "ANY" | "LOW_POWER" | "IDLE";
|
||||||
|
|
||||||
export class Scheduler {
|
export class Scheduler {
|
||||||
private tasks: Map<TaskId, Task> = new Map();
|
private tasks: Map<TaskId, Task> = new Map();
|
||||||
private timer: NodeJS.Timeout | null = null;
|
private timer: NodeJS.Timeout | null = null;
|
||||||
|
private monitorTimer: NodeJS.Timeout | null = null;
|
||||||
|
private cpuUsage: number = 0;
|
||||||
|
|
||||||
constructor(private readonly minTickInterval: number = 500) {
|
constructor(private readonly minTickInterval: number = 500) {
|
||||||
this.start();
|
this.start();
|
||||||
}
|
}
|
||||||
|
|
||||||
private start(): void {
|
private start(): void {
|
||||||
this.scheduleNextTick();
|
this.scheduleNextTick();
|
||||||
|
this.monitorTimer = setInterval(() => this.monitor(), 1000);
|
||||||
|
}
|
||||||
|
|
||||||
|
private monitor(): void {
|
||||||
|
osu.cpu.usage().then((cpuPercentage) => {
|
||||||
|
this.cpuUsage = cpuPercentage / 100;
|
||||||
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
private scheduleNextTick(): void {
|
private scheduleNextTick(): void {
|
||||||
@ -66,7 +81,17 @@ export class Scheduler {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
const isTaskReadyForIntervalRun = task.interval && task.nextRun && now >= task.nextRun;
|
const taskRequiredLowPower = task.requiredSystemState === "LOW_POWER";
|
||||||
|
const cpuUsage = this.cpuUsage;
|
||||||
|
const isSystemLowPower = cpuUsage < 0.75;
|
||||||
|
const isTaskReadyForLowPowerRun = taskRequiredLowPower ? isSystemLowPower : true;
|
||||||
|
const reachedTaskNextRun = task.interval && task.nextRun && now >= task.nextRun;
|
||||||
|
const isTaskReadyForIntervalRun = reachedTaskNextRun && isTaskReadyForLowPowerRun;
|
||||||
|
|
||||||
|
if (!isTaskReadyForLowPowerRun) {
|
||||||
|
this.delayTask(task.id, 1000)
|
||||||
|
}
|
||||||
|
|
||||||
if (isTaskReadyForIntervalRun) {
|
if (isTaskReadyForIntervalRun) {
|
||||||
task.func();
|
task.func();
|
||||||
task.lastRun = now;
|
task.lastRun = now;
|
||||||
@ -100,15 +125,17 @@ export class Scheduler {
|
|||||||
* @param id A unique string identifier for the task.
|
* @param id A unique string identifier for the task.
|
||||||
* @param func The function to be executed by the task.
|
* @param func The function to be executed by the task.
|
||||||
* @param interval The interval (in milliseconds) between task executions.
|
* @param interval The interval (in milliseconds) between task executions.
|
||||||
|
* @param requiredSystemState The required system state for the task to run.
|
||||||
*/
|
*/
|
||||||
addTask(id: TaskId, func: TaskFunction, interval?: number): void {
|
addTask(id: TaskId, func: TaskFunction, interval?: number, requiredSystemState: SystemState = "ANY"): void {
|
||||||
this.tasks.set(id, {
|
this.tasks.set(id, {
|
||||||
id,
|
id,
|
||||||
func,
|
func,
|
||||||
interval,
|
interval,
|
||||||
isPaused: false,
|
isPaused: false,
|
||||||
lastRun: undefined,
|
lastRun: undefined,
|
||||||
nextRun: interval ? Date.now() + interval : undefined
|
nextRun: interval ? Date.now() + interval : undefined,
|
||||||
|
requiredSystemState: requiredSystemState,
|
||||||
});
|
});
|
||||||
|
|
||||||
this.scheduleNextTick();
|
this.scheduleNextTick();
|
||||||
@ -172,6 +199,9 @@ export class Scheduler {
|
|||||||
const task = this.tasks.get(id);
|
const task = this.tasks.get(id);
|
||||||
if (task) {
|
if (task) {
|
||||||
task.delayUntil = Date.now() + delayMs;
|
task.delayUntil = Date.now() + delayMs;
|
||||||
|
if (task.nextRun) {
|
||||||
|
task.nextRun += delayMs;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
this.scheduleNextTick();
|
this.scheduleNextTick();
|
||||||
@ -215,5 +245,9 @@ export class Scheduler {
|
|||||||
clearTimeout(this.timer);
|
clearTimeout(this.timer);
|
||||||
this.timer = null;
|
this.timer = null;
|
||||||
}
|
}
|
||||||
|
if (this.monitorTimer) {
|
||||||
|
clearTimeout(this.monitorTimer);
|
||||||
|
this.monitorTimer = null;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -112,7 +112,7 @@ app.on("ready", () => {
|
|||||||
initDatabase().then((db) => {
|
initDatabase().then((db) => {
|
||||||
scheduler.addTask("screenshot", takeScreenshot, 2000);
|
scheduler.addTask("screenshot", takeScreenshot, 2000);
|
||||||
scheduler.addTask("check-encoding", checkFramesForEncoding, 5000);
|
scheduler.addTask("check-encoding", checkFramesForEncoding, 5000);
|
||||||
scheduler.addTask("process-encoding", processEncodingTasks, 10000);
|
scheduler.addTask("process-encoding", processEncodingTasks, 10000, "LOW_POWER");
|
||||||
scheduler.addTask("delete-screenshots", deleteUnnecessaryScreenshots, 20000);
|
scheduler.addTask("delete-screenshots", deleteUnnecessaryScreenshots, 20000);
|
||||||
dbConnection = db;
|
dbConnection = db;
|
||||||
cache.put("server:dbConnection", dbConnection);
|
cache.put("server:dbConnection", dbConnection);
|
||||||
|
Loading…
Reference in New Issue
Block a user