Processes get cleaned up when process quits
This commit is contained in:
parent
5b03182b3d
commit
acd7e3bae2
|
@ -62,5 +62,6 @@ export declare class FD {
|
|||
stop(image: string): Promise<fdResult>;
|
||||
isConnected(): boolean;
|
||||
private test;
|
||||
exit(): Promise<void>;
|
||||
}
|
||||
export type { Action, Mode, fdOutgoingPosition, fdOutgoingMessage, fdIncomingMessage, fdResult };
|
||||
|
|
|
@ -26,6 +26,8 @@ var Mode;
|
|||
})(Mode || (Mode = {}));
|
||||
class FD {
|
||||
constructor(bin, width, height, host, port, mock = false) {
|
||||
this.shell = null;
|
||||
this.client = null;
|
||||
this.socketAvailable = false;
|
||||
this.socketConnected = false;
|
||||
this.waiting = null;
|
||||
|
@ -104,7 +106,7 @@ class FD {
|
|||
send(msg) {
|
||||
const json = JSON.stringify(msg);
|
||||
this.log.info(json);
|
||||
if (!this.mock)
|
||||
if (!this.mock && this.client !== null)
|
||||
this.client.write(json);
|
||||
}
|
||||
receive(json) {
|
||||
|
@ -243,6 +245,12 @@ class FD {
|
|||
this.log.warn('QUITTING!!!!');
|
||||
process.exit();
|
||||
}
|
||||
async exit() {
|
||||
if (this.client !== null)
|
||||
this.client.end();
|
||||
if (this.shell !== null)
|
||||
this.shell.kill();
|
||||
}
|
||||
}
|
||||
exports.FD = FD;
|
||||
module.exports = { FD };
|
||||
|
|
File diff suppressed because one or more lines are too long
|
@ -17,7 +17,8 @@ const imageExtensions = [
|
|||
'.png',
|
||||
'.tif',
|
||||
'.tiff',
|
||||
'.bmp'
|
||||
'.bmp',
|
||||
'.dpx'
|
||||
];
|
||||
class Files {
|
||||
static async init(sequencesDir) {
|
||||
|
@ -106,7 +107,6 @@ class Files {
|
|||
if (!await this.isSequence(dirPath)) {
|
||||
continue;
|
||||
}
|
||||
console.log(`Adding ${dirPath}`);
|
||||
dirs.push({
|
||||
created: +stats.birthtime,
|
||||
path: dirPath,
|
||||
|
@ -131,7 +131,6 @@ class Files {
|
|||
catch (err) {
|
||||
//
|
||||
}
|
||||
console.dir(`${dirPath} ${all.length}`);
|
||||
for (let elem of all) {
|
||||
filePath = (0, path_1.join)(dirPath, elem);
|
||||
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) {
|
||||
console.log(`Has file ${filePath}`);
|
||||
sequence = true;
|
||||
break;
|
||||
}
|
||||
|
|
File diff suppressed because one or more lines are too long
|
@ -1,10 +1,14 @@
|
|||
/// <reference types="node" />
|
||||
export declare class Image {
|
||||
private prefix;
|
||||
private thumbnailCache;
|
||||
private thumbnailHash;
|
||||
private blankCache;
|
||||
private blankHash;
|
||||
private tmp;
|
||||
constructor();
|
||||
private mktemp;
|
||||
private dpx2png;
|
||||
thumbnail(path: string, width: number, height: number): Promise<Buffer>;
|
||||
blank(width: number, height: number): Promise<Buffer>;
|
||||
}
|
||||
|
|
|
@ -6,16 +6,64 @@ Object.defineProperty(exports, "__esModule", { value: true });
|
|||
exports.Image = void 0;
|
||||
const sharp_1 = __importDefault(require("sharp"));
|
||||
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 {
|
||||
constructor() {
|
||||
this.prefix = 'fm_thumbs';
|
||||
this.thumbnailCache = null;
|
||||
this.thumbnailHash = null;
|
||||
this.blankCache = 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) {
|
||||
const hash = hash_1.Hashes.stringHash(`${path},${width},${height}`);
|
||||
let newPath = null;
|
||||
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 = {
|
||||
width,
|
||||
height,
|
||||
|
@ -23,6 +71,14 @@ class Image {
|
|||
};
|
||||
this.thumbnailCache = await (0, sharp_1.default)(path).resize(options).jpeg().toBuffer();
|
||||
this.thumbnailHash = hash;
|
||||
if (newPath !== null) {
|
||||
try {
|
||||
await (0, promises_1.unlink)(newPath);
|
||||
}
|
||||
catch (err) {
|
||||
//
|
||||
}
|
||||
}
|
||||
}
|
||||
return this.thumbnailCache;
|
||||
}
|
||||
|
|
|
@ -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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"}
|
|
@ -480,4 +480,28 @@ async function main() {
|
|||
setInterval(keepAlive, 30000);
|
||||
}
|
||||
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
|
File diff suppressed because one or more lines are too long
|
@ -56,9 +56,9 @@ export class FD {
|
|||
private height : number;
|
||||
private host : string;
|
||||
private port : number;
|
||||
private shell : Shell;
|
||||
private shell : Shell = null;
|
||||
private log : Logger;
|
||||
private client : Socket;
|
||||
private client : Socket = null;
|
||||
private socketAvailable : boolean = false;
|
||||
private socketConnected : boolean = false;
|
||||
|
||||
|
@ -145,7 +145,7 @@ export class FD {
|
|||
private send (msg : fdOutgoingMessage) {
|
||||
const json : string = JSON.stringify(msg);
|
||||
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) {
|
||||
|
@ -292,6 +292,11 @@ export class FD {
|
|||
this.log.warn('QUITTING!!!!');
|
||||
process.exit();
|
||||
}
|
||||
|
||||
public async exit () {
|
||||
if (this.client !== null) this.client.end();
|
||||
if (this.shell !== null) this.shell.kill();
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = { FD };
|
||||
|
|
|
@ -37,7 +37,8 @@ const imageExtensions : string[] = [
|
|||
'.png',
|
||||
'.tif',
|
||||
'.tiff',
|
||||
'.bmp'
|
||||
'.bmp',
|
||||
'.dpx'
|
||||
];
|
||||
|
||||
export class Files {
|
||||
|
|
|
@ -1,18 +1,67 @@
|
|||
import sharp from 'sharp';
|
||||
import type { SharpOptions, ResizeOptions } from 'sharp';
|
||||
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 {
|
||||
private prefix : string = 'fm_thumbs';
|
||||
private thumbnailCache : Buffer = null;
|
||||
private thumbnailHash : string = null;
|
||||
private blankCache : Buffer = 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>{
|
||||
const hash : string = Hashes.stringHash(`${path},${width},${height}`);
|
||||
let newPath : string = null;
|
||||
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 = {
|
||||
width,
|
||||
height,
|
||||
|
@ -20,6 +69,13 @@ export class Image {
|
|||
}
|
||||
this.thumbnailCache = await sharp(path).resize(options).jpeg().toBuffer();
|
||||
this.thumbnailHash = hash;
|
||||
if (newPath !== null) {
|
||||
try {
|
||||
await unlink(newPath);
|
||||
} catch (err) {
|
||||
//
|
||||
}
|
||||
}
|
||||
}
|
||||
return this.thumbnailCache;
|
||||
}
|
||||
|
|
28
src/index.ts
28
src/index.ts
|
@ -485,3 +485,31 @@ async function 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}));
|
Loading…
Reference in New Issue