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

Error interceptor does not work as expected when using R2DBC repositories #342

Closed
vincentditlevinz opened this issue Mar 30, 2023 · 23 comments
Labels
bug Auto-generates notes
Milestone

Comments

@vincentditlevinz
Copy link

vincentditlevinz commented Mar 30, 2023

Hello,

I tried to make LogNet/grpc-spring-boot-starter work with R2DBC Spring data repositories. Here is a minimal project that helps to reproduce the issue.

Issue:
When an exception is thrown, the error interceptor (GRpcExceptionHandlerInterceptor) provided by the starter does not catch it and thus does not provide the correct error code to the client (see the readme file of my project for more details).

This is due to the way I map R2DBC results (I believe this is the right way to leverage R2DBC reactor api, isn't it ?):

skillService.findAllSkills().map(SkillMapper::toGrpc).collectList().map(SkillMapper::toGrpcResponse)
                     .subscribe(responseObserver::onNext, responseObserver::onError, responseObserver::onCompleted);

Note that the interceptor "works" if I use:

responseObserver.onNext(SkillMapper.toGrpcResponse(skillService.findAllSkills()));
responseObserver.onCompleted();

With the following helper which unfortunately uses toIterable()

public final class SkillMapper {
    private SkillMapper() {
    }


    public static ListSkills.ListSkillsResponse.Skill toGrpc(Skill skill) {
        return ListSkills.ListSkillsResponse.Skill.newBuilder()
                .setId(skill.getId())
                .setName(skill.getName())
                .setDescription(skill.getDescription())
                .build();
    }

    public static ListSkills.ListSkillsResponse toGrpcResponse(Flux<Skill> skills) {
        return ListSkills.ListSkillsResponse.newBuilder()
                .addAllSkills(skills.map(skill -> toGrpc(skill)).toIterable())
                .build();
    }
}

but I believe this is not the right way if I want to "really be reactive".

@jvmlet
Copy link
Collaborator

jvmlet commented Mar 30, 2023

Does this answer your question ?

@jvmlet
Copy link
Collaborator

jvmlet commented Mar 30, 2023

Looking at this line, if you throw exception from findAllSkills() without returning Flux, the exception won't be propagated to your responseObserver::onError

@jvmlet
Copy link
Collaborator

jvmlet commented Mar 30, 2023

Anyway, if you prefer to work with reactive API, I strongly suggest you to employ reactive-plugin and not implementing it by yourself. This starter seamlessly integrates with this protoc-plugin (or vise versa)

@vincentditlevinz
Copy link
Author

vincentditlevinz commented Mar 30, 2023

Anyway, if you prefer to work with reactive API, I strongly suggest you to employ reactive-plugin and not implementing it by yourself. This starter seamlessly integrates with this protoc-plugin (or vise versa)

I tried too, in order to have reactive API in handlers. I got the same issue.

Looking at this line, if you throw exception from findAllSkills() without returning Flux, the exception won't be propagated to your responseObserver::onError

Good point, I've replaced with this ugly code without any luck:

try {
            if (true) throw new IllegalStateException("test");
            return skillRepository.findAll(Sort.by("name"));
        } catch (Error e) {
            return Flux.error(e);
        }

Does this answer your question ?

Thank you ! I withdraw the @transactional and It works... I just wonder how to deal with transactions with such a limitation.

@jvmlet
Copy link
Collaborator

jvmlet commented Mar 30, 2023

I just wonder how to deal with transactions with such a limitation.

Suggest you to ask this question spring team, they should probably have the @Transactional which follows reactive observer and not method returns

If @Transactional is indeed the culprit, then nothing stops you from integrating reactive-plugin

@jvmlet
Copy link
Collaborator

jvmlet commented Mar 30, 2023

Another problem in your test :

try {
            if (true) throw new IllegalStateException("test");
            return skillRepository.findAll(Sort.by("name"));
        } catch (Error e) {
            return Flux.error(e);
        }

catch Error doesn't catch the IllegalStateException, can you just if (true) return Flux.error(new Exception());

@vincentditlevinz
Copy link
Author

catch Error doesn't catch the IllegalStateException, can you just if (true) return Flux.error(new Exception());

I did it with @transactional, put some more logs

public void listSkills(ListSkills.ListSkillsRequest request, StreamObserver<ListSkills.ListSkillsResponse> responseObserver) {
         skillService.findAllSkills().map(SkillMapper::toGrpc).collectList().map(SkillMapper::toGrpcResponse).log()
                 .subscribe(responseObserver::onNext, responseObserver::onError, responseObserver::onCompleted);
    }

and I tested with both

if (true) return Flux.error(new IllegalStateException("test"));
return skillRepository.findAll(Sort.by("name"));

and

if (true) throw new IllegalStateException("test");
return skillRepository.findAll(Sort.by("name"));

I have the exact same behavior and the same logs:

2023-03-30T17:01:29.389+02:00 DEBUG 74371 --- [ault-executor-0] o.s.r.c.R2dbcTransactionManager          : Creating new transaction with name [com.acme.apidomains.process_design.services.SkillServiceImpl.findAllSkills]: PROPAGATION_REQUIRED,ISOLATION_DEFAULT,readOnly
2023-03-30T17:01:29.391+02:00 DEBUG 74371 --- [ault-executor-0] o.s.r.c.R2dbcTransactionManager          : Acquired Connection [PooledConnection[PostgresqlConnection{client=io.r2dbc.postgresql.client.ReactorNettyClient@532bf0b0, codecs=io.r2dbc.postgresql.codec.DefaultCodecs@1e8a9892}]] for R2DBC transaction
2023-03-30T17:01:29.391+02:00 DEBUG 74371 --- [ault-executor-0] o.s.r.c.R2dbcTransactionManager          : Switching R2DBC Connection [PooledConnection[PostgresqlConnection{client=io.r2dbc.postgresql.client.ReactorNettyClient@532bf0b0, codecs=io.r2dbc.postgresql.codec.DefaultCodecs@1e8a9892}]] to manual commit
2023-03-30T17:01:29.392+02:00 DEBUG 74371 --- [ault-executor-0] o.s.r.c.R2dbcTransactionManager          : Starting R2DBC transaction on Connection [PooledConnection[PostgresqlConnection{client=io.r2dbc.postgresql.client.ReactorNettyClient@532bf0b0, codecs=io.r2dbc.postgresql.codec.DefaultCodecs@1e8a9892}]] using [ExtendedTransactionDefinition [transactionName='com.acme.apidomains.process_design.services.SkillServiceImpl.findAllSkills', readOnly=true, isolationLevel=null, lockWaitTimeout=PT0S]]
2023-03-30T17:01:29.397+02:00 DEBUG 74371 --- [tor-tcp-epoll-1] o.s.r.c.R2dbcTransactionManager          : Initiating transaction rollback
2023-03-30T17:01:29.397+02:00 DEBUG 74371 --- [tor-tcp-epoll-1] o.s.r.c.R2dbcTransactionManager          : Rolling back R2DBC transaction on Connection [PooledConnection[PostgresqlConnection{client=io.r2dbc.postgresql.client.ReactorNettyClient@532bf0b0, codecs=io.r2dbc.postgresql.codec.DefaultCodecs@1e8a9892}]]
2023-03-30T17:01:29.398+02:00 DEBUG 74371 --- [tor-tcp-epoll-1] o.s.r.c.R2dbcTransactionManager          : Releasing R2DBC Connection [PooledConnection[PostgresqlConnection{client=io.r2dbc.postgresql.client.ReactorNettyClient@532bf0b0, codecs=io.r2dbc.postgresql.codec.DefaultCodecs@1e8a9892}]] after transaction
2023-03-30T17:01:29.400+02:00 ERROR 74371 --- [tor-tcp-epoll-1] reactor.Mono.MapFuseable.1               : | onError(java.lang.IllegalStateException: test)
2023-03-30T17:01:29.400+02:00 ERROR 74371 --- [tor-tcp-epoll-1] reactor.Mono.MapFuseable.1               : 

java.lang.IllegalStateException: test
	at com.acme.apidomains.process_design.services.SkillServiceImpl.findAllSkills(SkillServiceImpl.java:21) ~[classes/:na]
	at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method) ~[na:na]
	at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:77) ~[na:na]
	at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) ~[na:na]
	at java.base/java.lang.reflect.Method.invoke(Method.java:568) ~[na:na]
	at org.springframework.aop.support.AopUtils.invokeJoinpointUsingReflection(AopUtils.java:343) ~[spring-aop-6.0.7.jar:6.0.7]
	at org.springframework.aop.framework.ReflectiveMethodInvocation.invokeJoinpoint(ReflectiveMethodInvocation.java:196) ~[spring-aop-6.0.7.jar:6.0.7]
	at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:163) ~[spring-aop-6.0.7.jar:6.0.7]
	at org.springframework.aop.framework.CglibAopProxy$CglibMethodInvocation.proceed(CglibAopProxy.java:750) ~[spring-aop-6.0.7.jar:6.0.7]
	at org.springframework.transaction.interceptor.TransactionInterceptor$1.proceedWithInvocation(TransactionInterceptor.java:123) ~[spring-tx-6.0.7.jar:6.0.7]
	at org.springframework.transaction.interceptor.TransactionAspectSupport$ReactiveTransactionSupport.lambda$invokeWithinTransaction$2(TransactionAspectSupport.java:947) ~[spring-tx-6.0.7.jar:6.0.7]
	at reactor.core.publisher.FluxUsingWhen.deriveFluxFromResource(FluxUsingWhen.java:120) ~[reactor-core-3.5.4.jar:3.5.4]
	at reactor.core.publisher.FluxUsingWhen.access$000(FluxUsingWhen.java:54) ~[reactor-core-3.5.4.jar:3.5.4]
	at reactor.core.publisher.FluxUsingWhen$ResourceSubscriber.onNext(FluxUsingWhen.java:193) ~[reactor-core-3.5.4.jar:3.5.4]
	at reactor.core.publisher.FluxSwitchIfEmpty$SwitchIfEmptySubscriber.onNext(FluxSwitchIfEmpty.java:74) ~[reactor-core-3.5.4.jar:3.5.4]
	at reactor.core.publisher.FluxMapFuseable$MapFuseableSubscriber.onNext(FluxMapFuseable.java:129) ~[reactor-core-3.5.4.jar:3.5.4]
	at reactor.core.publisher.MonoFlatMap$FlatMapMain.secondComplete(MonoFlatMap.java:245) ~[reactor-core-3.5.4.jar:3.5.4]
	at reactor.core.publisher.MonoFlatMap$FlatMapInner.onNext(MonoFlatMap.java:305) ~[reactor-core-3.5.4.jar:3.5.4]
	at reactor.core.publisher.MonoFlatMap$FlatMapMain.secondComplete(MonoFlatMap.java:245) ~[reactor-core-3.5.4.jar:3.5.4]
	at reactor.core.publisher.MonoFlatMap$FlatMapInner.onNext(MonoFlatMap.java:305) ~[reactor-core-3.5.4.jar:3.5.4]
	at reactor.core.publisher.MonoFlatMap$FlatMapMain.secondComplete(MonoFlatMap.java:245) ~[reactor-core-3.5.4.jar:3.5.4]
	at reactor.core.publisher.MonoFlatMap$FlatMapInner.onNext(MonoFlatMap.java:305) ~[reactor-core-3.5.4.jar:3.5.4]
	at reactor.core.publisher.FluxOnErrorResume$ResumeSubscriber.onNext(FluxOnErrorResume.java:79) ~[reactor-core-3.5.4.jar:3.5.4]
	at reactor.core.publisher.MonoIgnoreThen$ThenIgnoreMain.complete(MonoIgnoreThen.java:292) ~[reactor-core-3.5.4.jar:3.5.4]
	at reactor.core.publisher.MonoIgnoreThen$ThenIgnoreMain.onNext(MonoIgnoreThen.java:187) ~[reactor-core-3.5.4.jar:3.5.4]
	at reactor.core.publisher.MonoIgnoreThen$ThenIgnoreMain.subscribeNext(MonoIgnoreThen.java:236) ~[reactor-core-3.5.4.jar:3.5.4]
	at reactor.core.publisher.MonoIgnoreThen$ThenIgnoreMain.onComplete(MonoIgnoreThen.java:203) ~[reactor-core-3.5.4.jar:3.5.4]
	at reactor.core.publisher.MonoPeekTerminal$MonoTerminalPeekSubscriber.onComplete(MonoPeekTerminal.java:299) ~[reactor-core-3.5.4.jar:3.5.4]
	at reactor.core.publisher.MonoIgnoreElements$IgnoreElementsSubscriber.onComplete(MonoIgnoreElements.java:89) ~[reactor-core-3.5.4.jar:3.5.4]
	at reactor.core.publisher.MonoIgnoreElements$IgnoreElementsSubscriber.onComplete(MonoIgnoreElements.java:89) ~[reactor-core-3.5.4.jar:3.5.4]
	at reactor.core.publisher.Operators$MultiSubscriptionSubscriber.onComplete(Operators.java:2205) ~[reactor-core-3.5.4.jar:3.5.4]
	at reactor.core.publisher.MonoFlatMap$FlatMapMain.secondComplete(MonoFlatMap.java:246) ~[reactor-core-3.5.4.jar:3.5.4]
	at reactor.core.publisher.MonoFlatMap$FlatMapInner.onNext(MonoFlatMap.java:305) ~[reactor-core-3.5.4.jar:3.5.4]
	at reactor.core.publisher.FluxOnErrorResume$ResumeSubscriber.onNext(FluxOnErrorResume.java:79) ~[reactor-core-3.5.4.jar:3.5.4]
	at reactor.core.publisher.MonoIgnoreThen$ThenIgnoreMain.complete(MonoIgnoreThen.java:292) ~[reactor-core-3.5.4.jar:3.5.4]
	at reactor.core.publisher.MonoIgnoreThen$ThenIgnoreMain.onNext(MonoIgnoreThen.java:187) ~[reactor-core-3.5.4.jar:3.5.4]
	at reactor.core.publisher.MonoIgnoreThen$ThenIgnoreMain.subscribeNext(MonoIgnoreThen.java:236) ~[reactor-core-3.5.4.jar:3.5.4]
	at reactor.core.publisher.MonoIgnoreThen$ThenIgnoreMain.onComplete(MonoIgnoreThen.java:203) ~[reactor-core-3.5.4.jar:3.5.4]
	at reactor.core.publisher.MonoPeekTerminal$MonoTerminalPeekSubscriber.onComplete(MonoPeekTerminal.java:299) ~[reactor-core-3.5.4.jar:3.5.4]
	at reactor.core.publisher.MonoIgnoreThen$ThenIgnoreMain.onComplete(MonoIgnoreThen.java:209) ~[reactor-core-3.5.4.jar:3.5.4]
	at reactor.core.publisher.MonoIgnoreThen$ThenIgnoreMain.subscribeNext(MonoIgnoreThen.java:238) ~[reactor-core-3.5.4.jar:3.5.4]
	at reactor.core.publisher.MonoIgnoreThen$ThenIgnoreMain.onComplete(MonoIgnoreThen.java:203) ~[reactor-core-3.5.4.jar:3.5.4]
	at reactor.core.publisher.MonoPeekTerminal$MonoTerminalPeekSubscriber.onComplete(MonoPeekTerminal.java:299) ~[reactor-core-3.5.4.jar:3.5.4]
	at reactor.core.publisher.FluxPeekFuseable$PeekConditionalSubscriber.onComplete(FluxPeekFuseable.java:940) ~[reactor-core-3.5.4.jar:3.5.4]
	at reactor.core.publisher.MonoIgnoreElements$IgnoreElementsSubscriber.onComplete(MonoIgnoreElements.java:89) ~[reactor-core-3.5.4.jar:3.5.4]
	at io.r2dbc.postgresql.util.FluxDiscardOnCancel$FluxDiscardOnCancelSubscriber.onComplete(FluxDiscardOnCancel.java:104) ~[r2dbc-postgresql-1.0.1.RELEASE.jar:1.0.1.RELEASE]
	at reactor.core.publisher.Operators.complete(Operators.java:137) ~[reactor-core-3.5.4.jar:3.5.4]
	at reactor.core.publisher.FluxEmpty.subscribe(FluxEmpty.java:42) ~[reactor-core-3.5.4.jar:3.5.4]
	at reactor.core.publisher.FluxDefer.subscribe(FluxDefer.java:54) ~[reactor-core-3.5.4.jar:3.5.4]
	at io.r2dbc.postgresql.util.FluxDiscardOnCancel.subscribe(FluxDiscardOnCancel.java:49) ~[r2dbc-postgresql-1.0.1.RELEASE.jar:1.0.1.RELEASE]
	at reactor.core.publisher.Mono.subscribe(Mono.java:4485) ~[reactor-core-3.5.4.jar:3.5.4]
	at reactor.core.publisher.MonoIgnoreThen$ThenIgnoreMain.subscribeNext(MonoIgnoreThen.java:263) ~[reactor-core-3.5.4.jar:3.5.4]
	at reactor.core.publisher.MonoIgnoreThen$ThenIgnoreMain.onComplete(MonoIgnoreThen.java:203) ~[reactor-core-3.5.4.jar:3.5.4]
	at reactor.core.publisher.MonoIgnoreElements$IgnoreElementsSubscriber.onComplete(MonoIgnoreElements.java:89) ~[reactor-core-3.5.4.jar:3.5.4]
	at io.r2dbc.postgresql.util.FluxDiscardOnCancel$FluxDiscardOnCancelSubscriber.onComplete(FluxDiscardOnCancel.java:104) ~[r2dbc-postgresql-1.0.1.RELEASE.jar:1.0.1.RELEASE]
	at reactor.core.publisher.MonoIgnoreElements$IgnoreElementsSubscriber.onComplete(MonoIgnoreElements.java:89) ~[reactor-core-3.5.4.jar:3.5.4]
	at io.r2dbc.postgresql.util.FluxDiscardOnCancel$FluxDiscardOnCancelSubscriber.onComplete(FluxDiscardOnCancel.java:104) ~[r2dbc-postgresql-1.0.1.RELEASE.jar:1.0.1.RELEASE]
	at reactor.core.publisher.FluxPeek$PeekSubscriber.onComplete(FluxPeek.java:260) ~[reactor-core-3.5.4.jar:3.5.4]
	at reactor.core.publisher.FluxPeek$PeekSubscriber.onComplete(FluxPeek.java:260) ~[reactor-core-3.5.4.jar:3.5.4]
	at reactor.core.publisher.FluxHandle$HandleSubscriber.onComplete(FluxHandle.java:222) ~[reactor-core-3.5.4.jar:3.5.4]
	at io.r2dbc.postgresql.util.FluxDiscardOnCancel$FluxDiscardOnCancelSubscriber.onComplete(FluxDiscardOnCancel.java:104) ~[r2dbc-postgresql-1.0.1.RELEASE.jar:1.0.1.RELEASE]

And in both cases (return Flux.error or throw it) the streamObserver.onError is correctly called (see line 2023-03-30T17:01:29.400+02:00 ERROR 74371 --- [tor-tcp-epoll-1] reactor.Mono.MapFuseable.1 : | onError(java.lang.IllegalStateException: test) printed by .log())

@vincentditlevinz
Copy link
Author

vincentditlevinz commented Mar 30, 2023

Some takeaways:

  • I don't have to wrap exceptions in a Flux.
  • Removing Spring Transaction interceptor is a workaround. Maybe GRpcExceptionHandlerInterceptor is called too early ?

Actually, to correctly handle the exception I have to do this

public void listSkills(ListSkills.ListSkillsRequest request, StreamObserver<ListSkills.ListSkillsResponse> responseObserver) {
         skillService.findAllSkills().map(SkillMapper::toGrpc).collectList().map(SkillMapper::toGrpcResponse).log()
                 .onErrorMap(ex -> Status.INTERNAL.withDescription(ex.getLocalizedMessage()).withCause(ex).asRuntimeException())
                 .subscribe(responseObserver::onNext, responseObserver::onError, responseObserver::onCompleted);
    }

But I expected the GRpcExceptionHandlerInterceptor to do this automatically.

I did the same experience with your concurrent starter and It worked as expected (that is I can handle all exceptions with a global interceptor), but I like your stack too !

@vincentditlevinz
Copy link
Author

vincentditlevinz commented Mar 30, 2023

I did some tests, Spring Tx interceptor has LowestPrecedence and GRpcExceptionHandlerInterceptor has HighestPrecedence.
I even played with various precedences thanks to:

  • grpc.recovery.interceptor-order
  • Or :
@SpringBootApplication
@EnableTransactionManagement(proxyTargetClass = true, order = Ordered.LOWEST_PRECEDENCE)
public class ApiDomainsApplication {

	public static void main(String[] args) {
		SpringApplication.run(ApiDomainsApplication.class, args);
	}

}

Always the same outcome.

I tried to get some debug logs with logging.level.org.lognet=debug but there is not much log in the code. With a debugger it appeared GRpcExceptionHandlerInterceptor is always called before Spring transactions management so I think this is probably the explanation. Playing with interceptor ordering didn't help much although I checked values of precedence I provided were correctly taken into account. There is a kind of magic somewhere, I am a bit confused with this reactive stack.

Note: If you look at the log of my LogGrpcInterceptor and add @Order(Ordered.LOWEST_PRECEDENCE) or @Order(Ordered.HIGHEST_PRECEDENCE), it is always positionned before Spring Tx logs, so too early. So, if GRpcExceptionHandlerInterceptor works the same we have a confirmation.
I wonder why I don't have the issue with this other starter

@vincentditlevinz
Copy link
Author

Well the answer is : their interceptor has precedence over Spring Tx interceptor out of the box.

@jvmlet
Copy link
Collaborator

jvmlet commented Mar 30, 2023

higher than highest?

@jvmlet
Copy link
Collaborator

jvmlet commented Mar 30, 2023

Have a closer look at this blog post :
https://spring.io/blog/2019/05/16/reactive-transactions-with-spring , especially at this :

Spring distinguishes (based on method return types) which type of transaction management to apply:

* Method returns a Publisher type: Reactive Transaction Management
* All other return types: Imperative Transaction Management

Looks you have no choice but extract the transactional method into separate service that returns Publisher and call it from grpc service.

I have doubts that order of tx interceptor matters here because I'm processing only grpc interceptors.

@vincentditlevinz
Copy link
Author

vincentditlevinz commented Mar 31, 2023

All other return types: Imperative Transaction Management
Looks you have no choice but extract the transactional method into separate service that returns Publisher and call it from grpc service.

This is already what I do, don't I ?

higher than highest

No, that's why there is probably an issue when using this starter with r2dbc. I tested various config of precedence without any effect, there is a smell here...

@jvmlet
Copy link
Collaborator

jvmlet commented Mar 31, 2023

Can you please try to add Throwable to your GrpcExceptionAdvice

@jvmlet
Copy link
Collaborator

jvmlet commented Mar 31, 2023

If you put break point here

, line 52 , 61 and 75 ?

@vincentditlevinz
Copy link
Author

I did, same outcome, I stopped in each break point you specified before Spring Tx manager wrote any logs in the console. You can give it a try yourself with the project I packaged, it should run rather easily on any laptop.

For the moment I have to consider that this starter is not compatible with a fully reactive stack, whereas this one is.
Thanks for your time.

@jvmlet jvmlet added bug Auto-generates notes enhancement Auto-generates notes and removed enhancement Auto-generates notes labels Apr 11, 2023
@jvmlet jvmlet added this to the 5.1.0 milestone Apr 11, 2023
@jvmlet jvmlet closed this as completed in 0ef79fe Apr 11, 2023
@jvmlet
Copy link
Collaborator

jvmlet commented Apr 11, 2023

@vincentditlevinz , I was able to reproduce the issue (not related to @Transactional)
Please have a look at tests and service implementation in this commit
I'll appreciate if you can update your demo project to version 5.1.0-SNAPSHOT and retry

@vincentditlevinz
Copy link
Author

vincentditlevinz commented Apr 11, 2023

Hello @jvmlet.
I upgraded to 5.1.0 and switched to Reactor API with this commit.
I still have an issue (which disappears when removing @transactional annotation):

java.lang.NullPointerException: Cannot invoke "java.util.concurrent.atomic.AtomicBoolean.get()" because the return value of "io.grpc.Context$Key.get()" is null
	at org.lognet.springboot.grpc.recovery.GRpcExceptionHandlerInterceptor$1.close(GRpcExceptionHandlerInterceptor.java:47) ~[grpc-spring-boot-starter-5.1.0.jar:na]
	at io.grpc.PartialForwardingServerCall.close(PartialForwardingServerCall.java:48) ~[grpc-api-1.54.0.jar:1.54.0]
	at io.grpc.ForwardingServerCall.close(ForwardingServerCall.java:22) ~[grpc-api-1.54.0.jar:1.54.0]
	at io.grpc.ForwardingServerCall$SimpleForwardingServerCall.close(ForwardingServerCall.java:44) ~[grpc-api-1.54.0.jar:1.54.0]
	at org.lognet.springboot.grpc.autoconfigure.metrics.GRpcMetricsAutoConfiguration$MonitoringServerCall.close(GRpcMetricsAutoConfiguration.java:88) ~[grpc-spring-boot-starter-5.1.0.jar:na]
	at io.grpc.stub.ServerCalls$ServerCallStreamObserverImpl.onError(ServerCalls.java:389) ~[grpc-stub-1.53.0.jar:1.53.0]
	at com.salesforce.reactorgrpc.stub.ServerCalls.lambda$oneToOne$1(ServerCalls.java:49) ~[reactor-grpc-stub-1.2.3.jar:na]
	at reactor.core.publisher.LambdaMonoSubscriber.doError(LambdaMonoSubscriber.java:155) ~[reactor-core-3.5.4.jar:3.5.4]
	at reactor.core.publisher.LambdaMonoSubscriber.onError(LambdaMonoSubscriber.java:150) ~[reactor-core-3.5.4.jar:3.5.4]
	at reactor.core.publisher.MonoPeekTerminal$MonoTerminalPeekSubscriber.onError(MonoPeekTerminal.java:258) ~[reactor-core-3.5.4.jar:3.5.4]
	at reactor.core.publisher.FluxMapFuseable$MapFuseableConditionalSubscriber.onError(FluxMapFuseable.java:340) ~[reactor-core-3.5.4.jar:3.5.4]
	at reactor.core.publisher.MonoCollectList$MonoCollectListSubscriber.onError(MonoCollectList.java:108) ~[reactor-core-3.5.4.jar:3.5.4]
	at reactor.core.publisher.FluxMapFuseable$MapFuseableSubscriber.onError(FluxMapFuseable.java:142) ~[reactor-core-3.5.4.jar:3.5.4]
	at reactor.core.publisher.FluxContextWrite$ContextWriteSubscriber.onError(FluxContextWrite.java:121) ~[reactor-core-3.5.4.jar:3.5.4]
	at reactor.core.publisher.FluxContextWrite$ContextWriteSubscriber.onError(FluxContextWrite.java:121) ~[reactor-core-3.5.4.jar:3.5.4]
	at reactor.core.publisher.MonoFlatMapMany$FlatMapManyInner.onError(MonoFlatMapMany.java:255) ~[reactor-core-3.5.4.jar:3.5.4]
	at reactor.core.publisher.FluxOnErrorResume$ResumeSubscriber.onError(FluxOnErrorResume.java:106) ~[reactor-core-3.5.4.jar:3.5.4]
	at reactor.core.publisher.Operators.error(Operators.java:198) ~[reactor-core-3.5.4.jar:3.5.4]
	at reactor.core.publisher.MonoError.subscribe(MonoError.java:53) ~[reactor-core-3.5.4.jar:3.5.4]
	at reactor.core.publisher.Mono.subscribe(Mono.java:4485) ~[reactor-core-3.5.4.jar:3.5.4]
	at reactor.core.publisher.FluxOnErrorResume$ResumeSubscriber.onError(FluxOnErrorResume.java:103) ~[reactor-core-3.5.4.jar:3.5.4]
	at reactor.core.publisher.FluxUsingWhen$UsingWhenSubscriber.deferredError(FluxUsingWhen.java:398) ~[reactor-core-3.5.4.jar:3.5.4]
	at reactor.core.publisher.FluxUsingWhen$RollbackInner.onComplete(FluxUsingWhen.java:475) ~[reactor-core-3.5.4.jar:3.5.4]
	at reactor.core.publisher.Operators$MultiSubscriptionSubscriber.onComplete(Operators.java:2205) ~[reactor-core-3.5.4.jar:3.5.4]
	at reactor.core.publisher.MonoFlatMap$FlatMapMain.secondComplete(MonoFlatMap.java:250) ~[reactor-core-3.5.4.jar:3.5.4]
	at reactor.core.publisher.MonoFlatMap$FlatMapInner.onComplete(MonoFlatMap.java:324) ~[reactor-core-3.5.4.jar:3.5.4]
	at reactor.core.publisher.MonoIgnoreThen$ThenIgnoreMain.onComplete(MonoIgnoreThen.java:209) ~[reactor-core-3.5.4.jar:3.5.4]
	at reactor.core.publisher.MonoIgnoreThen$ThenIgnoreMain.onComplete(MonoIgnoreThen.java:209) ~[reactor-core-3.5.4.jar:3.5.4]
	at reactor.core.publisher.FluxOnErrorReturn$ReturnSubscriber.onComplete(FluxOnErrorReturn.java:169) ~[reactor-core-3.5.4.jar:3.5.4]
	at reactor.core.publisher.MonoPeekTerminal$MonoTerminalPeekSubscriber.onComplete(MonoPeekTerminal.java:299) ~[reactor-core-3.5.4.jar:3.5.4]
	at reactor.core.publisher.Operators$MultiSubscriptionSubscriber.onComplete(Operators.java:2205) ~[reactor-core-3.5.4.jar:3.5.4]
	at reactor.core.publisher.Operators$MultiSubscriptionSubscriber.onComplete(Operators.java:2205) ~[reactor-core-3.5.4.jar:3.5.4]
	at reactor.core.publisher.MonoFlatMap$FlatMapMain.secondComplete(MonoFlatMap.java:250) ~[reactor-core-3.5.4.jar:3.5.4]
	at reactor.core.publisher.MonoFlatMap$FlatMapInner.onComplete(MonoFlatMap.java:324) ~[reactor-core-3.5.4.jar:3.5.4]
	at reactor.core.publisher.FluxPeek$PeekSubscriber.onComplete(FluxPeek.java:260) ~[reactor-core-3.5.4.jar:3.5.4]
	at reactor.core.publisher.Operators$MultiSubscriptionSubscriber.onComplete(Operators.java:2205) ~[reactor-core-3.5.4.jar:3.5.4]
	at reactor.core.publisher.MonoIgnoreThen$ThenIgnoreMain.onComplete(MonoIgnoreThen.java:209) ~[reactor-core-3.5.4.jar:3.5.4]
	at reactor.core.publisher.MonoIgnoreThen$ThenIgnoreMain.onComplete(MonoIgnoreThen.java:209) ~[reactor-core-3.5.4.jar:3.5.4]
	at reactor.pool.SimpleDequePool.maybeRecycleAndDrain(SimpleDequePool.java:531) ~[reactor-pool-1.0.0.jar:1.0.0]
	at reactor.pool.SimpleDequePool$QueuePoolRecyclerInner.onComplete(SimpleDequePool.java:761) ~[reactor-pool-1.0.0.jar:1.0.0]
	at reactor.core.publisher.Operators.complete(Operators.java:137) ~[reactor-core-3.5.4.jar:3.5.4]
	at reactor.core.publisher.MonoEmpty.subscribe(MonoEmpty.java:46) ~[reactor-core-3.5.4.jar:3.5.4]
	at reactor.core.publisher.Mono.subscribe(Mono.java:4485) ~[reactor-core-3.5.4.jar:3.5.4]
	at reactor.pool.SimpleDequePool$QueuePoolRecyclerMono.subscribe(SimpleDequePool.java:873) ~[reactor-pool-1.0.0.jar:1.0.0]
	at reactor.core.publisher.MonoDefer.subscribe(MonoDefer.java:52) ~[reactor-core-3.5.4.jar:3.5.4]
	at reactor.core.publisher.MonoIgnoreThen$ThenIgnoreMain.subscribeNext(MonoIgnoreThen.java:240) ~[reactor-core-3.5.4.jar:3.5.4]
	at reactor.core.publisher.MonoIgnoreThen$ThenIgnoreMain.onComplete(MonoIgnoreThen.java:203) ~[reactor-core-3.5.4.jar:3.5.4]
	at reactor.core.publisher.FluxPeek$PeekSubscriber.onComplete(FluxPeek.java:260) ~[reactor-core-3.5.4.jar:3.5.4]
	at reactor.core.publisher.Operators.complete(Operators.java:137) ~[reactor-core-3.5.4.jar:3.5.4]
	at reactor.core.publisher.MonoEmpty.subscribe(MonoEmpty.java:46) ~[reactor-core-3.5.4.jar:3.5.4]
	at reactor.core.publisher.Mono.subscribe(Mono.java:4485) ~[reactor-core-3.5.4.jar:3.5.4]
	at reactor.core.publisher.MonoIgnoreThen$ThenIgnoreMain.subscribeNext(MonoIgnoreThen.java:263) ~[reactor-core-3.5.4.jar:3.5.4]
	at reactor.core.publisher.MonoIgnoreThen.subscribe(MonoIgnoreThen.java:51) ~[reactor-core-3.5.4.jar:3.5.4]
	at reactor.core.publisher.MonoDefer.subscribe(MonoDefer.java:52) ~[reactor-core-3.5.4.jar:3.5.4]
	at reactor.core.publisher.MonoIgnoreThen$ThenIgnoreMain.subscribeNext(MonoIgnoreThen.java:240) ~[reactor-core-3.5.4.jar:3.5.4]
	at reactor.core.publisher.MonoIgnoreThen$ThenIgnoreMain.onComplete(MonoIgnoreThen.java:203) ~[reactor-core-3.5.4.jar:3.5.4]
	at reactor.core.publisher.MonoIgnoreElements$IgnoreElementsSubscriber.onComplete(MonoIgnoreElements.java:89) ~[reactor-core-3.5.4.jar:3.5.4]
	at reactor.core.publisher.FluxHandleFuseable$HandleFuseableSubscriber.onComplete(FluxHandleFuseable.java:238) ~[reactor-core-3.5.4.jar:3.5.4]
	at reactor.core.publisher.MonoSupplier$MonoSupplierSubscription.request(MonoSupplier.java:148) ~[reactor-core-3.5.4.jar:3.5.4]
	at reactor.core.publisher.FluxHandleFuseable$HandleFuseableSubscriber.request(FluxHandleFuseable.java:259) ~[reactor-core-3.5.4.jar:3.5.4]
	at reactor.core.publisher.MonoIgnoreElements$IgnoreElementsSubscriber.onSubscribe(MonoIgnoreElements.java:72) ~[reactor-core-3.5.4.jar:3.5.4]
	at reactor.core.publisher.FluxHandleFuseable$HandleFuseableSubscriber.onSubscribe(FluxHandleFuseable.java:163) ~[reactor-core-3.5.4.jar:3.5.4]
	at reactor.core.publisher.MonoSupplier.subscribe(MonoSupplier.java:48) ~[reactor-core-3.5.4.jar:3.5.4]
	at reactor.core.publisher.Mono.subscribe(Mono.java:4485) ~[reactor-core-3.5.4.jar:3.5.4]
	at reactor.core.publisher.MonoIgnoreThen$ThenIgnoreMain.subscribeNext(MonoIgnoreThen.java:263) ~[reactor-core-3.5.4.jar:3.5.4]
	at reactor.core.publisher.MonoIgnoreThen.subscribe(MonoIgnoreThen.java:51) ~[reactor-core-3.5.4.jar:3.5.4]
	at reactor.core.publisher.InternalMonoOperator.subscribe(InternalMonoOperator.java:64) ~[reactor-core-3.5.4.jar:3.5.4]
	at reactor.core.publisher.MonoDefer.subscribe(MonoDefer.java:52) ~[reactor-core-3.5.4.jar:3.5.4]
	at reactor.core.publisher.MonoFlatMap$FlatMapMain.onNext(MonoFlatMap.java:165) ~[reactor-core-3.5.4.jar:3.5.4]
	at reactor.core.publisher.FluxMap$MapSubscriber.onNext(FluxMap.java:122) ~[reactor-core-3.5.4.jar:3.5.4]
	at reactor.core.publisher.Operators$ScalarSubscription.request(Operators.java:2545) ~[reactor-core-3.5.4.jar:3.5.4]
	at reactor.core.publisher.FluxMap$MapSubscriber.request(FluxMap.java:164) ~[reactor-core-3.5.4.jar:3.5.4]
	at reactor.core.publisher.MonoFlatMap$FlatMapMain.request(MonoFlatMap.java:194) ~[reactor-core-3.5.4.jar:3.5.4]
	at reactor.core.publisher.Operators$MultiSubscriptionSubscriber.set(Operators.java:2341) ~[reactor-core-3.5.4.jar:3.5.4]
	at reactor.core.publisher.FluxOnErrorResume$ResumeSubscriber.onSubscribe(FluxOnErrorResume.java:74) ~[reactor-core-3.5.4.jar:3.5.4]
	at reactor.core.publisher.MonoFlatMap$FlatMapMain.onSubscribe(MonoFlatMap.java:117) ~[reactor-core-3.5.4.jar:3.5.4]
	at reactor.core.publisher.FluxMap$MapSubscriber.onSubscribe(FluxMap.java:92) ~[reactor-core-3.5.4.jar:3.5.4]
	at reactor.core.publisher.MonoJust.subscribe(MonoJust.java:55) ~[reactor-core-3.5.4.jar:3.5.4]
	at reactor.core.publisher.MonoDeferContextual.subscribe(MonoDeferContextual.java:55) ~[reactor-core-3.5.4.jar:3.5.4]
	at reactor.core.publisher.InternalMonoOperator.subscribe(InternalMonoOperator.java:64) ~[reactor-core-3.5.4.jar:3.5.4]
	at reactor.core.publisher.MonoDefer.subscribe(MonoDefer.java:52) ~[reactor-core-3.5.4.jar:3.5.4]
	at reactor.core.publisher.MonoIgnoreThen$ThenIgnoreMain.subscribeNext(MonoIgnoreThen.java:240) ~[reactor-core-3.5.4.jar:3.5.4]
	at reactor.core.publisher.MonoIgnoreThen$ThenIgnoreMain.onComplete(MonoIgnoreThen.java:203) ~[reactor-core-3.5.4.jar:3.5.4]
	at reactor.core.publisher.FluxOnErrorReturn$ReturnSubscriber.onComplete(FluxOnErrorReturn.java:169) ~[reactor-core-3.5.4.jar:3.5.4]
	at reactor.core.publisher.MonoPeekTerminal$MonoTerminalPeekSubscriber.onComplete(MonoPeekTerminal.java:299) ~[reactor-core-3.5.4.jar:3.5.4]
	at reactor.core.publisher.MonoIgnoreElements$IgnoreElementsSubscriber.onComplete(MonoIgnoreElements.java:89) ~[reactor-core-3.5.4.jar:3.5.4]
	at io.r2dbc.postgresql.util.FluxDiscardOnCancel$FluxDiscardOnCancelSubscriber.onComplete(FluxDiscardOnCancel.java:104) ~[r2dbc-postgresql-1.0.1.RELEASE.jar:1.0.1.RELEASE]
	at reactor.core.publisher.Operators.complete(Operators.java:137) ~[reactor-core-3.5.4.jar:3.5.4]
	at reactor.core.publisher.FluxEmpty.subscribe(FluxEmpty.java:42) ~[reactor-core-3.5.4.jar:3.5.4]
	at reactor.core.publisher.FluxDefer.subscribe(FluxDefer.java:54) ~[reactor-core-3.5.4.jar:3.5.4]
	at io.r2dbc.postgresql.util.FluxDiscardOnCancel.subscribe(FluxDiscardOnCancel.java:49) ~[r2dbc-postgresql-1.0.1.RELEASE.jar:1.0.1.RELEASE]
	at reactor.core.publisher.Mono.subscribe(Mono.java:4485) ~[reactor-core-3.5.4.jar:3.5.4]
	at reactor.core.publisher.MonoIgnoreThen$ThenIgnoreMain.subscribeNext(MonoIgnoreThen.java:263) ~[reactor-core-3.5.4.jar:3.5.4]
	at reactor.core.publisher.MonoIgnoreThen.subscribe(MonoIgnoreThen.java:51) ~[reactor-core-3.5.4.jar:3.5.4]
	at reactor.core.publisher.MonoDefer.subscribe(MonoDefer.java:52) ~[reactor-core-3.5.4.jar:3.5.4]
	at reactor.core.publisher.MonoDefer.subscribe(MonoDefer.java:52) ~[reactor-core-3.5.4.jar:3.5.4]
	at reactor.core.publisher.MonoIgnoreThen$ThenIgnoreMain.subscribeNext(MonoIgnoreThen.java:240) ~[reactor-core-3.5.4.jar:3.5.4]
	at reactor.core.publisher.MonoIgnoreThen$ThenIgnoreMain.onComplete(MonoIgnoreThen.java:203) ~[reactor-core-3.5.4.jar:3.5.4]
	at reactor.core.publisher.Operators$MultiSubscriptionSubscriber.onComplete(Operators.java:2205) ~[reactor-core-3.5.4.jar:3.5.4]
	at reactor.core.publisher.MonoIgnoreThen$ThenIgnoreMain.onComplete(MonoIgnoreThen.java:209) ~[reactor-core-3.5.4.jar:3.5.4]
	at reactor.core.publisher.MonoIgnoreElements$IgnoreElementsSubscriber.onComplete(MonoIgnoreElements.java:89) ~[reactor-core-3.5.4.jar:3.5.4]
	at reactor.core.publisher.FluxContextWrite$ContextWriteSubscriber.onComplete(FluxContextWrite.java:126) ~[reactor-core-3.5.4.jar:3.5.4]
	at reactor.core.publisher.FluxConcatMapNoPrefetch$FluxConcatMapNoPrefetchSubscriber.onComplete(FluxConcatMapNoPrefetch.java:240) ~[reactor-core-3.5.4.jar:3.5.4]
	at reactor.core.publisher.Operators.complete(Operators.java:137) ~[reactor-core-3.5.4.jar:3.5.4]
	at reactor.core.publisher.FluxIterable.subscribe(FluxIterable.java:144) ~[reactor-core-3.5.4.jar:3.5.4]
	at reactor.core.publisher.FluxIterable.subscribe(FluxIterable.java:83) ~[reactor-core-3.5.4.jar:3.5.4]
	at reactor.core.publisher.MonoFromFluxOperator.subscribe(MonoFromFluxOperator.java:81) ~[reactor-core-3.5.4.jar:3.5.4]
	at reactor.core.publisher.MonoDefer.subscribe(MonoDefer.java:52) ~[reactor-core-3.5.4.jar:3.5.4]
	at reactor.core.publisher.MonoIgnoreThen$ThenIgnoreMain.subscribeNext(MonoIgnoreThen.java:240) ~[reactor-core-3.5.4.jar:3.5.4]
	at reactor.core.publisher.MonoIgnoreThen$ThenIgnoreMain.onComplete(MonoIgnoreThen.java:203) ~[reactor-core-3.5.4.jar:3.5.4]
	at reactor.core.publisher.Operators$MultiSubscriptionSubscriber.onComplete(Operators.java:2205) ~[reactor-core-3.5.4.jar:3.5.4]
	at reactor.core.publisher.MonoIgnoreThen$ThenIgnoreMain.onComplete(MonoIgnoreThen.java:209) ~[reactor-core-3.5.4.jar:3.5.4]
	at reactor.core.publisher.Operators$MultiSubscriptionSubscriber.onComplete(Operators.java:2205) ~[reactor-core-3.5.4.jar:3.5.4]
	at reactor.core.publisher.FluxPeek$PeekSubscriber.onComplete(FluxPeek.java:260) ~[reactor-core-3.5.4.jar:3.5.4]
	at reactor.core.publisher.MonoIgnoreElements$IgnoreElementsSubscriber.onComplete(MonoIgnoreElements.java:89) ~[reactor-core-3.5.4.jar:3.5.4]
	at io.r2dbc.postgresql.util.FluxDiscardOnCancel$FluxDiscardOnCancelSubscriber.onComplete(FluxDiscardOnCancel.java:104) ~[r2dbc-postgresql-1.0.1.RELEASE.jar:1.0.1.RELEASE]
	at reactor.core.publisher.FluxPeek$PeekSubscriber.onComplete(FluxPeek.java:260) ~[reactor-core-3.5.4.jar:3.5.4]
	at reactor.core.publisher.FluxPeek$PeekSubscriber.onComplete(FluxPeek.java:260) ~[reactor-core-3.5.4.jar:3.5.4]
	at reactor.core.publisher.FluxHandle$HandleSubscriber.onComplete(FluxHandle.java:222) ~[reactor-core-3.5.4.jar:3.5.4]
	at io.r2dbc.postgresql.util.FluxDiscardOnCancel$FluxDiscardOnCancelSubscriber.onComplete(FluxDiscardOnCancel.java:104) ~[r2dbc-postgresql-1.0.1.RELEASE.jar:1.0.1.RELEASE]
	at reactor.core.publisher.FluxContextWrite$ContextWriteSubscriber.onComplete(FluxContextWrite.java:126) ~[reactor-core-3.5.4.jar:3.5.4]
	at reactor.core.publisher.FluxCreate$BaseSink.complete(FluxCreate.java:460) ~[reactor-core-3.5.4.jar:3.5.4]
	at reactor.core.publisher.FluxCreate$BufferAsyncSink.drain(FluxCreate.java:805) ~[reactor-core-3.5.4.jar:3.5.4]
	at reactor.core.publisher.FluxCreate$BufferAsyncSink.complete(FluxCreate.java:753) ~[reactor-core-3.5.4.jar:3.5.4]
	at reactor.core.publisher.FluxCreate$SerializedFluxSink.drainLoop(FluxCreate.java:247) ~[reactor-core-3.5.4.jar:3.5.4]
	at reactor.core.publisher.FluxCreate$SerializedFluxSink.drain(FluxCreate.java:213) ~[reactor-core-3.5.4.jar:3.5.4]
	at reactor.core.publisher.FluxCreate$SerializedFluxSink.complete(FluxCreate.java:204) ~[reactor-core-3.5.4.jar:3.5.4]
	at io.r2dbc.postgresql.client.ReactorNettyClient$Conversation.complete(ReactorNettyClient.java:671) ~[r2dbc-postgresql-1.0.1.RELEASE.jar:1.0.1.RELEASE]
	at io.r2dbc.postgresql.client.ReactorNettyClient$BackendMessageSubscriber.emit(ReactorNettyClient.java:937) ~[r2dbc-postgresql-1.0.1.RELEASE.jar:1.0.1.RELEASE]
	at io.r2dbc.postgresql.client.ReactorNettyClient$BackendMessageSubscriber.onNext(ReactorNettyClient.java:813) ~[r2dbc-postgresql-1.0.1.RELEASE.jar:1.0.1.RELEASE]
	at io.r2dbc.postgresql.client.ReactorNettyClient$BackendMessageSubscriber.onNext(ReactorNettyClient.java:719) ~[r2dbc-postgresql-1.0.1.RELEASE.jar:1.0.1.RELEASE]
	at reactor.core.publisher.FluxHandle$HandleSubscriber.onNext(FluxHandle.java:128) ~[reactor-core-3.5.4.jar:3.5.4]
	at reactor.core.publisher.FluxPeekFuseable$PeekConditionalSubscriber.onNext(FluxPeekFuseable.java:854) ~[reactor-core-3.5.4.jar:3.5.4]
	at reactor.core.publisher.FluxMap$MapConditionalSubscriber.onNext(FluxMap.java:224) ~[reactor-core-3.5.4.jar:3.5.4]
	at reactor.core.publisher.FluxMap$MapConditionalSubscriber.onNext(FluxMap.java:224) ~[reactor-core-3.5.4.jar:3.5.4]
	at reactor.netty.channel.FluxReceive.drainReceiver(FluxReceive.java:294) ~[reactor-netty-core-1.1.5.jar:1.1.5]
	at reactor.netty.channel.FluxReceive.onInboundNext(FluxReceive.java:403) ~[reactor-netty-core-1.1.5.jar:1.1.5]
	at reactor.netty.channel.ChannelOperations.onInboundNext(ChannelOperations.java:411) ~[reactor-netty-core-1.1.5.jar:1.1.5]
	at reactor.netty.channel.ChannelOperationsHandler.channelRead(ChannelOperationsHandler.java:113) ~[reactor-netty-core-1.1.5.jar:1.1.5]
	at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:444) ~[netty-transport-4.1.90.Final.jar:4.1.90.Final]
	at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:420) ~[netty-transport-4.1.90.Final.jar:4.1.90.Final]
	at io.netty.channel.AbstractChannelHandlerContext.fireChannelRead(AbstractChannelHandlerContext.java:412) ~[netty-transport-4.1.90.Final.jar:4.1.90.Final]
	at io.netty.handler.codec.ByteToMessageDecoder.fireChannelRead(ByteToMessageDecoder.java:346) ~[netty-codec-4.1.90.Final.jar:4.1.90.Final]
	at io.netty.handler.codec.ByteToMessageDecoder.channelRead(ByteToMessageDecoder.java:318) ~[netty-codec-4.1.90.Final.jar:4.1.90.Final]
	at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:444) ~[netty-transport-4.1.90.Final.jar:4.1.90.Final]
	at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:420) ~[netty-transport-4.1.90.Final.jar:4.1.90.Final]
	at io.netty.channel.AbstractChannelHandlerContext.fireChannelRead(AbstractChannelHandlerContext.java:412) ~[netty-transport-4.1.90.Final.jar:4.1.90.Final]
	at io.netty.channel.DefaultChannelPipeline$HeadContext.channelRead(DefaultChannelPipeline.java:1410) ~[netty-transport-4.1.90.Final.jar:4.1.90.Final]
	at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:440) ~[netty-transport-4.1.90.Final.jar:4.1.90.Final]
	at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:420) ~[netty-transport-4.1.90.Final.jar:4.1.90.Final]
	at io.netty.channel.DefaultChannelPipeline.fireChannelRead(DefaultChannelPipeline.java:919) ~[netty-transport-4.1.90.Final.jar:4.1.90.Final]
	at io.netty.channel.epoll.AbstractEpollStreamChannel$EpollStreamUnsafe.epollInReady(AbstractEpollStreamChannel.java:800) ~[netty-transport-classes-epoll-4.1.90.Final.jar:4.1.90.Final]
	at io.netty.channel.epoll.EpollEventLoop.processReady(EpollEventLoop.java:499) ~[netty-transport-classes-epoll-4.1.90.Final.jar:4.1.90.Final]
	at io.netty.channel.epoll.EpollEventLoop.run(EpollEventLoop.java:397) ~[netty-transport-classes-epoll-4.1.90.Final.jar:4.1.90.Final]
	at io.netty.util.concurrent.SingleThreadEventExecutor$4.run(SingleThreadEventExecutor.java:997) ~[netty-common-4.1.90.Final.jar:4.1.90.Final]
	at io.netty.util.internal.ThreadExecutorMap$2.run(ThreadExecutorMap.java:74) ~[netty-common-4.1.90.Final.jar:4.1.90.Final]
	at io.netty.util.concurrent.FastThreadLocalRunnable.run(FastThreadLocalRunnable.java:30) ~[netty-common-4.1.90.Final.jar:4.1.90.Final]
	at java.base/java.lang.Thread.run(Thread.java:833) ~[na:na]

@jvmlet
Copy link
Collaborator

jvmlet commented Apr 11, 2023

Hmm, from the stack trace it seems that transactional some how switches threads and the context is lost... I'll continue with investigation, please keep the repo alive...

@jvmlet
Copy link
Collaborator

jvmlet commented Apr 13, 2023

@vincentditlevinz , I've added test that reproduces the behavior of your project, test passes after the fix, please upgrade to the latest 5.1.1-SNAPSHOT

@vincentditlevinz
Copy link
Author

Hello @jvmlet.
I've upgraded to 5.1.1-SNAPSHOT, and I confirm, it fixes the issue !
Well done and thanks a lot for your time 👍

@jvmlet
Copy link
Collaborator

jvmlet commented Apr 13, 2023

Thanks @vincentditlevinz for helping with the resolution.

@jvmlet
Copy link
Collaborator

jvmlet commented Apr 25, 2023

@vincentditlevinz , 5.1.1 is out

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bug Auto-generates notes
Projects
None yet
Development

No branches or pull requests

2 participants