Skip to content
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

Support adding gRPC interceptors using annotation '@GrpcInterceptor' #5397

Open
wants to merge 13 commits into
base: main
Choose a base branch
from

Conversation

Dogacel
Copy link
Contributor

@Dogacel Dogacel commented Jan 21, 2024

Motivation:

#5359

Adding annotations to add interceptors to gRPC services and methods.

Modifications:

  • Create the GrpcInterceptor annotation.
  • Update GrpcServerBuilder to find interceptors defined by annotations on gRPC servers and methods.

Result:

The way services are added to the HandlerRegistry has changed slightly, now we are not adding the whole Service objects as an entry but rather we find all MethodDescriptors under those services and add those methods one by one as Entry objects. The reason is that we can't create a single interceptor under a single Service object that would intercept individual methods, those methods need to be added as separate entries.

It can be checked if there is any method interception annotations and if there isn't any, it can fallback to the legacy logic (add the whole Service object as an Entry).

Question Do you think adding each method as a separate Entry would create performance issues?

Also, let me know if the interceptor order looks right based on the test.

Copy link
Contributor

@minwoox minwoox left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Sorry about the late review. Left some suggestions. 😄

public @interface GrpcInterceptor {

/**
* {@link GrpcExceptionHandlerFunction} implementation type.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
* {@link GrpcExceptionHandlerFunction} implementation type.
* {@link ServerInterceptor} implementation type.

@Dogacel Dogacel requested a review from minwoox January 26, 2024 15:17
Copy link

codecov bot commented Feb 4, 2024

Codecov Report

Attention: Patch coverage is 88.31169% with 9 lines in your changes missing coverage. Please review.

Project coverage is 74.01%. Comparing base (14c5566) to head (78e9d53).
Report is 72 commits behind head on main.

Current head 78e9d53 differs from pull request most recent head 89f1b76

Please upload reports for the commit 89f1b76 to get more accurate results.

Files Patch % Lines
.../linecorp/armeria/server/grpc/HandlerRegistry.java 89.18% 3 Missing and 5 partials ⚠️
...necorp/armeria/server/grpc/GrpcServiceBuilder.java 66.66% 0 Missing and 1 partial ⚠️
Additional details and impacted files
@@             Coverage Diff              @@
##               main    #5397      +/-   ##
============================================
- Coverage     74.05%   74.01%   -0.04%     
+ Complexity    21253    20745     -508     
============================================
  Files          1850     1800      -50     
  Lines         78600    76488    -2112     
  Branches      10032     9737     -295     
============================================
- Hits          58209    56615    -1594     
+ Misses        15686    15263     -423     
+ Partials       4705     4610      -95     

☔ View full report in Codecov by Sentry.
📢 Have feedback on the report? Share it here.

@github-actions github-actions bot added Stale and removed Stale labels Apr 9, 2024
Copy link
Member

@trustin trustin left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think this PR looks good. Is there anything left for discussion or feedback, @Dogacel ?

@Dogacel
Copy link
Contributor Author

Dogacel commented Apr 10, 2024

I think this PR looks good. Is there anything left for discussion or feedback, @Dogacel ?

I don't think anything left for discussion, @minwoox 's comment should be resolved now 🙂 I merged latest master to double check the state of the tests.

Comment on lines 474 to 477
final DependencyInjector dependencyInjector = new ReflectiveDependencyInjector();

// Intercept entries using {@link GrpcInterceptor} annotations and globally added interceptors.
interceptEntries(dependencyInjector);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It is not your work but there was a bug before. We should not create a DependencyInjector internally but use ServerConfig.dependencyInjector() instead.
Let me add a commit for that.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It was difficult to inject ServerConfig.dependencyInjector() without a huge refactoring. It would be better to use ReflectiveDependencyInjector as is in this PR. I will send a f/u PR to fix it when this PR is merged.
Could you add a TODO comment so as not to forget it?

// TODO(ikhoon): Use ServerConfig.dependencyInjector() instead of creating ReflectiveDependencyInjector directly.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

For now, I will review the implementation correctness.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I pushed a commit to fix checkstyle error. Let me know if there are any other concerns 🙂

@github-actions github-actions bot added the Stale label May 13, 2024
@Dogacel Dogacel force-pushed the dogac/5359-add-grpc-interceptor-annotation branch from 13d7826 to 1ffe89d Compare June 8, 2024 05:14
@Dogacel Dogacel requested review from trustin and ikhoon June 8, 2024 05:15
Copy link
Member

@trustin trustin left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looks good to me! I think we should do a follow-up so this uses the configured dependency injector.

@github-actions github-actions bot removed the Stale label Jun 9, 2024
private static class AnnotatedInterceptorServiceImpl extends TestServiceImplBase {

@Override
@GrpcInterceptor(InterceptorAddQux.class)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think the order should be:

  • global decorator -> class level decorator -> method level decorator
    like how @Decorator works.

However, the current order is reversed. Could you fix it?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Good point, let me fix 👍

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hmm taking a look at the test,

assertThat(headersCapture.get().get(TEST_HEADER)).isEqualTo("foobarqux");

Here first Foo (global) is appended, later bar which is the class level and finally qux which is the method level. Am I reading this incorrectly? I feel like this is the right order?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Note that we append headers in requests, not responses so the order of foo bar qux indicate order of decorators being executed.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It seems like addToHeader is called in the reverse order.
You can check the order by simply adding a log:

private static class InterceptorAddFoo implements ServerInterceptor {
    @Override
    public <REQ, RESP> Listener<REQ> interceptCall(ServerCall<REQ, RESP> call, Metadata headers,
                                                   ServerCallHandler<REQ, RESP> next) {
        System.err.println("Should call first");
        return next.startCall(addToHeader("foo", call), headers);
    }
}

private static class InterceptorAddBar implements ServerInterceptor {
    @Override
    public <REQ, RESP> Listener<REQ> interceptCall(ServerCall<REQ, RESP> call, Metadata headers,
                                                   ServerCallHandler<REQ, RESP> next) {
        System.err.println("Should call second");
        return next.startCall(addToHeader("bar", call), headers);
    }
}

private static class InterceptorAddQux implements ServerInterceptor {
    @Override
    public <REQ, RESP> Listener<REQ> interceptCall(ServerCall<REQ, RESP> call, Metadata headers,
                                                   ServerCallHandler<REQ, RESP> next) {
        System.err.println("Should call third");
        return next.startCall(addToHeader("qux", call), headers);
    }
}

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Fixed 🙌

@Dogacel Dogacel requested a review from minwoox June 24, 2024 19:10
@github-actions github-actions bot added the Stale label Jul 25, 2024
@Dogacel
Copy link
Contributor Author

Dogacel commented Jul 29, 2024

Bump ^ 🙂 Seems like this was forgotten

@github-actions github-actions bot removed the Stale label Jul 30, 2024
@github-actions github-actions bot added the Stale label Aug 29, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Add @GrpcInterceptor
4 participants