-
Notifications
You must be signed in to change notification settings - Fork 1.7k
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
Encode filter parameter as a base64-encoded JSON string in List requests #563
Conversation
/assign @yebrahim |
The frontend needs to change the API calls to pass the object. I can help take a look at this soon. |
frontend/src/apis/experiment/api.ts
Outdated
* @param {*} [options] Override http request option. | ||
* @throws {RequiredError} | ||
*/ | ||
createExperiment(body: ApiExperiment, options: any = {}): FetchArgs { |
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 are these removed?
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.
Thanks for the heads up. This was indeed messed up, because both create and list used the same endpoints with differing verbs (POST and GET).
I decided to go another route: encode the filter as a simple JSON string and put it in a single parameter. Maybe this was what you were alluding to earlier, and I think this should work better, as it doesn't break any of the existing semantics. See what you think.
@@ -44,7 +46,23 @@ func (s *ExperimentServer) ListExperiment(ctx context.Context, request *api.List | |||
if request.PageToken != "" { | |||
opts, err = list.NewOptionsFromToken(request.PageToken, int(request.PageSize)) | |||
} else { | |||
opts, err = list.NewOptions(&model.Experiment{}, int(request.PageSize), request.SortBy, request.Filter) | |||
var f *api.Filter |
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.
Any chance we can reuse this code instead of copying it?
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.
Thanks! I consolidated this logic into a new function, and also added tests for it. PTAL.
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.
/lgtm
just one minor 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.
/lgtm
just a minor comment.
} | ||
|
||
got, err := parseAPIFilter(in) | ||
if !cmp.Equal(got, want) || err != nil { |
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 not just assert.Equal(...
? It takes care of showing the compared objects in the error message right?
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.
True, but I actually prefer the cmp package, as it prints a more precise diff. It's also maintained and recommended by the Go team.
|
||
// SetFilter adds the filter to the list experiment params | ||
func (o *ListExperimentParams) SetFilter(filter *string) { | ||
o.Filter = filter |
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.
If this function is so simple, and not widely used, why not just inline it?
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.
This is auto-generated by the swagger tool. Everything under api/go_http_client and api/go_client is autogenerated.
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.
Ah, sorry, I didn't realize they were auto-generated
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.
Sorry, yeah, it's definitely not obvious :-)
/lgtm |
/test kubeflow-pipeline-e2e-test |
@@ -44,7 +44,12 @@ func (s *ExperimentServer) ListExperiment(ctx context.Context, request *api.List | |||
if request.PageToken != "" { | |||
opts, err = list.NewOptionsFromToken(request.PageToken, int(request.PageSize)) | |||
} else { | |||
opts, err = list.NewOptions(&model.Experiment{}, int(request.PageSize), request.SortBy, request.Filter) | |||
f, err := parseAPIFilter(request.Filter) |
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.
not quite understand the if else statement here. does it means only one of pagetoken and filter can exist?
Are filtered results paginated?
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.
pagetoken encapsulates both sorting and filtering, so if you already have a non-empty page token, we ignore further filtering + sorting criteria.
return nil, nil | ||
} | ||
|
||
errorF := func(err error) (*api.Filter, error) { |
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.
is any good reason of having this function instead of returning errors directly?
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.
Avoids duplicate in error handling, since the message is the same. It's a very idiomatic Go thing to do.
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.
sgtm
if err := jsonpb.UnmarshalString(string(b), f); err != nil { | ||
return errorF(err) | ||
} | ||
return f, nil |
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.
can we add additional validation to make sure the filter format is correct?
e.g. value missing, op missing etc.
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 api filter will get parsed into a filter.Filter object that can actually be used to do filtering. That parsing will sanity check to ensure the filter is well formed and return an error otherwise.
Thanks @rileyjbauer for pointing out that the Filter definitions for Swagger went missing with this change. This was caused by the fact that Filter is only implicitly used by the API, so protoc-gen-swagger will not generate Swagger files correctly for this proto. I modified the Makefile to hack in a dummy service during generation to ensure we get the Swagger definitions. And I updated the PTAL. |
b76a827
to
83e2b89
Compare
/retest |
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.
Oof, that hack!
So the protoc->swagger tool can't generate a standalone message, and only works with service definitions?
What's the harm of leaving that service defined in the proto?
/lgtm
backend/api/Makefile
Outdated
@@ -52,6 +52,13 @@ all: dependencies | |||
--grpc-gateway_out=logtostderr=true:go_client \ | |||
*.proto | |||
|
|||
# Filter.proto is implicitly used by clients and server, and transmitted as a |
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.
nit: indentation (this file uses tabs for some reason).
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.
Done.
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.
nit: indentation (this file uses tabs for some reason).
It's not a nit. Makefile requires tabs for receipt prefixes and will misbehave if they are not there.
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.
Weird, but good to know.
Yeah, it's a pretty ugly hack. I did have the dummy service in initially, but it was generating a corresponding client/server code in Go, which didn't seem like the right thing to do. Hence, this hack :-( |
/retest |
/test kubeflow-pipeline-e2e-test |
Generate new swagger definitions and use these to generate the frontend APIs using `npm run apis`. This is to support filtering in List requests, as the current grpc-gateway swagger generator tool does not support repeated fields in requests used in GET endpoints.
This lets us keep filter as a simple parameter in the ListXXX requests, and gets around having to use POST for List requests.
e3bc065
to
7ceddfa
Compare
How about setting up "go vet -shadow" for catching these errors. I think shadowing is bad practice anyway. |
Agreed! We can set this up in Travis as part of the presubmit. If you're ok with it, I can try to do that, and also fix any existing shadow errors. |
I'd prefer it in a separate change, this one had already gotten big enough, but if you feel you want to add it here please feel free to. |
/lgtm |
/lgtm
|
[APPROVALNOTIFIER] This PR is APPROVED This pull-request has been approved by: IronPan The full list of commands accepted by this bot can be found here. The pull request process is described here
Needs approval from an approver in each of these files:
Approvers can indicate their approval by writing |
1 similar comment
[APPROVALNOTIFIER] This PR is APPROVED This pull-request has been approved by: IronPan The full list of commands accepted by this bot can be found here. The pull request process is described here
Needs approval from an approver in each of these files:
Approvers can indicate their approval by writing |
Generate new swagger definitions and use these to generate the frontend
APIs using
npm run apis
.This is to support filtering in List requests, as the current
grpc-gateway swagger generator tool does not support repeated fields in
requests used in GET endpoints.
Using POST lets us get around the problem in issue grpc-ecosystem/grpc-gateway#492
This change is