-
Notifications
You must be signed in to change notification settings - Fork 100
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
feat(pagination): move pagination and sorting image summary results a…
…fter conversion Signed-off-by: Laurentiu Niculae <[email protected]>
- Loading branch information
1 parent
abba6aa
commit d73b8c8
Showing
30 changed files
with
1,995 additions
and
3,092 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,164 @@ | ||
package pagination | ||
|
||
import ( | ||
"fmt" | ||
"sort" | ||
"time" | ||
|
||
zerr "zotregistry.io/zot/errors" | ||
zcommon "zotregistry.io/zot/pkg/common" | ||
gql_gen "zotregistry.io/zot/pkg/extensions/search/gql_generated" | ||
) | ||
|
||
type ImageSummariesPageFinder struct { | ||
limit int | ||
offset int | ||
sortBy SortCriteria | ||
pageBuffer []*gql_gen.ImageSummary | ||
} | ||
|
||
func NewImgSumPageFinder(limit, offset int, sortBy SortCriteria) (*ImageSummariesPageFinder, error) { | ||
if sortBy == "" { | ||
sortBy = AlphabeticAsc | ||
} | ||
|
||
if limit < 0 { | ||
return nil, zerr.ErrLimitIsNegative | ||
} | ||
|
||
if offset < 0 { | ||
return nil, zerr.ErrOffsetIsNegative | ||
} | ||
|
||
if _, found := ImgSumSortFuncs()[sortBy]; !found { | ||
return nil, fmt.Errorf("sorting repos by '%s' is not supported %w", | ||
sortBy, zerr.ErrSortCriteriaNotSupported) | ||
} | ||
|
||
return &ImageSummariesPageFinder{ | ||
limit: limit, | ||
offset: offset, | ||
sortBy: sortBy, | ||
pageBuffer: []*gql_gen.ImageSummary{}, | ||
}, nil | ||
} | ||
|
||
func (pf *ImageSummariesPageFinder) Add(imgSum *gql_gen.ImageSummary) { | ||
pf.pageBuffer = append(pf.pageBuffer, imgSum) | ||
} | ||
|
||
func (pf *ImageSummariesPageFinder) Page() ([]*gql_gen.ImageSummary, zcommon.PageInfo) { | ||
if len(pf.pageBuffer) == 0 { | ||
return []*gql_gen.ImageSummary{}, zcommon.PageInfo{} | ||
} | ||
|
||
pageInfo := zcommon.PageInfo{} | ||
|
||
sort.Slice(pf.pageBuffer, ImgSumSortFuncs()[pf.sortBy](pf.pageBuffer)) | ||
|
||
// the offset and limit are calculated in terms of repos counted | ||
start := pf.offset | ||
end := pf.offset + pf.limit | ||
|
||
// we'll return an empty array when the offset is greater than the number of elements | ||
if start >= len(pf.pageBuffer) { | ||
start = len(pf.pageBuffer) | ||
end = start | ||
} | ||
|
||
if end >= len(pf.pageBuffer) { | ||
end = len(pf.pageBuffer) | ||
} | ||
|
||
page := pf.pageBuffer[start:end] | ||
|
||
pageInfo.ItemCount = len(page) | ||
|
||
if start == 0 && end == 0 { | ||
page = pf.pageBuffer | ||
pageInfo.ItemCount = len(page) | ||
} | ||
|
||
pageInfo.TotalCount = len(pf.pageBuffer) | ||
|
||
return page, pageInfo | ||
} | ||
|
||
func ImgSumSortFuncs() map[SortCriteria]func(pageBuffer []*gql_gen.ImageSummary) func(i, j int) bool { | ||
return map[SortCriteria]func(pageBuffer []*gql_gen.ImageSummary) func(i, j int) bool{ | ||
AlphabeticAsc: ImgSortByAlphabeticAsc, | ||
AlphabeticDsc: ImgSortByAlphabeticDsc, | ||
UpdateTime: ImgSortByUpdateTime, | ||
Relevance: ImgSortByRelevance, | ||
Downloads: ImgSortByDownloads, | ||
} | ||
} | ||
|
||
func ImgSortByAlphabeticAsc(pageBuffer []*gql_gen.ImageSummary) func(i, j int) bool { | ||
return func(i, j int) bool { //nolint: varnamelen | ||
if *pageBuffer[i].RepoName < *pageBuffer[j].RepoName { | ||
return true | ||
} | ||
|
||
if *pageBuffer[i].RepoName == *pageBuffer[j].RepoName { | ||
return *pageBuffer[i].Tag < *pageBuffer[j].Tag | ||
} | ||
|
||
return false | ||
} | ||
} | ||
|
||
func ImgSortByAlphabeticDsc(pageBuffer []*gql_gen.ImageSummary) func(i, j int) bool { | ||
return func(i, j int) bool { //nolint: varnamelen | ||
if *pageBuffer[i].RepoName > *pageBuffer[j].RepoName { | ||
return true | ||
} | ||
|
||
if *pageBuffer[i].RepoName == *pageBuffer[j].RepoName { | ||
return *pageBuffer[i].Tag > *pageBuffer[j].Tag | ||
} | ||
|
||
return false | ||
} | ||
} | ||
|
||
func ImgSortByRelevance(pageBuffer []*gql_gen.ImageSummary) func(i, j int) bool { | ||
return func(i, j int) bool { //nolint: varnamelen | ||
if *pageBuffer[i].RepoName < *pageBuffer[j].RepoName { | ||
return true | ||
} | ||
|
||
if *pageBuffer[i].RepoName == *pageBuffer[j].RepoName { | ||
return *pageBuffer[i].Tag < *pageBuffer[j].Tag | ||
} | ||
|
||
return false | ||
} | ||
} | ||
|
||
// SortByUpdateTime sorting descending by time. | ||
func ImgSortByUpdateTime(pageBuffer []*gql_gen.ImageSummary) func(i, j int) bool { | ||
repos2LastUpdated := map[string]time.Time{} | ||
|
||
for _, img := range pageBuffer { | ||
lastUpdated, ok := repos2LastUpdated[*img.RepoName] | ||
|
||
if !ok || lastUpdated.Before(*img.LastUpdated) { | ||
repos2LastUpdated[*img.RepoName] = *img.LastUpdated | ||
} | ||
} | ||
|
||
return func(i, j int) bool { | ||
iRepoTime, jRepoTime := repos2LastUpdated[*pageBuffer[i].RepoName], repos2LastUpdated[*pageBuffer[j].RepoName] | ||
|
||
return (iRepoTime.After(jRepoTime) || iRepoTime.Equal(jRepoTime)) && | ||
pageBuffer[i].LastUpdated.After(*pageBuffer[j].LastUpdated) | ||
} | ||
} | ||
|
||
// SortByDownloads returns a comparison function for descendant sorting by downloads. | ||
func ImgSortByDownloads(pageBuffer []*gql_gen.ImageSummary) func(i, j int) bool { | ||
return func(i, j int) bool { | ||
return *pageBuffer[i].DownloadCount > *pageBuffer[j].DownloadCount | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,18 @@ | ||
package pagination | ||
|
||
type SortCriteria string | ||
|
||
type PageInput struct { | ||
Limit int | ||
Offset int | ||
SortBy SortCriteria | ||
} | ||
|
||
const ( | ||
Relevance = SortCriteria("RELEVANCE") | ||
UpdateTime = SortCriteria("UPDATE_TIME") | ||
AlphabeticAsc = SortCriteria("ALPHABETIC_ASC") | ||
AlphabeticDsc = SortCriteria("ALPHABETIC_DSC") | ||
Stars = SortCriteria("STARS") | ||
Downloads = SortCriteria("DOWNLOADS") | ||
) |
Oops, something went wrong.