Does kotlin-native have destructors? - kotlin

In kotlin native there is memScoped function that automatically free allocated memory when control is going out of scope.
Is there something like destructors for local objects?

Current Kotlin/Native does not provide mechanism for calling a method when certain object is no longer needed in memory (finalizer in Java speech) but inline lambdas easily allow to implement mechanisms, similar to RAII in C++. For example, if you want to be sure, that some resource is always released after leaving certain scope, you may do:
class Resource {
fun take() = println("took")
fun free() = println("freed")
}
inline fun withResource(resource: Resource, body: () -> Unit) =
try {
resource.take()
body()
} finally {
resource.free()
}
fun main(args: Array<String>) {
withResource(Resource()) {
println("body")
}
}

Related

When I use the generic method in Route then I am getting compiler Backend Internal error: Exception during IR lowering in Ktor

I am trying to create a dynamic service based on the data class model defined by user and they registerDataModels() method appDataModule() it should automatically create all based method in the router service. When I try to achive using generics in those method I am getting a compiler error. Is there any other better way to dynamically create route methods like by defining the datamodel by developer and then service should be automatically created?
org.jetbrains.kotlin.backend.common.BackendException: Backend Internal error: Exception during IR lowering
File being compiled: */api/AppConfigService.kt
The root cause java.lang.RuntimeException was thrown at: org.jetbrains.kotlin.backend.jvm.codegen.FunctionCodegen.generate(FunctionCodegen.kt:47)
File is unknown
The root cause java.lang.AssertionError was thrown at: org.jetbrains.kotlin.codegen.coroutines.CoroutineTransformerMethodVisitor.spillVariables(CoroutineTransformerMethodVisitor.kt:636)
fun Application.registerDataModels() {
appDataModule<M1>()
appDataModule<M2>()
appDataModule<M3>()
}
inline fun <reified T: DBModel> Application.appDataModule() {
routing {
createAppData<T>()
updateAppData<T>()
deleteAppData<T>()
}
}
inline fun <reified T: DBModel> Route.createAppData() {
put("/api/data/${getName<T>()}/create") {
authenticated {
create<T>{}
}
}
}
inline fun <reified T: DBModel> Route.updateAppData() {
put("/api/data/${getName<T>()}/update") {
authenticated {
update<T>{}
}
}
}
inline fun <reified T: DBModel> Route.deleteAppData() {
put("/api/data/${getName<T>()}/delete") {
authenticated {
delete<T>{}
}
}
}
Note: This answer assumed that code would be loaded at runtime, which seems not to be the case, and is therefore not completely matching OP's question.
You are using inline functions with reified.
To make a long story short, inline functions are compiled and 'copied' to the location where they are being used, already with a fixed (thats what reified does) class. So when you use an inline function
inline fun <reified T> foo(t: T): T { ... }
and you call it like this:
val myVal = foo("test").uppercase()
then at compile time of that calling line of code, the type of T is known to be String and the target line is compiled accordingly, so you know at runtime which type T is within your function.
It is (for this one calling line) as if that function was like this to begin with:
fun foo(t: String): String { ... }
Because you want to compile these classes dynamically, however, this process fails, because the class obviously does not exist yet. This is simply due to the nature of reified. If you can somehow remove it, it might work.
I agree that the error message of the compiler could be more telling here. Maybe you can raise a task on kotlin's issue tracking platform?: https://youtrack.jetbrains.com/issues/kt?_gl=1*5r6x4d*_ga*MTQyMDYxMjc2MS4xNjMzMzQwMzk5*_ga_9J976DJZ68*MTY2OTM1NjM1MS4yMS4xLjE2NjkzNTYzNTcuMC4wLjA.&_ga=2.265829455.1332696793.1669356352-1420612761.1633340399

How to dynamically chose a transform function based on current observable in project reactor?

Hello dear reactive programmers, I started to learn project reactor but I still struggle to figure out what operator to use when. I figured out, that if I want to have reusable parts to define a reactor flow, I can use the transform operator. What I would like to achieve is to use a certain implementation of such a flow function based on the current observables context. For a Mono flow, I came up with this, but I am very unsure, if it is a good solution:
So here is a part of the flow
class CloudeventOverDelegatorRoute(
val fromHttpToDelegatorRoute: FromHttpToDelegatorRoute,
val delegatorProvider: DelegatorProvider,
val fromDelegatorToHttpRoute: FromDelegatorToHttpRoute
): MessageRoute<HttpBaseMessage, HttpResponseMessage> {
override fun isHandlerFor(context: RouteContext): Boolean {
return fromHttpToDelegatorRoute.isHandlerFor(context)
&& fromDelegatorToHttpRoute.isHandlerFor(context)
}
override fun buildPipeline(input: Mono<RoutableMessage<HttpBaseMessage>>): Mono<RoutableMessage<HttpResponseMessage>> {
var dynamicallyDeterminedDelegator: Delegator? = null
return input.transform {
fromHttpToDelegatorRoute.buildPipeline(input)
}.handle<RoutableMessage<InternalMessage>> { t, u ->
dynamicallyDeterminedDelegator = delegatorProvider.provideDelegatorFor(t.routeContext)
u.next(t)
u.complete()
}.transform {
dynamicallyDeterminedDelegator!!.sendDelegated(it)
}.transform { fromDelegatorToHttpRoute.buildPipeline(it) }
}
}
Here is the dynamic selection logic
interface DelegatorProvider {
fun provideDelegatorFor(context: RouteContext): Delegator
}
class FirstMatchDelegatorProvider(
private val delegators: List<Delegator>
): DelegatorProvider {
override fun provideDelegatorFor(context: RouteContext): Delegator {
return delegators.firstOrNull {
it.isHandlerFor(context)
}?: throw IllegalStateException("No Delegator route available for context: $context")
}
}
And this is the delegator providing an essential sub-part of the whole flow
interface Delegator {
fun isHandlerFor(context: RouteContext): Boolean
fun sendDelegated(input: Mono<RoutableMessage<InternalMessage>>): Mono<RoutableMessage<InternalStatusMessage>>
}
What do you think? How would you solve it?
this approach is problematic because it relies on shared state (the dynamicallyDeterminedDelegator variable). If multiple subscribers subscribe to the returned Mono, they could overwrite each other delegator. Maybe that (multiple subscriptions) can't happen in your application, but this is a very bad habit to get into in any case.
looks like you can derive a delegator out of a RoutableMessage<InternalMessage> , and that you don't really need to retain that delegator.
the easiest way to resolve and apply the delegator to the routableMessage in one go is simply to use flatMap. see the (pseudo) java code below:
.flatMap(routableMessage -> {
val delegator = delegatorProvider.provideDelegatorFor(routableMessage.routeContext);
return delegator.sendDelegated(routableMessage);
})

How to compose IO functions with other effects in Kotlin Arrow FX

We often need some request validation before handling it. With arrow v 0.8 a typical message handler looked like:
fun addToShoppingCart(request: AddToShoppingCartRequest): IO<Either<ShoppingCardError, ItemAddedEvent>> = fx {
request
.pipe (::validateShoppingCard)
.flatMap { validatedRequest ->
queryShoppingCart().bind().map { validatedRequest to it } // fun queryShoppingCart(): IO<Either<DatabaseError, ShoppingCart>>
}
.flatMap { (validatedRequest, shoppingCart) ->
maybeAddToShoppingCart(shoppingCart, validatedRequest) // fun maybeAddToShoppingCart(...): Either<DomainError, ShoppingCart>
}
.flatMap { updatedShoppingCart ->
storeShoppingCart(updatedShoppingCart).bind() // fun storeShoppingCart(ShoppingCart): IO<Either<DatabaseError, Unit>>
.map {
computeItemAddedEvent(updatedShoppingCart)
}
}
.mapLeft(::computeShoppingCartError)
}
This seems to be a convenient and expressive definition of a workflow. I tried to define similar function in arrow v 0.10.5:
fun handleDownloadRequest(strUrl: String): IO<Either<BadUrl, MyObject>> = IO.fx {
parseUrl(strUrl) // fun(String): Either<BadUrl,Url>
.map {
!effect{ downloadObject(it) } // suspended fun downloadObject(Url): MyObject
}
}
Which results in a compiler error "Suspension functions can be called only within coroutine body". The reason is both map and flatMap functions of Either and Option are not inline.
Indeed, the blog post about fx says
"Soon you will find that you cannot call suspend functions inside the
functions declared for Either such as the ones mentioned above, and
other fan favorites like map() and handleErrorWith(). For that you
need a concurrency library!"
So the question is why is it so and what is the idiomatic way of such composition?
The idiomatic way is
fun handleDownloadRequest(strUrl: String): IO<Either<BadUrl, MyObject>> =
parseUrl(strUrl)
.fold({
IO.just(it.left()) // forward the error
}, {
IO { downloadObject(it) }
.attempt() // get an Either<Throwable, MyObject>
.map { it.mapLeft { /* Throwable to BadURL */ } } // fix the left side
})
Personally I wouldn't go to the deep end of IO with that one, and rewrite as a suspend function instead
suspend fun handleDownloadRequest(strUrl: String): Either<BadUrl, MyObject> =
parseUrl(strUrl)
.fold(::Left) { // forward the error
Either.catch({ /* Throwable to BadURL */ }) { downloadObject(it) }
}
What happened is, in 0.8.X the functions for Either used to be inlined. An unintended side-effect of this was that you could call suspend functions anywhere. While this is nice, it can lead to exceptions thrown (or jumping threads or deadlocks 🙈) in the middle of a map or a flatMap, which is terrible for correctness. It's a crutch.
In 0.9 (or was it 10?) we removed that crutch and made it into something explicit in the API: Either.catch. We kept fold as inlined because it's the same as when, so there was no real correctness tradeoff there.
So, the recommended thing is to use suspend everywhere and only reach for IO when trying to do threading, parallelism, cancellation, retries and scheduling, or anything really advanced.
For basic use cases suspend and Either.catch is enough. To call into a suspend function at the edge of your program or where you need to bridge with these advanced behaviors then use IO.
If you want to continue using Either you can define suspend/inline versions of regular functions at your own risk; or wait until IO<E, A> in 0.11 where you can use effectEither and effectMapEither.

What's the recommended way to delay Kotlin's buildSequence?

I'm trying to poll a paginated API and provide new items to the user as they appear.
fun connect(): Sequence<T> = buildSequence {
while (true) {
// result is a List<T>
val result = dataSource.getFirstPage()
yieldAll(/* the new data in `result` */)
// Block the thread for a little bit
}
}
Here's the sample usage:
for (item in connect()) {
// do something as each item is made available
}
My first thought was to use the delay function, but I get this message:
Restricted suspended functions can only invoke member or extension suspending functions on their restricted coroutine scope
This is the signature for buildSequence:
public fun <T> buildSequence(builderAction: suspend SequenceBuilder<T>.() -> Unit): Sequence<T>
I think this message means that I can only use the suspend functions in SequenceBuilder: yield and yieldAll and that using arbitrary suspend function calls aren't allowed.
Right now I'm using this to block the sequence building by one second after every time the API is polled:
val resumeTime = System.nanoTime() + TimeUnit.SECONDS.toNanos(1)
while (resumeTime > System.nanoTime()) {
// do nothing
}
This works, but it really doesn't seem like a good solution. Has anybody encountered this issue before?
Why does it not work? Some research
When we look at buildSequence, we can see that it takes an builderAction: suspend SequenceBuilder<T>.() -> Unit as its argument. As a client of that method, you'll be able to hand on a suspend lambda that has SequenceBuilder as its receiver (read about lambda with receiver here).
The SequenceBuilder itself is annotated with RestrictSuspension:
#RestrictsSuspension
#SinceKotlin("1.1")
public abstract class SequenceBuilder<in T> ...
The annotation is defined and commented like this:
/**
* Classes and interfaces marked with this annotation are restricted
* when used as receivers for extension `suspend` functions.
* These `suspend` extensions can only invoke other member or extension
* `suspend` functions on this particular receiver only
* and are restricted from calling arbitrary suspension functions.
*/
#SinceKotlin("1.1") #Target(AnnotationTarget.CLASS) #Retention(AnnotationRetention.BINARY)
public annotation class RestrictsSuspension
As the RestrictSuspension documentation tells, in the case of buildSequence, you can pass a lambda with SequenceBuilder as its receiver but with restricted possibilities since you'll only be able to call "other member or extension suspend functions on this particular receiver". That means, the block passed to buildSequence may call any method defined on SequenceBuilder (like yield, yieldAll). Since, on the other hand, the block is "restricted from calling arbitrary suspension functions", using delay does not work. The resulting compiler error verifies it:
Restricted suspended functions can only invoke member or extension suspending functions on their restricted coroutine scope.
Ultimately, you need to be aware that the buildSequence creates a coroutine that is an example of a synchronous coroutine. In your example, the sequence code will be executed in the same thread that consumes the sequence by calling connect().
How to delay the sequence?
As we learned, The buildSequence creates a synchronous sequence. It's fine to use regular Thread blocking here:
fun connect(): Sequence<T> = buildSequence {
while (true) {
val result = dataSource.getFirstPage()
yieldAll(result)
Thread.sleep(1000)
}
}
But, do you really want an entire thread to be blocked? Alternatively, you can implement asynchronous sequences as described here. As a result, using delay and other suspending functions will be valid.
Just for an alternate solution...
If what you're really trying to do is asynchronously produce elements, you can use Flows which are basically asynchronous sequences.
Here is a quick table:
Sync
Async
Single
Normal valuefun example(): String
suspendingsuspend fun example(): Stringorfun example(): Deferred<String>
Many
Sequencefun example(): Sequence<String>
Flowfun example(): Flow<String>
You can convert your Sequence<T> to a Flow<T> by replacing the sequence { ... } builder with the flow { ... } builder and then replace yield/yieldAll with emit/emitAll:
fun example(): Flow<String> = flow {
(1..5).forEach { getString().let { emit(it) } }
}
suspend fun getString(): String = { ... }
So, for your example:
fun connect(): Flow<T> = flow {
while (true) {
// Call suspend function to get data from dataSource
val result: List<T> = dataSource.getFirstPage()
emitAll(result)
// _Suspend_ for a little bit
delay(1000)
}
}

Getting access to an instance in a wrapper function

In Kotlin I have this function to wrap a transaction:
fun wrapInTransaction(code: () -> Unit) {
realmInstance.beginTransaction();
code.invoke()
realmInstance.commitTransaction();
}
How can I get access to realmInstance in the invoked code?
The easy solution here is to make code a function with receiver:
fun wrapInTransaction(code: Realm.() -> Unit) {
realmInstance.beginTransaction();
realmInstance.code()
realmInstance.commitTransaction();
}
Inside a lambda which you pass as code you will be able to use this to reference the RealmInstance and to use its members directly as if inside a member function.
Calling realmInstance.code() is just calling code with passing realmInstance as a receiver to it.
The other answers correctly demonstrate how to pass the RealmInstance object to the lambda. In addition, you can make the whole function an extension function which makes the call site a bit prettier:
fun Realm.wrapInTransaction(code: Realm.() -> Unit) {
//this is implicit
beginTransaction();
code()
commitTransaction();
}
The call site will look like this:
Realm.getInstance(this).wrapInTransaction {
createObject(User.class)
}
Change the wrapInTransaction function to accept an extensions method on realmInstance like so:
fun wrapInTransaction(code:Realm.() -> Unit){
realmInstance.beginTransaction();
realmInstance.code()
realmInstance.commitTransaction();
}
Then you can use it like:
wrapInTransaction {
println("realm instance is $this, instanceId: $instanceId")
}
Where for the sake of the example the Realm looks like:
class Realm {
val instanceId = 42
fun beginTransaction() {
}
fun commitTransaction() {
}
}
The above technique is possible thanks to Kotlin's Function Literals with Receiver that make it possible to set the this instance (receiver) within lambda function body. It makes it easy to build type safe builders that reassemble ones from Groovy or Ruby.
This answer provides more samples on the technique.