Ryotaro Nagahara 1 месяц назад
Родитель
Сommit
0e9d081370

+ 8 - 8
apps/app/src/features/page-bulk-export/server/service/page-bulk-export-job-cron/steps/compress-and-upload.ts

@@ -76,7 +76,7 @@ export async function compressAndUpload(
 
   const fileUploadService: FileUploader = this.crowi.fileUploadService;
 
-  logger.info('compressAndUpload: starting');
+  logger.info('starting');
 
   // Wrap with Node.js native PassThrough so that AWS SDK recognizes the stream as a native Readable
   const uploadStream = new PassThrough();
@@ -84,32 +84,32 @@ export async function compressAndUpload(
   // Establish pipe before finalize to ensure data flows correctly
   pageArchiver.pipe(uploadStream);
   pageArchiver.on('error', (err) => {
-    logger.error('compressAndUpload: pageArchiver error', err);
+    logger.error('pageArchiver error', err);
     uploadStream.destroy(err);
     pageArchiver.destroy();
   });
 
   pageArchiver.directory(this.getTmpOutputDir(pageBulkExportJob), false);
   pageArchiver.finalize();
-  logger.info('compressAndUpload: finalize called');
+  logger.info('finalize called');
 
   this.setStreamsInExecution(pageBulkExportJob._id, pageArchiver, uploadStream);
 
   try {
-    logger.info('compressAndUpload: starting upload');
+    logger.info('starting upload');
     await fileUploadService.uploadAttachment(uploadStream, attachment);
-    logger.info('compressAndUpload: upload completed, running postProcess');
+    logger.info('upload completed, running postProcess');
     await postProcess.bind(this)(
       pageBulkExportJob,
       attachment,
       pageArchiver.pointer(),
     );
-    logger.info('compressAndUpload: postProcess completed');
+    logger.info('postProcess completed');
   } catch (e) {
-    logger.error('compressAndUpload: error caught', e);
+    logger.error('error caught', e);
     this.handleError(e, pageBulkExportJob);
   } finally {
-    logger.info('compressAndUpload: finally block, destroying streams');
+    logger.info('finally block, destroying streams');
     pageArchiver.destroy();
     uploadStream.destroy();
   }

+ 11 - 4
apps/app/src/server/service/file-uploader/aws/index.ts

@@ -282,10 +282,17 @@ class AwsFileUploader extends AbstractFileUploader {
         `File upload completed successfully: fileName=${attachment.fileName}`,
       );
     } catch (error) {
-      logger.error(
-        `File upload failed: fileName=${attachment.fileName}`,
-        error,
-      );
+      // Handle timeout error specifically
+      if (error.name === 'AbortError') {
+        logger.warn(`Upload timeout: fileName=${attachment.fileName}`, error);
+      } else {
+        logger.error(
+          `File upload failed: fileName=${attachment.fileName}`,
+          error,
+        );
+      }
+      // Re-throw the error to be handled by the caller.
+      // The pipeline automatically handles stream cleanup on error.
       throw error;
     } finally {
       clearTimeout(timeoutId);