Live data from Hacker News

Cap'n Web: a new RPC system for browsers and web servers

blog.cloudflare.com

181–190 of 305 posts

Re: Cap'n Web: a new RPC system for browsers and web servers

#181
post #36

Earlier quoted context omitted.

The state only lives for a single RPC session. When using WebSockets, that's the lifetime of the WebSocket. But when using the HTTP batch transport, a session is a single HTTP request, that performs a batch of calls all at once. So there's actually no need to hold state across multiple HTTP requests or connections, at least as far as Cap'n Web is concerned. This does imply that you shouldn't design a protocol where i…

^ maybe the most knowledgable person in the world about these gritty details RPC SDKs should have session management, otherwise you end up in this situation: "Any sufficiently complicated gRPC or Cap'n'Proto program contains an ad hoc, informally-specified, bug-ridden, slow implementation of half of Akka"

Isn't akka just a poor man's erlang

Re: Cap'n Web: a new RPC system for browsers and web servers

#182
post #149

Earlier quoted context omitted.

"RPC" originally referred to a programming paradigm where remote calls looked just like any other method calls, and it might not even be any of the programmer's business whether they're implemented in-process or on another machine. This obviously required wire protocols, client and server libraries, etc. to implement. There's been a renaissance in the tools, but now we mainly use them like "REST" endpoints with the t…

mm, i think you're describing corba, not rpc in general

CORBA is trippier than that. A client’s request could include elements not normally serializable, like callbacks. A server could provide an object in response to your query and then continue mutating it, with the mutations reflected (effectively) in your address space, without your knowledge or participation.

Re: Cap'n Web: a new RPC system for browsers and web servers

#183

I'm curious about two things: 1. What's the best way to do app deploys that update the RPC semantics? In other words how do you ensure that the client and server are speaking the same version of the RPC? This is a challenge that protos/grpc/avro explicitly sought to solve. 2. Relatedly, what's the best way to handle flaky connections? It seems that the export/import table is attached directly to a stateful WS connect…

1. Think of it like updating a JavaScript API without breaking existing callers. The rules are essentially the over RPC as they would be for local calls. So, you can add new methods and new optional arguments, etc.

2. After losing the connection, you'll have to reconnect and reconstruct the objects from scratch. The way I've structured this in an actual React app is, I pass the main RPC stub as an argument to the top-level component. It calls methods to get sub-objects and passes them down to various child components. When the connection is lost, I recreate it, and then pass the new stub into the top-level component, causing it to "rerender" just like any other state change. All the children will fetch the sub-objects they need again.

If you have an object that represents some sort of subscription with a callback, you'll need to design the API so that when initiating the subscription, the caller can specify the last message they saw on the subscription, so that it can pick up where they left off without missing anything.

Hmm, I suppose we'll need to do a blog post of design patterns at some point...

Re: Cap'n Web: a new RPC system for browsers and web servers

#184
post #149

Earlier quoted context omitted.

mm, i think you're describing corba, not rpc in general

CORBA is trippier than that. A client’s request could include elements not normally serializable, like callbacks. A server could provide an object in response to your query and then continue mutating it, with the mutations reflected (effectively) in your address space, without your knowledge or participation.

That's exactly what Cap'n Web does...

Re: Cap'n Web: a new RPC system for browsers and web servers

#185
post #90

Earlier quoted context omitted.

In C#, there's expression trees which handle things like this and it's how Entity Framework is able to convert the lambdas it's given into SQL. This means that you can pass around code that can be inspected or transformed instead of being executed. Take this EntityFramework snippet: db.People.Where(p => p.Name == "Joe") `Where` takes an `Expression > predicate`. It isn't taking the `Func` itself, but an `Expression`…

Is there anything C# _doesn’t_ have? :-) It feels like C# has an answer to every problem I’ve ever had with other languages - dynamic loading, ADTs with pattern matching, functional programming, whatever this expression tree is, reflection, etc etc. Yet somehow it’s still a niche language that isn't widely used (outside of particular ecosystems).

It's one of the most widely used languages out there actually. But it's primarily used at buttoned up and boring SMB's/enterprise backoffices. We're not out here touting our new framework of the month to kafloogle the whatzit. We're just building systems with a good language and ecosystem that's getting better every year.

I've worked only at startups/small businesses since I graduated university and it's all been in C#.

Re: Cap'n Web: a new RPC system for browsers and web servers

#186

I'm curious about two things: 1. What's the best way to do app deploys that update the RPC semantics? In other words how do you ensure that the client and server are speaking the same version of the RPC? This is a challenge that protos/grpc/avro explicitly sought to solve. 2. Relatedly, what's the best way to handle flaky connections? It seems that the export/import table is attached directly to a stateful WS connect…

1. Think of it like updating a JavaScript API without breaking existing callers. The rules are essentially the over RPC as they would be for local calls. So, you can add new methods and new optional arguments, etc. 2. After losing the connection, you'll have to reconnect and reconstruct the objects from scratch. The way I've structured this in an actual React app is, I pass the main RPC stub as an argument to the top…

A blog post of design patterns would be really great. Again - amazing work!

Re: Cap'n Web: a new RPC system for browsers and web servers

#187
post #43

Earlier quoted context omitted.

I generally agree that the .map() trick doesn't actually replace GraphQL without some sort of server-side optimizations to avoid turning this into N+1 selects. However, if your database is sqlite in a Cloudflare Durable Object, and the RPC protocol is talking directly to it, then N+1 selects are actually just fine. https://www.sqlite.org/np1queryprob.html

Agree, and to add, from what I see, the main issue is that server-side data frameworks (e.g., ORMs) aren't generally built for the combination of security & composability that make them naturally synergize with Cap'n Web. Another way to put it: promise pipelining is a killer feature but if your ORM doesn't support pipelining, then you have to build a complex bridge to support them both. I've been working on this issu…

This seems really cool and I'd be happy to help (I'm currently a pgtyped + Kysely user and community contributor), and I see how this solves n+1 from promise pipelining when fetched "nested" data with a similar approach as Cap'n Web, but I don't we've solved the map problem.

If I run, in client side Cap'n Web land (from the post): ``` let friendsWithPhotos = friendsPromise.map(friend => { return {friend, photo: api.getUserPhoto(friend.id))}; } ```

And I implement my server class naively, the server side implementation will still call `getUserPhoto` on a materialized friend returned from the database (with a query actually being run) instead of an intermediate query builder.

@kentonv, I'm tempted to say that in order for a query builder like typegres to do a good job optimizing these RPC calls, the RpcTarget might need to expose the pass by reference control flow so the query builder can decide to never actually run "select id from friends" without the join to the user_photos table, or whatever.

Re: Cap'n Web: a new RPC system for browsers and web servers

#188
Tangential from a discussion in TFA about GraphQL:

> One benefit of GraphQL was to solve the “waterfall” problem of traditional REST APIs by allowing clients to ask for multiple pieces of data in one query. For example, instead of making three sequential HTTP calls:

    GET /user
    GET /user/friends
    GET /user/friends/photos
…you can write one GraphQL query to fetch it all at once.

Or you could have designed a schema to allow easy tree traversal. Or you could use a recursive CTE.

Re: Cap'n Web: a new RPC system for browsers and web servers

#189

I find the choice of TypeScript to be disappointing. One of the reasons that capproto has struggled for market share is the lack of implementations. Is the overhead for calling into WASM too high for a Rust implementation to be feasible? A Haxe or Dafny implementation have let us generate libraries in multiple languages from the same source.

> I find the choice of TypeScript to be disappointing. Genuinely curious, is the disappointment because it's limited to the JS/TS ecosystem? My take is that by going all-in on TypeScript, they get a huge advantage: they can skip a separate schema language and use pure TS interfaces as the source of truth for the API. The moment they need to support multiple languages, they need to introduce a new complex layer (like…

You can generate TypeScript schema for Haxe JS output. I'm honestly a bit surprised that TS isn't a supported target!

That could change with some investments. Haxe is a great toolkit to develop libraries in because it reduces the overhead for each implementation. It would be nice to see some commercial entity invest in Haxe or Dafny (which can also enable verification of the reference implementation).

> The moment they need to support multiple languages, they need to introduce a new complex layer (like Protobuf),

So this just won't be used outside of Node servers then?

Re: Cap'n Web: a new RPC system for browsers and web servers

#190
post #34

What would this look like for other language backends to support? Eg would be neat if Rust (my webservers) could support this on the backend edit : Downvoted, is this a bad question? The title is generically "web servers", obviously the content of the post focuses primarily on TypeScript, but i'm trying to determine if there's something unique about this that means it cannot be implemented in other languages. The ser…

I'm hoping the answer will be: * Use Cap'n Proto in your Rust backend. This is what you want in a type-safe language like Rust: generated code based on a well-defined schema. * We'll build some sort of proxy that, given a Cap'n Proto schema, converts between Cap'n Web and Cap'n Proto. So your frontend can speak Cap'n Web. But this proxy is just an idea for now. No idea if or when it'll exist.

Do you feel like we are reaching the final form for RPC protocols yet?
Post reply on HN