Browse Source

[ui-storagebrowser] fixes chunk upload for new storage browser (#3977)

Ram Prasad Agarwal 10 months ago
parent
commit
93f0ebdabd

+ 55 - 34
desktop/core/src/desktop/js/utils/hooks/useFileUpload/useChunkUpload.ts

@@ -57,21 +57,34 @@ const useChunkUpload = ({
 }: ChunkUploadOptions): UseUploadQueueResponse => {
 }: ChunkUploadOptions): UseUploadQueueResponse => {
   const config = getLastKnownConfig();
   const config = getLastKnownConfig();
   const chunkSize = config?.storage_browser?.file_upload_chunk_size ?? DEFAULT_CHUNK_SIZE;
   const chunkSize = config?.storage_browser?.file_upload_chunk_size ?? DEFAULT_CHUNK_SIZE;
-  const [pendingItems, setPendingItems] = useState<UploadItem[]>([]);
+  const [processingItem, setProcessingItem] = useState<UploadItem>();
+  const [pendingUploadItems, setPendingUploadItems] = useState<UploadItem[]>([]);
+  const [awaitingStatusItems, setAwaitingStatusItems] = useState<UploadItem[]>([]);
+
+  const onError = () => {
+    if (processingItem) {
+      onStatusUpdate(processingItem, FileUploadStatus.Failed);
+      setProcessingItem(undefined);
+    }
+  };
+
+  const onSuccess = (item: UploadItem) => () => {
+    setAwaitingStatusItems(prev => [...prev, item]);
+    setProcessingItem(undefined);
+  };
 
 
   const { save } = useSaveData(undefined, {
   const { save } = useSaveData(undefined, {
     postOptions: {
     postOptions: {
       qsEncodeData: false,
       qsEncodeData: false,
-      headers: {
-        'Content-Type': 'multipart/form-data'
-      }
-    }
+      headers: { 'Content-Type': 'multipart/form-data' }
+    },
+    onError
   });
   });
 
 
   const updateItemStatus = (serverResponse: TaskServerResponse[]) => {
   const updateItemStatus = (serverResponse: TaskServerResponse[]) => {
     const statusMap = getStatusHashMap(serverResponse);
     const statusMap = getStatusHashMap(serverResponse);
 
 
-    const remainingItems = pendingItems.filter(item => {
+    const remainingItems = awaitingStatusItems.filter(item => {
       const status = statusMap[item.uuid];
       const status = statusMap[item.uuid];
       if (status === TaskStatus.Success || status === TaskStatus.Failure) {
       if (status === TaskStatus.Success || status === TaskStatus.Failure) {
         const ItemStatus =
         const ItemStatus =
@@ -84,14 +97,14 @@ const useChunkUpload = ({
     if (remainingItems.length === 0) {
     if (remainingItems.length === 0) {
       onComplete();
       onComplete();
     }
     }
-    setPendingItems(remainingItems);
+    setAwaitingStatusItems(remainingItems);
   };
   };
 
 
   const { data: tasksStatus } = useLoadData<TaskServerResponse[]>(
   const { data: tasksStatus } = useLoadData<TaskServerResponse[]>(
     '/desktop/api2/taskserver/get_taskserver_tasks/',
     '/desktop/api2/taskserver/get_taskserver_tasks/',
     {
     {
-      pollInterval: pendingItems.length ? 5000 : undefined,
-      skip: !pendingItems.length
+      pollInterval: awaitingStatusItems.length ? 5000 : undefined,
+      skip: !awaitingStatusItems.length
     }
     }
   );
   );
 
 
@@ -101,16 +114,14 @@ const useChunkUpload = ({
     }
     }
   }, [tasksStatus]);
   }, [tasksStatus]);
 
 
-  const addItemToPending = (item: UploadItem) => {
-    setPendingItems(prev => [...prev, item]);
-  };
-
-  const onChunksUploadComplete = async (item: UploadItem) => {
-    const { url, payload } = getChunksCompletePayload(item, chunkSize);
-    return save(payload, {
-      url,
-      onSuccess: () => addItemToPending(item)
-    });
+  const onChunksUploadComplete = async () => {
+    if (processingItem) {
+      const { url, payload } = getChunksCompletePayload(processingItem, chunkSize);
+      return save(payload, {
+        url,
+        onSuccess: onSuccess(processingItem)
+      });
+    }
   };
   };
 
 
   const uploadChunk = async (chunkItem: UploadChunkItem) => {
   const uploadChunk = async (chunkItem: UploadChunkItem) => {
@@ -118,21 +129,21 @@ const useChunkUpload = ({
     return save(payload, { url });
     return save(payload, { url });
   };
   };
 
 
-  const { enqueueAsync } = useQueueProcessor<UploadChunkItem>(uploadChunk, {
-    concurrentProcess
+  const { enqueue } = useQueueProcessor<UploadChunkItem>(uploadChunk, {
+    concurrentProcess,
+    onSuccess: onChunksUploadComplete
   });
   });
 
 
-  const uploadItemInChunks = async (item: UploadItem) => {
+  const uploadItemInChunks = (item: UploadItem) => {
     const chunks = createChunks(item, chunkSize);
     const chunks = createChunks(item, chunkSize);
-    await enqueueAsync(chunks);
-    return onChunksUploadComplete(item);
+    return enqueue(chunks);
   };
   };
 
 
-  const uploadItemInSingleChunk = (item: UploadItem) => {
+  const uploadItemInSingleChunk = async (item: UploadItem) => {
     const { url, payload } = getChunkSinglePayload(item, chunkSize);
     const { url, payload } = getChunkSinglePayload(item, chunkSize);
     return save(payload, {
     return save(payload, {
       url,
       url,
-      onSuccess: () => addItemToPending(item)
+      onSuccess: onSuccess(item)
     });
     });
   };
   };
 
 
@@ -158,15 +169,25 @@ const useChunkUpload = ({
     return uploadItemInChunks(item);
     return uploadItemInChunks(item);
   };
   };
 
 
-  const {
-    enqueue: addFiles,
-    dequeue: removeFile,
-    isLoading
-  } = useQueueProcessor<UploadItem>(uploadItem, {
-    concurrentProcess: 1 // This value must be 1 always
-  });
+  const addFiles = (newItems: UploadItem[]) => {
+    setPendingUploadItems(prev => [...prev, ...newItems]);
+  };
+
+  const removeFile = (item: UploadItem) => {
+    setPendingUploadItems(prev => prev.filter(i => i.uuid !== item.uuid));
+  };
+
+  useEffect(() => {
+    // Ensures one file is broken down in chunks and uploaded to the server
+    if (!processingItem && pendingUploadItems.length) {
+      const item = pendingUploadItems[0];
+      setProcessingItem(item);
+      setPendingUploadItems(prev => prev.slice(1));
+      uploadItem(item);
+    }
+  }, [pendingUploadItems, processingItem]);
 
 
-  return { addFiles, removeFile, isLoading };
+  return { addFiles, removeFile, isLoading: !!processingItem || !!pendingUploadItems.length };
 };
 };
 
 
 export default useChunkUpload;
 export default useChunkUpload;