Как создать запись в объекте Context в начале запроса и получить его в конце запроса?

(отказ от ответственности: я балуюсь grpc)

У меня есть объект, который я хотел бы связать с каждым запросом, initializeв начале запроса и closeПосле того, как запрос сделан.

В настоящее время я достигаю этого, используя два ServerInterceptorsпервый заполняет объект в контексте, второй перехватывает onReady а также onComplete инициализировать и закрыть объект соответственно.

PopulateObjectServerInterceptor:

public class FooBarInterceptor implements ServerInterceptor {
@Override
public <ReqT, RespT> ServerCall.Listener<ReqT> interceptCall(ServerCall<ReqT, RespT> call, Metadata headers, ServerCallHandler<ReqT, RespT> next) {
    FooBar foobar = FooBar.create(foo, bar);
    Context ctx = Context.current().withValue(Constants.FOO_BAR, foobar);

    return Contexts.interceptCall(ctx, call, headers, next);
}

RequestLifecycleInterceptor

public class FooBarLifecycleServerInterceptor implements ServerInterceptor {
    @Override
    public <ReqT, RespT> ServerCall.Listener<ReqT> interceptCall(ServerCall<ReqT, RespT> call,
                                                                 Metadata headers,
                                                                 ServerCallHandler<ReqT, RespT> next) {

        final ServerCall.Listener<ReqT> original = next.startCall(call, headers);

        return new ForwardingServerCallListener.SimpleForwardingServerCallListener<ReqT>(original) {
            @Override
            public void onReady() {
                FooBar foobar = (FooBar) Context.key("foobarname").get();
                foobar.initialize()
                super.onReady();
            }

            @Override
            public void onMessage(final ReqT message) {
                FooBar foo = (FooBar) Context.key("foobar").get();
                foobar.someaction()
                super.onMessage(message);
            }

            @Override
            public void onComplete() {
                FooBar foo = (FooBar) Context.key("foobar").get();
                foobar.close()
                super.onComplete();
            }
        }
    } 
}

Это правильный / рекомендуемый способ? Мне интересно, могу ли я сделать это только с одним перехватчиком...

1 ответ

То, что вы делаете, выглядит хорошо. Другим способом является создание объекта в FooBarLifecycleServerInterceptor и, в первую очередь, избегание использования Context, но могут быть некоторые другие требования, не показанные в вашем примере.

Замечания:onReady может не делать то, что вы думаете, что делает. Если идея состоит в том, чтобы вызывать инициализацию в начале каждого вызова сервера, я думаю, вы должны просто сделать это, когда происходит перехват вызова.

Один из onComplete а также onCancel будет вызван, поэтому вы должны также позвонить close() когда onCancel называется.

Другие вопросы по тегам