-
Notifications
You must be signed in to change notification settings - Fork 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
[WIP/Proposal] Add Stream/Iterator based versions of methods with paginated results #166
Conversation
Hi! Thanks a lot for the contribution. I definitely like the idea. It's a big step towards #124. Here are a few questions:
|
|
I'd prefer to have paginated API reachable. Sometimes it's good to have more low-level control over API calls than have an abstraction. For example, I want to keep a local database of track metadata and update it in batches from time to time. It's easier to do it if I'm able to ask API for a single page of tracks, the exact slice I want to update locally. With streaming API only it would be a little inconvenient and hacky. |
|
It's a great idea to have some new ergonomics API, but I have it's reasonable to keep the paginated API, since some developers use Maybe, we could add a new feature named |
I agree. Maybe this could be feature-gated. That way we can avoid the |
I've updated this PR to include the latest changes in Also, I think the module/feature name should be So, what's missing:
In my opinion, we should would only about the user experience. Using a feature for pagination doesn't really matter for compilation time/size; the important part is that they're easy to use. And we can't rely on default features either because users are expected to disable them when configuring a different client. I suggest we just create methods with I also tried to generalize the manual/iterator/stream behavior with types but we need GATs for that, so it's currently impossible. But it would have been great to just pass a Maybe I can open an issue to implement that in the future, once we have GATs? In that case we wouldn't even need the endpoint(ManualPaginator::new(50)); // Returns a Page over the return type of `endpoint`
endpoint(ManualPaginator::with_offset(50, 150)); // Same, but it can be configured to start at 150
endpoint(IterPaginator::new()); // Returns an iterator over the return type of `endpoint`
endpoint(StreamPaginator::new()); // Returns a stream over the return type of `endpoint` |
src/client.rs
Outdated
/// library. | ||
/// | ||
/// [Reference](https://developer.spotify.com/web-api/get-users-saved-tracks/) | ||
pub fn current_user_saved_tracks_stream( |
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.
After this PR merged, what's the next step? Planing to add a new method with _stream
suffix for each endpoint except current_user_saved_tracks
?
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.
That's what I was explaining and questioning in this comment - #166 (comment)
Seeing as there isn't anyone else giving their opinion I would just come to an agreement between you and I and just use 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.
I prefer _stream
suffix to _auto
suffix, since the latter one is not that self-explanatory as _stream
suffix, and stream
is defined as a sequence of elements supporting sequential and parallel aggregate operations in a we-all-know way, such as Java's Stream
and Rust's Future stream
.
And let me know what you think now :-)
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 but the thing is that _stream
might be confusing, as it returns an Iterator
when sync mode is enabled, and it returns a Stream
when async mode is enabled. _auto
works for both, and so does Paginator
, IMO. Perhaps there's a better alternative than _auto
, but my concern was that we were mixing up the async implementation with the generalized one.
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, I get you point! It makes sense. Perhaps there's indeed a better choice than _auto
. But in this moment, no clue comes to my mind
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.
By the way, I am thinking about is it possible to generate the new method with _stream or _auto suffix by macro, since the code pattern is similar.
This is non-trivial to implement because of generic types in functions. A macro that takes these into account is quite complicated and not worth the effort in this case, unfortunately.
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.
There is another suffix name came to my mind, _range
suffix, inspiration from C++ Range library :)
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.
Here's another idea I added to my comment, which I modified: what if the endpoints are automatically paginated by default, and you can use the _manual
-suffixed endpoints in case you want more control over them? It's a saner default, as most times you just want an iterator, and we solve the naming issue pretty easily :)
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, it makes much sense. We could make the endpoints paginated by default, since the developers want iterator at most times as you point out. My concern is that if we change all manual endpoints to be paginated and then add a _manual
suffix for the original one, then we will change the function signature of all endpoints, it does break the compatibility.
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.
Lol we're completely breaking compatibility with this release anyway haha
ff8a429
to
6eef453
Compare
6eef453
to
941c096
Compare
Nooo @ramsayleung don't merge this! It was only a showcase of how it should work. I still had to implement the rest of the endpoints and use |
Anyway, I'll just open a new PR. |
Ooooh, I though this PR is a prototype, and it's ready to merge, my fault :( It seems the works has been moved to this #201 PR, then we need to switch to this PR. |
Yup, don't worry. I'll finish everything there and after we're done with that we can finally work on the auth rewrite! |
Note, this currently only implements the streaming version for one method to avoid wasting work until we're certain of the design.
Description
Adds an alternative version of methods that return paginated results, providing instead an
Iterator
orStream
(forsync
/async
respectively)Motivation and Context
Manually iterating over paginated results is pretty annoying to do, by providing an streaming alternative we can make this a lot easier for consumers of the api.
Dependencies
New dependencies:
Stream
traitType of change
How Has This Been Tested?
Added examples using the new methods and running them