Add pagination support for generic table API - #5533
MonkeyCanCode wants to merge 6 commits into
Conversation
There was a problem hiding this comment.
🟡 Changes recommended
Address unsized CLI pagination, compatibility and disabled-pagination coverage, page-uniqueness assertions, and user-facing documentation.
Get a fresh assessment by requesting another Copilot review.
Pull request overview
Adds end-to-end pagination for generic-table listings across the REST service, catalog layer, integration tests, and Python CLI.
Changes:
- Threads page tokens through catalog and REST layers.
- Adds CLI pagination support and tests.
- Adds unit/integration coverage and a changelog entry.
File summaries
| File | Summary |
|---|---|
runtime/service/src/test/java/org/apache/polaris/service/catalog/generic/PolarisGenericTableCatalogHandlerAuthzTest.java |
Updates authorization coverage for generic-table listing. |
runtime/service/src/test/java/org/apache/polaris/service/catalog/generic/AbstractPolarisGenericTableCatalogTest.java |
Adds unit coverage for paginated catalog behavior. |
runtime/service/src/main/java/org/apache/polaris/service/catalog/generic/PolarisGenericTableCatalog.java |
Implements metastore-backed pagination. |
runtime/service/src/main/java/org/apache/polaris/service/catalog/generic/GenericTableCatalogHandler.java |
Handles page parameters and continuation tokens. |
runtime/service/src/main/java/org/apache/polaris/service/catalog/generic/GenericTableCatalogAdapter.java |
Forwards pagination parameters. |
polaris-core/src/main/java/org/apache/polaris/core/catalog/GenericTableCatalog.java |
Adds the paginated catalog API. |
integration-tests/src/main/java/org/apache/polaris/service/it/test/PolarisRestCatalogIntegrationBase.java |
Adds REST pagination integration coverage. |
integration-tests/src/main/java/org/apache/polaris/service/it/env/GenericTableApi.java |
Supports paginated REST test requests. |
client/python/tests/test_generic_tables_command.py |
Tests CLI pagination behavior. |
client/python/apache_polaris/cli/command/generic_tables.py |
Adds generic-table pagination handling. |
client/python/apache_polaris/cli/command/__init__.py |
Wires pagination options into the CLI. |
CHANGELOG.md |
Documents the pagination feature. |
Review details
Suppressed comments (4)
client/python/apache_polaris/cli/command/generic_tables.py:76
paginatereturns after one request whenpage_sizeisNone. However, withLIST_PAGINATION_MAX_PAGE_SIZEconfigured, the new server handler can return a continuation token even when the client omits--page-size; this loop then discards all subsequent generic tables. Please make the shared pagination path follownext_page_tokenfor unsized requests as well, or otherwise pass an explicit size.
for resp in paginate(
generic_api.list_generic_tables,
page_size=self.page_size,
prefix=catalog_name,
namespace=ns_str,
integration-tests/src/main/java/org/apache/polaris/service/it/test/PolarisRestCatalogIntegrationBase.java:2966
- The new integration test covers only pagination-enabled catalogs. Please add a generic-table case with
LIST_PAGINATION_ENABLED=false(including an invalid token), matchingtestNonPaginatedListTablesViewNamespaces, because this handler now introduces a separatePageToken.buildpath whose disabled-feature behavior is not covered for this endpoint.
@Test
public void testPaginatedListGenericTables() {
integration-tests/src/main/java/org/apache/polaris/service/it/test/PolarisRestCatalogIntegrationBase.java:2988
- This assertion only sums page sizes, so a broken cursor that repeats an identifier while omitting another still passes as long as it returns 30 entries. Since pagination correctness depends on stable, non-overlapping pages, collect the identifiers and assert that they equal the 30 tables created above for each page size.
assertThat(response.getIdentifiers().size()).isLessThanOrEqualTo(pageSize);
total += response.getIdentifiers().size();
pageToken = response.getNextPageToken();
} while (pageToken != null);
assertThat(total).as("Total paginated results for pageSize = " + pageSize).isEqualTo(30);
runtime/service/src/main/java/org/apache/polaris/service/catalog/generic/GenericTableCatalogHandler.java:112
- This introduces a user-visible pagination contract for generic-table listing, but the tracked generic-table guide still only documents an unqualified “list all” request and a response with a null token (site/content/in-dev/unreleased/generic-table.md:128-146). Please update the REST guide and the generic-tables CLI section to explain
page-size/page-token, continuation handling, and theLIST_PAGINATION_ENABLEDbehavior so clients can use the new API correctly.
PageToken pageRequest =
PageToken.build(pageToken, pageSize, maxPageSize(), this::shouldDecodeToken);
Page<TableIdentifier> page = genericTableCatalog.listGenericTables(parent, pageRequest);
return ListGenericTablesResponse.builder()
.setIdentifiers(new LinkedHashSet<>(page.items()))
.setNextPageToken(page.encodedResponseToken())
- Files reviewed: 12/12 changed files
- Comments generated: 2
- Review effort level: Lite
💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.
| default Page<TableIdentifier> listGenericTables(Namespace namespace, PageToken pageToken) { | ||
| return Page.fromItems(listGenericTables(namespace)); |
| backend, since `S3FileIO`, `GCSFileIO`, `ADLSFileIO` and `HadoopFileIO` all implement | ||
| `DelegateFileIO`. | ||
| - Async task retries no longer fail with a `NullPointerException` when the task entity has already been dropped by a previous attempt. Such a retry is now recognized as an already-completed task and exits cleanly, instead of exhausting all retry attempts and logging a `NullPointerException` on each one. | ||
| - Honored pagination for generic table API. |
There was a problem hiding this comment.
This is not correct. --page-size is global option and it is already documented in command-line-interface.md
dimas-b
left a comment
There was a problem hiding this comment.
LGTM 👍 Just one comment about SPI evolution. Thanks, @MonkeyCanCode !
flyrain
left a comment
There was a problem hiding this comment.
+1 Thanks @MonkeyCanCode !
ayushtkn
left a comment
There was a problem hiding this comment.
Thanx @MonkeyCanCode for chasing this, some minor stuff in the CHANGELOG, maybe due to conflict resolution, else the code changes LGTM
| scheme stripping (e.g. `s3://bucket/path` → `//bucket/path`). `//` and `///` are retained so | ||
| scheme-root ancestors remain visible to the overlap check. | ||
|
|
||
| >>>>>>> main |
There was a problem hiding this comment.
this maybe came in from conflict resolution
There was a problem hiding this comment.
Yes. Thanks for review and this extra line is now removed.
Per ML, this PR honors the pagination support for generic table API. This is partial fix for #5311
Here is sample output:
Checklist
CHANGELOG.md(if needed)site/content/in-dev/unreleased(if needed)