apiserver/storage: factor PrepareContinueToken to a new function (#125548)

* apiserver/storage/continue: intro PrepareContinueToken

PrepareContinueToken prepares optional
parameters for retrieving additional results for a paginated request.

This function sets up parameters that a client can use to fetch the remaining results
from the server if they are available.

* apiserver/storage/etcd3: refactor to use PrepareContinueToken
This commit is contained in:
Lukasz Szaszkiewicz 2024-06-17 16:47:19 +02:00 committed by GitHub
parent fb7bbd2e5d
commit efef32652a
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
2 changed files with 31 additions and 20 deletions

View File

@ -91,3 +91,30 @@ func EncodeContinue(key, keyPrefix string, resourceVersion int64) (string, error
}
return base64.RawURLEncoding.EncodeToString(out), nil
}
// PrepareContinueToken prepares optional
// parameters for retrieving additional results for a paginated request.
//
// This function sets up parameters that a client can use to fetch the remaining results
// from the server if they are available.
func PrepareContinueToken(keyLastItem, keyPrefix string, resourceVersion int64, itemsCount int64, hasMoreItems bool, opts ListOptions) (string, *int64, error) {
var remainingItemCount *int64
var continueValue string
var err error
if hasMoreItems {
// Instruct the client to begin querying from immediately after the last key.
continueValue, err = EncodeContinue(keyLastItem+"\x00", keyPrefix, resourceVersion)
if err != nil {
return "", remainingItemCount, err
}
// Etcd response counts in objects that do not match the pred.
// Instead of returning inaccurate count for non-empty selectors, we return nil.
// We only set remainingItemCount if the predicate is empty.
if opts.Predicate.Empty() {
remainingItems := itemsCount - opts.Predicate.Limit
remainingItemCount = &remainingItems
}
}
return continueValue, remainingItemCount, err
}

View File

@ -811,27 +811,11 @@ func (s *store) GetList(ctx context.Context, key string, opts storage.ListOption
v.Set(reflect.MakeSlice(v.Type(), 0, 0))
}
// instruct the client to begin querying from immediately after the last key we returned
// we never return a key that the client wouldn't be allowed to see
if hasMore {
// we want to start immediately after the last key
next, err := storage.EncodeContinue(string(lastKey)+"\x00", keyPrefix, withRev)
if err != nil {
return err
}
var remainingItemCount *int64
// getResp.Count counts in objects that do not match the pred.
// Instead of returning inaccurate count for non-empty selectors, we return nil.
// Only set remainingItemCount if the predicate is empty.
if opts.Predicate.Empty() {
c := int64(getResp.Count - opts.Predicate.Limit)
remainingItemCount = &c
}
return s.versioner.UpdateList(listObj, uint64(withRev), next, remainingItemCount)
continueValue, remainingItemCount, err := storage.PrepareContinueToken(string(lastKey), keyPrefix, withRev, getResp.Count, hasMore, opts)
if err != nil {
return err
}
// no continuation
return s.versioner.UpdateList(listObj, uint64(withRev), "", nil)
return s.versioner.UpdateList(listObj, uint64(withRev), continueValue, remainingItemCount)
}
// growSlice takes a slice value and grows its capacity up