higherkindness/mu-scala

Access Metadata in service

ThatScalaGuy opened this issue · 11 comments

Hi,

right now, I am migrating a bunch of gRPC services to mu-scala. Those Services heavily use Metadata to store JWT tokens.

Is there a way to access Metadata in the service?

Hi @ThatScalaGuy!

I would say that one of the best options is to create your own interceptor. We have an example of using interceptors for the metrics. Take a look at how they are added to the server and the client here:

And then the source code of the implementation:

Let me know if you have any doubts.

Hi, @fedefernandez
Sorry for the late reply.

Your suggestions were quite helpful for another issue I had. But unfortunately, it does not solve the problem I have right now.

I see no way to access the metadata directly in the service.
I think it needs some adoption in the macro and code generation part.

trait Greeter[F[_]] {
    def SayHello(req: HelloRequest): F[HelloResponse]
  }

Will become

trait Greeter[F[_]] {
    def SayHello(req: HelloRequest, meta: Metadata): F[HelloResponse]
  }

Next week I will spend some afford to adopt your library. I am looking forward to finding an implementation that fits in the project's roadmap.
Open for any discussion. Hopefully, my changes will be in the main branch soon

@ThatScalaGuy oh, I understand now. Yeah, at this moment is not possible. Your suggestion could make sense but the macro doesn't change the public interface. Another option is to have all the request objects extending from a type that contains the metadata. This is something we evaluated in the past.

@fedefernandez hi, finally, I fixed all M1 issues, and I can start working on that topic.

My approach is inspired by the akka grpc implementation I am currently using. They call it power API. In the end they have two traits - one with metadata and one without -
https://doc.akka.io/docs/akka-grpc/current/server/details.html

I don't know if that is the best approach, but it introduced no breaking changes. And you have a clean interface if you don't need metadata.

Your idea is also valid, but I have no idea for nice-looking client implementation. (or I misunderstood you)

Can you provide some sample code of the final trait and what client calls look like in the end? Probably that will help me to understand your thoughts.

ok, after reading your comment again, I understand your point.

@ThatScalaGuy thanks for the explanation, the approach of having two different traits could be a good choice.

I have a use case for this as well. This is effectively the way one can send arbitrary non-contextual information to the call itself. For additional logging, auth, etc without modification of the data. One ideally would be able to realize it on both the sender and on the receiver.

Similar to what the natchez tracing integration does.

Even if we could derive it like Kleisli[F, Metadata, *] as our algebra derivation.

@fedefernandez yep, looks promising.

@fedefernandez migrated the last 15 services. No issues have been found so far. From my side, the issue can be closed.

@ThatScalaGuy thanks for letting me know!