Kotlin - ArrowCore ensureNotNull in either.eager? - kotlin

I can utilize ensure, but not ensureNotNull in this MRE validation function. I cannot create a suspend fun, so I need to be able to use either.eager. The ability to utilize this would drastically increase the readability for my code.
fun isValid(integer: Int?): Either<Throwable, Int> = either.eager {
ensure(true) {
Exception()
}
ensureNotNull(integer) { // Restricted suspending functions can only invoke member or extension suspending functions on their restricted coroutine scope.
Exception()
}
integer // ^eager
}

Related

Kotlin coroutines not running in parallel?

I am trying to use Kotlin coroutines to run 2 queries in parallel. I get the result as expected, but they are running sequentially.
fun getSearchResults(
sql: SqlBuilder,
): Pair<Int?, List<T>> {
return runBlocking {
val one = async {
count(sql)
}
val two = async {
query(sql)
}
Pair(one.await(), two.await())
}
}
suspend fun count(sql: SqlBuilder): Int? {
return namedParameterJdbcTemplate.queryForObject(sql.countSql, sql.params) { rs: ResultSet, _: Int ->
rs.retrieveInteger("count")!!
}
}
suspend fun query(sql: SqlBuilder): List<T> {
return namedParameterJdbcTemplate.query(sql.sql, sql.params) { rs: ResultSet, _: Int ->
createEntity(rs)
}
}
Why is this not running in parallel? Also, why is my IDE telling me the suspend keywords are "redundant"? How do I fix this?
When you launch a coroutine in runBlocking, the default dispatcher is a single-threaded dispatcher running in the thread that called runBlocking. You should not be using runBlocking anyway, since it defeats the purpose of using coroutines. Your getSearchResults function is a blocking function.
The reason suspend is redundant on your other functions is that those functions are not calling any other suspend functions. Aside from being redundant, the suspend keyword implies that the function will cooperate with cancellation and by convention does not block. Your implementation is breaking both of those rules because they do not call other suspend functions and they are calling blocking functions without wrapping them in withContext with an appropriate dispatcher, so they are themselves blocking functions. Blocking suspend functions must never exist by convention.
So the solution is to change getSearchResults to be a suspend function, and use coroutineScope instead of runBlocking in it so it will run its children coroutines in parallel and it will not block. If it is a suspend function, it won't be redundant for your other functions that call it to be marked suspend.
suspend fun getSearchResults(
sql: SqlBuilder,
): Pair<Int?, List<T>> = coroutineScope {
val one = async {
count(sql)
}
val two = async {
query(sql)
}
Pair(one.await(), two.await())
}
If count and query are blocking IO functions, you should use async(Dispatchers.IO) to call them. But if they are suspend functions you don't need to specify a dispatcher.

Why is this extension function slower than non extension counterpart?

I was trying to write a parallel map extension function to do map operation over a List in parallel using coroutines.
However there is a significant overhead in my solution and I can't find out why.
This is my implementation of the pmap extension function:
fun <T, U> List<T>.pmap(scope: CoroutineScope = GlobalScope,
transform: suspend (T) -> U): List<U> {
return map { i -> scope.async { transform(i) } }.map { runBlocking { it.await() } }
}
However, when I do the exact same operation in a normal function, it takes up to extra 100ms (which is a lot).
I tried using inline but it had no effect.
I'm leaving here the full test I've done to demonstrate this behavior:
import kotlinx.coroutines.*
import kotlin.system.measureTimeMillis
fun main() {
test()
}
fun <T, U> List<T>.pmap(scope: CoroutineScope = GlobalScope,
transform: suspend (T) -> U): List<U> {
return this.map { i -> scope.async { transform(i) } }.map { runBlocking { it.await() } }
}
fun test() {
val list = listOf<Long>(100,200,300)
val transform: suspend (Long) -> Long = { long: Long ->
delay(long)
long*2
}
val timeTakenPmap = measureTimeMillis {
list.pmap(GlobalScope) { transform(it) }
}
val manualpmap = measureTimeMillis {
list.map { GlobalScope.async { transform(it) } }
.map { runBlocking { it.await() } }
}
val timeTakenMap = measureTimeMillis {
list.map { runBlocking { transform(it) } }
}
println("pmapTime: $timeTakenPmap - mapTime: $timeTakenMap - manualpmap: $manualpmap")
}
It can be run in kotlin playground: https://pl.kotl.in/CIXVqezg3
In the playground it prints this result:
pmapTime: 411 - mapTime: 602 - manualpmap: 302
MapTime and manualPmap give reasonable results, only 2ms of time outside the delays. But pmapTime is way off. And the code between manualpmap and pmap looks exactly the same to me.
In my own machine it runs a little faster, pmap takes around 350ms.
Does anyone know why this happens?
First of all, manual benchmarks like this are usually of very little significance. There are many things that can be optimized away by the compiler or the JIT and any conclusion can be quite wrong. If you really want to compare things, you should instead use benchmarking libraries which take into account JVM warmup etc.
Now, the overhead you see (if you could confirm there was an actual overhead) might be caused by the fact that your higher-order extension is not marked inline, so instances of the lambda you pass need to be created - but as #Tenfour04 noted there are many other possible reasons: thread pool lazy initialization, significance of the list size, etc.
That being said, this is really not an appropriate way to write parallel map, for several reasons:
GlobalScope is a pretty bad default in general, and should be used in very specific situations only. But don't worry about it because of the next point.
You don't need an externally provided CoroutineScope if the coroutines you launch do not outlive your method. Instead, use coroutineScope { ... } and make your function suspend, and the caller will choose the context if they need to
map { it.await() } is inefficient in case of errors: if the last element's transformation immediately fails, map will wait for all previous elements to finish before failing. You should prefer awaitAll which takes care of this.
runBlocking should be avoided in coroutines (blocking threads in general, especially when you don't control which thread you're blocking), so using it in deep library-like functions like this is dangerous, because it will likely be used in coroutines at some point.
Applying those points gives:
suspend inline fun <T, U> List<T>.pmap(transform: suspend (T) -> U): List<U> {
return coroutineScope {
map { async { transform(it) } }.awaitAll()
}
}

In Kotlin, is it possible to substitute a suspend fun with a non-suspend version, without breaking the caller?

I'm learning concurrency in Kotlin, coming from C#/JavaScript background, and I can't help comparing some concepts.
In C# and JavaScript, technically we can rewrite an async function as a regular non-async version doing the same thing, using Task.ContinueWith or Promise.then etc.
The caller of the function wouldn't even notice the difference (I ranted about it in a blog post).
Is something like that possible for a suspend function in Kotlin (i.e., without changing the calling code)? I don't think it is, but I thought I'd still ask.
The closest thing I could come up with is below (Kotlin playground link), I still have to call .await():
import kotlinx.coroutines.*
suspend fun suspendableDelay(ms: Long): Long {
delay(ms);
return ms;
}
fun regularDelay(ms: Long): Deferred<Long> {
val d = CompletableDeferred<Long>()
GlobalScope.async { delay(ms); d.complete(ms) }
return d;
}
suspend fun test(ms: Long): Long {
delay(ms);
return ms;
}
fun main() {
val r1 = runBlocking { suspendableDelay(250) }
println("suspendableDelay ended: $r1");
val r2 = runBlocking { regularDelay(500).await() }
println("regularDelay ended: $r2");
}
https://pl.kotl.in/_AmzanwcB
If you're on JVM 8 or higher, you can make a function that calls the suspend function in an async job and returns a CompletableFuture, which can be used to get your result with a callback (thenApplyAsync()) or synchronously (get()).
val scope = CoroutineScope(SupervisorJob())
suspend fun foo(): Int {
delay(500)
return Random.nextInt(10)
}
fun fooAsync(): CompletableFuture<Int> = scope.async { foo() }.asCompletableFuture()
fun main() {
fooAsync()
.thenApplyAsync { println(it) }
Thread.sleep(1000)
}
The above requires the kotlinx-coroutines-jdk8 library.
I don't know of a solution that works across multiple platforms.
This can only work if you change your suspending function to a non-suspending blocking function, for example
private fun method(){
GlobalScope.launch {
val value = getInt()
}
}
// Calling coroutine can be suspended and resumed when result is ready
private suspend fun getInt(): Int{
delay(2000) // or some suspending IO call
return 5;
}
// Calling coroutine can't be suspended, it will have to wait (block)
private fun getInt(): Int{
Thread.sleep(2000) // some blocking IO
return 5;
}
Here you can simply use the non-suspending version, without any change on the caller.
But the issue here is that without suspend modifier the function becomes blocking and as such it can not cause the coroutine to suspend, basically throwing away the advantage of using coroutiens.

Mix and match Coroutines and Rxjava

Coroutines and RxJava3
I have the following method that first makes a call to a suspend method and in the same launch scope I make 2 calls to RxJava.
I am wondering if there is a way to remove the Rxjava code out of the viewModelScope.launch scope and return the result of fetchRecentUseCase.execute().
Basically, is it possible for the viewModelScope.launch to return the listOfProducts rather than doing everything in the launch scope?
fun loadRecentlyViewed() {
viewModelScope.launch {
val listOfProducts = withContext(Dispatchers.IO) {
fetchRecentUseCase.execute()
}
val listOfSkus = listOfProducts.map { it.sku }
if (listOfSkus.isNotEmpty()) {
loadProductUseCase.execute(listOfSkus)
.subscribeOn(schedulersFacade.io)
.flatMap(convertProductDisplayUseCase::execute)
.map { /* work being done */ }
.observeOn(schedulersFacade.ui)
.subscribeBy(
onError = Timber::e,
onSuccess = { }
)
}
}
}
Usecase for the suspend method
class FetchRecentUseCaseImp() {
override suspend fun execute(): List<Products> {
// Call to network
}
}
Many thanks in advance
With coroutines, the way to return a single item that is produced asynchronously is to use a suspend function. So instead of launching a coroutine, you mark the function as suspend and convert blocking or async callback functions into non-blocking code.
The places where coroutines are launched are typically at UI interactions (click listeners), or when classes are first created (on Android, this is places like in a ViewModel constructor or Fragment's onViewCreated()).
As a side note, it is against convention for any suspend function to expect the caller to have to specify a dispatcher. It should internally delegate if it needs to, for example:
class FetchRecentUseCaseImp() {
override suspend fun execute(): List<Products> = withContext(Dispatchers.IO) {
// Synchronous call to network
}
}
But if you were using a library like Retrofit, you'd simply make your Request and await() it without specifying a dispatcher, because await() is a suspend function itself.
So your function should look something like:
suspend fun loadRecentlyViewed(): List<SomeProductType> {
val listOfSkus = fetchRecentUseCase.execute().map(Product::sku)
if (listOfSkus.isEmpty()) {
return emptyList()
}
return runCatching {
loadProductUseCase.execute(listOfSkus) // A Single, I'm assuming
.await() // Only if you're not completely stripping Rx from project
.map { convertProductDisplayUseCase.execute(it).await() } // Ditto for await()
.toList()
.flatten()
}.onFailure(Timber::e)
.getOrDefault(emptyList())
}

Can I access the "enclosing" object for an inlined function call in Kotlin?

Idea: Make an inlined convenience function to synchronize a function call on the "inlining" object's intrinsic lock:
public inline fun <T> intrinsicSync(block: () -> T): T {
return synchronized(intrinsicLockOfTheObjectUsingTheFunction) {
block()
}
}
fun someFunction(parameter: SomeClass) {
intrinsicSync(sharedResource.operation(parameter))
}
Is this possible? If not, is there a different but equally convenient way? I concede that
fun someFunction(parameter: SomeClass) {
synchronized(this) {
sharedResource.operation(parameter)
}
}
isn't the biggest hassle in the world, but I'd still like to know if it's possible to do something similar to what I imagined.
The most you can do is give the function a receiver (i.e. make it an extension function):
public inline fun <T> Any.intrinsicSync(crossinline block: () -> T): T {
// ^ within this function, `this` refers to the receiver
return synchronized(this, block)
}
and then in a member function, you can do
this.intrinsicSync { sharedResource.operation() }
and since this is inferred you should be able to shorten this to
intrinsicSync { sharedResource.operation() }
Keep in mind that extension functions cannot shadow member functions, so if this object has another function with the same signature, it won't choose the extension function.
In your case, though, this seems unlikely.