-
Notifications
You must be signed in to change notification settings - Fork 73
Add support for method_attribute() #137
Comments
I don't quite follow. What would the user code look like? |
By user code if you mean how would the generated method would eventually look like? Let's consider this proto definition (taken from the examples):
and from it, the client's method generated by
which, depending on the implementation of
Does that make sense? There are many such possibilities. Also, the support for |
And what's the proposed API here? What would a user write in their |
Here is what I think:
And the same can be done for As for how would users
|
Would love to hear from @carllerche and/or @per-gron as well. |
I think the general idea is good. I have not considered the details yet. One question worth exploring is what functionality can be added via this strategy vs. modifying the tower Service that the client dispatches into. Obviously, using attributes on methods allows avoiding a conditional on each request to check the gRPC method, but is that useful in practice? I would think so... what are some specific examples of method specific transformations? |
I think modifying the tower service wouldn't be flexible enough, as it doesn't probably allow plugging arbitrary behavior to the generated code. Also, think of cross-cutting concerns using the attribute-approach such as distributing tracing, regular loggings, measuring latency, call-counts, success-counts, failure-counts, other metrics generations, etc.
I've given few examples in the posts directed at @seanmonstar. Please have a look at them. I'd also like to add that adding this feature doesn't harm |
@snawaz i saw the examples, I just wasn't sure how common it would be to apply those annotations to only specific methods. Why not track latency and use zipkin for all methods? Anyway, I'm generally fine w/ the proposed strategy. |
I understand that most annotations would probably apply to all methods. However, since annotations allow arbitrary code to be plugged-in and it is not only about things which we can imagine like I feel I shouldn't prevent users from using it for specific methods just because I cannot imagine such a scenario — especially when it's kinda opt-in feature. And at the same time, I don't want to make the implementation too complex, so I'll use the following selectors:
to keep things relatively simple. If you like the idea, please assign this to me (I don't have the permission). I'll plan and start working on it. |
I think this seems like a cool idea. One question I have is if it isn't a bit too low level? This proposal seems to add two distinct features:
My thoughts:
If there is value in the attribute macro aspect of this, is it possible to avoid the attribute vs middleware incompatibility by making something that can convert an attribute into a tower middleware, or is that impossible by definition? Separate comment re your proposed |
One possibly large benefit of applying middleware for individual methods vs how Tower middleware is currently used in tower-grpc is that it would allow the middleware function to be instantiated for the specific request and response types of a given method rather than some generic "prost message"/"blob of bytes" type. It seems like this improvement is on its own nearly enough to implement the |
Another piece of feedback that is orthogonal to the other comments I've made: I would personally prefer to keep this out of
So I think it's worth exploring if it would be possible to make it so that the API for this is used where the services and middleware are set up. Not sure how to best do this... If it's not possible to do this with normal Rust generics this seems to me like a reasonable place to use a macro. Let me know if you want me to come up with a concrete example for how this could be done. |
A use case to consider: Middleware/attribute methods that need to be instantiated with run-time state. For example:
I'm not sure that it is required to support this*, but to me it seems like this could be easier to implement in a middleware (because they are closures that can naturally contain state)/non- *: It's possible to make the per-method attributes add metadata to the request and have some global middleware do the stateful things but it seems like an awkward approach to me. |
As we know,
prost_build::Config
supportsfield_attribute()
andtype_attribute()
. Sincetower-grpc
provides implementation of the traitprost_build::ServiceGenerator
, it'd be really good to havemethod_attribute()
on the generator, so that the generated methods can do things like initiating distributed tracing (zipkin):And then the users of
tower-grpc
can implement their ownzipkin_span
or whatever they want for their cross-cutting concerns.If the idea is good, then I can implement this feature and create the PR. Please review and let me know your thoughts.
The text was updated successfully, but these errors were encountered: