Skip to content

Allow to send services as RPC method arguments #341

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
snej opened this issue May 15, 2025 · 1 comment
Open

Allow to send services as RPC method arguments #341

snej opened this issue May 15, 2025 · 1 comment
Assignees
Labels
feature New feature or request

Comments

@snej
Copy link

snej commented May 15, 2025

I’m looking at using KRPC to reimplement an RPC interface previously implemented with CapnProto. The limitation I’m running into is that calls can be made in only one direction: one peer is the “client” and can make calls, the other is the “server” and can only receive and reply to calls. The interface I’m using is symmetrical: both sides can send requests to the other.

(This interface is for a form of data sync involving hash trees; it involves a sequence of negotiations where the ‘client’ side requests information about a tree node, examines it, and as a result may need to request more information or [recursively] send requests for child nodes. To enable bidirectional sync, both sides of a connection need to be able to adopt either the server or client role.)

Issue #238 describes a similar use case, and the (unofficial) answer was "I think the intended solution for server->client communication is flows.” This does make sense for a specific type of server-to-client communication, a “push” model where the server just sends notifications. But it doesn’t suffice when the server needs responses to the messages it sends.

To do the server-to-client communication with a flow would involve an implementation like:

  • Client initiates sending an RPC request that the server responds to with a flow.
  • When the server needs to request, it sends an object over the flow that contains a request-type enum and arguments, as well as some unique request ID generated by a counter
  • The client receives the request from the flow, dispatches it according to the ‘type’ field, and processes it.
  • The client sends the response by sending another RPC request, passing the server’s request ID.
  • The server’s RPC implementation looks up the request ID in a table of pending requests, and pass the args to whoever’s waiting for it.

This really looks like it’s artificially re-inventing a lot of what’s going on inside KRPC. It would be so much simpler if KRPC were symmetrical, so the client could register its own service and the server could access a client implementation of it.

@snej snej added the feature New feature or request label May 15, 2025
@Mr3zee
Copy link
Collaborator

Mr3zee commented May 16, 2025

Hi @snej! I understand what you mean by it. From our internal discussions, the most probable implementation is service arguments:

@Rpc
interface ClientToServer {
    suspend fun openConnection(service: ServerToClient)
}

@Rpc
interface ServerToClient {
    suspend fun askClientName(): String
}

And something like this on the server:

class ClientToServerImpl : ClientToServer {
    override suspend fun openConnection(service: ServerToClient) {
        val clientName = service.askClientName()
        // ... handle it
    }
}

This option though viable, requires some thorough research. We'll keep it in mind

@Mr3zee Mr3zee changed the title Allow “server” on both sides of a connection Allow to send services as RPC method arguments May 16, 2025
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
feature New feature or request
Projects
None yet
Development

No branches or pull requests

2 participants