Aspect around Kotlin suspended function - kotlin

What is the right way to create an aspect around Kotlin suspended function?
From my observation, Micrometer's #Timed aspect does work with them, but shows incorrect result - looks like it measures time between method invocation and suspension, not the full time spent in the method (which should include post-suspension period)
Example of what I'd like to achieve:
#CoroutineTimer
suspend fun dbCall() {
repository.someQuery().awaitFirst() // suspension point
}
In this case I'd like to know the full time spent on dbCall function, marked with a custom #CoroutineTimer annotation. Is there a way do so?

Related

Is there a use for the "with" function that I can't achieve by "apply", "run", "also" or "let" in Kotlin?

When would we ever need with in Kotlin if we can already use apply, run, also and let?
Can anyone give me a clear example?
In most situations, a with call can be transformed to a run like this:
with(foo) {
// some code ...
}
// is the same as:
foo.run {
// the same code ...
}
run and with will both return the lambda result, and will use foo as the lambda receiver.
However, I can think of one case where this wouldn't work - when foo declares its own run method that takes a lambda, e.g.
// having something like this isn't too uncommon, right?
fun run(x: () -> Unit) {}
The lambda type doesn't have to be exactly the same as the scope function run. Any function type should work. Then overload resolution wouldn't resolve to the built-in run.
You can force the resolution by doing some casts, but using with in this case is much better. Don't you agree?
I don’t think there’s any better example than with(context). Maybe it’s not clear if English isn’t one of your primary languages, but it semantically is translated into English much clearer than context.run when the object is being used to produce a result but isn’t the primary actor, so it makes code a little easier to read.
This of course raises the question of why run exists. Well, it semantically makes more sense in English when the object is the thing doing the action. In English, the context of an action is what you’re doing something with. But if the object is what is directly producing the result, then it is running the action.
Also, you can’t do ?.with.

How to wait for Room to update?

I'm trying to make a function that first updates a model field in a Database, then imediatly retrives this same model. I'd like to get that model with the udpated field. I'm trying this:
var snack = appViewModel.getSnack(snackId)
runBlocking { appViewModel.updateSnack(snack.copy(total = value)) }
snack = appViewModel.getSnack(snackId)
However, even when using runBlocking, snack ends up being with the old total value. I don't know how Room suspending functions for #Update are implemented, but it seems that even with runBlocking this runs assyncrhronaly, so the field doesn't get updated in time. How do I proceed?
As #Tenfour04 pointed out, my implementation in the ViewModel was launching a viewModelScope, so the function returned imediately, and runBlocking{} was useless. As a temporary measure, I just added .join() to the runBlocking call, so it waits for the Job to finish:
runBlocking { appViewModel.updateSnack(snack.copy(total = value)).join() }
As #Tenfour04 also pointed out, my design is flawed, because we shoudn't be blocking the UI. I'm now trying to implement everything with Flow<> and collectAsState().

Dealing with suspend and non-suspend in Kotlin function parameters

I am fairly new to Kotlin, and am getting to grips with it's implementation of co-routines. I understand that any function that we may want Kotlin to deal with in a non-blocking way needs to be annotated with suspend, and that such functions can only be executed within a co-routine (or within another suspend function). So far so good.
However I keep coming across a problem with utility functions that accept other functions as parameters. For instance with arrow's Try:
suspend fun somethingAsync() = 1 + 1
Try { 1 + 1 } // All is well
Try { somethingAsync() } // Uh oh....
As the parameter to Try's invoke function/operator is not annotated with suspend, the second call will be rejected by the compiler. How does someone deal with this when writing utility functions that can not know if the code inside the passed function or lambda requires suspend or not? Writing a suspend and a non-suspend version of every such function seems incredibly tedious. Have I missed an obvious way to deal with this situation?
First, let's deal with suspend. What it means is this particular function blocks. Not that this function is asynchronous.
Usually, blocking means IO, but not always. In your example, the function doesn't block, nor does it something in an asynchronous manner (hence Async suffix is incorrect there). But lets assume actual utility code does block for some reason.
Now dealing with suspending functions is something that is done on the caller side. Meaning, what would you like to do while this is being executed:
fun doSomething() {
Try { somethingAsync() }
}
If you're fine with doSomething to block, then you can use runBlocking:
fun doSomething() = runBlocking {
Try { somethingAsync() }
}

#Around aspect and Kotlin suspended function

I try to understand how to create an #Around aspect for a Kotlin’s suspended function (for example, to measure time spent in this function, or for a custom #Transactional aspect):
#Timed("my-timer")
suspend fun test() {
println("before")
delay(50) // invokes ProceedingJoinPoint#proceed() before this line
println("after")
}
Since this function has a suspend function call, the #Around aspect’s proceed function will be invoked right before delay() call. But obviously I’d like to measure full time spent in the function.
What is the right way to solve it? Maybe I can somehow subscribe on the last continuation in the method, or smth like that?
I think you can solve your problem easily, if you want to measure, the execution time of function, you can do it using built-in functionality like this:
val time = measureTimeMillis {
// yourSuperFunc()
}
Also, you can use measureNanoTime. For full reference look at here.
This is tracked by https://github.com/spring-projects/spring-framework/issues/22462 and will most likely be fixed in 5.3
The same issue happens for #Transactional.

Pointcuts and Aspect-Oriented Programming

How are pointcuts used in aspect-oriented programming language to add functionality into an existing program?
To my understanding, from this Wikipedia article - http://en.wikipedia.org/wiki/Pointcut
Pointcuts are placed into a specific spot in a piece of code, and when that point is reached, based on the evaluation of the pointcut, more code can be executed at a specific point somewhere in the code based on the evaluation of the pointcut. Is this a correct understanding?
If so, then that would add functionality because the programmer can execute different piece of code based off that evaluation.
For example, I have an application with a number of service objects and I want to time every method. Using AspectJ notation:
class MyAspect
{
#Around("execution(public * my.service.package.*(..))")
public Object aroundAdvice(JoinPoint jp)
{
// start timer
Object o = jp.proceed();
// stop timer, etc.
return o;
}
}
Here, the "execution(public * my.service.package.*(..))" is the pointcut: it specifies the set of join points for which the advice will be executed (the execution of all methods in all classes in the service package).
Pointcut is what connects advices ("pure" code fragments that don't care where exactly it will be run) and join points (points of execution like method call or return, that don't care what code will be run).
I would call pointcut a predicate function that chooses which join points are going to be used with current aspect (predicate that gives true/false for each join point for each advice).