-
Notifications
You must be signed in to change notification settings - Fork 13
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
Quay API v2 #24
base: main
Are you sure you want to change the base?
Quay API v2 #24
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,140 @@ | ||
--- | ||
title: Quay API V2 design | ||
authors: | ||
- "@sdadi" | ||
reviewers: | ||
- "@syahmed" | ||
- "@sleesinc" | ||
- "@obulatov" | ||
- "@bcaton" | ||
approvers: | ||
- "@syahmed" | ||
- "@sleesinc" | ||
- "@obulatov" | ||
- "@bcaton" | ||
creation-date: 2023-07-24 | ||
last-updated: yyyy-mm-dd | ||
status: implementable | ||
--- | ||
|
||
# Quay API v2 | ||
|
||
This is a proposal to design a generic strategy to improve Quay API's to support pagination, filtering and sorting. | ||
|
||
## Release Signoff Checklist | ||
|
||
- [x] Enhancement is `implementable` | ||
- [x] Design details are appropriately documented from clear requirements | ||
- [ ] Test plan is defined | ||
- [ ] Graduation criteria for dev preview, tech preview, GA | ||
|
||
## Summary | ||
|
||
Currently, only a few APIs have the option to paginate results on the backend. The goal of the proposal is to have a re-usable system to perform actions on the backend and send the curated result on the frontend. Ideally frontend should only display the results and allow the backend to perform | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Is "resources" instead of "APIs" more accurate? |
||
all the heavy lifting. | ||
|
||
## Motivation | ||
|
||
In the quay ui, filtering, sorting and occasionally paginating the results happen on the frontend. | ||
This leads to high rendering time on the frontend and thereby a poor user experience. | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. What are the implication of delegating that work to the server-side? |
||
|
||
### Goals | ||
|
||
Implement a generic system that is consistent across different endpoints to support the following operations on Quay endpoints: | ||
- pagination | ||
- filtering | ||
- sorting | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. See comment above. I assume doing filtering and sorting on the server side vs client-side has some significant performance trade-offs. |
||
|
||
## Design Details | ||
|
||
### API Design | ||
|
||
- Proposed path of the endpoints: In an attempt to not change the existing endpoints, new APIs will be under `/api/v2_draft/`. | ||
`v2_draft` will be replaced with `v2` when ready to release. | ||
- Existing decorators like the scope of API, page parameters will be reused where ever required. | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Is this not going to be backward-compatible? If just adding pagination to the current existing resources. |
||
|
||
### Pagination | ||
|
||
It is difficult to say that one pagination strategy suits all needs. After understanding the pros and cons of various pagination strategies, | ||
cusor-based pagination seems to work best for our current needs. | ||
|
||
Cursor will contain a unique sequential db column to base cursors on along with additional data when required. | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. How is this different from what we currently support in terms of pagination? How is this proposal different or supposed to improved what's already there, performance or otherwise? |
||
For example, sorting results on non-unique keys, like datetime (currently used in the UI for sorting usage logs) | ||
|
||
Cursor data is extensible and can look like: | ||
``` | ||
{"id": 123} | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Can a cursor from the request with one set of query parameters be reused with the request with another set of parameters (with different sorting or different filters)? |
||
{"id": "2023-08-02T12:34:56Z", "offset": 20} | ||
{"id": "2023-08-02T12:34:56Z", "some_other_key": val1, "another_key": val2} | ||
``` | ||
|
||
The following will be expected request parameters for an API that is to be paginated: | ||
1. limit: number of items to be returned for the page, max limit set to 100 items per page (based from current Quay API guidelines). | ||
2. prev_cursor/next_cursor | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. What's the use case for a pointer to the previous page? |
||
|
||
a. prev_cursor: encrypted string to fetch previous page results | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. How will this cursor be generated? |
||
|
||
b. next_cursor: encrypted string to fetch next page results | ||
|
||
Response body: | ||
``` | ||
{ | ||
results: [items per page], | ||
total_count: count of all items on all pages, | ||
dmage marked this conversation as resolved.
Show resolved
Hide resolved
|
||
page_info: { | ||
next_cursor: encrypted metadata for next page | ||
prev_cursor: encrypted metadata for prev page | ||
} | ||
} | ||
``` | ||
|
||
### Filtering | ||
|
||
Typical syntax of an API filter will look like: `key1[operation1]=<value1>&key2[operation2]=<value2>` where: | ||
- key: is the field on which the search will be performed (Eg: repo name, org name, etc) | ||
- operation: can be different based on the datatype of the key. (Eg: for integers, `lt|lte|gt|gte`, for strings: `like|eq|regex`) | ||
- value: is what the query will filter for | ||
- multiple supported filters can be added to the query parameters using `&` | ||
|
||
Eg: (GET `/tags?tag_name[like]=quay`, GET `/logs?created_at[lte]=2023-07-20 19:56`) | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Do we have examples when multiple filters are needed for the UI? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I don't see a use case of multiple filters in the designs. I want the design to accommodate this as this will be a one time investment. Can be good to have for future needs. |
||
|
||
### Sorting | ||
|
||
Sort order will be represented by the query parameter `sort`, ascending order by `+` and descending order by `-`. | ||
Multiple sorts can be passed in the url by adding comma separated keys. | ||
Eg: (GET `/tags?sort=+created_at`, GET `/users?sort=+creation_date,-last_accessed`) | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Will users be able to sort by any column? How do we deal with columns that are not indexed and sorting on which can be terribly slow? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. My thoughts are to restrict sorts on only the cols the UI needs today. If a user makes a request with unsupported col sort, 400 will be sent back. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I will document the above. |
||
|
||
Sorting will be supported only on select keys. Every API endpoint will maintain a list of supported sortable keys. If a user | ||
makes a request with an unsupported key, 400 Bad Request response will be sent along with a list of supported sortable keys. | ||
Example of 400 response: | ||
``` | ||
{ | ||
"title": "Unsupported sort key", | ||
"detail": "The request is sortable only on one of these keys: [a, b, c]", | ||
"status": 400, | ||
} | ||
``` | ||
|
||
### Notes/Constraints | ||
|
||
The major caveat of cursor-based pagination is that we cannot fetch results from page number. User cannot directly navigate to the nth page. | ||
They'd need to request pages from 1 - n as next page results are derived from the previous page's cursor. | ||
|
||
### Graduation Criteria | ||
|
||
##### Dev Preview -> Tech Preview | ||
|
||
- Ability to utilize the enhancement end to end | ||
- Sufficient test coverage | ||
- End user documentation, relative API stability | ||
|
||
##### Tech Preview -> GA | ||
|
||
- More testing (on scale) | ||
- Sufficient time for feedback | ||
- Available by default | ||
|
||
## Open questions | ||
|
||
> 1. Do we want to set expiration time on cursors? If yes, how to choose this time? | ||
|
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 header should start and end with
---
.https://github.blog/2013-09-27-viewing-yaml-metadata-in-your-documents/
https://jekyllrb.com/docs/front-matter/