albrechtroehm
06/06/2024, 8:13 AMcontext(ResourceScope)
suspend fun initDependencies() =
either {
val env = env()
val client: HttpClient = autoCloseable { httpClient() }
...
}
}
--> Type mismatch: inferred type is 'arrow.fx.coroutines.Resource<A>', but 'io.ktor.client.HttpClient' was expected.
simon.vergauwen
06/06/2024, 8:21 AMAlejandro Serrano.Mena
06/06/2024, 8:22 AMAlejandro Serrano.Mena
06/06/2024, 8:22 AMAlejandro Serrano.Mena
06/06/2024, 8:23 AMResourcrScope.initDependencies()
instead of a context receiver?albrechtroehm
06/06/2024, 8:23 AMsimon.vergauwen
06/06/2024, 8:24 AMalbrechtroehm
06/06/2024, 8:24 AMAlejandro Serrano.Mena
06/06/2024, 8:27 AMinitDependencies()
?albrechtroehm
06/06/2024, 8:27 AMfun main() =
SuspendApp {
val logger = LoggerFactory.getLogger("ktor.application")
logger.info("Starting application...")
either {
resourceScope {
val deps = initDependencies()
heartbeat().onEach { processEvent(deps) }.launchIn(this@SuspendApp)
awaitCancellation()
}
}.onLeft { error -> logger.error(error.toString()) }
}
context(ResourceScope, Raise<Problem>)
suspend fun initDependencies(): Deps {
val env = env()
val client: HttpClient = autoCloseable { httpClient() }
val mattermostClient = mattermostClient(client, env)
val quotesService = QuotesService()
val reminderService = ReminderService(quotesService, mattermostClient)
return Deps(reminderService)
}
class Deps( val reminderService: IReminderService)
albrechtroehm
06/06/2024, 8:32 AMsimon.vergauwen
06/06/2024, 8:33 AMhttpClient
is not coming from Ktor here, right? What does the httpClient
function look like?albrechtroehm
06/06/2024, 8:34 AMimport de.roehm.serialization.registerJacksonConverter
import io.ktor.client.HttpClient
import io.ktor.client.engine.okhttp.OkHttp
import io.ktor.client.plugins.contentnegotiation.ContentNegotiation
import io.ktor.client.plugins.logging.*
import io.ktor.client.plugins.logging.LogLevel
import io.ktor.client.plugins.logging.Logging
fun httpClient(logging: Boolean = true) =
HttpClient(OkHttp) {
expectSuccess = false
install(ContentNegotiation) {
registerJacksonConverter()
}
if (logging) {
install(Logging) {
logger = Logger.SIMPLE
level = LogLevel.ALL
}
}
}
simon.vergauwen
06/06/2024, 8:35 AMfun httpClient(logging: Boolean = true): HttpClient
, if that's the case, then its probably a compiler bug indeed.albrechtroehm
06/06/2024, 8:36 AMalbrechtroehm
06/06/2024, 8:39 AMAlso seems to be unrelated to httpClient()
context(ResourceScope, Raise<Problem>)
suspend fun initDependencies(): Deps {
val env = env()
val test: Tester = autoCloseable { getTester() }
}
fun getTester() : Tester = Tester()
class Tester: AutoCloseable{
override fun close() {
TODO("Not yet implemented")
}
}
--> Initializer type mismatch: expected 'de.roehm.client.Tester', actual 'arrow.fx.coroutines.Resource<ERROR CLASS: Cannot infer argument for type parameter A>'.
edit: also with explicit type on getTester()Alejandro Serrano.Mena
06/06/2024, 8:44 AMautoCloseable
?albrechtroehm
06/06/2024, 8:55 AMautoCloseable
i end up in ResourceExtension.kt:141 (arrow-fx-coroutines-jvm-1.2.4.jar), but IDE is happy so might not be actually true?'
Removed some more noise, this is enough to produce the error for me.
import arrow.fx.coroutines.ResourceScope
import arrow.fx.coroutines.autoCloseable
import arrow.fx.coroutines.resourceScope
import kotlinx.coroutines.runBlocking
fun main() =
runBlocking {
resourceScope {
val deps = initDependency()
}
}
context(ResourceScope)
suspend fun initDependency(): Tester {
val test: Tester = autoCloseable { getTester() }
return test
}
fun getTester() : Tester = Tester()
class Tester: AutoCloseable{
override fun close() {
TODO("Not yet implemented")
}
}
simon.vergauwen
06/06/2024, 9:04 AMalbrechtroehm
06/06/2024, 9:08 AMAlejandro Serrano.Mena
06/07/2024, 7:44 AMautoCloseable
, one that works inside ResourceScope
and returns A
, one which works outside of it and returns Resource<A>
• the compiler prioritizes the one with an extension receiver if you are inside of that implicit scope; this is why moving ResourceScope
from context to receiver fixes the problem
• however, the rules for context receivers are not set in stone; so they may have been unadvertedly changed, giving now more priority to the autoCloseable
without it, which returns Resource<A>
Alejandro Serrano.Mena
06/07/2024, 7:45 AMResourceScope.foo()
as far as you cansimon.vergauwen
06/07/2024, 7:45 AMsimon.vergauwen
06/07/2024, 7:46 AMAlejandro Serrano.Mena
06/07/2024, 7:47 AMsaga
)simon.vergauwen
06/07/2024, 7:48 AMsaga
for a while. I liked the duality, but you warned me 😅 😅
Saga could be fixed by deprecating saga { }.transact()
and providing a sagaScope
alias.