Add pagination for listing KV worker namespaces#394
Add pagination for listing KV worker namespaces#394patryk merged 3 commits intocloudflare:masterfrom
Conversation
| // API reference: https://api.cloudflare.com/#workers-kv-namespace-list-namespaces | ||
| func (api *API) ListWorkersKVNamespaces(ctx context.Context) (ListWorkersKVNamespacesResponse, error) { | ||
| uri := fmt.Sprintf("/accounts/%s/storage/kv/namespaces", api.AccountID) | ||
| uri := fmt.Sprintf("/accounts/%s/storage/kv/namespaces?per_page=100", api.AccountID) |
There was a problem hiding this comment.
Per #377, increasing this to reduce the number of API calls made.
There was a problem hiding this comment.
I'm fine with this for now but if we get any more query parameters, we are going to need to swap to using url.Values to ensure we don't thrash the others.
| result := ListWorkersKVNamespacesResponse{} | ||
| if err := json.Unmarshal(res, &result); err != nil { | ||
| return result, errors.Wrap(err, errUnmarshalError) | ||
| overallResult := ListWorkersKVNamespacesResponse{} |
There was a problem hiding this comment.
This function returns a ListWorkersKVNamespacesResponse as opposed to, for example, []WorkersKVNamespace. This makes it awkward to return the full list. In the current changeset, I'm hijacking the first ListWorkersKVNamespacesResponse and augmenting its Result list, but leaving ResultInfo and Response alone.
Would it make more sense to move the paging into a separate method which returns a []WorkersKVNamespace?
There was a problem hiding this comment.
Yeah, I would expect this to match the other methods like it and return []WorkersKVNamespace. I'm not sure if we have use for the ListWorkersKVNamespacesResponse as is.
There was a problem hiding this comment.
Would it make sense to have that breaking change in this PR?
| wg.Add(totalPageCount - 1) | ||
| errc := make(chan error) | ||
|
|
||
| for i := 2; i <= totalPageCount; i++ { |
There was a problem hiding this comment.
In #288, we seem to duplicate the request for the first page of zones. Maybe there's a reason for that? Here, we don't duplicate the request, so I'm calling that out.
|
|
||
| select { | ||
| case err := <-errc: | ||
| return err |
There was a problem hiding this comment.
This error handling is modeled on #288. I don't do much work in golang, so please advise if this is inadequate. I'm not sure that these errors are actually being consumed in any way.
|
|
||
| wg.Wait() | ||
|
|
||
| return overallResult, nil |
There was a problem hiding this comment.
Previously was doing return result, err. To my eye, any error would have been returned prior to reaching that point, so this returns nil for the error. Is that a mistake?
|
|
||
| for i := 2; i <= totalPageCount; i++ { | ||
| go func(pageNumber int) error { | ||
| res, err = api.makeRequestContext(ctx, http.MethodGet, fmt.Sprintf("%s&page=%d", uri, pageNumber), nil) |
There was a problem hiding this comment.
I don't think we really need the makeRequestContext here and makerequest should suffice.
jbergknoff-rival
left a comment
There was a problem hiding this comment.
Thanks for the comments, @jacobbednarz. Please see if these changes bring the PR closer to what you had in mind. I prefer the new implementation, though I wonder about whether it's alright to make the breaking change to the function's signature.
| if err != nil { | ||
| return ListWorkersKVNamespacesResponse{}, errors.Wrap(err, errMakeRequestError) | ||
| } | ||
| func (api *API) ListWorkersKVNamespaces() ([]WorkersKVNamespace, error) { |
There was a problem hiding this comment.
I've changed the signature of this function, which is a breaking change for the library, after the discussion on the first iteration of the PR. Is this acceptable? Now this function is a bit unique in workers_kv.go, but it's a cleaner implementation than my first attempt, and, IMO, more useful functionality for most users of the library.
There was a problem hiding this comment.
I'd keep context, reasoning in comment below. Changing return type is fine.
| for { | ||
| v.Set("page", strconv.Itoa(page)) | ||
| uri := fmt.Sprintf("/accounts/%s/storage/kv/namespaces?%s", api.AccountID, v.Encode()) | ||
| res, err := api.makeRequest(http.MethodGet, uri, nil) |
There was a problem hiding this comment.
I've replaced api.makeRequestContext by api.makeRequest per the comments on the first version of this PR. I also dropped context as an argument to this function.
There was a problem hiding this comment.
I would keep context here, we might want to eventually make all API calls context-aware (issue #324).
| for { | ||
| v.Set("page", strconv.Itoa(page)) | ||
| uri := fmt.Sprintf("/accounts/%s/storage/kv/namespaces?%s", api.AccountID, v.Encode()) | ||
| res, err := api.makeRequest(http.MethodGet, uri, nil) |
There was a problem hiding this comment.
I would keep context here, we might want to eventually make all API calls context-aware (issue #324).
| if err != nil { | ||
| return ListWorkersKVNamespacesResponse{}, errors.Wrap(err, errMakeRequestError) | ||
| } | ||
| func (api *API) ListWorkersKVNamespaces() ([]WorkersKVNamespace, error) { |
There was a problem hiding this comment.
I'd keep context, reasoning in comment below. Changing return type is fine.
|
Thanks for taking a look, @patryk. I've reinstated the request context. |
|
Thanks! |
Description
Listing KV worker namespaces only brings back the first page of (20) results. While that's the default quota for a CF account, it is possible to have more than 20 namespaces, in which case the behavior is inadequate. We're seeing issues with this downstream in the Cloudflare Terraform provider, which is incorrectly trying to create a namespace that already exists (on the second page of results).
This PR updates
ListWorkersKVNamespacesto return all namespaces by paging through the result set. This was modeled after the work done in#288 and #377#389 .This changes the signature of the
ListWorkersKVNamespacesfunction. Does that require a change to the docs? Where would that be made?Types of changes
What sort of change does your code introduce/modify?
ListWorkersKVNamespaces)Checklist: