2024-05-01 13:39:29 +01:00
|
|
|
import { v4 as uuidv4 } from 'uuid';
|
|
|
|
import { spawn } from 'child_process';
|
|
|
|
import * as fs from 'fs';
|
|
|
|
|
|
|
|
//TESTING
|
|
|
|
const delay = async (ms: number) => await new Promise(resolve => setTimeout(resolve, ms));
|
|
|
|
|
|
|
|
export interface Job {
|
|
|
|
state: string;
|
|
|
|
fetch_url: string | null;
|
|
|
|
error: string | null;
|
|
|
|
}
|
|
|
|
|
|
|
|
export interface context {
|
|
|
|
jobManager: JobManager;
|
|
|
|
jobId: string;
|
|
|
|
filePath: string;
|
|
|
|
}
|
|
|
|
|
|
|
|
export interface options {
|
|
|
|
quality: string;
|
|
|
|
}
|
|
|
|
|
|
|
|
export interface command {
|
|
|
|
cmd: string;
|
|
|
|
opts: string[];
|
|
|
|
}
|
|
|
|
|
|
|
|
export class JobManager {
|
|
|
|
private jobs: { [job_id: string]: Job } = {};
|
|
|
|
|
|
|
|
public create_job(job_id: string): void {
|
|
|
|
this.jobs[job_id] = { state: 'pending', fetch_url: null, error: null };
|
|
|
|
console.log("Created job id:", job_id)
|
|
|
|
}
|
|
|
|
|
|
|
|
public set_job_state(job_id: string, state: string): void {
|
|
|
|
this.jobs[job_id].state = state;
|
|
|
|
console.log("Job state change:", job_id, " - ", state)
|
|
|
|
}
|
|
|
|
|
|
|
|
public set_fetch_url(job_id: string, url: string): void {
|
|
|
|
this.jobs[job_id].fetch_url = url;
|
|
|
|
console.log("Job fetch url:", job_id, " - ", url)
|
|
|
|
}
|
|
|
|
|
|
|
|
public set_error(job_id: string, error: string): void {
|
|
|
|
this.jobs[job_id].error = error;
|
|
|
|
console.error("Job error:", job_id, " - ", error)
|
|
|
|
}
|
|
|
|
|
|
|
|
public get_job_status(job_id: string): Job {
|
|
|
|
return this.jobs[job_id] || {};
|
|
|
|
}
|
|
|
|
|
|
|
|
public remove_job(job_id: string): void {
|
|
|
|
if (this.jobs[job_id]) {
|
|
|
|
delete this.jobs[job_id];
|
|
|
|
console.log("Removed job id:", job_id);
|
|
|
|
} else {
|
|
|
|
console.log("Job id not found:", job_id);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
const presets: { [preset: string]: string } = {
|
|
|
|
screen: './sh/screen.sh',
|
2024-05-01 14:41:08 +01:00
|
|
|
print: './sh/print.sh',
|
|
|
|
monochrome: './sh/monochrome.sh'
|
2024-05-01 13:39:29 +01:00
|
|
|
};
|
|
|
|
|
|
|
|
export function createJobId(): string {
|
|
|
|
return uuidv4()
|
|
|
|
}
|
|
|
|
|
|
|
|
export async function runGhostscript(ctx: context, opts: options): Promise<void> {
|
|
|
|
ctx.jobManager.create_job(ctx.jobId)
|
|
|
|
ctx.jobManager.set_job_state(ctx.jobId, "pending")
|
2024-05-01 14:41:08 +01:00
|
|
|
// Add some kind of limit here to prevent too many jobs from being spawned
|
|
|
|
await delay(7500) // Currently a rate limiting delay is introduced
|
2024-05-01 13:39:29 +01:00
|
|
|
const inputFilePath = `./uploads/${ctx.jobId}/in.pdf`
|
|
|
|
const outputFilePath = `./uploads/${ctx.jobId}/out.pdf`
|
|
|
|
ctx.jobManager.set_job_state(ctx.jobId, "running")
|
|
|
|
const gsProcess = spawn(presets[opts.quality], [ctx.jobId], {shell: true})
|
|
|
|
gsProcess.stdout.on('data', (data) => {
|
|
|
|
console.log(`stdout: ${data}`);
|
|
|
|
});
|
|
|
|
|
|
|
|
gsProcess.stderr.on('data', (data) => {
|
|
|
|
console.error(`stderr: ${data}`);
|
|
|
|
});
|
|
|
|
gsProcess.on("exit", (code) => {
|
|
|
|
if (code === 0) {
|
|
|
|
fs.unlink(inputFilePath, (err) => {
|
|
|
|
if (err) {
|
|
|
|
console.error(`Error deleting input PDF file: ${err}`);
|
|
|
|
} else {
|
|
|
|
console.log(`Input PDF file deleted: ${inputFilePath}`);
|
|
|
|
}
|
|
|
|
});
|
|
|
|
ctx.jobManager.set_job_state(ctx.jobId, "done")
|
|
|
|
ctx.jobManager.set_fetch_url(ctx.jobId, `/download?job_id=${ctx.jobId}`)
|
|
|
|
const timeout = 60 * 10 * 1000; // 10 minutes (ms)
|
|
|
|
setTimeout(() => {
|
|
|
|
fs.unlink(outputFilePath, (err) => {
|
|
|
|
if (err) {
|
|
|
|
console.error(`Error deleting static PDF file: ${err}`);
|
|
|
|
} else {
|
|
|
|
console.log(`Static PDF file deleted: ${outputFilePath}`);
|
|
|
|
}
|
|
|
|
});
|
|
|
|
}, timeout);
|
|
|
|
} else {
|
|
|
|
ctx.jobManager.set_job_state(ctx.jobId, "error")
|
|
|
|
ctx.jobManager.set_error(ctx.jobId, "Ghostscript exited with error: " + code)
|
|
|
|
}
|
|
|
|
})
|
|
|
|
console.log("Job Complete")
|
|
|
|
}
|