-
Notifications
You must be signed in to change notification settings - Fork 5.9k
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
[file system][ios] Add download and upload in background #7380
[file system][ios] Add download and upload in background #7380
Conversation
f237602
to
dfcb8a0
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Generally looks good 👍
- Changelog entry and docs are missing 😞
- Would it be possible to add examples in NCL and add some tests?
Also some comments below 👇
packages/expo-file-system/ios/EXFileSystem/EXSessionTasks/EXSessionTaskDelegate.m
Outdated
Show resolved
Hide resolved
...es/expo-file-system/ios/EXFileSystem/EXSessionTasks/EXSessionResumableDownloadTaskDelegate.m
Outdated
Show resolved
Hide resolved
...es/expo-file-system/ios/EXFileSystem/EXSessionTasks/EXSessionResumableDownloadTaskDelegate.h
Outdated
Show resolved
Hide resolved
@tsapeta, I'll add an entry to the changelog and update docs in separate PR. It'll be difficult to add tests - we need a server to test upload functionality properly. However, I can add a session type switch to NCL. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Great job! 💯
Is it possible for you to create some python
or node
script that would allow us to test it? 😅
It would be nice to be sure it always works 🤔
packages/expo-file-system/ios/EXFileSystem/EXSessionTasks/EXSessionDownloadTaskDelegate.h
Outdated
Show resolved
Hide resolved
packages/expo-file-system/ios/EXFileSystem/EXSessionTasks/EXSessionDownloadTaskDelegate.h
Outdated
Show resolved
Hide resolved
packages/expo-file-system/ios/EXFileSystem/EXSessionTasks/EXSessionDownloadTaskDelegate.h
Outdated
Show resolved
Hide resolved
packages/expo-file-system/ios/EXFileSystem/EXSessionTasks/EXSessionDownloadTaskDelegate.m
Outdated
Show resolved
Hide resolved
packages/expo-file-system/ios/EXFileSystem/EXSessionTasks/EXSessionDownloadTaskDelegate.m
Outdated
Show resolved
Hide resolved
Sorry but I'm against adding changelog entries in different PRs - changelogs must always be updated together with a change that changed anything in module's behavior. We're going to use Danger.js to enforce changelog entries on all PRs so why should we make any exceptions before the actual Danger.js action is done? Let's say that before this happens, I'm the one who manually checks all these PRs 😃 |
1f65208
to
d6707e1
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Nice work! 👍
packages/expo-file-system/ios/EXFileSystem/EXSessionTasks/EXSessionDownloadTaskDelegate.h
Outdated
Show resolved
Hide resolved
packages/expo-file-system/ios/EXFileSystem/EXSessionTasks/EXSessionTaskDelegate.h
Outdated
Show resolved
Hide resolved
packages/expo-file-system/ios/EXFileSystem/EXSessionTasks/EXSessionTaskDelegate.h
Outdated
Show resolved
Hide resolved
...es/expo-file-system/ios/EXFileSystem/EXSessionTasks/EXSessionResumableDownloadTaskDelegate.h
Outdated
Show resolved
Hide resolved
packages/expo-file-system/ios/EXFileSystem/EXSessionTasks/EXSessionTaskDelegate.h
Outdated
Show resolved
Hide resolved
647bbd1
to
4596415
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Sorry it took me so long! Thank you for making the structure clear! Looking forward to reviewing it again!
packages/expo-file-system/android/src/main/java/expo/modules/filesystem/FileSystemModule.java
Show resolved
Hide resolved
@@ -48,6 +86,12 @@ export enum EncodingType { | |||
Base64 = 'base64', | |||
} | |||
|
|||
export enum FileSystemHttpMethods { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The conversation at #7380 (comment) has been resolved — was it by accident, or is it a strong decision to keep using enums for HTTP methods, or have I missed some discussion?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Nonetheless, I think this enum should be named with a singular form, i.e. FileSystemHttpMethod
.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Sorry, it was resolved by accident.
However, I think we should give the user the ability to change the HTTP method. And we can do it by using strings or enum. I prefer using enum - it is safer. If you strongly disagree with this, I can change it ;)
...es/expo-file-system/ios/EXFileSystem/EXSessionTasks/EXSessionResumableDownloadTaskDelegate.m
Show resolved
Hide resolved
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
LGTM 💯 I think we are ready to ship it once all concerns are resolved 😄
packages/expo-file-system/ios/EXFileSystem/EXSessionTasks/EXSessionUploadTaskDelegate.m
Outdated
Show resolved
Hide resolved
packages/expo-file-system/ios/EXFileSystem/EXSessionTasks/EXSessionUploadTaskDelegate.m
Outdated
Show resolved
Hide resolved
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🏅
packages/expo-file-system/ios/EXFileSystem/EXSessionTasks/EXSessionUploadTaskDelegate.m
Outdated
Show resolved
Hide resolved
packages/expo-file-system/ios/EXFileSystem/EXSessionTasks/EXSessionUploadTaskDelegate.m
Show resolved
Hide resolved
...es/expo-file-system/ios/EXFileSystem/EXSessionTasks/EXSessionResumableDownloadTaskDelegate.m
Show resolved
Hide resolved
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🙇
packages/expo-file-system/ios/EXFileSystem/EXSessionTasks/EXSessionUploadTaskDelegate.m
Outdated
Show resolved
Hide resolved
return [[NSFileManager defaultManager] fileExistsAtPath:path]; | ||
} | ||
|
||
- (NSString * _Nullable)_importHttpMethod:(NSNumber *)httpMethod |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think this is a fourth time I mention this concern, it somehow always gets discarded on push 😃 — how about accepting a string httpMethod
, like fetch
does?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I've commented on that here: #7380 (comment) ;)
Moreover, I don't like strings here, cause someone might pass get
- that will crash the app. So, it would be nice to have some kind of validations. And what if someone misspelled it.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
IMHO it would be best to:
try-catch
not to crash the app if a user passed aget
- throw an error with a helpful message if an invalid method has been passed in.
This would make sure we don't limit the developers if they wanted to use some other HTTP method that is supported we don't know of. But I don't have a very strong opinion, so I will defer to @bbarthec's opinion on that.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@lukmccall, I've discussed the thing with @sjchmiela and I think that going with fetch-like
approach is desirable: https://fetch.spec.whatwg.org/#methods
I suggest enforcing TS type: type AcceptedHttpMethod = 'POST' | 'PUT' | 'PATCH'
is sufficient guarding point, but later on let's go with String.toUpperCase()
anyway while passing arguments to native side.
Are there any consequences of passing method that is not expected, eg. CHICKEN
(I mean: are we semantically base on this value?)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Are there any consequences of passing method that is not expected, eg. CHICKEN (I mean: are we semantically base on this value?)
The task will be canceled by the system later on. Then we will reject the promise. So, I think that everything will work fine ;)
|
||
- (void)URLSession:(NSURLSession *)session task:(NSURLSessionTask *)task didCompleteWithError:(NSError *)error | ||
{ | ||
if (_isActive) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
So… since first we deactivate
the dispatcher and only then invalidateAndCancel
the sessions in EXFileSystem
's dealloc
, doesn't it mean that here we wouldn't act on tasks cancellation?
Is it the way we want to handle this? Don't we want to reject the Promise
, or inform of the termination?
This _isActive
logic seems too easy 😃.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yes, we deactivate the dispatcher before invalidateAndCancel
because we don't want to act on the task events.
We are in the middle of the deallocating of the react context. So, I believe we shouldn't reject the Promise or inform of the termination. Tasks will be canceled, but we don't know when.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Do you think that adding a separate invalidate
call to native modules would make it easier to handle this situation? If we invalidatedAndCancelled
sessions while invalidating modules maybe the task:didCompleteWithError:
would be called in time before deallocating the bridge and a Promise rejection would come through? If this would be the case I think it could be worth to implement it… 🤔
packages/expo-file-system/ios/EXFileSystem/EXSessionTasks/EXSessionTaskDispatcher.h
Outdated
Show resolved
Hide resolved
35e2394
to
937d247
Compare
return [[NSFileManager defaultManager] fileExistsAtPath:path]; | ||
} | ||
|
||
- (NSString * _Nullable)_importHttpMethod:(NSNumber *)httpMethod |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
IMHO it would be best to:
try-catch
not to crash the app if a user passed aget
- throw an error with a helpful message if an invalid method has been passed in.
This would make sure we don't limit the developers if they wanted to use some other HTTP method that is supported we don't know of. But I don't have a very strong opinion, so I will defer to @bbarthec's opinion on that.
...es/expo-file-system/ios/EXFileSystem/EXSessionTasks/EXSessionResumableDownloadTaskDelegate.m
Outdated
Show resolved
Hide resolved
packages/expo-file-system/ios/EXFileSystem/EXSessionTasks/EXSessionTaskDispatcher.m
Outdated
Show resolved
Hide resolved
...es/expo-file-system/ios/EXFileSystem/EXSessionTasks/EXSessionResumableDownloadTaskDelegate.h
Outdated
Show resolved
Hide resolved
packages/expo-file-system/ios/EXFileSystem/EXSessionTasks/EXResumablesManager.h
Outdated
Show resolved
Hide resolved
|
||
- (void)URLSession:(NSURLSession *)session task:(NSURLSessionTask *)task didCompleteWithError:(NSError *)error | ||
{ | ||
if (_isActive) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Do you think that adding a separate invalidate
call to native modules would make it easier to handle this situation? If we invalidatedAndCancelled
sessions while invalidating modules maybe the task:didCompleteWithError:
would be called in time before deallocating the bridge and a Promise rejection would come through? If this would be the case I think it could be worth to implement it… 🤔
I think, this a good idea in general. However, I'm not sure if this helps here. Maybe we can reject all promises before the react context dies, but I don't think we need this in that particular case. Moreover, the js code will not know what causes rejection. So, the user could write a code that retries the download and this will cause bugs - the |
...es/expo-file-system/ios/EXFileSystem/EXSessionTasks/EXSessionResumableDownloadTaskDelegate.m
Outdated
Show resolved
Hide resolved
...es/expo-file-system/ios/EXFileSystem/EXSessionTasks/EXSessionResumableDownloadTaskDelegate.m
Outdated
Show resolved
Hide resolved
packages/expo-file-system/ios/EXFileSystem/EXSessionTasks/EXSessionDownloadTaskDelegate.m
Outdated
Show resolved
Hide resolved
So, to sum up, the only updates we drop are download/upload progress updates which happened after What I'm worried about is the scenario when a developer manages the downloads depending on the callbacks, so eg.:
Is this how one would use the |
d3ebdc9
to
9af4920
Compare
* [file-system] make downloadAsync work in backgroud * [file-system] Upload method * [file-system] Add body to response * [file-system] Refactor * [file system] Handle resumable downloads * [file system] Add background/foreground option * [file system] Make background session default * [file system] Apply requested changes * [file system] Fix typo * [file system] Apply requested changes * [file system] Add changelog * [expo-file-system] Apply requested changes * [expo-file-system] Fix session lifetime * [expo-file-system] Refactor * [expo-file-system] Fix headers * [expo-file-system] Apply requested changes * [expo-file-system] Fix lifetime of EXFileSystem * [expo-file-system] Extract resumables manger * [expo-file-system] Pass body safely * [expo-file-system] Pod install * [expo-file-system] Apply requested changes * [expo-file-system] Apply requested changes * [expo-file-system] Apply requested changes * [expo-file-system] Pod install in bare-expo * [expo-file-system] EXResumableManager -> EXResumablesManager * [expo-file-system] Fix error codes
Why
Part of #5841.
How
NSURLSessionUploadTask
andNSURLSessionDownloadTask
ToDo
pod install
in bare expoTest Plan