[bugfix] further paging mishaps (#2884)

* FURTHER paging shenanigans 🥲

* remove cursor logic from ToLinkURL()

* fix up paging tests

---------

Co-authored-by: tobi <tobi.smethurst@protonmail.com>
This commit is contained in:
kim
2024-04-30 15:22:23 +01:00
committed by GitHub
parent ec7c983e46
commit a8254a40e7
5 changed files with 163 additions and 138 deletions

View File

@@ -54,6 +54,13 @@ func EitherMinID(minID, sinceID string) Boundary {
the cursor value, and max_id provides a
limiting value to the results.
But to further complicate it...
The "next" and "prev" relative links provided
in the link header are ALWAYS DESCENDING. Which
means we will ALWAYS provide next=?max_id and
prev=?min_id. *shakes fist at mastodon api*
*/
switch {
case minID != "":
@@ -67,7 +74,12 @@ func EitherMinID(minID, sinceID string) Boundary {
// SinceID ...
func SinceID(sinceID string) Boundary {
return Boundary{
Name: "since_id",
// even when a since_id query is
// provided, the next / prev rel
// links are DESCENDING with
// next:max_id and prev:min_id.
// so ALWAYS use min_id as name.
Name: "min_id",
Value: sinceID,
Order: OrderDescending,
}

View File

@@ -202,8 +202,9 @@ func Page_PageFunc[WithID any](p *Page, in []WithID, get func(WithID) string) []
return in
}
// Next creates a new instance for the next returnable page, using
// given max value. This preserves original limit and max key name.
// Prev creates a new instance for the next returnable page, using
// given max value. This will always assume DESCENDING for Mastodon
// API compatibility, but in case of change it can support both.
func (p *Page) Next(lo, hi string) *Page {
if p == nil || lo == "" || hi == "" {
// no paging.
@@ -216,25 +217,22 @@ func (p *Page) Next(lo, hi string) *Page {
// Set original limit.
p2.Limit = p.Limit
if p.order().Ascending() {
// When ascending, next page
// needs to start with min at
// the next highest value.
p2.Min = p.Min.new(hi)
p2.Max = p.Max.new("")
} else {
// When descending, next page
// needs to start with max at
// the next lowest value.
p2.Min = p.Min.new("")
p2.Max = p.Max.new(lo)
}
// NOTE:
// We ALWAYS assume the order
// when creating next / prev
// links is DESCENDING. It will
// always use prev: ?max_name
p2.Min = p.Min.new("")
p2.Max = p.Max.new(lo)
p2.Min.Order = OrderDescending
p2.Max.Order = OrderDescending
return p2
}
// Prev creates a new instance for the prev returnable page, using
// given min value. This preserves original limit and min key name.
// given min value. This will always assume DESCENDING for Mastodon
// API compatibility, but in case of change it can support both.
func (p *Page) Prev(lo, hi string) *Page {
if p == nil || lo == "" || hi == "" {
// no paging.
@@ -247,19 +245,15 @@ func (p *Page) Prev(lo, hi string) *Page {
// Set original limit.
p2.Limit = p.Limit
if p.order().Ascending() {
// When ascending, prev page
// needs to start with max at
// the next lowest value.
p2.Min = p.Min.new("")
p2.Max = p.Max.new(lo)
} else {
// When descending, next page
// needs to start with max at
// the next lowest value.
p2.Min = p.Min.new(hi)
p2.Max = p.Max.new("")
}
// NOTE:
// We ALWAYS assume the order
// when creating next / prev
// links is DESCENDING. It will
// always use prev: ?min_name
p2.Min = p.Min.new(hi)
p2.Max = p.Max.new("")
p2.Min.Order = OrderDescending
p2.Max.Order = OrderDescending
return p2
}
@@ -289,27 +283,14 @@ func (p *Page) ToLinkURL(proto, host, path string, queryParams url.Values) *url.
queryParams = cloneQuery(queryParams)
}
var cursor string
// Depending on page ordering, the
// page will be cursored by either
// the min or max query parameter.
if p.order().Ascending() {
cursor = p.Min.Name
} else {
cursor = p.Max.Name
if p.Min.Value != "" {
// Set page-minimum cursor value.
queryParams.Set(p.Min.Name, p.Min.Value)
}
if cursor != "" {
if p.Min.Value != "" {
// Set page-minimum cursor value.
queryParams.Set(cursor, p.Min.Value)
}
if p.Max.Value != "" {
// Set page-maximum cursor value.
queryParams.Set(cursor, p.Max.Value)
}
if p.Max.Value != "" {
// Set page-maximum cursor value.
queryParams.Set(p.Max.Name, p.Max.Value)
}
if p.Limit > 0 {