-
Notifications
You must be signed in to change notification settings - Fork 215
Support non exception errors from fetcher #123
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
Conversation
| */ | ||
| fun disableCache(): StoreBuilder<Key, Output> | ||
|
|
||
| fun<UnwrappedOutput> fetcherTransformer(fetcherTransformer: (Output) -> FetcherResult<UnwrappedOutput>) |
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.
Ignore anything in this file aside from this line. Everything bellow is a mess that I didn't want to get into before we decide this is the way to go.
I think the only scalable way to add support to another generic type changing parameter (like source of truth) would be for change the builder API it only receive the source of truth in the constructor.
Aside from builder changes (and tests) all the other changes needed to support this change are in the PR (and are pretty minimal)
yigit
left a comment
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.
Just a quick look from the phone.
| origin = ResponseOrigin.Fetcher | ||
| ) | ||
| } | ||
| }.catch { |
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 in this new world, it should crash the whole flow and hopefully the app
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.
This change is only intended to allow the use of a wider variety of fetchers. Why do you think we should change the behavior of Store? In general we don't propagate exceptions but concert then to errors, why would this change affect this?
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.
because in the previous API, they can only return values hence we have to catch exceptions for errors.
In this new world, they get the ability to return errors so any exception can be considered exceptional. FYI this is also what paging does but we are considering options to maybe catch IO Exceptions by default to be more pragmatic.
A reason to opt into this new API would be to catch errors like NPE's and if we eat them, it would probably make people unhappy.
| */ | ||
| fun disableCache(): StoreBuilder<Key, Output> | ||
|
|
||
| fun<UnwrappedOutput: Any> fetcherTransformer(fetcherTransformer: (Output) -> FetcherResult<UnwrappedOutput>) |
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.
Would store response work here? Or is it too generic?
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.
Store response has an origin, which I don't want to let users override.
|
Sorry this was open for so long. finally got around to finish it. Note that this would be a major API change for how we build store (but no change to Store's API itself). |
|
the tl;dr of the api change is that you have to pass a source of truth when you create a builder rather than later: |
Codecov Report
@@ Coverage Diff @@
## master #123 +/- ##
=========================================
Coverage ? 83.04%
Complexity ? 229
=========================================
Files ? 48
Lines ? 973
Branches ? 145
=========================================
Hits ? 808
Misses ? 109
Partials ? 56
Continue to review full report at Codecov.
|
Codecov Report
@@ Coverage Diff @@
## master #123 +/- ##
============================================
- Coverage 84.19% 83.49% -0.71%
Complexity 242 242
============================================
Files 45 45
Lines 949 957 +8
Branches 151 147 -4
============================================
Hits 799 799
- Misses 95 104 +9
+ Partials 55 54 -1
Continue to review full report at Codecov.
|
|
(still need to add a couple of tests here, will add soon hopefully) |
|
@yigit @digitalbuddha this is now ready for review - it looks bigger than it is because of the changes to the builder's interface (and exposing sourceOfTruth through the interface) |
|
Sorry i didn't have time to check this, planning to do it now. Does it make sense to also make the fetcher a class instead of a function? That could help w/ two things: I just wanted to ask in case you've already evaluated that option. |
yigit
left a comment
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'm not rally super happy with this change. i think it creates a lot of API load.
I'll try to prototype the Fetcher as a class idea where we can make it something that always retturns value or error and then provide a wrapper that returns the value type which we will catch exceptions.
I would like to know if you've already tried that though.
| val adapter = moshi.adapter<RedditConfig>(RedditConfig::class.java) | ||
| return StoreBuilder | ||
| .fromNonFlow<Unit, RedditConfig> { | ||
| .fromNonFlow<Unit, RedditConfig, RedditConfig> (fetcher = { |
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.
this was something we tried to avoid in the new store builder. is it required now?
build.gradle
Outdated
|
|
||
| ext.versions = [ | ||
| androidGradlePlugin : '4.0.0-beta01', | ||
| androidGradlePlugin : '3.6.0', |
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.
not important but probably better to use 3.6.1 ?
store/src/main/java/com/dropbox/android/external/store4/SourceOfTruth.kt
Show resolved
Hide resolved
| * WARNING: Delete operation is not supported when using a legacy [com.dropbox.android.external.store4.Persister], | ||
| * please use another override | ||
| */ | ||
| fun <Key, Output> fromLegacyPresister( |
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.
should we mark this deprecated?
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.
or delete it, we're still in alpha
| */ | ||
| fun <Key : Any, RawOutput : Any, Output : Any> fromNonFlow( | ||
| fetcher: suspend (key: Key) -> RawOutput, | ||
| fetcherTransformer: (RawOutput) -> FetcherResult<Output> |
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.
this is a bit weird., why cant it just provide a FetcherResponse? Name conflict?
| /** | ||
| * Creates a new [StoreBuilder] from a [Flow] fetcher. | ||
| * | ||
| * Use when creating a [Store] that fetches objects in an websocket-like multiple responses |
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.
websocket seems weird example as people may not be able to relate to it (i might be wrong). Maybe we can use firebase as an example instead?
| origin = ResponseOrigin.Fetcher | ||
| ) | ||
| } | ||
| }.catch { |
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.
because in the previous API, they can only return values hence we have to catch exceptions for errors.
In this new world, they get the ability to return errors so any exception can be considered exceptional. FYI this is also what paging does but we are considering options to maybe catch IO Exceptions by default to be more pragmatic.
A reason to opt into this new API would be to catch errors like NPE's and if we eat them, it would probably make people unhappy.
|
created #139 to make discussions easier. unlike this one, it is not a complete PR. |
|
Sorry for dropping off here. It's been hard to find OSS time in the last few weeks with the shelter in place and all. #139 seems good to me. I put a comment around the fetcher's API. I'll try to integrate those changes into this revision over the next week of so, but feel free to finish up #139 you feel like it and if I'm taking too long. |
store/src/main/java/com/dropbox/android/external/store4/impl/FetcherController.kt
Outdated
Show resolved
Hide resolved
store/src/main/java/com/dropbox/android/external/store4/impl/RealSourceOfTruth.kt
Show resolved
Hide resolved
yigit
left a comment
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 overall is good, thank you. just small comments.
store-rx2/src/main/kotlin/com/dropbox/store/rx2/RxSourceOfTruth.kt
Outdated
Show resolved
Hide resolved
store-rx2/src/main/kotlin/com/dropbox/store/rx2/RxSourceOfTruth.kt
Outdated
Show resolved
Hide resolved
store/src/main/java/com/dropbox/android/external/store4/Fetcher.kt
Outdated
Show resolved
Hide resolved
store/src/main/java/com/dropbox/android/external/store4/Fetcher.kt
Outdated
Show resolved
Hide resolved
store/src/main/java/com/dropbox/android/external/store4/StoreResponse.kt
Show resolved
Hide resolved
store/src/main/java/com/dropbox/android/external/store4/StoreResponse.kt
Outdated
Show resolved
Hide resolved
store/src/main/java/com/dropbox/android/external/store4/impl/FetcherController.kt
Outdated
Show resolved
Hide resolved
store/src/test/java/com/dropbox/android/external/store4/impl/TransformingFetcherTest.kt
Outdated
Show resolved
Hide resolved
|
@yigit Thanks for all the great feedback. This should be ready to go now. |
yigit
left a comment
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, just small nits.
thanks!
store/src/main/java/com/dropbox/android/external/store4/Fetcher.kt
Outdated
Show resolved
Hide resolved
store/src/main/java/com/dropbox/android/external/store4/SourceOfTruth.kt
Outdated
Show resolved
Hide resolved
store/src/main/java/com/dropbox/android/external/store4/SourceOfTruth.kt
Outdated
Show resolved
Hide resolved
| */ | ||
| interface SourceOfTruth<Key, Input, Output> { | ||
| val defaultOrigin: ResponseOrigin |
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.
| val defaultOrigin: ResponseOrigin | |
| /** | |
| * The data origin value which will be reported in [StoreResponse.origin]. For instance, if the SourceOfTruth keeps | |
| * the data on disk, this value should be [ResponseOrigin.Persister]. | |
| */ | |
| val defaultOrigin: ResponseOrigin |
store/src/main/java/com/dropbox/android/external/store4/SourceOfTruth.kt
Outdated
Show resolved
Hide resolved
store/src/main/java/com/dropbox/android/external/store4/SourceOfTruth.kt
Outdated
Show resolved
Hide resolved
store/src/main/java/com/dropbox/android/external/store4/SourceOfTruth.kt
Outdated
Show resolved
Hide resolved
store/src/main/java/com/dropbox/android/external/store4/StoreResponse.kt
Show resolved
Hide resolved
| override val defaultOrigin = | ||
| ResponseOrigin.Persister |
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.
| override val defaultOrigin = | |
| ResponseOrigin.Persister | |
| override val defaultOrigin = ResponseOrigin.Persister |
| override val defaultOrigin = | ||
| ResponseOrigin.Persister |
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.
| override val defaultOrigin = | |
| ResponseOrigin.Persister | |
| override val defaultOrigin = ResponseOrigin.Persister |
yigit
left a comment
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.
just a small nit, lgtm; Thanks!
store/src/main/java/com/dropbox/android/external/store4/Fetcher.kt
Outdated
Show resolved
Hide resolved
…r.kt Co-Authored-By: Yigit Boyar <[email protected]>
|
reverting #159 for now because it makes it impossible to update both the source and the sample in the same diff. Let's discuss bringing it back in an issue. there are pros and cons for it, but for now, while the API is unstable it's just to block us. FYI @DYJParker |
|
Just tagging @digitalbuddha in this, since he drove the change.
|
* Support non exception errors from fetcher * revert parital changes to store builder to reduce noise * finish off diff * Allow to create a FetcherResult.Error without a Throwable. Add tests * Add missing funcion and more tests * lint * unflake RxFlowableStoreTest * try to rename FakeFetcher to FakeRxFetcher to (maybe) solve missing codcov * move SourceOfTruth out of impl package * Rename accidental change of RxStoreBuilder.fromMaybe back to formSingle * Introduce Fetcher from MobileNativeFoundation#139 * fix Rx artifact * delete legacy presistor factory * fix api file * move fetcher to be a typealias * code review comments + clean up documentation * code review comments * Update store/src/main/java/com/dropbox/android/external/store4/Fetcher.kt Co-Authored-By: Yigit Boyar <[email protected]> * Revert "Update sample app's build.gradle to refer to the externally released version of Store (MobileNativeFoundation#159)" This reverts commit fc8da86. * update releasing.md Co-authored-by: Yigit Boyar <[email protected]>
Non-working PR to show the proposed way of adding support for allowing the fetcher to communicate errors not via exceptions.
The main complication here is in the builder API. we already have 2 builders because we support a builder with and without source of truth (to change to generic type). If we went this way we would either need to support 4 builder or we will need to change the builder API to force providing the source of truth (and the new translator) in the builder's constructor