Skip to content

Conversation

@just-be-dev
Copy link

I find the typescript usage of RpcTarget to be significantly more ergonomic.

class MyApiServer extends RpcTarget {
  hello(name) {
    return `Hello, ${name}!`
  }
}

In their usage, all you really need to do is extend from RpcTarget and define some methods. Every non-private method is then callable from the RPC connection. I thought it'd be nice to do the same thing here. So instead this

class MyApiServer(RpcTarget):
  async def call(self, method: str, args: list[Any]) -> Any:
    match method:
      case "hello":
        return f"Hello, {args[0]}"

we could just implement it as

class MyApiServer(RpcTarget):
  def hello(self, name: str) -> str:
    return f"Hello, {name}"

The nice thing about my implementation approach is that if you already have a definition of call, it'll continue to work exactly the same as it does today. You just are no longer required to implement call because there's a default implementation.


There's a few longer term things that I think would be nice to do

  1. Make the client interface seem more like it's a regular object (instead of the call method)
  2. Make the target Pydantic compatible to ensure inputs/outputs can be validated

The `call` implementation doesn't feel very ergonmic. Instead of having to define `call` and switch on different methods, the RpcTarget class is updated with a default call implementation that pulls non-private methods from the class.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant