[revert] remove worker code

This commit is contained in:
Jean-Louis Leysens 2022-02-17 17:47:34 +01:00
parent dcffac3117
commit caf67a88b8
No known key found for this signature in database
GPG key ID: 28B3B4DFF3677CDC
3 changed files with 76 additions and 226 deletions

View file

@ -24,7 +24,7 @@ import { PdfWorkerOutOfMemoryError } from './pdfmaker_errors';
import type { GeneratePdfRequest, GeneratePdfResponse, WorkerData } from './worker';
// Ensure that the worker and all dependencies are included in the release bundle.
import './worker';
// import './worker';
export class PdfMaker {
_layout: Layout;
@ -141,87 +141,88 @@ export class PdfMaker {
this._title = title;
}
private getGeneratePdfRequestData(): GeneratePdfRequest['data'] {
return {
layout: {
hasFooter: this._layout.hasFooter,
hasHeader: this._layout.hasHeader,
orientation: this._layout.getPdfPageOrientation(),
useReportingBranding: this._layout.useReportingBranding,
pageSize: this._layout.getPdfPageSize({
pageMarginTop,
pageMarginBottom,
pageMarginWidth,
tableBorderWidth,
headingHeight,
subheadingHeight,
}),
},
title: this._title,
logo: this._logo,
content: this._content as unknown as SerializableRecord[],
};
}
// private getGeneratePdfRequestData(): GeneratePdfRequest['data'] {
// return {
// layout: {
// hasFooter: this._layout.hasFooter,
// hasHeader: this._layout.hasHeader,
// orientation: this._layout.getPdfPageOrientation(),
// useReportingBranding: this._layout.useReportingBranding,
// pageSize: this._layout.getPdfPageSize({
// pageMarginTop,
// pageMarginBottom,
// pageMarginWidth,
// tableBorderWidth,
// headingHeight,
// subheadingHeight,
// }),
// },
// title: this._title,
// logo: this._logo,
// content: this._content as unknown as SerializableRecord[],
// };
// }
private createWorker(port: MessagePort): Worker {
const workerData: WorkerData = {
port,
};
return new Worker(this.workerModulePath, {
workerData,
resourceLimits: {
maxYoungGenerationSizeMb: this.workerMaxYoungHeapSizeMb,
maxOldGenerationSizeMb: this.workerMaxOldHeapSizeMb,
},
transferList: [port],
});
}
// private createWorker(port: MessagePort): Worker {
// const workerData: WorkerData = {
// port,
// };
// return new Worker(this.workerModulePath, {
// workerData,
// resourceLimits: {
// maxYoungGenerationSizeMb: this.workerMaxYoungHeapSizeMb,
// maxOldGenerationSizeMb: this.workerMaxOldHeapSizeMb,
// },
// transferList: [port],
// });
// }
private async cleanupWorker(): Promise<void> {
if (this.worker) {
await this.worker.terminate();
this.worker = undefined;
}
}
// private async cleanupWorker(): Promise<void> {
// if (this.worker) {
// await this.worker.terminate();
// this.worker = undefined;
// }
// }
public async generate(): Promise<Uint8Array> {
if (this.worker) throw new Error('PDF generation already in progress!');
return new Uint8Array();
// if (this.worker) throw new Error('PDF generation already in progress!');
try {
return await new Promise<Uint8Array>((resolve, reject) => {
const { port1: myPort, port2: theirPort } = new MessageChannel();
this.worker = this.createWorker(theirPort);
this.worker.on('error', (workerError: NodeJS.ErrnoException) => {
if (workerError.code === 'ERR_WORKER_OUT_OF_MEMORY') {
reject(new PdfWorkerOutOfMemoryError(workerError.message));
} else {
reject(workerError);
}
});
// try {
// return await new Promise<Uint8Array>((resolve, reject) => {
// const { port1: myPort, port2: theirPort } = new MessageChannel();
// this.worker = this.createWorker(theirPort);
// this.worker.on('error', (workerError: NodeJS.ErrnoException) => {
// if (workerError.code === 'ERR_WORKER_OUT_OF_MEMORY') {
// reject(new PdfWorkerOutOfMemoryError(workerError.message));
// } else {
// reject(workerError);
// }
// });
// Send the initial request
const generatePdfRequest: GeneratePdfRequest = {
data: this.getGeneratePdfRequestData(),
};
myPort.postMessage(generatePdfRequest);
// // Send the initial request
// const generatePdfRequest: GeneratePdfRequest = {
// data: this.getGeneratePdfRequestData(),
// };
// myPort.postMessage(generatePdfRequest);
// We expect one message from the worker generating the PDF buffer.
myPort.on('message', ({ error, data }: GeneratePdfResponse) => {
if (error) {
reject(new Error(`PDF worker returned the following error: ${error}`));
return;
}
if (!data) {
reject(new Error(`Worker did not generate a PDF!`));
return;
}
this.pageCount = data.metrics.pages;
resolve(data.buffer);
});
});
} finally {
await this.cleanupWorker();
}
// // We expect one message from the worker generating the PDF buffer.
// myPort.on('message', ({ error, data }: GeneratePdfResponse) => {
// if (error) {
// reject(new Error(`PDF worker returned the following error: ${error}`));
// return;
// }
// if (!data) {
// reject(new Error(`Worker did not generate a PDF!`));
// return;
// }
// this.pageCount = data.metrics.pages;
// resolve(data.buffer);
// });
// });
// } finally {
// await this.cleanupWorker();
// }
}
getPageCount(): number {

View file

@ -1,9 +0,0 @@
/*
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
* or more contributor license agreements. Licensed under the Elastic License
* 2.0; you may not use this file except in compliance with the Elastic License
* 2.0.
*/
require('../../../../../../../src/setup_node_env');
require('./worker.ts');

View file

@ -1,142 +0,0 @@
/*
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
* or more contributor license agreements. Licensed under the Elastic License
* 2.0; you may not use this file except in compliance with the Elastic License
* 2.0.
*/
import { Ensure, SerializableRecord } from '@kbn/utility-types';
import { isMainThread, MessagePort, workerData } from 'worker_threads';
import _ from 'lodash';
import path from 'path';
import Printer from 'pdfmake';
import { getTemplate } from './get_template';
import type { TemplateLayout } from './types';
import { assetPath } from './constants';
export interface WorkerData {
port: MessagePort;
}
export type GenerateReportRequestData = Ensure<
{
layout: TemplateLayout;
title: string;
content: SerializableRecord[];
logo?: string;
},
SerializableRecord
>;
export interface GeneratePdfRequest {
data: GenerateReportRequestData;
}
export type GeneratePdfResponse = SuccessResponse | ErrorResponse;
export interface SuccessResponse {
error?: undefined;
data: {
buffer: Uint8Array;
metrics: {
pages: number;
};
};
}
export interface ErrorResponse {
error: string;
data: null;
}
if (!isMainThread) {
const { port } = workerData as WorkerData;
port.on('message', execute);
}
const getPageCount = (pdfDoc: PDFKit.PDFDocument): number => {
const pageRange = pdfDoc.bufferedPageRange();
if (!pageRange) {
return 0;
}
const { count, start } = pageRange;
return start + count;
};
async function execute({ data: { layout, logo, title, content } }: GeneratePdfRequest) {
const { port } = workerData as WorkerData;
try {
const tableBorderWidth = 1;
const fontPath = (filename: string) => path.resolve(assetPath, 'fonts', filename);
const fonts = {
Roboto: {
normal: fontPath('roboto/Roboto-Regular.ttf'),
bold: fontPath('roboto/Roboto-Medium.ttf'),
italics: fontPath('roboto/Roboto-Italic.ttf'),
bolditalics: fontPath('roboto/Roboto-Italic.ttf'),
},
'noto-cjk': {
// Roboto does not support CJK characters, so we'll fall back on this font if we detect them.
normal: fontPath('noto/NotoSansCJKtc-Regular.ttf'),
bold: fontPath('noto/NotoSansCJKtc-Medium.ttf'),
italics: fontPath('noto/NotoSansCJKtc-Regular.ttf'),
bolditalics: fontPath('noto/NotoSansCJKtc-Medium.ttf'),
},
};
const printer = new Printer(fonts);
const docDefinition = _.assign(getTemplate(layout, logo, title, tableBorderWidth, assetPath), {
content,
});
const pdfDoc = printer.createPdfKitDocument(docDefinition, {
tableLayouts: {
noBorder: {
// format is function (i, node) { ... };
hLineWidth: () => 0,
vLineWidth: () => 0,
paddingLeft: () => 0,
paddingRight: () => 0,
paddingTop: () => 0,
paddingBottom: () => 0,
},
},
});
if (!pdfDoc) {
throw new Error('Document stream has not been generated');
}
const buffer = await new Promise<Buffer>((resolve, reject) => {
const buffers: Buffer[] = [];
pdfDoc.on('error', reject);
pdfDoc.on('data', (data: Buffer) => {
buffers.push(data);
});
pdfDoc.on('end', () => {
resolve(Buffer.concat(buffers));
});
pdfDoc.end();
});
const successResponse: SuccessResponse = {
data: {
buffer,
metrics: {
pages: getPageCount(pdfDoc),
},
},
};
port.postMessage(successResponse, [buffer.buffer /* Transfer buffer instead of copying */]);
} catch (error) {
const errorResponse: ErrorResponse = { error: error.message, data: null };
port.postMessage(errorResponse);
}
}