-
Notifications
You must be signed in to change notification settings - Fork 31
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
Common design for PaginatedResult-related methods #278
Comments
Replying to @lmars at #206 (comment):
This has a number of issues:
So, here's my proposal. Idiomatic PaginatedResultThe specified API for PaginatedResult is:
A direct translation to Go would be: type PaginatedResult[T] interface {
Items() []T
First(context.Context) (PaginatedResult[T], error)
HasNext() bool
IsLast() bool
Next(context.Context) (PaginatedResult[T], error) // io.EOF-like error
} If you just wanted to iterate all items from all pages, you'd use it maybe like: for r, err := rest.Foo(ctx, ...); err == nil; r, err = r.Next(ctx) {
for _, item := range r.Items() {
...
}
}
if !errors.Is(err, ably.EndOfPages) { // or similar
...
} This is pretty awkward. I think something like this would be more idiomatic: // Explicitly going through each page.
pages := rest.Foo(...)
for pages.Next(ctx) {
for _, item := range pages.Items() {
...
}
}
if err := r.Err(); err != nil {
...
}
// Paging implicit; just iterate over items.
items := rest.Foo(...).Items()
for items.Next(ctx) {
item := items.Item()
...
}
if err := r.Err(); err != nil {
...
} This is more in line with the stdlib, e. g. database/sql#DB.Query, bufio#Scanner. Generics, or lack thereofSo, obviously, another issue with the above is that Go doesn't have generics (yet). We actually have a couple precedents for generic types: EventEmitter (Channel, Connection) and Channels (Realtime, REST). So I think we should do the same for all instances of PaginatedResult: have separate types for each with the same interface, except for the item type. That is: Stats, Message, PresenceMessage, and JsonObject (this one embedded in in HTTPPaginatedResponse, and which I'd just leave as json.RawMessage). Query parametersSpec:
Given we have mostly optional parameters, we should follow the optional parameters pattern as defined in #197 (example). Each method would have its own |
@tcard this is great! I support this, the only thing I would say is that I think the initial call should return an error. So rather than: pages := rest.Foo(...) it would be: pages, err := rest.Foo(...) Reasons for this:
|
That sounds reasonable, the counterargument being that bufio.Scanner does the opposite and that having to check the error twice is more verbose and maybe makes it more likely that the second check is ignored. But no strong preferences either way. |
#278 The innards of paginated result handling have been simplified too. (Only for stats; once all paginated results are refactored, the old handling code can be removed and the "New" suffixes dropped.)
#278 The innards of paginated result handling have been simplified too. (Only for stats; once all paginated results are refactored, the old handling code can be removed and the "New" suffixes dropped.)
#278 The innards of paginated result handling have been simplified too. (Only for stats; once all paginated results are refactored, the old handling code can be removed and the "New" suffixes dropped.)
Continue this discussion.
The text was updated successfully, but these errors were encountered: