-
Notifications
You must be signed in to change notification settings - Fork 866
Description
The context
I want to be able to use spring Transactional support (using annotation or transactionalOperator) in a method called from a GrpcService.
`
class GrpcServiceTransactionalTest : IntegrationTest() {
@GrpcClient("inProcess")
private lateinit var grpcStub: grpcStub
@Autowired
private lateinit var myService: MyService
// THIS FAILS WITH COROUTINE TIMEOUT
@Test
fun `calling from grpc stub`() = runTest {
for (i in 1..100) {
shouldNotThrowAny {
grpcStub.create(
createRequest()
)
}
}
}
// THIS DOES NOT FAIL
@Test
fun `calling directly service`() = runTest {
for (i in 1..100) {
shouldNotThrowAny {
myService.create(
createRequest()
)
}
}
}
}
`
The question
Right now I can't use transactional neither in the Grpc method or in any method it calls because I get myself in what it seems to be a deadlock. I want to know if this is a bug or what, because using the transactional annotation from spring without calling it from the GrpcService works fine.
Stacktraces and logs
Here is log of the coroutine context with the transaction context
2024-10-02T13:12:55.431-03:00 INFO 147887 --- [my-component] [2 @coroutine#11] c.s.c.b.m.d.a.MyService : [io.grpc.kotlin.GrpcContextElement@109247f7, Context2{class org.springframework.transaction.reactive.TransactionContextHolder=org.springframework.transaction.reactive.TransactionContextHolder@53bd2de5, class org.springframework.transaction.reactive.TransactionContext=org.springframework.transaction.reactive.TransactionContext@6a52073f}, CoroutineId(11), "coroutine#11":ScopeCoroutine{Active}@fe4db76, Dispatchers.Default]
Error:
When I run the test where I call the coroutine grpc service stub, during the execution the code stops for a moment, as if it was waiting for something (this is where I imagine that a deadlock happened within my transaction). After a while the execution failed because the test timed out waiting for the coroutine to complete.
Coroutine timeout:
After waiting for 1m, the test coroutine is not completing, there were active child jobs: [ScopeCoroutine{Active}@39d8f157] kotlinx.coroutines.test.UncompletedCoroutinesError: After waiting for 1m, the test coroutine is not completing, there were active child jobs: [ScopeCoroutine{Active}@39d8f157] at kotlinx.coroutines.test.TestBuildersKt__TestBuildersKt$runTest$2$1$2$1.invoke(TestBuilders.kt:351) at kotlinx.coroutines.test.TestBuildersKt__TestBuildersKt$runTest$2$1$2$1.invoke(TestBuilders.kt:335) at kotlinx.coroutines.InternalCompletionHandler$UserSupplied.invoke(CompletionHandler.common.kt:67) at kotlinx.coroutines.InvokeOnCancelling.invoke(JobSupport.kt:1438) at kotlinx.coroutines.JobSupport.notifyCancelling(JobSupport.kt:1483) at kotlinx.coroutines.JobSupport.tryMakeCancelling(JobSupport.kt:806) at kotlinx.coroutines.JobSupport.makeCancelling(JobSupport.kt:766) at kotlinx.coroutines.JobSupport.cancelImpl$kotlinx_coroutines_core(JobSupport.kt:682) at kotlinx.coroutines.JobSupport.cancelCoroutine(JobSupport.kt:669) at kotlinx.coroutines.TimeoutCoroutine.run(Timeout.kt:156) at kotlinx.coroutines.EventLoopImplBase$DelayedRunnableTask.run(EventLoop.common.kt:498) at kotlinx.coroutines.EventLoopImplBase.processNextEvent(EventLoop.common.kt:277) at kotlinx.coroutines.DefaultExecutor.run(DefaultExecutor.kt:105) at java.base/java.lang.Thread.run(Thread.java:1583) Suppressed: java.lang.AssertionError: No exception expected, but a CancellationException was thrown.
The application's environment
Which versions do you use?
- Spring (boot): 3.3.2
- grpc-kotlin-stub: 1.4.1
- grpc-spring-boot-starter: 3.1.0.RELEASE
- java: 21 64bit
- kotlinVersion: 2.0.10
Additional information
-
Did it ever work before?
It works if I don't call from the grpc service or stub -
How can we reproduce it?
Create a kotlin coroutine grpc service and create a service with a method annotated with @transactional from spring
In the method annotated with @transactional you have to launch new coroutines and do some database operation, in my case I'm inserting in mysql using r2dbc driver and CoroutineCrudRepository. -
Do you have a demo?
No