Kotlin / kotlinx-rpc

Add asynchronous RPC services to your multiplatform applications.
https://kotlin.github.io/kotlinx-rpc/
Apache License 2.0
512 stars 7 forks source link

Support for serverless RPC responses #75

Open natanfudge opened 1 month ago

natanfudge commented 1 month ago

Currently, kotlinx.rpc supports serving RPC responses via ktor, with a syntax like so:

rpc("/awesome") {
   registerService<AwesomeService> { ctx -> AwesomeServiceImpl(ctx) }
}

This means that a dedicated server may be deployed to continuously run a ktor server that responds to AwesomeService. Since the architecture is similar, it would be simple to expand this functionality to other dedicated server frameworks (e.g. Spring).

The question is if you would be able to use kotlinx.rpc with serverless services such as AWS Lambda that have an API like so:

// Theoretical API: 
val rpc = kotlinx.rpc.createService<AwesomeService>() 
class WebHttpHandler : RequestHandler<APIGatewayV2HTTPEvent, APIGatewayV2HTTPResponse> {
    override fun handleRequest(input: APIGatewayV2HTTPEvent, context: Context): APIGatewayV2HTTPResponse = runBlocking {
        // Theoretical API: 
        return rpc.handle(input, context)
        // Or more generally:
        return rpcToAws(rpc.handle(awsToRpc(input, context)) 
    }
}

In this case, a specific handle method needs to be exposed in order to handle each individual serverless request like so. Additionally, flows need special treatment. In a serverless environment, you cannot keep around an instance of a MutableSharedFlow and emit objects to it to reach clients, since you must assume the memory (and disk) is erased for each individual Procedure Call. Instead, you must store subscriptions (essentially, calls to an RPC function returning Flow) on an external service, chosen by the developer. I'm guessing it would be possible to still abstract this behind the Flow interfaces. You can have a generic interface for the way subscription is done and then have one that is memory based for dedicated servers and one that is e.g. DynamoDB based for serverless.

Because of this difference it requires a bit of engineering to support this, but it is possible.

Is an API like this planned and will you accept PRs implementing it? It is necessary for a big portion of applications.

Mr3zee commented 1 month ago

Hi @natanfudge ! Thank for your interest in the library! Let me try to answer two of your questions

Is an API like this planned?

We didn't yet consider this particular case. But, what we do want to have is a very flexible set of APIs, that will allow for users (or us, depending on the demand) to implement a broad variety of integrations.

Will you accept PRs implementing it?

I general yes, but I want to be clear, that current kRPC protocol implementation (which is used with Ktor now) is very experimental and probably will be replaced with a new version once we come up with it. So implementing such an API with kRPC probably is not a good idea right now. On the other hand, if you plan to try it without kRPC, but just implementing RPCServer for example - you are more than welcome to share with us your results, as this part should not change drastically before going stable