Merge pull request #967 from ente-io/fix-export-issue

Fix all promise related eslint issue for export
This commit is contained in:
Abhinav Kumar 2023-03-02 15:01:06 +05:30 committed by GitHub
commit c37b93c3e0
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
3 changed files with 168 additions and 107 deletions

View file

@ -70,14 +70,24 @@ export default function ExportModal(props: Props) {
if (!isElectron()) { if (!isElectron()) {
return; return;
} }
try {
setExportFolder(getData(LS_KEYS.EXPORT)?.folder); setExportFolder(getData(LS_KEYS.EXPORT)?.folder);
exportService.electronAPIs.registerStopExportListener(stopExport); exportService.electronAPIs.registerStopExportListener(
exportService.electronAPIs.registerPauseExportListener(pauseExport); stopExportHandler
exportService.electronAPIs.registerResumeExportListener(resumeExport);
exportService.electronAPIs.registerRetryFailedExportListener(
retryFailedExport
); );
exportService.electronAPIs.registerPauseExportListener(
pauseExportHandler
);
exportService.electronAPIs.registerResumeExportListener(
resumeExportHandler
);
exportService.electronAPIs.registerRetryFailedExportListener(
retryFailedExportHandler
);
} catch (e) {
logError(e, 'error in exportModal');
}
}, []); }, []);
useEffect(() => { useEffect(() => {
@ -85,19 +95,25 @@ export default function ExportModal(props: Props) {
return; return;
} }
const main = async () => { const main = async () => {
try {
const exportInfo = await exportService.getExportRecord(); const exportInfo = await exportService.getExportRecord();
setExportStage(exportInfo?.stage ?? ExportStage.INIT); setExportStage(exportInfo?.stage ?? ExportStage.INIT);
setLastExportTime(exportInfo?.lastAttemptTimestamp); setLastExportTime(exportInfo?.lastAttemptTimestamp);
setExportProgress(exportInfo?.progress ?? { current: 0, total: 0 }); setExportProgress(
exportInfo?.progress ?? { current: 0, total: 0 }
);
setExportStats({ setExportStats({
success: exportInfo?.exportedFiles?.length ?? 0, success: exportInfo?.exportedFiles?.length ?? 0,
failed: exportInfo?.failedFiles?.length ?? 0, failed: exportInfo?.failedFiles?.length ?? 0,
}); });
if (exportInfo?.stage === ExportStage.INPROGRESS) { if (exportInfo?.stage === ExportStage.INPROGRESS) {
resumeExport(); await resumeExport();
}
} catch (e) {
logError(e, 'error handling exportFolder change');
} }
}; };
main(); void main();
}, [exportFolder]); }, [exportFolder]);
useEffect(() => { useEffect(() => {
@ -117,7 +133,7 @@ export default function ExportModal(props: Props) {
const failedFilesCnt = exportRecord.failedFiles?.length; const failedFilesCnt = exportRecord.failedFiles?.length;
const syncedFilesCnt = userPersonalFiles.length; const syncedFilesCnt = userPersonalFiles.length;
if (syncedFilesCnt > exportedFileCnt + failedFilesCnt) { if (syncedFilesCnt > exportedFileCnt + failedFilesCnt) {
updateExportProgress({ await updateExportProgress({
current: exportedFileCnt + failedFilesCnt, current: exportedFileCnt + failedFilesCnt,
total: syncedFilesCnt, total: syncedFilesCnt,
}); });
@ -131,11 +147,11 @@ export default function ExportModal(props: Props) {
getExportRecordFileUID(file) getExportRecordFileUID(file)
) )
); );
exportService.addFilesQueuedRecord( await exportService.addFilesQueuedRecord(
exportFolder, exportFolder,
unExportedFiles unExportedFiles
); );
updateExportStage(ExportStage.PAUSED); await updateExportStage(ExportStage.PAUSED);
} }
} catch (e) { } catch (e) {
setExportStage(ExportStage.INIT); setExportStage(ExportStage.INIT);
@ -143,7 +159,7 @@ export default function ExportModal(props: Props) {
} }
} }
}; };
main(); void main();
}, [props.show]); }, [props.show]);
useEffect(() => { useEffect(() => {
@ -158,19 +174,21 @@ export default function ExportModal(props: Props) {
setData(LS_KEYS.EXPORT, { folder: newFolder }); setData(LS_KEYS.EXPORT, { folder: newFolder });
}; };
const updateExportStage = (newStage: ExportStage) => { const updateExportStage = async (newStage: ExportStage) => {
setExportStage(newStage); setExportStage(newStage);
exportService.updateExportRecord({ stage: newStage }); await exportService.updateExportRecord({ stage: newStage });
}; };
const updateExportTime = (newTime: number) => { const updateExportTime = async (newTime: number) => {
setLastExportTime(newTime); setLastExportTime(newTime);
exportService.updateExportRecord({ lastAttemptTimestamp: newTime }); await exportService.updateExportRecord({
lastAttemptTimestamp: newTime,
});
}; };
const updateExportProgress = (newProgress: ExportProgress) => { const updateExportProgress = async (newProgress: ExportProgress) => {
setExportProgress(newProgress); setExportProgress(newProgress);
exportService.updateExportRecord({ progress: newProgress }); await exportService.updateExportRecord({ progress: newProgress });
}; };
// ====================== // ======================
@ -182,15 +200,15 @@ export default function ExportModal(props: Props) {
if (!exportFolder) { if (!exportFolder) {
await selectExportDirectory(); await selectExportDirectory();
} }
updateExportStage(ExportStage.INPROGRESS); await updateExportStage(ExportStage.INPROGRESS);
await sleep(100); await sleep(100);
}; };
const postExportRun = async (exportResult?: { paused?: boolean }) => { const postExportRun = async (exportResult?: { paused?: boolean }) => {
if (!exportResult?.paused) { if (!exportResult?.paused) {
updateExportStage(ExportStage.FINISHED); await updateExportStage(ExportStage.FINISHED);
await sleep(100); await sleep(100);
updateExportTime(Date.now()); await updateExportTime(Date.now());
syncExportStatsWithRecord(); await syncExportStatsWithRecord();
} }
}; };
@ -217,7 +235,7 @@ export default function ExportModal(props: Props) {
const startExport = async () => { const startExport = async () => {
try { try {
await preExportRun(); await preExportRun();
updateExportProgress({ current: 0, total: 0 }); await updateExportProgress({ current: 0, total: 0 });
const exportResult = await exportService.exportFiles( const exportResult = await exportService.exportFiles(
updateExportProgress, updateExportProgress,
ExportType.NEW ExportType.NEW
@ -233,7 +251,7 @@ export default function ExportModal(props: Props) {
const stopExport = async () => { const stopExport = async () => {
try { try {
exportService.stopRunningExport(); exportService.stopRunningExport();
postExportRun(); await postExportRun();
} catch (e) { } catch (e) {
if (e.message !== CustomError.REQUEST_CANCELLED) { if (e.message !== CustomError.REQUEST_CANCELLED) {
logError(e, 'stopExport failed'); logError(e, 'stopExport failed');
@ -241,11 +259,11 @@ export default function ExportModal(props: Props) {
} }
}; };
const pauseExport = () => { const pauseExport = async () => {
try { try {
updateExportStage(ExportStage.PAUSED); await updateExportStage(ExportStage.PAUSED);
exportService.pauseRunningExport(); exportService.pauseRunningExport();
postExportRun({ paused: true }); await postExportRun({ paused: true });
} catch (e) { } catch (e) {
if (e.message !== CustomError.REQUEST_CANCELLED) { if (e.message !== CustomError.REQUEST_CANCELLED) {
logError(e, 'pauseExport failed'); logError(e, 'pauseExport failed');
@ -282,7 +300,10 @@ export default function ExportModal(props: Props) {
const retryFailedExport = async () => { const retryFailedExport = async () => {
try { try {
await preExportRun(); await preExportRun();
updateExportProgress({ current: 0, total: exportStats.failed }); await updateExportProgress({
current: 0,
total: exportStats.failed,
});
const exportResult = await exportService.exportFiles( const exportResult = await exportService.exportFiles(
updateExportProgress, updateExportProgress,
@ -296,10 +317,26 @@ export default function ExportModal(props: Props) {
} }
}; };
const startExportHandler = () => {
void startExport();
};
const stopExportHandler = () => {
void stopExport();
};
const pauseExportHandler = () => {
void pauseExport();
};
const resumeExportHandler = () => {
void resumeExport();
};
const retryFailedExportHandler = () => {
void retryFailedExport();
};
const ExportDynamicContent = () => { const ExportDynamicContent = () => {
switch (exportStage) { switch (exportStage) {
case ExportStage.INIT: case ExportStage.INIT:
return <ExportInit startExport={startExport} />; return <ExportInit startExport={startExportHandler} />;
case ExportStage.INPROGRESS: case ExportStage.INPROGRESS:
case ExportStage.PAUSED: case ExportStage.PAUSED:
@ -307,9 +344,9 @@ export default function ExportModal(props: Props) {
<ExportInProgress <ExportInProgress
exportStage={exportStage} exportStage={exportStage}
exportProgress={exportProgress} exportProgress={exportProgress}
resumeExport={resumeExport} resumeExport={resumeExportHandler}
cancelExport={stopExport} cancelExport={stopExportHandler}
pauseExport={pauseExport} pauseExport={pauseExportHandler}
/> />
); );
case ExportStage.FINISHED: case ExportStage.FINISHED:
@ -318,8 +355,8 @@ export default function ExportModal(props: Props) {
onHide={props.onHide} onHide={props.onHide}
lastExportTime={lastExportTime} lastExportTime={lastExportTime}
exportStats={exportStats} exportStats={exportStats}
exportFiles={startExport} exportFiles={startExportHandler}
retryFailed={retryFailedExport} retryFailed={retryFailedExportHandler}
/> />
); );

View file

@ -49,6 +49,7 @@ import { User } from 'types/user';
import { FILE_TYPE, TYPE_JPEG, TYPE_JPG } from 'constants/file'; import { FILE_TYPE, TYPE_JPEG, TYPE_JPG } from 'constants/file';
import { ExportType, ExportNotification, RecordType } from 'constants/export'; import { ExportType, ExportNotification, RecordType } from 'constants/export';
import { ElectronAPIs } from 'types/electron'; import { ElectronAPIs } from 'types/electron';
import { CustomError } from 'utils/error';
const LATEST_EXPORT_VERSION = 1; const LATEST_EXPORT_VERSION = 1;
const EXPORT_RECORD_FILE_NAME = 'export_status.json'; const EXPORT_RECORD_FILE_NAME = 'export_status.json';
@ -83,10 +84,11 @@ class ExportService {
this.pauseExport = true; this.pauseExport = true;
} }
async exportFiles( async exportFiles(
updateProgress: (progress: ExportProgress) => void, updateProgress: (progress: ExportProgress) => Promise<void>,
exportType: ExportType exportType: ExportType
) { ) {
try { try {
// eslint-disable-next-line @typescript-eslint/no-misused-promises
if (this.exportInProgress) { if (this.exportInProgress) {
this.electronAPIs.sendNotification( this.electronAPIs.sendNotification(
ExportNotification.IN_PROGRESS ExportNotification.IN_PROGRESS
@ -177,7 +179,7 @@ class ExportService {
newCollections: Collection[], newCollections: Collection[],
renamedCollections: Collection[], renamedCollections: Collection[],
collectionIDPathMap: CollectionIDPathMap, collectionIDPathMap: CollectionIDPathMap,
updateProgress: (progress: ExportProgress) => void, updateProgress: (progress: ExportProgress) => Promise<void>,
exportDir: string exportDir: string
): Promise<{ paused: boolean }> { ): Promise<{ paused: boolean }> {
try { try {
@ -212,7 +214,7 @@ class ExportService {
this.electronAPIs.showOnTray({ this.electronAPIs.showOnTray({
export_progress: `0 / ${files.length} files exported`, export_progress: `0 / ${files.length} files exported`,
}); });
updateProgress({ await updateProgress({
current: 0, current: 0,
total: files.length, total: files.length,
}); });
@ -239,23 +241,28 @@ class ExportService {
RecordType.SUCCESS RecordType.SUCCESS
); );
} catch (e) { } catch (e) {
logError(e, 'export failed for a file');
if (
e.message ===
CustomError.ADD_FILE_EXPORTED_RECORD_FAILED
) {
throw e;
}
await this.addFileExportedRecord( await this.addFileExportedRecord(
exportDir, exportDir,
file, file,
RecordType.FAILED RecordType.FAILED
); );
logError(
e,
'download and save failed for file during export'
);
} }
this.electronAPIs.showOnTray({ this.electronAPIs.showOnTray({
export_progress: `${index + 1} / ${ export_progress: `${index + 1} / ${
files.length files.length
} files exported`, } files exported`,
}); });
updateProgress({ current: index + 1, total: files.length }); await updateProgress({
current: index + 1,
total: files.length,
});
} }
if (this.stopExport) { if (this.stopExport) {
this.electronAPIs.sendNotification(ExportNotification.ABORT); this.electronAPIs.sendNotification(ExportNotification.ABORT);
@ -266,7 +273,7 @@ class ExportService {
} else if (failedFileCount > 0) { } else if (failedFileCount > 0) {
this.electronAPIs.sendNotification(ExportNotification.FAILED); this.electronAPIs.sendNotification(ExportNotification.FAILED);
this.electronAPIs.showOnTray({ this.electronAPIs.showOnTray({
retry_export: `export failed - retry export`, retry_export: `Retry failed exports`,
}); });
} else { } else {
this.electronAPIs.sendNotification(ExportNotification.FINISH); this.electronAPIs.sendNotification(ExportNotification.FINISH);
@ -289,6 +296,7 @@ class ExportService {
file: EnteFile, file: EnteFile,
type: RecordType type: RecordType
) { ) {
try {
const fileUID = getExportRecordFileUID(file); const fileUID = getExportRecordFileUID(file);
const exportRecord = await this.getExportRecord(folder); const exportRecord = await this.getExportRecord(folder);
exportRecord.queuedFiles = exportRecord.queuedFiles.filter( exportRecord.queuedFiles = exportRecord.queuedFiles.filter(
@ -315,6 +323,10 @@ class ExportService {
exportRecord.queuedFiles = dedupe(exportRecord.queuedFiles); exportRecord.queuedFiles = dedupe(exportRecord.queuedFiles);
exportRecord.failedFiles = dedupe(exportRecord.failedFiles); exportRecord.failedFiles = dedupe(exportRecord.failedFiles);
await this.updateExportRecord(exportRecord, folder); await this.updateExportRecord(exportRecord, folder);
} catch (e) {
logError(e, 'addFileExportedRecord failed');
throw Error(CustomError.ADD_FILE_EXPORTED_RECORD_FAILED);
}
} }
async addCollectionExportedRecord( async addCollectionExportedRecord(
@ -354,6 +366,7 @@ class ExportService {
); );
} catch (e) { } catch (e) {
logError(e, 'error updating Export Record'); logError(e, 'error updating Export Record');
throw e;
} }
} }
@ -372,6 +385,7 @@ class ExportService {
} }
} catch (e) { } catch (e) {
logError(e, 'export Record JSON parsing failed '); logError(e, 'export Record JSON parsing failed ');
throw e;
} }
} }
@ -428,6 +442,7 @@ class ExportService {
} }
async downloadAndSave(file: EnteFile, collectionPath: string) { async downloadAndSave(file: EnteFile, collectionPath: string) {
try {
file.metadata = mergeMetadata([file])[0].metadata; file.metadata = mergeMetadata([file])[0].metadata;
const fileSaveName = getUniqueFileSaveName( const fileSaveName = getUniqueFileSaveName(
collectionPath, collectionPath,
@ -456,9 +471,17 @@ class ExportService {
if (file.metadata.fileType === FILE_TYPE.LIVE_PHOTO) { if (file.metadata.fileType === FILE_TYPE.LIVE_PHOTO) {
await this.exportMotionPhoto(fileStream, file, collectionPath); await this.exportMotionPhoto(fileStream, file, collectionPath);
} else { } else {
await this.saveMediaFile(collectionPath, fileSaveName, fileStream); await this.saveMediaFile(
collectionPath,
fileSaveName,
fileStream
);
await this.saveMetadataFile(collectionPath, fileSaveName, file); await this.saveMetadataFile(collectionPath, fileSaveName, file);
} }
} catch (e) {
logError(e, 'download and save failed');
throw e;
}
} }
private async exportMotionPhoto( private async exportMotionPhoto(

View file

@ -55,6 +55,7 @@ export const CustomError = {
'Windows native image processing is not supported', 'Windows native image processing is not supported',
NETWORK_ERROR: 'Network Error', NETWORK_ERROR: 'Network Error',
NOT_FILE_OWNER: 'not file owner', NOT_FILE_OWNER: 'not file owner',
ADD_FILE_EXPORTED_RECORD_FAILED: 'add file exported record failed',
}; };
export function parseUploadErrorCodes(error) { export function parseUploadErrorCodes(error) {