kosi-libs/Kodein

Suspending factories: any plans?

milgner opened this issue · 1 comments

I read in TODO.md that suspending factories would be a major change. I'm wondering whether there are any plans to implement them?

In a project based on Vert.x, where most APIs are asynchronous and called through suspending functions, I'm currently doing the following to construct an object:

    typealias DIInit = DI.MainBuilder.() -> Unit
 
    override fun configureDI(): DIInit = {
        bind {
            provider {
                val configRetriever = instance<ConfigRetriever>()
                // just calling `runBlocking` here would deadlock the application. 
                // But when launching through a different dispatcher, it's
                // possible to await its result through `runBlocking` afterwards.
                val configJob = GlobalScope.async(Dispatchers.IO) { configuration(configRetriever) }
                val config = runBlocking { configJob.await() }
                RabbitMQClient.create(instance(), config)
            }
        }
    }

    private suspend fun configuration(configRetriever: ConfigRetriever): RabbitMQOptions {
        val config = configRetriever.config.await()
        val rabbitConfig = config.getJsonObject("rabbitmq")

        val uri = rabbitConfig.getString("uri")

        return RabbitMQOptions().setUri(uri) // detailed configuration omitted for brevity
    }

Now I was thinking about just wrapping that in a helper function - but having it built-in would probably be preferable 😅

I have been thinking a lot about this lately.
This is maybe dangerous to have suspendable code inside the dependency retrieving mechanism.
I would consider using something like a Deferred type to bind any awaited value / instance.