0

Context: it is my first time working with RxJava.

When coding with RxJava to (1) select documents from NoSql DB and (2) insert to NoSql (ex. MongoDb), what is the the recommended emmitter taking in account a Reactive Stack?

For instance, should I normally prefer use Flowable for reading and Single for saving?

This code works perrfectly to save a message received from a Kafka Topic to MongoDb but I am wondering if io.reactivex.Single is really the best way to accomplish it.

import com.mongodb.client.result.InsertOneResult
import com.mongodb.reactivestreams.client.MongoClient
import com.mongodb.reactivestreams.client.MongoCollection
import io.micronaut.configuration.kafka.annotation.KafkaKey
import io.micronaut.configuration.kafka.annotation.KafkaListener
import io.micronaut.configuration.kafka.annotation.OffsetReset
import io.micronaut.configuration.kafka.annotation.Topic
import io.micronaut.messaging.annotation.Body
import io.reactivex.Observable
import io.reactivex.Single
import javax.inject.Inject
import io.reactivex.functions.Function

@KafkaListener(offsetReset = OffsetReset.EARLIEST)
class DebitConsumer {

    @Inject
    lateinit var mongoClient: MongoClient

    @Topic("debit")
    fun receive(@KafkaKey key: String, name: String) {

        save(key.toInt(), name)

    }

    private fun save( id: Int?,name: String?) {
        val debitMessage =  DebitMessage(id, name)
        Single
                .fromPublisher(getCollection().insertOne(debitMessage))
                .map<DebitMessage>(Function<InsertOneResult, DebitMessage> { debitMessage })
                .subscribe()
    }

    private fun getCollection(): MongoCollection<DebitMessage?> {
        return mongoClient
                .getDatabase("mydb")
                .getCollection("mycollection", DebitMessage::class.java)
    }
}

I came from Spring Data which is a bit straighforward a CRUD in Reactive world and, for not relevent reasons for this question, I will not use Spring and I am looking for best practices while writing/reading data on Reactive/No Blocking/BackPressure world.

prasad_
  • 12,755
  • 2
  • 24
  • 36
Jim C
  • 3,957
  • 25
  • 85
  • 162
  • 1
    I think you're not getting any benefit from the reactive pattern here, due to creating a new Single every time you call `save`. Are you aiming to push each save call into a single stream? – Carson Holzheimer Dec 06 '20 at 05:12
  • @CarsonHolzheimer, thanks. Well, my main goal here is to use no-blocking way to save the data received from Kafka. By "no-blocking" I mean avoit heavy resource like a thread stopped until it is accomplished. Can you either suggest how would you reach that with RxJava or point the reasons if I am doing something foolish? Regard to your question, no, I am not aimed to push each save call into a single stream. You can sse I subscribe immediatelly. – Jim C Dec 06 '20 at 15:05
  • As a simple analogy, in the past, I have coded similiar idea with Spring Data Reactive with mono...subscribe() assuming I have design it to consume less resource (threads). Hopefully I haven't done some stupid thing because the code is already promoted. So, you see some weird expectation, kindly, advise it – Jim C Dec 06 '20 at 15:09
  • 1
    I think your code is fine. It's just that it isn't using any reactive streams features, it's just acting like a callback. I see that Mongo has removed their async driver, in favour of Reactive Streams driver, so I think that to get async behaviour you have to use that driver as you have. BTW I'm quite sure the line `.map...` is doing nothing. – Carson Holzheimer Dec 07 '20 at 00:37
  • If "...it isn't using any reactive streams features" then I have an issue because it is exactly the final goal. How would you save REACTVELY using RxJava? – Jim C Dec 07 '20 at 02:11
  • 1
    To clarify, it is using the feature of MongoDBs Reactive Streams Driver, which moves write operations to a background thread and therefore provides non-blocking writes. However that isn't really a "Reactive Streams" feature, but simply async writes on a different thread. See this link for why I was confused: https://mongodb.github.io/mongo-java-driver-reactivestreams/1.13/ – Carson Holzheimer Dec 07 '20 at 02:28

1 Answers1

1

Your code looks fine. A Single makes sense for saving, since you will only get one result back. Flowable makes sense for reading, but really the choice is up to you and your application. Do you want to listen for database changes via Change Streams? Then you will have to use Flowable so you can react to multiple updates in the stream. It may be good practice to use Flowable, even if currently you don't listen to multiple updates, but you think you might in the future.

If you're sure you only ever want to deal with 1 event, use Single. It will save you some effort in your application code dealing with the possibility of multiple events.

Carson Holzheimer
  • 2,890
  • 25
  • 36