-
Notifications
You must be signed in to change notification settings - Fork 5
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
feat: enable referrers pagination #56
Conversation
Signed-off-by: wangxiaoxuan273 <[email protected]>
Codecov Report
@@ Coverage Diff @@
## main #56 +/- ##
==========================================
- Coverage 56.27% 56.14% -0.14%
==========================================
Files 108 108
Lines 11239 11266 +27
==========================================
Hits 6325 6325
- Misses 4202 4229 +27
Partials 712 712
Help us with your feedback. Take ten seconds to tell us how you rate us. Have a feature suggestion? Share it here. |
registry/handlers/referrers.go
Outdated
// query parameter. The default page size is 100. | ||
pageSize, nParseError := strconv.Atoi(r.URL.Query().Get("n")) | ||
if nParseError != nil || pageSize < minPageSize || pageSize > maxPageSize { | ||
pageSize = maxPageSize |
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.
We may want to make the default size to 10
, which is common.
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.
Changed maxPageSize
to 10.
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.
You should have three constants.
constant (
pageSizeMin = 1
pageSizeDefault = 10
pageSizeMax = 100
)
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.
Added the three constants.
registry/handlers/referrers.go
Outdated
@@ -80,6 +97,19 @@ func (h *referrersHandler) GetReferrers(w http.ResponseWriter, r *http.Request) | |||
referrers = []v1.Descriptor{} | |||
} | |||
|
|||
// only consider pagination if # of referrers is greater than page size | |||
if len(referrers) > pageSize { |
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.
This if
statement is redundant.
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.
deleted.
registry/handlers/referrers.go
Outdated
} | ||
|
||
// extract the page number info. | ||
pageNumber, _ := strconv.Atoi(r.URL.Query().Get("p")) |
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.
The pageNumber
is not validated. What if it is negative?
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.
Added the validation. Negative pageNumber
would make startIndex
invalid.
registry/handlers/referrers.go
Outdated
if artifactType != "" { | ||
url = fmt.Sprintf("%s&artifactType=%s", url, artifactType) | ||
} |
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.
You may consider to use url.Value
since artifactType
may contain special characters like /
.
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.
Used url.Values
here. Thanks for this good advice.
Signed-off-by: wangxiaoxuan273 <[email protected]>
registry/handlers/referrers.go
Outdated
// query parameter. The default page size is 100. | ||
pageSize, nParseError := strconv.Atoi(r.URL.Query().Get("n")) | ||
if nParseError != nil || pageSize < minPageSize || pageSize > maxPageSize { | ||
pageSize = maxPageSize |
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.
You should have three constants.
constant (
pageSizeMin = 1
pageSizeDefault = 10
pageSizeMax = 100
)
registry/handlers/referrers.go
Outdated
} | ||
|
||
// extract the page number info. | ||
pageNumber, pParseError := strconv.Atoi(r.URL.Query().Get("p")) |
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.
We don't need to name each error with a different name.
pageNumber, pParseError := strconv.Atoi(r.URL.Query().Get("p")) | |
pageNumber, err:= strconv.Atoi(r.URL.Query().Get("p")) |
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.
changed accordingly.
registry/handlers/referrers.go
Outdated
var annotations map[string]string | ||
var artifactTypeFilter string | ||
if artifactTypeFilter = r.URL.Query().Get("artifactType"); artifactTypeFilter != "" { | ||
annotations = map[string]string{ | ||
v1.AnnotationReferrersFiltersApplied: "artifactType", | ||
} | ||
} | ||
|
||
// extract the page size info. Users define page size by using the n | ||
// query parameter. The default page size is 100. |
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.
Comment needs to be updated.
// query parameter. The default page size is 100. | |
// query parameter. The default page size is 10. |
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.
sorry. Updated.
registry/handlers/referrers.go
Outdated
if referrers == nil || startIndex > len(referrers) { | ||
referrers = []v1.Descriptor{} | ||
} |
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.
When fall into this code path, the code from line 107 - 113 is still executed but should not.
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.
Used an else
to enclose this part.
registry/handlers/referrers.go
Outdated
@@ -195,6 +227,20 @@ func readlink(ctx context.Context, path string, stDriver driver.StorageDriver) ( | |||
return digest.Parse(string(content)) | |||
} | |||
|
|||
func generateLinkHeader(repoName, subjectDigest, artifactType string, lastDigests []string, nPage int, p int) string { |
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.
lastDigests
is never used.
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.
Forgot to delete this from legacy code. Deleted.
Signed-off-by: wangxiaoxuan273 <[email protected]>
Signed-off-by: wangxiaoxuan273 <[email protected]>
Signed-off-by: wangxiaoxuan273 <[email protected]>
Signed-off-by: wangxiaoxuan273 <[email protected]>
registry/handlers/referrers.go
Outdated
func generateLinkHeader(repoName, subjectDigest, artifactType string, pageSize int, p int) string { | ||
linkURL := fmt.Sprintf("/v2/%s/referrers/%s", repoName, subjectDigest) | ||
v := url.Values{} | ||
v.Add("p", fmt.Sprint(p)) |
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.
nit: prefer strconv.Itoa
to fmt.Sprint
for performance.
v.Add("p", fmt.Sprint(p)) | |
v.Add("p", strconv.Itoa(p)) |
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.
changed.
registry/handlers/referrers.go
Outdated
v.Add("artifactType", artifactType) | ||
} | ||
if pageSize > 0 { | ||
v.Add("n", fmt.Sprint(pageSize)) |
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.
same here
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.
changed.
registry/handlers/referrers.go
Outdated
startIndex := pageNumber * pageSize | ||
|
||
if referrers == nil || startIndex >= len(referrers) { | ||
referrers = []v1.Descriptor{} | ||
} else { | ||
// if there's only 1 page of results left | ||
if len(referrers)-startIndex <= pageSize { | ||
referrers = referrers[startIndex:] | ||
} else { | ||
referrers = referrers[startIndex:(startIndex + pageSize)] | ||
w.Header().Set("Link", generateLinkHeader(h.Repository.Named().Name(), h.Digest.String(), artifactTypeFilter, pageSize, pageNumber+1)) | ||
} | ||
} |
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.
nit: code style: readability
startIndex := pageNumber * pageSize | |
if referrers == nil || startIndex >= len(referrers) { | |
referrers = []v1.Descriptor{} | |
} else { | |
// if there's only 1 page of results left | |
if len(referrers)-startIndex <= pageSize { | |
referrers = referrers[startIndex:] | |
} else { | |
referrers = referrers[startIndex:(startIndex + pageSize)] | |
w.Header().Set("Link", generateLinkHeader(h.Repository.Named().Name(), h.Digest.String(), artifactTypeFilter, pageSize, pageNumber+1)) | |
} | |
} | |
startIndex := pageNumber * pageSize | |
if referrers == nil || len(referrers) <= startIndex { | |
referrers = []v1.Descriptor{} | |
} else if len(referrers) <= startIndex+pageSize { | |
// only 1 page of results left | |
referrers = referrers[startIndex:] | |
} else { | |
referrers = referrers[startIndex:(startIndex + pageSize)] | |
w.Header().Set("Link", generateLinkHeader(h.Repository.Named().Name(), h.Digest.String(), artifactTypeFilter, pageSize, pageNumber+1)) | |
} |
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.
changed.
Signed-off-by: wangxiaoxuan273 <[email protected]>
registry/handlers/referrers.go
Outdated
// only 1 page of results left | ||
referrers = referrers[startIndex:] | ||
} else { | ||
referrers = referrers[startIndex:(startIndex + pageSize)] |
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.
nit:
referrers = referrers[startIndex:(startIndex + pageSize)] | |
referrers = referrers[startIndex:startIndex + pageSize] |
registry/handlers/referrers.go
Outdated
@@ -195,6 +229,19 @@ func readlink(ctx context.Context, path string, stDriver driver.StorageDriver) ( | |||
return digest.Parse(string(content)) | |||
} | |||
|
|||
func generateLinkHeader(repoName, subjectDigest, artifactType string, pageSize int, p int) string { |
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.
nit: code style: variable naming
func generateLinkHeader(repoName, subjectDigest, artifactType string, pageSize int, p int) string { | |
func generateLinkHeader(repoName, subjectDigest, artifactType string, pageSize int, pageNumber int) string { |
Signed-off-by: wangxiaoxuan273 <[email protected]>
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.
LGTM
Signed-off-by: wangxiaoxuan273 [email protected]
Resolves #40
This pr enables the pagination feature of referrers API. The current implementation is slow as it calls
generateReferrersList
multiple times when pagination is needed.Users can define page size by using the
?n
query parameter. If not used, the default page size is set to 100. Pagination is automatically enabled when the number of returned referrers is greater than the page size (this is conformant to the distribution spec).Test result with
pageSize = 4
. The test subject has 6 referrers and are returned with 2 pages.Test result with
pageSize = 5
using the same test subject. 2 Pages are returned.