pigallery2/src/backend/model/jobs/JobProgressManager.ts

87 lines
2.5 KiB
TypeScript

import {promises as fsp} from 'fs';
import * as path from 'path';
import {ProjectPath} from '../../ProjectPath';
import {Config} from '../../../common/config/private/Config';
import {JobProgressDTO, JobProgressStates} from '../../../common/entities/job/JobProgressDTO';
export class JobProgressManager {
private static readonly VERSION = 3;
private db: {
version: number,
progresses: { [key: string]: { progress: JobProgressDTO, timestamp: number } }
} = {
version: JobProgressManager.VERSION,
progresses: {}
};
private readonly dbPath: string;
private timer: NodeJS.Timeout = null;
constructor() {
this.dbPath = path.join(ProjectPath.getAbsolutePath(Config.Server.Database.dbFolder), 'jobs.db');
this.loadDB().catch(console.error);
}
get Progresses(): { [key: string]: JobProgressDTO } {
const m: { [key: string]: JobProgressDTO } = {};
for (const key of Object.keys(this.db.progresses)) {
m[key] = this.db.progresses[key].progress;
if (this.db.progresses[key].progress.state === JobProgressStates.running) {
m[key].time.end = Date.now();
}
}
return m;
}
onJobProgressUpdate(progress: JobProgressDTO) {
this.db.progresses[progress.HashName] = {progress: progress, timestamp: Date.now()};
this.delayedSave();
}
private async loadDB() {
try {
await fsp.access(this.dbPath);
} catch (e) {
return;
}
const data = await fsp.readFile(this.dbPath, 'utf8');
const db = JSON.parse(data);
if (db.version !== JobProgressManager.VERSION) {
return;
}
this.db = db;
while (Object.keys(this.db.progresses).length > Config.Server.Jobs.maxSavedProgress) {
let min: string = null;
for (const key of Object.keys(this.db.progresses)) {
if (min === null || this.db.progresses[min].timestamp > this.db.progresses[key].timestamp) {
min = key;
}
}
delete this.db.progresses[min];
}
for (const key of Object.keys(this.db.progresses)) {
if (this.db.progresses[key].progress.state === JobProgressStates.running ||
this.db.progresses[key].progress.state === JobProgressStates.cancelling) {
this.db.progresses[key].progress.state = JobProgressStates.interrupted;
}
}
}
private async saveDB() {
await fsp.writeFile(this.dbPath, JSON.stringify(this.db));
}
private delayedSave() {
if (this.timer !== null) {
return;
}
this.timer = setTimeout(async () => {
this.saveDB().catch(console.error);
this.timer = null;
}, 5000);
}
}