-
Notifications
You must be signed in to change notification settings - Fork 6.5k
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
Adding paging capabilities for the admin entity-providers endpoints #21487
Conversation
@Operation( summary = "Get identity providers") | ||
public Response getIdentityProviders(@Parameter(description = "Provider id") @PathParam("provider_id") String providerId) { | ||
@Operation( summary = "Get the identity provider factory for that provider id") | ||
public Response getIdentityProviders(@Parameter(description = "The provider id to get the factory") @PathParam("provider_id") String providerId) { |
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.
Perhaps this can also be less generic then 'Response'? Is there no way we can do a IdentityProviderRepresentation
as a response?
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 just changed the description that was copied from the other method. I can do it. No problem with this.
@Operation( summary = "Get identity providers") | ||
public Stream<IdentityProviderRepresentation> getIdentityProviders() { | ||
@Operation(summary = "List identity providers") | ||
public Stream<IdentityProviderRepresentation> getIdentityProviders( |
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.
Do we not have some sort of generic solution for pagination? We would need to know how many pages are left to do proper pagination on the client side. Ideally a response for this endpoint would include all the information needed to handle pagination state:
{
"hasNextPage": true,
"hasPreviousPage": true,
"currentPage": 3,
"totalPages": 5,
"entriesPerPage": 20,
"totalEntries": 100,
"results": [
{
"id": 1,
"name": "Foo"
},
{
"id": 2,
"name": "Bar"
}
]
}
Something like a PaginatedResponse<IdentityProviderRepresentation>
would be great, so it can be re-used between endpoints.
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.
@jonkoops AFAIK there is no standard response in keycloak for pagination. The other endpoints just have this, a count method and a find method (more or less, you can see the users for example, here and here). That's why I followed the same idea.
If we want to create a generic solution I would propose a much simpler response with no pages. The reason is that some storages (ldap for example) are extremely far from the idea of common paging (in ldap you don't know the total number of entries that matches a filter for example). For that I would only return something like the following:
{
"firstResult": 100,
"numResults": 50,
"results": [... 50 results ...],
"hasMore": true
}
And the console would do something different, something like showing the initial list and a button saying more
. If you click it the next bunch of results are added to the list. The user can always filter or refine the search to get less results.
For sure I would not give so much data for pagination as you propose, the server doesn't control the page. I think that part is for the frontend. So if we want to main something like we have now but with a better response. I vote for something like:
{
"hasMore": true,
"firstResult": 10,
"numResults": 20,
"totalEntries": 100,
"results": [... 20 results ]
}
If we go with something like this the method will be new (I have reused the same method in this test). We need more people of team to decide about this point. And @mposolda should be involved for sure.
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 reason is that some storages (ldap for example) are extremely far from the idea of common paging (in ldap you don't know the total number of entries that matches a filter for example).
I see, yeah that is very unfortunate indeed. Reading this I feel like we can split this into two types of pagination:
- Finite paging, the total number of entries is known and this information can be constructed.
- Infinite paging, here we can only determine the cursor, but we have no idea of where the end is.
It feel to me that a large amount of our data can fit in nr. 1, so I would not go and compromise the data structure of all API endpoints for these edge-cases. But perhaps I am mistaken, and this is a large amount of our data. I think you would know better if this is the case.
Naturally, we do need to handle these edge-cases, and I think your solution makes sense.
And the console would do something different, something like showing the initial list and a button saying
more
. If you click it the next bunch of results are added to the list. The user can always filter or refine the search to get less results.
I like this approach, at least for the places in the API where we cannot determine an accurate count.
For sure I would not give so much data for pagination as you propose, the server doesn't control the page.
I have to disagree slightly with that. The server is is certainly not responsible for maintaining state (such as the current page we're on), but I do believe it is the responsibility of the API to serve as a single source of truth where possible (including computed state).
However, this is more of a philosophical debate, and I would already be more than happy if we can already compute the page state 👍 We can always add this later if we feel like it is necessary.
What would also be great is if we could have some generalized error handling for common pagination errors, such as exceeding the max page size, or exceeding the bounds of the entries. I imagine this is something we could do in a generalized abstraction.
Also agree, we should get more of the team involved if we do want to generalize this into a common pattern. I'd really like to get this specced out, as (inconsistent) pagination is something that frequently is a point of frustration (and bugs) for the UI team.
@mposolda @ssilvert would definitely be interested in your take on this as well.
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.
Also agree, we should get more of the team involved if we do want to generalize this into a common pattern. I'd really like to get this specced out, as (inconsistent) pagination is something that frequently is a point of frustration (and bugs) for the UI team.
@mposolda @ssilvert would definitely be interested in your take on this as well.
I agree with @jonkoops on this. The UI needs to know what it is dealing with. Perhaps providers should have a choice of implementing a paginated or unpaginated version of each interface. And the UI should be able to ask if pagination is supported so we know how to get and display the data.
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.
@rmartinc @ssilvert @jonkoops The proposed ideas are great, however here the main question is if we:
- Follow the same pattern for identity-providers pagination like we're already doing for bunch of other Keycloak objects, which already support pagination (users, clients, roles etc)
- Introduce some new pagination approach (v2 pagination), which might be better and more effective as described in the ideas proposed above (among others, it would allow to avoid sending separate request to "count" endpoint etc)
My vote is to go with (1) for identity-providers pagination and follow the same as we do for all other Keycloak pagination entities.
I don't think we should introduce some new approach just for identity-providers TBH and make it inconsistent with other objects. It would makes more sense to postpone this possibly to admin REST API v2 (which is planned to be done at some point) and make sure it is consistent for all objects.
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 am okay with deferring this to a potential v2. But be aware that currently none of the UIs actually use any of the /count
endpoints.
@Produces(MediaType.APPLICATION_JSON) | ||
@Tag(name = KeycloakOpenAPI.Admin.Tags.IDENTITY_PROVIDERS) | ||
@Operation( summary = "Count identity providers") | ||
public Integer countIdentityProviders( |
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.
Why do we have a separate count endpoint? Under what circumstances should we be using this? If this a separate pre-flight that the client has to do to determine the pagination that is less than ideal as:
- This complicates client logic for something we already fully know the state of on the server.
- This state can become out of sync with reality as new records are inserted or deleted.
- Because of nr. 2 we now need to do this request every time we also request the identity providers.
- This results in poorer performance due to network overhead (although not significantly I imagine).
- We cannot handle this generically in the client, as endpoints do not implement this consistently.
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.
Yeah! It's the same, I did this way because it how it's usually done. See my previous comment.
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.
Unreported flaky test detected, please review
Unreported flaky test detectedIf the below flaky tests below are affected by the changes, please review and update the changes accordingly. Otherwise, a maintainer should report the flaky tests prior to merging the PR. org.keycloak.testsuite.admin.IdentityProviderTest#testFindKeycloak CI - Legacy Store IT (oracle)
|
I believe that for Identity Provider pager we can create a toBriefRepresentation method in ModelToRepresentation class. |
The tests are failing because didn't ordered the results. I can do it if necessary for the tests. @cgeorgilakis Yes, we can add also the |
@rmartinc @cgeorgilakis +1 for |
@jonkoops We discussed with @rmartinc to do some small adjustments to this PR (like support for IMO possible improvements for pagination can be done in unified way for all objects when we have some "Admin REST API v2". Is it ok with you? |
@mposolda Yeah, I have no issue with that, this issue needs to get resolved sooner than later. But we'll have to start thinking about a V2 API sometime in the near future, this is kinda all duct tape and toothpicks at the moment. |
@jonkoops Yes, I understand and I agree with V2 API need. Thanks! |
Closing as this was replaced by #22003 |
Draft changes for the identity-providers rest API. No real implementation changes at db level.