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

Transactional not working with grpc coroutine service #1142

Open
gbtrevisan opened this issue Oct 2, 2024 · 0 comments
Open

Transactional not working with grpc coroutine service #1142

gbtrevisan opened this issue Oct 2, 2024 · 0 comments
Labels
question A question about this library or its usage

Comments

@gbtrevisan
Copy link

gbtrevisan commented Oct 2, 2024

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

@gbtrevisan gbtrevisan added the question A question about this library or its usage label Oct 2, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
question A question about this library or its usage
Projects
None yet
Development

No branches or pull requests

1 participant