Hacker Newsnew | past | comments | ask | show | jobs | submit | benpacker's commentslogin

I get segfaults all the time when using it with Bun and the new Node neo api. What’s your recipe, are you not getting these?


Does this have support for generators / streams, or any ideas how you'd do it? With LLMs that an increasingly large part of client/server communication.


It does better. It supports callbacks, including callback objects with multiple methods. So to define a stream, you just send the other side an object with a `write()` and an `end()` method. The other side calls `write()` for each chunk of the stream, then eventually calls `end()`. You can also give the stream a `[Symbol.dispose]()` method which will be called when the other side disconnects, so you can detect premature disconnect.


I think crossing a language barrier here would be hard: you'd need a codegen step to compile the RPC spec to Typescript for the client-side DX and that would need take into account the full range of differences in serializability across the languages.

For cross-language RPC, I think we're still better sticking to a well defined system where the spec is data (OpenAPI, GraphQL, etc.) instead of the spec being code that only one side understands.


Would love to see pics of the interior!


My understanding is that your first read is right and your current understanding is wrong.

The client sends over separate 3 calls in one message, or one message describing some computation (run this function with the result of this function) and the server responds with one payload.


This seems great and I'm really excited to try it in place of trpc/orpc.

Although it seems to solve one of the problems that GraphQL solved that trpc doesn't (the ability to request nested information from items in a list or properties of an object without changes to server side code), there is no included solution for the server side problem that creates that the data loader pattern was intended to solve, where a naive GraphQL server implementation makes a database query per item in a list.

Until the server side tooling for this matures and has equivalents for the dataloader pattern, persisted/allowlist queries, etc., I'll probably only use this for server <-> server (worker <-> worker) or client <-> iframe communication and keep my client <-> server communication alongside more pre-defined boundaries.


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 issue from the other side. Specifically, a TS ORM that has the level of composability to make promise pipelining a killer feature out of the box. And analagous to Cap'n Web's use of classes, it even models tables as classes with methods that return composable SQL expressions.

If curious: https://typegres.com/play/


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.


> but I don't we've solved the map problem.

Agreed! If we use `map` directly, Cap'n Web is still constrained by the ORM.

The solution would be what you're getting at -- something that directly composes the query builder primitives. In Typegres, that would look like this:

``` let friendsWithPhotos = friendsPromise.select((f) => ({...f, photo: f.photo()}) // `photo()` is a scalar subquery -- it could also be a join ```

i.e., use promise pipelining to build up the query on the server.

The idea is that Cap'n Web would allow you to pipeline the Typegres query builder operations. Note this should be possible in other fluent-based query builders (e.g., Kysely/Drizzle). But where Typegres really synergizes with Cap'n Web is that everything is already expressed as methods on classes, so the architecture is capability-ready.

P.S. Thanks for your generous offer to help! My contact info is in my HN profile. Would love to connect.


That is actually pretty interesting!

Have you considered making a sqlite version that works in Durable Objects? :)


Thanks, Kenton! Really encouraging to hear you find the idea interesting.

Right now I'm focused on Postgres (biggest market-share for full-stack apps). A sqlite version is definitely possible conceptually.

You're right about the bigger picture, though: Cap'n Web + Typegres (or a "Typesqlite" :) could enable the dream dev stack: a SQL layer in the client that is both sandboxed (via capabilities) and fully-featured (via SQL composability).


I wonder if there's a way to process the RPC encoding inside a stored procedure, using the various JS-in-DB features out there.


You can do with with trpc WebSocket transport


trpc has the benefit of being highly adopted, supported, and with a community.


I have this setup and integrated for Node/Bun -

This is an example of a unit test of an API route on a fully isolated WASM backed Postgres - very few lines of code, and all your API unit tests can run fully in parallel without any shared state: https://github.com/ben-pr-p/bprp-react-router-starter/blob/m...

This is all of the code needed to use Postgres in prod and PGLite in test/dev: https://github.com/ben-pr-p/bprp-react-router-starter/blob/m...


Thanks for sharing this, I'm not a Node/Bun dev but it's quite understandable. One question: does each test/database need to wait for migrations to run, or are you somehow using template databases to run them once and then quickly clone a new database for each test?


wow thanks! Should I use bun instead of node now?


It’s the same - just saying it works in both.

I like it because I can do full stack development, including the database, with a single system level dependency (Bun).


ha, thanks, make sense


Cloudflare + SSE with any substantial delay is a nightmare


All frontier multi modal LLMs can do this - there’s likely something lighter weight as well.

In my experience, the latest Gemini is best at vision and OCR


> All frontier multi modal LLMs can do this

There's reliable, and there's reliable. For example [1] is a conversation where I ask ChatGPT 4o questions about a seven-page tabular PDF from [2] which contains a list of election polling stations.

The results are simultaneously impressive and unimpressive. The document contains some repeated addresses, and the LLM correctly identifies all 11 of them... then says it found ten.

It gracefully deals with the PDF table, and converts the all-caps input data into Title Case.

The table is split across multiple pages, and the title row repeats each time. It deals with that easily.

It correctly finds all five schools mentioned.

When asked to extract an address that isn't in the document it correctly refuses, instead of hallucinating an answer.

When asked to count churches, "Bunyan Baptist Church" gets missed out. Of two church halls, only one gets counted.

The "Friends Meeting House" also doesn't get counted, but arguably that's not a church even if it is a place of worship.

Longmeadow Evangelical Church has one address, three rows and two polling station numbers. When asked how many polling stations are in the table, the LLM counts that as two. A reasonable person might have expected one, two, three, or a warning. If I was writing an invoice parser, I would want this to be very predictable.

So, it's a mixed bag. I've certainly seen worse attempts at parsing a PDF.

[1] https://chatgpt.com/share/67812ad9-f2bc-8011-96be-faea40e48d... [2] https://www.stevenage.gov.uk/documents/elections/2024-pcc-el...


You can try to ask it to list all churches and assign them incremental number starting with 1. then print the last number. It's a variation of counting 'r' in 'raspberry' which works better than simple direct question.


> There's reliable, and there's reliable. For example [1] is a conversation where I ask ChatGPT 4o questions about a seven-page tabular PDF from [2] which contains a list of election polling stations.

From your description, it does perfectly at the task asked about upthread (extraction) and has mixed results on other, question-answering, tasks, that weren't the subject.


> From your description, it does perfectly at the task asked about upthread (extraction) and has mixed results on other, question-answering, tasks, that weren't the subject.

¯\_(ツ)_/¯

Which do you think was which?


Do I understand correctly that nearly all issues were related to counting (i.e. numerical operations)? that makes it still impressive because you can do that client-side with the structured data


Some would say the numerical information is among the most important parts of an invoice.


I wonder if performance would improve if you asked it to create csvs from the tables first, then fed the CSVs in to a new chat?


Guidelines | FAQ | Lists | API | Security | Legal | Apply to YC | Contact

Search: