1- //go:build go1.22 && goexperiment.rangefunc
2- // +build go1.22,goexperiment.rangefunc
1+ //go:build go1.23
2+ // +build go1.23
33
44package gitlab
55
66import (
77 "iter"
88)
99
10- // PageIterator is an EXPERIMENTAL iterator as defined in the "rangefunc" experiment for go 1.22.
11- // See https://go.dev/wiki/RangefuncExperiment for more details.
12- //
13- // It can be used as:
10+ // Paginatable is the type implemented by list functions that return paginated
11+ // content (e.g. [UsersService.ListUsers]).
12+ // It works for top-level entities (e.g. users). See [PaginatableForID] for
13+ // entities that require a parent ID (e.g. tags).
14+ type Paginatable [O , T any ] func (* O , ... RequestOptionFunc ) ([]* T , * Response , error )
15+
16+ // AllPages is a [iter.Seq2] iterator to be used with any paginated resource.
17+ // E.g. [UsersService.ListUsers]
1418//
15- // for user, err := range gitlab.PageIterator (gl.Users.List , nil) {
19+ // for user, err := range gitlab.AllPages (gl.Users.ListUsers , nil) {
1620// if err != nil {
1721// // handle error
1822// }
1923// // process individual user
2024// }
21- func PageIterator [O , T any ](f Paginatable [O , T ], opt * O , optFunc ... RequestOptionFunc ) iter.Seq2 [* T , error ] {
25+ //
26+ // It is also possible to specify additional pagination parameters:
27+ //
28+ // for mr, err := range gitlab.AllPages(
29+ // gl.MergeRequests.ListMergeRequests,
30+ // &gitlab.ListMergeRequestsOptions{
31+ // ListOptions: gitlab.ListOptions{
32+ // PerPage: 100,
33+ // Pagination: "keyset",
34+ // OrderBy: "created_at",
35+ // },
36+ // },
37+ // gitlab.WithContext(ctx),
38+ // ) {
39+ // // ...
40+ // }
41+ //
42+ // Errors while fetching pages are returned as the second value of the iterator.
43+ // It is the responsibility of the caller to handle them appropriately, e.g. by
44+ // breaking the loop. The iteration will otherwise continue indefinitely,
45+ // retrying to retrieve the erroring page on each iteration.
46+ func AllPages [O , T any ](f Paginatable [O , T ], opt * O , optFunc ... RequestOptionFunc ) iter.Seq2 [* T , error ] {
2247 return func (yield func (* T , error ) bool ) {
2348 nextLink := ""
2449 for {
2550 page , resp , err := f (opt , append (optFunc , WithKeysetPaginationParameters (nextLink ))... )
2651 if err != nil {
27- yield (nil , err )
28- return
52+ if ! yield (nil , err ) {
53+ return
54+ }
55+ continue
2956 }
3057 for _ , p := range page {
3158 if ! yield (p , nil ) {
@@ -40,10 +67,16 @@ func PageIterator[O, T any](f Paginatable[O, T], opt *O, optFunc ...RequestOptio
4067 }
4168}
4269
43- // PageIteratorForID is similar to [PageIterator] but for paginated resources that require a parent ID (e.g. tags of a project).
44- func PageIteratorForID [O , T any ](id any , f PaginatableForID [O , T ], opt * O , optFunc ... RequestOptionFunc ) iter.Seq2 [* T , error ] {
70+ // PaginatableForID is the type implemented by list functions that return
71+ // paginated content for sub-entities (e.g. [TagsService.ListTags]).
72+ // See also [Paginatable] for top-level entities (e.g. users).
73+ type PaginatableForID [O , T any ] func (any , * O , ... RequestOptionFunc ) ([]* T , * Response , error )
74+
75+ // AllPagesForID is similar to [AllPages] but for paginated resources that
76+ // require a parent ID (e.g. tags of a project).
77+ func AllPagesForID [O , T any ](id any , f PaginatableForID [O , T ], opt * O , optFunc ... RequestOptionFunc ) iter.Seq2 [* T , error ] {
4578 idFunc := func (opt * O , optFunc ... RequestOptionFunc ) ([]* T , * Response , error ) {
4679 return f (id , opt , optFunc ... )
4780 }
48- return PageIterator (idFunc , opt , optFunc ... )
81+ return AllPages (idFunc , opt , optFunc ... )
4982}
0 commit comments