-
Notifications
You must be signed in to change notification settings - Fork 54
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
Add POC for a proposed ListAll func for paginated resources #261
Conversation
management/client.go
Outdated
// If limit is 0 it will retrieve all the clients, otherwise it will retrieve all the clients until the limit is reached. | ||
// | ||
// See: https://auth0.com/docs/api/management/v2#!/Clients/get_clients | ||
func (m *ClientManager) ListAll(ctx context.Context, limit int, opts ...RequestOption) (clients []*Client, err error) { |
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.
Some further ideas for discussions over here on the topic of limit:
- A) Remove the limit entirely and always fetch everything
- B) Provide the limit as a designated RequestOption for ListAll funcs.
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.
Without a limit, this feature would not be very useful for the Auth0 CLI, because list
commands accept a -n
flag to limit the number of elements to output. Of course, we could still fetch it all and then drop the rest, but that's not particularly efficient nor DX-friendly (more requests than necessary take longer).
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 ListAll
function should do just that, list all. It is contradictory for the public API to state that you're getting all when in reality, it's only retrieving up to a limit. Further, the DX improvement here is that I as a user shouldn't need to worry about what the limit is, it's just asking for more cognitive overhead.
Re: Auth0 CLI, it certainly is a use-case to consider but IMO we shouldn't have that decide wether or not we expose a limit as the API. We can make it more private through other means like as a request option (as Sergiu suggested above).
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.
A request option certainly seems like a good fit for it, instead of a regular argument.
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.
+1 on moving to a RequestOption rather than a dedicated part of the API
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.
I think getting the first X elements without having to handle the pagination is a legitimate enough use case. I wonder if it should be a separate method, though. Or if this method should be renamed to something that does not imply getting 'all', like ListPaginated(), and take the limit as a regular argument.
Have you folks discussed this? @Widcket , @ewanharris , @willvedd ?
I'd be in favour of having 2 extra funcs instead of just one:
ListAll(ctx context.Context, opts ...RequestOption) (clients []*Client, err error)
# Or ListPaginated, ListWithLimit, ListFirstN,
ListUntilLimit(ctx context.Context, limit int, opts ...RequestOption) (clients []*Client, err error)
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.
@ewanharris and I had considered this. It's certainly a valid solution that would address all the technical concerns but I could also see it being too much being added at once. Frankly, as long as there is some ListAll
for all lists, we're good; its not the worst thing if custom pagination exists in the Auth0 CLI codebase.
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.
I'd also be concerned, if we add a way to "get all" without also adding a way to "get N", that we could be encouraging "getting all" and then extracting the first N from the result (because it'll be easier than implementing the pagination from scratch).
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.
Have you folks discussed this? @Widcket , @ewanharris , @willvedd ?
I'm afraid I wasn't part of those discussions.
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.
Fully agree with this @Widcket 👍🏻 , however we can split the 2 funcs in 2 separate PRs, but combine both in 1 release.
management/client.go
Outdated
opts []RequestOption, | ||
api func(ctx context.Context, opts ...RequestOption) (result []Resource, hasNext bool, err error), | ||
) ([]Resource, error) { | ||
const defaultPageSize = 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.
Should we keep this to 100? Or use the current GO SDK default of 50?
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.
- Fewer requests, fewer 429s, better performance.
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.
Should we then also change the default of 50 through out the entire SDK to 100?
Codecov ReportPatch coverage:
Additional details and impacted files@@ Coverage Diff @@
## main #261 +/- ##
==========================================
- Coverage 94.78% 94.72% -0.07%
==========================================
Files 46 46
Lines 8733 8757 +24
==========================================
+ Hits 8278 8295 +17
- Misses 353 358 +5
- Partials 102 104 +2
☔ View full report in Codecov by Sentry. |
management/client.go
Outdated
*Client | *Connection | *Organization | ||
} | ||
|
||
func getWithPagination[Resource paginatedResource]( |
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.
On the topic of testing, I think we can simply test the ListALl funcs and get this covered intrinsically as well, but open to other ideas.
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.
Yes, I think that's fine.
9c339fb
to
ce5a22a
Compare
@@ -87,6 +87,17 @@ func TestClient_List(t *testing.T) { | |||
assert.Contains(t, clientList.Clients, &Client{ClientID: expectedClient.ClientID}) | |||
} | |||
|
|||
func TestClient_ListAll(t *testing.T) { | |||
configureHTTPTestRecordings(t) |
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 doesn't really test the pagination aspect that well, it might be best to allow overriding the PerPage so that we can set it to a low value here and properly test that pagination aspect
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.
Should we add a test similar to https://github.com/auth0/auth0-cli/blob/7d27438692215cc4904f5116e1a3e82a030d25a9/internal/cli/terraform_fetcher_test.go#L43 ?
Interestingly, on node-auth0 v4 So not entirely sure we should go by that token here, given how we typically look at the node-auth0 v4 implementation to model things. |
Good point raised @Widcket, however I think that we shouldn't necessarily follow stricly what node-auth0 is doing, we can stay curious and do the best DX for the given programming language. Naming something |
Oh I totally agree, was just pointing out observed behavior. Given that this PoC was originally created after auth0/auth0-cli#797 was raised, to try and find a way to reduce the code needed to add new resources (as per Slack convo), and that as it stands now it won't be able to fulfill this purpose:
|
var list []Resource | ||
var pageNumber int | ||
for { | ||
opts = append(opts, PerPage(pageSize), Page(pageNumber)) |
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 will lead to opts
growing on each iteration. maybe this would be better?
opts = append(opts, PerPage(pageSize), Page(pageNumber)) | |
realOpts = append(opts, PerPage(pageSize), Page(pageNumber)) |
and then use realOpts
below on the API call.
I'm going to close this PR as we have decided that for now we do not wish to add a |
🔧 Changes
This PR contains a proposed POC for a ListAll func on all paginatable resources. This PR shouldn't get merged as the purpose of it is just to facilitate discussions over the solution. Tests were omitted as well in case the function signature needs adjustments.
📚 References
🔬 Testing
📝 Checklist