-
-
Notifications
You must be signed in to change notification settings - Fork 347
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
feat: batch check relations #1521
Conversation
d81f574
to
a3f2113
Compare
@alnr would you be able to let me know if this PR is on the right track? |
Thanks for implementing this. We've hit a roadblock and without this feature we have to write a bunch of custom code in our server which is getting cumbersome to maintain. Really looking forward to trying this. |
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.
Thank you very much for your contribution! This looks very good already.
Besides the comments below, the main thing that is missing are some tests. I'd like to see tests for the happy path, going over the batch limit (bad request), graceful handling of on errornous tuple in the batch (should not fail the whole batch, but just that check), empty batch, and whatever edge case you can think of.
I left some comments below. As for your questions, here's my take on it:
Should we limit the number of tuples this batch API accepts?
Yes, please make it configurable with a conservative default (10?)
Should we parallelize the check requests?
Yes, I'd make the number of concurrent checks another parameter.
Is implementing only the POST okay for the REST API?
Yes, that will suffice.
internal/check/handler.go
Outdated
@@ -49,13 +49,15 @@ func NewHandler(d handlerDependencies) *Handler { | |||
const ( | |||
RouteBase = "/relation-tuples/check" | |||
OpenAPIRouteBase = RouteBase + "/openapi" | |||
BatchRoute = "/relation-tuples/batchCheck" |
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.
How about /relation-tuples/batch/check
? Then we can have other batch ops in the future.
internal/check/handler.go
Outdated
} | ||
allowed, err := h.d.PermissionEngine().CheckIsMember(ctx, t[0], maxDepth) | ||
if err != nil { | ||
return nil, err |
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.
Should we annotate here which tuple caused the error? It might be frustrating to submit a batch of checks and get an error and then having to binary-search which tuple caused the error.
Alternatively we could just add the error to the results list and then commence with the next tuple. WDYT?
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.
Adding more context to the error is a good idea. The question then is whether to return errors at the tuple level vs for the API as a whole. If there are situations where clients might expect an error and would want to treat an error the same as receiving a false
allowed value, I could see a benefit in continuing on error and returning for each tuple if an error was generated. As far as I know though, that isn't a normal case, so I will just add tuple details to the error message.
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.
Changed my mind and went for proceeding with checking the whole batch and adding the error to the response for each tuple
internal/check/handler.go
Outdated
|
||
func (h *Handler) BatchCheck(ctx context.Context, req *rts.BatchCheckRequest) (*rts.BatchCheckResponse, error) { | ||
responses := make([]*rts.CheckResponse, len(req.Tuples)) | ||
for i, reqTuple := range req.Tuples { |
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 logic is duplicated from the REST handler here. Ideally we'd implement this once and have gRPC and REST call that function.
Thanks a lot for the review @hperl. I will let you know once this PR is updated. |
@hperl I have update the PR based on your feedback and it is now ready for review. |
I'm really looking forward to this functionality becoming available on Ory Network. @hperl is there anything else that needs to be done before this can be merged? |
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.
Thank you very much for your changes! This looks very good already. I just added some minor comments to imrpove this further.
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 looks perfect now! Thanks for all the good work! 🎉
Hey, thank you for the great feature! Now with this being merged in the master branch, could we also extend the Rest HTTP API (documentation) accordingly (https://www.ory.sh/docs/keto/reference/rest-api) and also make it available to the keto-client(s), especially for go (https://github.com/ory/keto-client-go)? Thank you! |
Very interesting! We were waiting for this since 2022. Awesome work! |
@hperl Cheers for getting this in, can we get a docker image released with this feature included? |
Related issue(s)
#812
Checklist
introduces a new feature.
contributing code guidelines.
vulnerability. If this pull request addresses a security vulnerability, I
confirm that I got the approval (please contact
[email protected]) from the maintainers to push
the changes.
works.
Further Comments
This change adds REST and gRPC endpoints for batch checking relations. The endpoint accepts a list of relation tuples to check, iterates through them (with concurrency), and returns a list of allowed responses.
REST API
New endpoint:
POST /relation-tuples/batch/check?max-depth=<depth>¶llelization-factor=<max-concurrent-requests>
Request body:
Response:
gRPC
New RPC:
CheckService/BatchCheck
Request:
Response
Notes: