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

stopDownload does not cause download promise to reject #72

Open
Alatius opened this issue Sep 18, 2024 · 5 comments · May be fixed by #73
Open

stopDownload does not cause download promise to reject #72

Alatius opened this issue Sep 18, 2024 · 5 comments · May be fixed by #73
Labels
In Progress Work in progress. On Hold Blocked for some reason. P2 Important issue.

Comments

@Alatius
Copy link

Alatius commented Sep 18, 2024

The documentation says about stopDownload that "the promise returned from the aborted downloadFile() call will reject with an error." This works fine on Android, but not on iOS: the download stops, but the promise remains. This seems to be an old issue, and I found this pull request to another fork: itinance#824
I have tried applying it locally to test it, and it seems to solve the problem, as far as I can see.

@Alatius
Copy link
Author

Alatius commented Sep 19, 2024

Having thought some more on this, maybe the current behaviour is by design?

If one does not have any intention of supporting resume, one could then supposedly do something like this:

const handleCancel = () => {
  // Clean up after cancellation
};

const handleFinish = () => {
  // What you want to do after both successful and cancelled download
};

try {
  const { jobId, promise } = downloadFile({
    fromUrl,
    toFile,
    resumable: (res) => {
      handleCancel();
      handleFinish();
    },
  });

  const result = await promise;

  // ...

} catch (error) {
  handleCancel();
} finally {
  handleFinish();
}

This works pretty well, but the promise will remain unresolved and unrejected, which feels like a memory leak.

Maybe a good compromise is to keep the current behaviour if resumable is set, and if it is not set, reject the promise when the download is stopped.

@Alatius Alatius linked a pull request Sep 19, 2024 that will close this issue
@birdofpreyru
Copy link
Owner

birdofpreyru commented Sep 19, 2024

Hi @Alatius , thanks for digging into it!

On your first message I though — great, let's adopt the PR from the upstream, an easy win!

On your second message, it seems, it deserves some thinking. My gut feeling tells — maybe reject the initial promise on stopDownload(), and modify resumeDownload() to return a new promise for the resumed download. Though, I'd look what NodeJS / other libraries do in similar scenarios, and copy the «mainstream» behavior.

I don't like your idea with different behavior dependent on resume value, because it feels very probable that someone makes use of stopDownload() without resume, wires some functionality to it, and then if he attempts to add «resume» feature down the line he'll probably bump into breaking his existing logic if the stopping feature behaves different when resume is enabled.

@birdofpreyru birdofpreyru added P2 Important issue. In Progress Work in progress. labels Sep 19, 2024
@Alatius
Copy link
Author

Alatius commented Sep 19, 2024

Yeah, it is a fair point that introducing changes in the behaviour risks breaking the implementation for some people, and maybe my suggestion is not the most elegant. I guess that the reverse situation to your scenario is also a possibility: that someone has implemented a resume functionality without making use of resumable. Then my proposal would break that code, as the promise will not be there anymore to handle the resume.

But if we want to minimize the risk of introducing breaking changes, I fear that the solution you suggest may equally, or even more, risk breaking current code, wouldn't it?

It seems to me that the root of the problem is that a method to actually fully cancel a download is strangely missing: the intention behind stopDownload() seems to be primarily to pause the download, until it can be resumed, and the original promise can finish. The situation where resume is not available (i.e. on Android) should then be seen as an exception, and is indeed treated as an error.

So maybe the proper solution is to introduce a new function, cancelDownload(), which always rejects the promise? (Or, alternatively, always resolves it with some informative message?) That way, nothing risks breaking, as no changes to the behaviour of current implementations are introduced. I have not looked more into other similar libraries however; as you say, it is probably a good idea to have similar logic to what people are accustomed to.

@birdofpreyru
Copy link
Owner

I mean, I have no problem with a breaking change between major/minor library versions, I was talking about changing the value of resume parameter while using the very same version of the library — if it will change the resolution/rejection behavior of stopDownload() promise, it would feel very unexpected and annoying to me.

@Alatius
Copy link
Author

Alatius commented Sep 20, 2024

Aha, yes, I think I understand your point now. But I wouldn't say that it changes stopDownload() per se. Rather, the way I look at it is that it would change the behaviour of the promise returned from downloadFile(): if resumable (note, not "resume") is not set (or "false") when calling downloadFile(), the download promise will not be "resumable", even on iOS, but will instead reject when stopDownload() is called. If resumable is set to a callback function (thus logically "true"), the download will be resumable (on the platform that supports it). This seems pretty logical, and what would be expected to me.

I am still not sure what solution is best though: all proposals mentioned (except for the old pull request I linked to in my first message) have their merits I think. To bring it in line with other similar libraries is probably the way to go, instead of reinventing wheels.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
In Progress Work in progress. On Hold Blocked for some reason. P2 Important issue.
Projects
None yet
Development

Successfully merging a pull request may close this issue.

2 participants