Merge branch 'main' into next

This commit is contained in:
nocobase[bot]
2026-07-27 13:28:32 +00:00
2 changed files with 21 additions and 2 deletions
@@ -14,14 +14,19 @@ import path from 'node:path';
export type DocumentLoaderWorkerOptions = {
filePath: string;
mimeType?: string;
/** Timeout in milliseconds for the worker to complete. Defaults to 5 minutes. */
timeout?: number;
};
const DEFAULT_WORKER_TIMEOUT = 5 * 60 * 1000;
export const loadByWorker = async (extname: string, options: DocumentLoaderWorkerOptions): Promise<Document[]> => {
const isTsRuntime = __filename.endsWith('.ts');
const workerPath = path.join(__dirname, `loader.worker.${isTsRuntime ? 'ts' : 'js'}`);
const worker = new Worker(workerPath, {
execArgv: isTsRuntime ? ['--require', 'tsx/cjs'] : undefined,
});
const timeout = options.timeout ?? DEFAULT_WORKER_TIMEOUT;
return new Promise<Document[]>((resolve, reject) => {
let settled = false;
const close = (error?: Error, result?: Document[]) => {
@@ -29,6 +34,7 @@ export const loadByWorker = async (extname: string, options: DocumentLoaderWorke
return;
}
settled = true;
clearTimeout(timer);
if (error) {
reject(error);
return;
@@ -36,6 +42,10 @@ export const loadByWorker = async (extname: string, options: DocumentLoaderWorke
resolve(result || []);
};
const timer = setTimeout(() => {
close(new Error(`Document loading timed out after ${Math.round(timeout / 1000)}s`));
}, timeout);
worker.once('message', (payload: { documents?: Document[]; error?: string }) => {
if (payload?.error) {
close(new Error(payload.error));
@@ -29,7 +29,15 @@ type WorkerResponse = {
const loadPdf = async (filePath: string): Promise<Document[]> => {
const loader = new PDFLoader(filePath);
return loader.load();
try {
return await loader.load();
} catch (error) {
const err = error as Error;
if (err?.name === 'PasswordException' || /password/i.test(err?.message)) {
throw new Error('The PDF file is password-protected and cannot be parsed. Please upload an unlocked version.');
}
throw error;
}
};
const loadDoc = async (filePath: string, type: 'docx' | 'doc'): Promise<Document[]> => {
@@ -90,8 +98,9 @@ parentPort?.on('message', async (payload: ParsePayload) => {
};
parentPort?.postMessage(response);
} catch (error) {
const err = error as Error;
const response: WorkerResponse = {
error: String(error?.stack || error),
error: err?.message || String(error),
};
parentPort?.postMessage(response);
}