|
@@ -13,7 +13,6 @@ import type { ObjectIdLike } from '~/server/interfaces/mongoose-utils';
|
|
|
import type { ActivityDocument } from '~/server/models/activity';
|
|
import type { ActivityDocument } from '~/server/models/activity';
|
|
|
import { configManager } from '~/server/service/config-manager';
|
|
import { configManager } from '~/server/service/config-manager';
|
|
|
import CronService from '~/server/service/cron';
|
|
import CronService from '~/server/service/cron';
|
|
|
-import type { FileUploader } from '~/server/service/file-uploader';
|
|
|
|
|
import { preNotifyService } from '~/server/service/pre-notify';
|
|
import { preNotifyService } from '~/server/service/pre-notify';
|
|
|
import loggerFactory from '~/utils/logger';
|
|
import loggerFactory from '~/utils/logger';
|
|
|
|
|
|
|
@@ -24,7 +23,7 @@ import PageBulkExportPageSnapshot from '../../models/page-bulk-export-page-snaps
|
|
|
|
|
|
|
|
|
|
|
|
|
import { BulkExportJobExpiredError, BulkExportJobRestartedError } from './errors';
|
|
import { BulkExportJobExpiredError, BulkExportJobRestartedError } from './errors';
|
|
|
-import { compressAndUploadAsync } from './steps/compress-and-upload-async';
|
|
|
|
|
|
|
+import { compressAndUpload } from './steps/compress-and-upload';
|
|
|
import { createPageSnapshotsAsync } from './steps/create-page-snapshots-async';
|
|
import { createPageSnapshotsAsync } from './steps/create-page-snapshots-async';
|
|
|
import { exportPagesToFsAsync } from './steps/export-pages-to-fs-async';
|
|
import { exportPagesToFsAsync } from './steps/export-pages-to-fs-async';
|
|
|
|
|
|
|
@@ -37,7 +36,8 @@ export interface IPageBulkExportJobCronService {
|
|
|
maxPartSize: number;
|
|
maxPartSize: number;
|
|
|
compressExtension: string;
|
|
compressExtension: string;
|
|
|
setStreamInExecution(jobId: ObjectIdLike, stream: Readable): void;
|
|
setStreamInExecution(jobId: ObjectIdLike, stream: Readable): void;
|
|
|
- handlePipelineError(err: Error | null, pageBulkExportJob: PageBulkExportJobDocument): void;
|
|
|
|
|
|
|
+ removeStreamInExecution(jobId: ObjectIdLike): void;
|
|
|
|
|
+ handleError(err: Error | null, pageBulkExportJob: PageBulkExportJobDocument): void;
|
|
|
notifyExportResultAndCleanUp(action: SupportedActionType, pageBulkExportJob: PageBulkExportJobDocument): Promise<void>;
|
|
notifyExportResultAndCleanUp(action: SupportedActionType, pageBulkExportJob: PageBulkExportJobDocument): Promise<void>;
|
|
|
getTmpOutputDir(pageBulkExportJob: PageBulkExportJobDocument): string;
|
|
getTmpOutputDir(pageBulkExportJob: PageBulkExportJobDocument): string;
|
|
|
}
|
|
}
|
|
@@ -157,7 +157,7 @@ class PageBulkExportJobCronService extends CronService implements IPageBulkExpor
|
|
|
exportPagesToFsAsync.bind(this)(pageBulkExportJob);
|
|
exportPagesToFsAsync.bind(this)(pageBulkExportJob);
|
|
|
}
|
|
}
|
|
|
else if (pageBulkExportJob.status === PageBulkExportJobStatus.uploading) {
|
|
else if (pageBulkExportJob.status === PageBulkExportJobStatus.uploading) {
|
|
|
- await compressAndUploadAsync.bind(this)(user, pageBulkExportJob);
|
|
|
|
|
|
|
+ compressAndUpload.bind(this)(user, pageBulkExportJob);
|
|
|
}
|
|
}
|
|
|
}
|
|
}
|
|
|
catch (err) {
|
|
catch (err) {
|
|
@@ -167,11 +167,11 @@ class PageBulkExportJobCronService extends CronService implements IPageBulkExpor
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
/**
|
|
|
- * Handle errors that occurred inside a stream pipeline
|
|
|
|
|
|
|
+ * Handle errors that occurred during page bulk export
|
|
|
* @param err error
|
|
* @param err error
|
|
|
* @param pageBulkExportJob PageBulkExportJob executed in the pipeline
|
|
* @param pageBulkExportJob PageBulkExportJob executed in the pipeline
|
|
|
*/
|
|
*/
|
|
|
- async handlePipelineError(err: Error | null, pageBulkExportJob: PageBulkExportJobDocument) {
|
|
|
|
|
|
|
+ async handleError(err: Error | null, pageBulkExportJob: PageBulkExportJobDocument) {
|
|
|
if (err == null) return;
|
|
if (err == null) return;
|
|
|
|
|
|
|
|
if (err instanceof BulkExportJobExpiredError) {
|
|
if (err instanceof BulkExportJobExpiredError) {
|
|
@@ -215,7 +215,6 @@ class PageBulkExportJobCronService extends CronService implements IPageBulkExpor
|
|
|
* Do the following in parallel:
|
|
* Do the following in parallel:
|
|
|
* - delete page snapshots
|
|
* - delete page snapshots
|
|
|
* - remove the temporal output directory
|
|
* - remove the temporal output directory
|
|
|
- * - abort multipart upload
|
|
|
|
|
*/
|
|
*/
|
|
|
async cleanUpExportJobResources(pageBulkExportJob: PageBulkExportJobDocument, restarted = false) {
|
|
async cleanUpExportJobResources(pageBulkExportJob: PageBulkExportJobDocument, restarted = false) {
|
|
|
const streamInExecution = this.getStreamInExecution(pageBulkExportJob._id);
|
|
const streamInExecution = this.getStreamInExecution(pageBulkExportJob._id);
|
|
@@ -226,19 +225,14 @@ class PageBulkExportJobCronService extends CronService implements IPageBulkExpor
|
|
|
else {
|
|
else {
|
|
|
streamInExecution.destroy(new BulkExportJobExpiredError());
|
|
streamInExecution.destroy(new BulkExportJobExpiredError());
|
|
|
}
|
|
}
|
|
|
|
|
+ this.removeStreamInExecution(pageBulkExportJob._id);
|
|
|
}
|
|
}
|
|
|
- this.removeStreamInExecution(pageBulkExportJob._id);
|
|
|
|
|
|
|
|
|
|
const promises = [
|
|
const promises = [
|
|
|
PageBulkExportPageSnapshot.deleteMany({ pageBulkExportJob }),
|
|
PageBulkExportPageSnapshot.deleteMany({ pageBulkExportJob }),
|
|
|
fs.promises.rm(this.getTmpOutputDir(pageBulkExportJob), { recursive: true, force: true }),
|
|
fs.promises.rm(this.getTmpOutputDir(pageBulkExportJob), { recursive: true, force: true }),
|
|
|
];
|
|
];
|
|
|
|
|
|
|
|
- const fileUploadService: FileUploader = this.crowi.fileUploadService;
|
|
|
|
|
- if (pageBulkExportJob.uploadKey != null && pageBulkExportJob.uploadId != null) {
|
|
|
|
|
- promises.push(fileUploadService.abortPreviousMultipartUpload(pageBulkExportJob.uploadKey, pageBulkExportJob.uploadId));
|
|
|
|
|
- }
|
|
|
|
|
-
|
|
|
|
|
const results = await Promise.allSettled(promises);
|
|
const results = await Promise.allSettled(promises);
|
|
|
results.forEach((result) => {
|
|
results.forEach((result) => {
|
|
|
if (result.status === 'rejected') logger.error(result.reason);
|
|
if (result.status === 'rejected') logger.error(result.reason);
|