kotlinx-rpc icon indicating copy to clipboard operation
kotlinx-rpc copied to clipboard

Provide some way for a KrpcTransport/KrpcServer implementation to know if a procedure call is done

Open natanfudge opened this issue 9 months ago • 4 comments

This is related to https://github.com/Kotlin/kotlinx-rpc/issues/75. After hacking a way a bit trying to adapt kotlinx-rpc to a serverless architecture, I hit an issue. To illustrate the problem, lets review the architecture of serverless computing.

Image

However, krpc assumes the traditional dedicated server architecture:

Image

If we look at the KrpcTransport interface:

interface KrpcTransport {
    fun send(message: KrpcTransportMessage)
    fun receive(): KrpcTransportMessage
}

KrpcTransportMessage only encodes the messages itself, and not whether this is the last message.

sealed interface KrpcTransportMessage {
    class StringMessage(val value: String) : KrpcTransportMessage
    class BinaryMessage(val value: ByteArray) : KrpcTransportMessage
}

As such, there is no way to know whether to enter the last step in the first diagram, and shut down the machine, outside of trying to parse the value, or counting the amount of sent messages, which is very fragile.

Proposed solution

Add a terminateProcedureCall() method to KrpcTransport / KrpcServer

public abstract class KrpcServer {
+  /**
+   * Notifies that a unit of work has been done, and resources associated with this transport may be safely released. 
+   * Implementation may safely ignore this method if they wish to reuse the same resources for multiple units of work (multiple procedure calls). 
+  */
+   public open suspend fun terminateProcedureCall(): Unit {}
}

Or alternatively:

public interface KrpcTransport : CoroutineScope {
    public suspend fun send(message: KrpcTransportMessage)
    public suspend fun receive(): KrpcTransportMessage
+   public suspend fun terminateProcedureCall(): Unit {}
    public suspend fun receiveCatching(): Result<KrpcTransportMessage> {
        return runCatching { receive() }
    }
}

natanfudge avatar Feb 17 '25 10:02 natanfudge

Hey @natanfudge ! Thanks for the interest in the lib! I have a question: I'm not sure I understand, when terminateProcedureCall is intended to be called?

Mr3zee avatar Feb 18 '25 13:02 Mr3zee

@Mr3zee terminateProcedureCall must be called when handling the procedure call is done. The workflow should be like this:

  • Call KrpcTransport.receive() to get a request.
  • Parse the request and send it to an RPC service implementation.
  • Send the response(s) with KrpcTransport.send() (this includes dispatching events made by emitting to streams)
  • Release resource with terminateProcedureCall(). By calling this, krpc acknowledges the hosting computer may shut down immediately.

natanfudge avatar Feb 18 '25 14:02 natanfudge

@Mr3zee Any thoughts?

natanfudge avatar Mar 05 '25 18:03 natanfudge

Hi, @natanfudge haven't had a chance to think it though yet, when will do - I'll let you know. Thank you for the issue, though!

Mr3zee avatar Mar 12 '25 19:03 Mr3zee

Recent changes in 0.8.0 might solve this problem?

https://kotlin.github.io/kotlinx-rpc/0-8-0.html#krpc-protocol-changes

KrpcClient sends REQUEST cancellation messages for every individually finished call, canceled or finished successfully

natanfudge avatar Jul 10 '25 20:07 natanfudge

@natanfudge those are protocol internals you shouldn't rely on probably, at least until we say it is stable (which won't be true for a while)

Mr3zee avatar Jul 10 '25 20:07 Mr3zee