|
|
@@ -5,6 +5,7 @@ import { pipeline as pipelinePromise } from 'node:stream/promises';
|
|
|
import { OnInit } from '@tsed/common';
|
|
|
import { Service } from '@tsed/di';
|
|
|
import { Logger } from '@tsed/logger';
|
|
|
+import type { PuppeteerNodeLaunchOptions } from 'puppeteer';
|
|
|
import { Cluster } from 'puppeteer-cluster';
|
|
|
|
|
|
interface PageInfo {
|
|
|
@@ -37,8 +38,6 @@ interface JobInfo {
|
|
|
class PdfConvertService implements OnInit {
|
|
|
private puppeteerCluster: Cluster | undefined;
|
|
|
|
|
|
- private maxConcurrency = 1;
|
|
|
-
|
|
|
private convertRetryLimit = 5;
|
|
|
|
|
|
private tmpOutputRootDir = '/tmp/page-bulk-export';
|
|
|
@@ -287,20 +286,56 @@ class PdfConvertService implements OnInit {
|
|
|
}
|
|
|
|
|
|
/**
|
|
|
- * Initialize puppeteer cluster
|
|
|
+ * Get puppeteer cluster configuration from environment variable
|
|
|
+ * @returns merged cluster configuration
|
|
|
*/
|
|
|
- private async initPuppeteerCluster(): Promise<void> {
|
|
|
- if (process.env.SKIP_PUPPETEER_INIT === 'true') return;
|
|
|
+ private getPuppeteerClusterConfig(): Record<string, any> {
|
|
|
+ // Default puppeteer options
|
|
|
+ const defaultPuppeteerOptions: PuppeteerNodeLaunchOptions = {
|
|
|
+ // ref) https://github.com/growilabs/growi/pull/10192
|
|
|
+ args: ['--no-sandbox'],
|
|
|
+ };
|
|
|
|
|
|
- this.puppeteerCluster = await Cluster.launch({
|
|
|
- concurrency: Cluster.CONCURRENCY_PAGE,
|
|
|
- maxConcurrency: this.maxConcurrency,
|
|
|
+ // Default cluster configuration
|
|
|
+ const defaultConfig = {
|
|
|
+ concurrency: Cluster.CONCURRENCY_CONTEXT,
|
|
|
+ maxConcurrency: 1,
|
|
|
workerCreationDelay: 10000,
|
|
|
+ puppeteerOptions: defaultPuppeteerOptions,
|
|
|
+ };
|
|
|
+
|
|
|
+ // Parse configuration from environment variable
|
|
|
+ let customConfig: Record<string, any> = {};
|
|
|
+ if (process.env.PUPPETEER_CLUSTER_CONFIG) {
|
|
|
+ try {
|
|
|
+ customConfig = JSON.parse(process.env.PUPPETEER_CLUSTER_CONFIG);
|
|
|
+ } catch (err) {
|
|
|
+ this.logger.warn(
|
|
|
+ 'Failed to parse PUPPETEER_CLUSTER_CONFIG, using default values',
|
|
|
+ err,
|
|
|
+ );
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ // Merge configurations (customConfig overrides defaultConfig)
|
|
|
+ return {
|
|
|
+ ...defaultConfig,
|
|
|
+ ...customConfig,
|
|
|
puppeteerOptions: {
|
|
|
- // ref) https://github.com/growilabs/growi/pull/10192
|
|
|
- args: ['--no-sandbox'],
|
|
|
+ ...defaultPuppeteerOptions,
|
|
|
+ ...customConfig.puppeteerOptions,
|
|
|
},
|
|
|
- });
|
|
|
+ };
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * Initialize puppeteer cluster
|
|
|
+ */
|
|
|
+ private async initPuppeteerCluster(): Promise<void> {
|
|
|
+ if (process.env.SKIP_PUPPETEER_INIT === 'true') return;
|
|
|
+
|
|
|
+ const config = this.getPuppeteerClusterConfig();
|
|
|
+ this.puppeteerCluster = await Cluster.launch(config);
|
|
|
|
|
|
await this.puppeteerCluster.task(async ({ page, data: htmlString }) => {
|
|
|
await page.setContent(htmlString, { waitUntil: 'domcontentloaded' });
|