tatethurston / TwirpScript

A protobuf RPC framework for JavaScript and TypeScript
MIT License
141 stars 14 forks source link

Websocket alternatives #222

Closed ghost closed 3 months ago

ghost commented 1 year ago

This might be the most unconventional place to do this. What is the alternative to Twirp for Websocket endpoints

tatthurs commented 1 year ago

😆 this is actually something I've thinking about.

Do you mean something like defining messages in protobuf and then autogenerating consumers / publishers that communicate over websockets?

ghost commented 1 year ago

Exactly. Something similar to that. The autonomy from the server, as seen in Twirp, along with support for HTTP/1.1, is what is most important. This resolves the compatibility issues between HTTP/2 and AWS Lambda and others. Moreover, an independent Handler would enable seamless integration with an existing server. Presently, the sole way to handle streaming that I’m aware of involves GRPC, but it brings along its own server and doesn’t use websockets. It can be like autogenerating messages and responses from protobuf.

Desired Features

•   WebSocket support
•   Independence from a specific server
•   Compatibility with HTTP/1.1

Protobuf example


service Foo {
    rpc FooEvent(FooMessage) returns FooResponses
}

message FooResponses {
        oneof data {
              Foo foo = 1;
              Bar bar = 2;
       }
}
tatethurston commented 1 year ago

I think high-level I'd approach this like:

// This indicates the server publishes Hat events

service Haberdasher {
  rpc HatCreated(google.protobuf.Empty) returns (stream Hat);
}
// This indicates the server accepts Hat events from the client

service Haberdasher {
  rpc HatCreated(stream Hat) returns (google.protobuf.Empty);
}
// This indicates bidirectional communication, both the server the client can publish Hat events

service Haberdasher {
  rpc HatCreated(stream Hat) returns (stream Hat);
}

The service name and rpc name would be concated with a period to create a message key, so the example above would publish messages that looked like:

message {
  key: 'Haberdasher.HatCreated',
  payload: Hat
}

And the client could look something like:

client.on('Haberdasher.HatCreated', () => { ... })`

or

client.publish('Haberdasher.HatCreated', message)

And the server could look like:

server.on('Haberdasher.HatCreated', Haberdasher.HatCreatedHandler)

or

server.publish('Haberdasher.HatCreated', message)
tatethurston commented 1 year ago

Could you expand on what you mean by

the compatibility issues between HTTP/2 and AWS Lambda and others

Or point me to something more context?

tatethurston commented 1 year ago

Also, is this roughly in line with what you’re thinking? Or are you more interested in something request / response style that supports streaming discrete messages?