Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

@uppy/core: make upload() idempotent #5677

Open
wants to merge 3 commits into
base: main
Choose a base branch
from
Open

Conversation

Murderlon
Copy link
Member

@Murderlon Murderlon commented Mar 5, 2025

Closes #5669
Closes #5676

Before

  1. Add a file
  2. Call uppy.upload() but make it fail (set throttling to offline in your browser)
  3. Call uppy.upload() again but no throttling
  4. Events are not fired, endless uploading state.

You must call retryAll() instead but it's better DX if you can simply call upload() again and let us figure it out.

After

upload() behaves like retryAll() when errors occurred in a backwards compatible way.

What if an upload fails and you also add a new file?

Backwards compatible behaviour similar to how it currently works when using the dashboard, first call to upload() only retries the failed files. You have to call upload() again to upload the new files. Making upload() do both at once is hard and makes the events a bit unclear, are emitting 'upload' or 'retry-all'?

Question

In this case:

  1. Add a file
  2. Call upload()` but make it fail (set throttling to offline in your browser)
  3. Add another file
  4. Call upload() to successfully upload the failed file
  5. Call `upload() again to upload the new file
    • should the 'completed' event here contain both files or only the last one? Currently it's the former. Maybe a breaking change if we change it?

@Murderlon Murderlon requested a review from mifi March 5, 2025 10:56
@Murderlon Murderlon self-assigned this Mar 5, 2025
Copy link
Contributor

github-actions bot commented Mar 5, 2025

Diff output files
diff --git a/packages/@uppy/core/lib/Uppy.js b/packages/@uppy/core/lib/Uppy.js
index 1ba8ade..87e04ba 100644
--- a/packages/@uppy/core/lib/Uppy.js
+++ b/packages/@uppy/core/lib/Uppy.js
@@ -994,6 +994,29 @@ export class Uppy {
     let {
       files,
     } = this.getState();
+    const filesToRetry = Object.keys(files).filter(fileID => files[fileID].error);
+    const hasFilesToRetry = filesToRetry.length > 0;
+    if (hasFilesToRetry) {
+      const updatedFiles = {
+        ...files,
+      };
+      filesToRetry.forEach(fileID => {
+        updatedFiles[fileID] = {
+          ...updatedFiles[fileID],
+          isPaused: false,
+          error: null,
+        };
+      });
+      this.setState({
+        files: updatedFiles,
+        error: null,
+      });
+      this.emit("retry-all", Object.values(updatedFiles));
+      const uploadID = _classPrivateFieldLooseBase(this, _createUpload)[_createUpload](filesToRetry, {
+        forceAllowNewUpload: true,
+      });
+      return _classPrivateFieldLooseBase(this, _runUpload)[_runUpload](uploadID);
+    }
     const onBeforeUploadResult = this.opts.onBeforeUpload(files);
     if (onBeforeUploadResult === false) {
       return Promise.reject(new Error("Not starting the upload because onBeforeUpload returned false"));

@Murderlon Murderlon marked this pull request as draft March 5, 2025 11:08
@Murderlon Murderlon marked this pull request as ready for review March 5, 2025 11:45
@Murderlon
Copy link
Member Author

One thing I'm not too happy about yet is that in the case of a failed upload and adding a new file before uploading again, is that you don't really know you have to call upload() twice. Maybe upload() should return something to indicate that or further exploration is needed to upload both at once.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

uppy.upload() does not work with XHRUploader
1 participant