Skip to content

Add Kotlin Coroutine extension (or API) for Change Streams consumption #4987

@huberchrigu

Description

@huberchrigu

Currently there seems to be no way to consume mongo event streams in a Kotlin coroutines setup. See the following test:

@DataMongoTest
@TestConstructor(autowireMode = TestConstructor.AutowireMode.ALL)
@Import(TestcontainersConfiguration::class)
class MongoAggregateChangesTest(private val mongoTemplate: ReactiveMongoTemplate) {
    @Test
    fun testFlux() { // success
        runTest { onHit ->
            mongoTemplate.changeStream<TestDocument>().listen()
                .subscribe { onHit.apply(it.body!!) }
        }
    }

    @Test
    fun testLaunch() { // fails
        runTest { onHit ->
            launch {
                mongoTemplate.changeStream<TestDocument>().listen()
                    .subscribe { onHit.apply(it.body!!) }
            }
        }
    }

    @Test
    fun testCoroutine() { // fails
        runTest { onHit ->
            launch {
                mongoTemplate.changeStream<TestDocument>().listen().asFlow()
                    .collect { onHit.apply(it.body!!) }
            }
        }
    }

    private fun runTest(listener: suspend CoroutineScope.(EventHandler) -> Unit) {
        runBlocking {
            val check = mutableSetOf<Int>()
            listener(DefaultEventHandler(check))
            Flux.range(0, 100).flatMap { mongoTemplate.save(TestDocument(it)) }.subscribe { println("Saved: ${it.id}") }

            await().atMost(Duration.ofSeconds(3)).until { check.size == 100 }
        }
    }

    class TestDocument(val id: Int)

    class DefaultEventHandler(private val check: MutableSet<Int>) : EventHandler {
        override fun apply(document: TestDocument) {
            val id = document.id
            println("Received: $id")
            check.add(id)
        }
    }

    fun interface EventHandler {
        fun apply(document: TestDocument)
    }
}

In my project, I cannot use event streams as flux, as the events need to be mapped by suspend functions. Is there any way to use event streams with coroutines? asFlow() seems to cause issues not only in this test, but also in projects where the flow is consumed by controller methods.

I think this would require a dedicated CoroutineMongoTemplate that makes use of the Kotlin MongoClient.

Metadata

Metadata

Assignees

Labels

status: declinedA suggestion or change that we don't feel we should currently apply

Type

No type

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions