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.
Related
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().
I want to call some api in the background every X minutes and then process the json file I get
I've lokked into this documentation: https://kotlinlang.org/api/latest/jvm/stdlib/kotlin.concurrent/java.util.-timer/schedule.html
I'm new to kotlin (I used java before) and I have no idea how to use those functions, any examples of usage would be helpful.
Right now I have something like this:
Timer("NameOfMyTimer", true).schedule(refreshImages(knownPosts, knownFiles, httpClient), TimeUnit.MINUTES.toMillis(5))
And the result is:
None of the following functions can be called with the arguments supplied:
public open fun schedule(p0: TimerTask!, p1: Date!): Unit defined in java.util.Timer
public open fun schedule(p0: TimerTask!, p1: Long): Unit defined in java.util.Timer
What did I wrong? How should I call those functions?
I thought that I'm supposed to pass my function "refreshImages" to the timer with list of arguments it should be called with...?
I think I just don't get the "function is object" philosophy right.
You're trying to call
.schedule(refreshImages(knownPosts, knownFiles, httpClient), TimeUnit.MINUTES.toMillis(5))
So you're passing as first argument the result of refreshImages(knownPosts, knownFiles, httpClient), and as second argument a number of milliseconds.
And as you can see from the compilation error, the Timer class has two schedule() methods, but both expect a TimerTask as argument. And your refreshImages method doesn't return a TimerTask, so that doesn't compile.
If you want to use one of these two Timer methods, you need to create an instance of TimerTask, and pass that as argument.
My guess is that you would like to pass a function that will be executed after some delay. That's not what you're doing right now. What you're doing is that you execute refreshImages() immediately, and pass its returned value to schedule().
Passing a function is not possible with the native Timer schedule method: it doesn't expect a function, but a TimerTask. But as the Kotlin documentation you linked to shows, it's possible by calling one of the extension functions of the Kotlin standard library.
The signature of the schedule extension function is
inline fun Timer.schedule(
delay: Long,
crossinline action: TimerTask.() -> Unit
): TimerTask
So, as you can see, its first argument is a delay, and its second argument is a function with TimerTaskas receiver. So you can call this extension function using a delay as first argument, and a lambda as second argment:
timer.schedule(TimeUnit.MINUTES.toMillis(5)) {
refreshImages(knownPosts, knownFiles, httpClient)
}
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() }
}
I'm new to Erlang and I want to suspend in a function. I use receive with infinity timeout, my function looks like:
suspend() ->
receive
after
infinity->ok
end.
When I ran dialyzer tool, it return "Function has no local return". Should I replace this function with timer:sleep(infinity). For suspend, which one is better? Thank you so much.
The function timer:sleep/1 is defined as:
sleep(T) ->
receive
after T -> ok
end.
which is essentially the same as your suspend/0 function, so either approach would work. I'd advise using timer:sleep/1, though, as it's already defined for you, and anyone reading it will instantly know what it is and what it does.
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?