s3tables: implement token-based pagination for table buckets listing

This commit is contained in:
Chris Lu
2026-01-28 12:30:33 -08:00
parent 1fb3aefa95
commit 6ff683a627

View File

@@ -90,14 +90,14 @@ func (h *S3TablesHandler) handleListTableBuckets(w http.ResponseWriter, r *http.
var buckets []TableBucketSummary var buckets []TableBucketSummary
var lastFileName string lastFileName := req.ContinuationToken
err := filerClient.WithFilerClient(false, func(client filer_pb.SeaweedFilerClient) error { err := filerClient.WithFilerClient(false, func(client filer_pb.SeaweedFilerClient) error {
for len(buckets) < maxBuckets { for len(buckets) < maxBuckets {
resp, err := client.ListEntries(r.Context(), &filer_pb.ListEntriesRequest{ resp, err := client.ListEntries(r.Context(), &filer_pb.ListEntriesRequest{
Directory: TablesPath, Directory: TablesPath,
Limit: uint32(maxBuckets * 2), // Fetch more than needed to account for filtering Limit: uint32(maxBuckets * 2), // Fetch more than needed to account for filtering
StartFromFileName: lastFileName, StartFromFileName: lastFileName,
InclusiveStartFrom: lastFileName == "", InclusiveStartFrom: lastFileName == "" || lastFileName == req.ContinuationToken,
}) })
if err != nil { if err != nil {
return err return err
@@ -115,6 +115,12 @@ func (h *S3TablesHandler) handleListTableBuckets(w http.ResponseWriter, r *http.
if entry.Entry == nil { if entry.Entry == nil {
continue continue
} }
// Skip the start item if it was included in the previous page
if len(buckets) == 0 && req.ContinuationToken != "" && entry.Entry.Name == req.ContinuationToken {
continue
}
hasMore = true hasMore = true
lastFileName = entry.Entry.Name lastFileName = entry.Entry.Name
@@ -173,8 +179,14 @@ func (h *S3TablesHandler) handleListTableBuckets(w http.ResponseWriter, r *http.
} }
} }
paginationToken := ""
if len(buckets) >= maxBuckets {
paginationToken = lastFileName
}
resp := &ListTableBucketsResponse{ resp := &ListTableBucketsResponse{
TableBuckets: buckets, TableBuckets: buckets,
ContinuationToken: paginationToken,
} }
h.writeJSON(w, http.StatusOK, resp) h.writeJSON(w, http.StatusOK, resp)