-
Notifications
You must be signed in to change notification settings - Fork 2.1k
Feature Request: Pagination Handlers #2618
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
Comments
Hi @xorima ! Yes, there is interest - see #1935 - but note that that issue was closed due to lack of volunteers. 😄 Also note that many endpoints handle pagination differently due to the organic growth of the GitHub v3 API. If you could come up with a way to support paginating through all results that supports all the different kinds of pagination schemes, that would be great. However, there is also one slightly tricky part - spoken from experience - and that is that you MUST respect the rate limits (or risk your access token being blocked for a period of "cool off" time). This means that the rate limit values must be monitored during your pagination and you must ensure that you let your pagination loop cool down if you get close to exceeding the rate limits. With all that in mind, you are welcome to put together a PR and we can explore this topic further. Thank you, @xorima ! |
Adding complexity to the discussion:
IMO #1 is a must-have for the feature (to avoid breaking backward compatibility), whilst #2 and #3 aren't, but would make the built-in pagination feature relevant only for some specific use cases. Finally, sharing a handler that can be used on a per-request basis (given the current status - without the pagination feature):
which is then used like that:
p.s. @gofri is my personal account. |
Thanks for the criteria @gal-legit, I think it's very solid. My initial idea was to have a separate function to call to have it auto handle pagiantion, similar to how the I am aiming to go with a version 1 works, version 2 works better approach, so I suspect whatever I include in v1 will change a lot by the time we are calling this ready to go. I should be able to get something up next week with it being CNY out here so I have plenty of time off to focus on this |
@xorima hi, just checking to see if you have been able to make any progress on the pagination helpers. i would be interested in helping. |
So I know I've been poor at responding on this. Still need more tests on it before I'm happy to contribute it into the codebase but it's here for comments on design and approach.
|
Correct me if I'm wrong, but this could easily reside in an external repo, right? |
that's what I'm thinking, making it an external repo people can use and then a conversation about joining it into the main repo in future when go 1.18 is the base requirements for other reasons |
Repository is up now: https://github.com/xorima/go-api-pagination note: the repo itself may be moved in a few weeks while I go through some work processes to have it as part of the main foss offerings from $dayjob |
Hey, looks great, @xorima ! I'll leave this issue open for you to create a PR that will update the |
hey, I know it's been a while and the pagination wrapper-function probably work fine for many users, |
I had a few hours today and I made some progress. Mainly, I solved merging the response json arrays/dictionaries in a smooth manner, so I only have to add the pagination headers stuff and glue it together to get a basic round-tripper going. In that context, I have a sort of a legal question. |
NOTE: I am NOT a lawyer and I do NOT speak for Google, so I cannot officially answer this question. However, in my humble opinion (that you can take with a grain of salt), it seems totally reasonable to me (with my limited understanding of the BSD license) to copy the function with a GitHub permalink comment added that says where you copied it from and also the exact phrase So, for example, it might look like this:
...and then concatenate this repo's LICENSE file to the end of your own repo's LICENSE file ... thereby your LICENSE file would actually contain two complete license declarations. Does that make sense? |
Reading my reply, maybe |
@gmlewis makes total sense, that's exactly what I was thinking would be appropriate. Thanks! |
So I have a first version going and it seems to work well: p.s. @gmlewis, it turned out that I couldn't use the discussed code after all. The implementation here sort of relies on the user to pick the right field from the response and place it in the relevant field for the specific request. p.s.2. now that I'm deep in the ocean of pagination, I think I can add some useful explanation to the readme (e.g., for the "since" param). do you think it's worth a PR? p.s.3. I'd be glad to add a reference to go-github-pagination to the README here, once I finish the extra bits I want the round tripper to have. let me know if that sounds ok. |
Hey @gofri - looks great! (I might try to reduce the stutter by rearranging the directories a bit and put unit tests within the same dir as the code, but those are really nit issues, so take that with a grain of salt.)
No problem.
Sure, improvements to our documentation are always welcome. If you are talking about your repo's README, then it probably wouldn't hurt.
Sure, improvements to our documentation are always welcome. Thank you, @gofri ! |
@gmlewis thanks ! :)
Actually I was referring to the README of this repo. |
You know that you can keep it in the same directory by changing the package from "package mypackage" to "package mypackage_test", right? |
@gmlewis I do now 😅 (and feel real stupid lol, I didn't know about the {pkg_name}_test exception for package name collisions) |
No worries! I learn new stuff every day, and hopefully will continue that trend. 😄 |
Hey all (@jnewland , @xorima , @danriedl)
I attached a sample for using the async wrapper with go-github below.
|
Fantastic @danielhochman I've also finally moved my variant to the final location: https://github.com/hsbc/go-api-pagination @gmlewis are you happy for an update to the readme pointing to the two different pagination handler options out there for this repository? |
Yes, absolutely, I think that makes sense. |
Looked at both repos mentioned here and wasn't too happy with their complexity and that all data would be fetched in one go. Using this in my project (ofc adding func Paginate1[T, O, V1 any](
ctx context.Context,
fn func(context.Context, V1, *O) ([]*T, *github.Response, error),
v1 V1,
opts *O,
perPage int,
) iter.Seq2[*T, error] {
if opts == nil {
opts = new(O)
}
return func(yield func(*T, error) bool) {
page := 1
for {
v := reflect.ValueOf(opts).Elem()
v.FieldByName("Page").Set(reflect.ValueOf(page))
v.FieldByName("PerPage").Set(reflect.ValueOf(perPage))
results, resp, err := fn(ctx, v1, opts)
if err != nil {
yield(nil, err)
return
}
for _, item := range results {
if !yield(item, nil) {
return
}
}
if resp.NextPage == 0 {
return
}
page = resp.NextPage
}
}
} And an example of consuming using this: repoIter := Paginate1(
ctx,
os.rest.Repositories.ListByOrg,
"foo-bar-baz",
&github.RepositoryListByOrgOptions{Sort: "full_name"},
)
for repo, err := range repoIter {
if err != nil {
return fmt.Errorf("failed to list repositories: %w", err)
}
fmt.Println(repo.GetName())
} Haven't tested it with all endpoints, but quite a few at this point. handling rate limiting through the HTTP client automatically. |
Hey 👋
I notice how most resources already have a way of handling pagination but we leave it to the users to implement the pagination methods themseleves.
Would it be to use to have additional appropriate functions/methods to handle the pagination for the user, so they can just focus on the data they want to get back and not how to handle the pagination. (potentially with some offsets/config for max objects returned)
I'm happy to code this up, just after feedback if this is a feature people want
The text was updated successfully, but these errors were encountered: