Processes get cleaned up when process quits

This commit is contained in:
Matt McWilliams 2024-10-26 21:47:13 -04:00
parent 5b03182b3d
commit acd7e3bae2
14 changed files with 197 additions and 16 deletions

1
dist/fd/index.d.ts vendored
View File

@ -62,5 +62,6 @@ export declare class FD {
stop(image: string): Promise<fdResult>; stop(image: string): Promise<fdResult>;
isConnected(): boolean; isConnected(): boolean;
private test; private test;
exit(): Promise<void>;
} }
export type { Action, Mode, fdOutgoingPosition, fdOutgoingMessage, fdIncomingMessage, fdResult }; export type { Action, Mode, fdOutgoingPosition, fdOutgoingMessage, fdIncomingMessage, fdResult };

10
dist/fd/index.js vendored
View File

@ -26,6 +26,8 @@ var Mode;
})(Mode || (Mode = {})); })(Mode || (Mode = {}));
class FD { class FD {
constructor(bin, width, height, host, port, mock = false) { constructor(bin, width, height, host, port, mock = false) {
this.shell = null;
this.client = null;
this.socketAvailable = false; this.socketAvailable = false;
this.socketConnected = false; this.socketConnected = false;
this.waiting = null; this.waiting = null;
@ -104,7 +106,7 @@ class FD {
send(msg) { send(msg) {
const json = JSON.stringify(msg); const json = JSON.stringify(msg);
this.log.info(json); this.log.info(json);
if (!this.mock) if (!this.mock && this.client !== null)
this.client.write(json); this.client.write(json);
} }
receive(json) { receive(json) {
@ -243,6 +245,12 @@ class FD {
this.log.warn('QUITTING!!!!'); this.log.warn('QUITTING!!!!');
process.exit(); process.exit();
} }
async exit() {
if (this.client !== null)
this.client.end();
if (this.shell !== null)
this.shell.kill();
}
} }
exports.FD = FD; exports.FD = FD;
module.exports = { FD }; module.exports = { FD };

File diff suppressed because one or more lines are too long

6
dist/files/index.js vendored
View File

@ -17,7 +17,8 @@ const imageExtensions = [
'.png', '.png',
'.tif', '.tif',
'.tiff', '.tiff',
'.bmp' '.bmp',
'.dpx'
]; ];
class Files { class Files {
static async init(sequencesDir) { static async init(sequencesDir) {
@ -106,7 +107,6 @@ class Files {
if (!await this.isSequence(dirPath)) { if (!await this.isSequence(dirPath)) {
continue; continue;
} }
console.log(`Adding ${dirPath}`);
dirs.push({ dirs.push({
created: +stats.birthtime, created: +stats.birthtime,
path: dirPath, path: dirPath,
@ -131,7 +131,6 @@ class Files {
catch (err) { catch (err) {
// //
} }
console.dir(`${dirPath} ${all.length}`);
for (let elem of all) { for (let elem of all) {
filePath = (0, path_1.join)(dirPath, elem); filePath = (0, path_1.join)(dirPath, elem);
try { try {
@ -141,7 +140,6 @@ class Files {
// //
} }
if (stats.isFile() && elem.substring(0, 1) !== '.' && imageExtensions.indexOf((0, path_1.extname)((0, path_1.basename)(elem).toLowerCase())) !== -1) { if (stats.isFile() && elem.substring(0, 1) !== '.' && imageExtensions.indexOf((0, path_1.extname)((0, path_1.basename)(elem).toLowerCase())) !== -1) {
console.log(`Has file ${filePath}`);
sequence = true; sequence = true;
break; break;
} }

File diff suppressed because one or more lines are too long

View File

@ -1,10 +1,14 @@
/// <reference types="node" /> /// <reference types="node" />
export declare class Image { export declare class Image {
private prefix;
private thumbnailCache; private thumbnailCache;
private thumbnailHash; private thumbnailHash;
private blankCache; private blankCache;
private blankHash; private blankHash;
private tmp;
constructor(); constructor();
private mktemp;
private dpx2png;
thumbnail(path: string, width: number, height: number): Promise<Buffer>; thumbnail(path: string, width: number, height: number): Promise<Buffer>;
blank(width: number, height: number): Promise<Buffer>; blank(width: number, height: number): Promise<Buffer>;
} }

56
dist/image/index.js vendored
View File

@ -6,16 +6,64 @@ Object.defineProperty(exports, "__esModule", { value: true });
exports.Image = void 0; exports.Image = void 0;
const sharp_1 = __importDefault(require("sharp")); const sharp_1 = __importDefault(require("sharp"));
const hash_1 = require("../hash"); const hash_1 = require("../hash");
const path_1 = require("path");
const os_1 = require("os");
const promises_1 = require("fs/promises");
const shell_1 = require("../shell");
class Image { class Image {
constructor() { constructor() {
this.prefix = 'fm_thumbs';
this.thumbnailCache = null; this.thumbnailCache = null;
this.thumbnailHash = null; this.thumbnailHash = null;
this.blankCache = null; this.blankCache = null;
this.blankHash = null; this.blankHash = null;
this.tmp = null;
if (this.tmp === null) {
this.tmp = (0, os_1.tmpdir)();
}
}
async mktemp(ext = '.png') {
const randomString = Math.random().toString(36).slice(2);
const tempPath = (0, path_1.join)(this.tmp, this.prefix, randomString + `.${ext}`);
try {
await (0, promises_1.mkdir)((0, path_1.join)(this.tmp, this.prefix));
}
catch (err) {
//
}
return tempPath;
}
async dpx2png(input, output) {
let dpx = null;
const args = [
'convert',
input,
'-colorspace', 'RGB',
'-depth', '8',
output
];
const shell = new shell_1.Shell(args, null, null, null, true);
try {
await shell.execute();
}
catch (err) {
//
}
} }
async thumbnail(path, width, height) { async thumbnail(path, width, height) {
const hash = hash_1.Hashes.stringHash(`${path},${width},${height}`); const hash = hash_1.Hashes.stringHash(`${path},${width},${height}`);
let newPath = null;
if (hash !== this.thumbnailHash) { if (hash !== this.thumbnailHash) {
if ((0, path_1.extname)(path).toLowerCase() === '.dpx') {
try {
newPath = await this.mktemp('png');
await this.dpx2png(path, newPath);
path = newPath;
}
catch (err) {
//
}
}
const options = { const options = {
width, width,
height, height,
@ -23,6 +71,14 @@ class Image {
}; };
this.thumbnailCache = await (0, sharp_1.default)(path).resize(options).jpeg().toBuffer(); this.thumbnailCache = await (0, sharp_1.default)(path).resize(options).jpeg().toBuffer();
this.thumbnailHash = hash; this.thumbnailHash = hash;
if (newPath !== null) {
try {
await (0, promises_1.unlink)(newPath);
}
catch (err) {
//
}
}
} }
return this.thumbnailCache; return this.thumbnailCache;
} }

View File

@ -1 +1 @@
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/image/index.ts"],"names":[],"mappings":";;;;;;AAAA,kDAA0B;AAE1B,kCAAiC;AAEjC,MAAa,KAAK;IAKjB;QAJQ,mBAAc,GAAY,IAAI,CAAC;QAC/B,kBAAa,GAAY,IAAI,CAAC;QAC9B,eAAU,GAAY,IAAI,CAAC;QAC3B,cAAS,GAAY,IAAI,CAAC;IAGlC,CAAC;IACM,KAAK,CAAC,SAAS,CAAE,IAAa,EAAE,KAAc,EAAE,MAAc;QACpE,MAAM,IAAI,GAAY,aAAM,CAAC,UAAU,CAAC,GAAG,IAAI,IAAI,KAAK,IAAI,MAAM,EAAE,CAAC,CAAC;QACtE,IAAI,IAAI,KAAK,IAAI,CAAC,aAAa,EAAE,CAAC;YACjC,MAAM,OAAO,GAAmB;gBAC/B,KAAK;gBACL,MAAM;gBACN,GAAG,EAAE,eAAK,CAAC,GAAG,CAAC,IAAI;aACnB,CAAA;YACD,IAAI,CAAC,cAAc,GAAG,MAAM,IAAA,eAAK,EAAC,IAAI,CAAC,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC,IAAI,EAAE,CAAC,QAAQ,EAAE,CAAC;YAC1E,IAAI,CAAC,aAAa,GAAG,IAAI,CAAC;QAC3B,CAAC;QACD,OAAO,IAAI,CAAC,cAAc,CAAC;IAC5B,CAAC;IAEM,KAAK,CAAC,KAAK,CAAE,KAAc,EAAE,MAAe;QAClD,MAAM,IAAI,GAAY,aAAM,CAAC,UAAU,CAAC,GAAG,KAAK,IAAI,MAAM,EAAE,CAAC,CAAC;QAC9D,IAAI,IAAI,KAAK,IAAI,CAAC,SAAS,EAAE,CAAC;YAC7B,MAAM,OAAO,GAAkB;gBAC9B,MAAM,EAAE;oBACP,KAAK;oBACL,MAAM;oBACN,QAAQ,EAAE,CAAC;oBACX,UAAU,EAAE,EAAE,CAAC,EAAE,GAAG,EAAE,CAAC,EAAE,GAAG,EAAE,CAAC,EAAE,GAAG,EAAE;iBACtC;aACD,CAAC;YACF,IAAI,CAAC,UAAU,GAAG,MAAM,IAAA,eAAK,EAAC,OAAO,CAAC,CAAC,IAAI,EAAE,CAAC,QAAQ,EAAE,CAAC;YACzD,IAAI,CAAC,SAAS,GAAG,IAAI,CAAC;QACvB,CAAC;QACD,OAAO,IAAI,CAAC,UAAU,CAAC;IACxB,CAAC;CACD;AAtCD,sBAsCC;AAED,MAAM,CAAC,OAAO,GAAG,EAAE,KAAK,EAAE,CAAC"} {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/image/index.ts"],"names":[],"mappings":"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"}

24
dist/index.js vendored
View File

@ -480,4 +480,28 @@ async function main() {
setInterval(keepAlive, 30000); setInterval(keepAlive, 30000);
} }
main(); main();
process.stdin.resume(); // so the program will not close instantly
async function exitHandler(options, exitCode) {
if (options.cleanup) {
log.info(`Cleaning up...`);
try {
await fd.exit();
}
catch (err) {
log.error('Error cleanly exiting filmout_display (fd) executable', err);
}
}
exitCode == 'SIGINT' ? log.info(`exit: ${exitCode}`) : log.error(`exit: ${exitCode}`, new Error(`Exited with non-zero code: "${exitCode}"`));
if (options.exit)
process.exit();
}
// do something when app is closing
process.on('exit', exitHandler.bind(null, { cleanup: true }));
// catches ctrl+c event
process.on('SIGINT', exitHandler.bind(null, { exit: true }));
// catches "kill pid" (for example: nodemon restart)
process.on('SIGUSR1', exitHandler.bind(null, { exit: true }));
process.on('SIGUSR2', exitHandler.bind(null, { exit: true }));
// catches uncaught exceptions
process.on('uncaughtException', exitHandler.bind(null, { exit: true }));
//# sourceMappingURL=index.js.map //# sourceMappingURL=index.js.map

2
dist/index.js.map vendored

File diff suppressed because one or more lines are too long

View File

@ -56,9 +56,9 @@ export class FD {
private height : number; private height : number;
private host : string; private host : string;
private port : number; private port : number;
private shell : Shell; private shell : Shell = null;
private log : Logger; private log : Logger;
private client : Socket; private client : Socket = null;
private socketAvailable : boolean = false; private socketAvailable : boolean = false;
private socketConnected : boolean = false; private socketConnected : boolean = false;
@ -145,7 +145,7 @@ export class FD {
private send (msg : fdOutgoingMessage) { private send (msg : fdOutgoingMessage) {
const json : string = JSON.stringify(msg); const json : string = JSON.stringify(msg);
this.log.info(json); this.log.info(json);
if (!this.mock) this.client.write(json); if (!this.mock && this.client !== null) this.client.write(json);
} }
private receive (json : string) { private receive (json : string) {
@ -292,6 +292,11 @@ export class FD {
this.log.warn('QUITTING!!!!'); this.log.warn('QUITTING!!!!');
process.exit(); process.exit();
} }
public async exit () {
if (this.client !== null) this.client.end();
if (this.shell !== null) this.shell.kill();
}
} }
module.exports = { FD }; module.exports = { FD };

View File

@ -37,7 +37,8 @@ const imageExtensions : string[] = [
'.png', '.png',
'.tif', '.tif',
'.tiff', '.tiff',
'.bmp' '.bmp',
'.dpx'
]; ];
export class Files { export class Files {

View File

@ -1,18 +1,67 @@
import sharp from 'sharp'; import sharp from 'sharp';
import type { SharpOptions, ResizeOptions } from 'sharp'; import type { SharpOptions, ResizeOptions } from 'sharp';
import { Hashes } from '../hash'; import { Hashes } from '../hash';
import { join, extname } from 'path';
import { tmpdir } from 'os';
import { mkdir, unlink } from 'fs/promises';
import { Shell } from '../shell';
export class Image { export class Image {
private prefix : string = 'fm_thumbs';
private thumbnailCache : Buffer = null; private thumbnailCache : Buffer = null;
private thumbnailHash : string = null; private thumbnailHash : string = null;
private blankCache : Buffer = null; private blankCache : Buffer = null;
private blankHash : string = null; private blankHash : string = null;
constructor () { private tmp : string = null;
constructor () {
if (this.tmp === null) {
this.tmp = tmpdir();
} }
}
private async mktemp (ext : string = '.png') : Promise<string> {
const randomString : string = Math.random().toString(36).slice(2);
const tempPath : string = join(this.tmp, this.prefix, randomString + `.${ext}`);
try {
await mkdir(join(this.tmp, this.prefix));
} catch (err) {
//
}
return tempPath;
}
private async dpx2png (input : string, output : string) {
let dpx : any = null;
const args : string[] = [
'convert',
input,
'-colorspace', 'RGB',
'-depth', '8',
output
];
const shell : Shell = new Shell(args, null, null, null, true);
try {
await shell.execute();
} catch (err) {
//
}
}
public async thumbnail (path : string, width : number, height: number) : Promise<Buffer>{ public async thumbnail (path : string, width : number, height: number) : Promise<Buffer>{
const hash : string = Hashes.stringHash(`${path},${width},${height}`); const hash : string = Hashes.stringHash(`${path},${width},${height}`);
let newPath : string = null;
if (hash !== this.thumbnailHash) { if (hash !== this.thumbnailHash) {
if (extname(path).toLowerCase() === '.dpx') {
try {
newPath = await this.mktemp('png');
await this.dpx2png(path, newPath);
path = newPath;
} catch (err) {
//
}
}
const options : ResizeOptions = { const options : ResizeOptions = {
width, width,
height, height,
@ -20,6 +69,13 @@ export class Image {
} }
this.thumbnailCache = await sharp(path).resize(options).jpeg().toBuffer(); this.thumbnailCache = await sharp(path).resize(options).jpeg().toBuffer();
this.thumbnailHash = hash; this.thumbnailHash = hash;
if (newPath !== null) {
try {
await unlink(newPath);
} catch (err) {
//
}
}
} }
return this.thumbnailCache; return this.thumbnailCache;
} }

View File

@ -485,3 +485,31 @@ async function main () {
main(); main();
process.stdin.resume(); // so the program will not close instantly
async function exitHandler(options : any, exitCode : string) {
if (options.cleanup) {
log.info(`Cleaning up...`);
try {
await fd.exit();
} catch (err) {
log.error('Error cleanly exiting filmout_display (fd) executable', err);
}
}
exitCode == 'SIGINT' ? log.info(`exit: ${exitCode}`) : log.error(`exit: ${exitCode}`, new Error(`Exited with non-zero code: "${exitCode}"`));
if (options.exit) process.exit();
}
// do something when app is closing
process.on('exit', exitHandler.bind(null,{cleanup:true}));
// catches ctrl+c event
process.on('SIGINT', exitHandler.bind(null, {exit:true}));
// catches "kill pid" (for example: nodemon restart)
process.on('SIGUSR1', exitHandler.bind(null, {exit:true}));
process.on('SIGUSR2', exitHandler.bind(null, {exit:true}));
// catches uncaught exceptions
process.on('uncaughtException', exitHandler.bind(null, {exit:true}));