Generalize record-replay: serialize closures passed to any RPC method#162
Generalize record-replay: serialize closures passed to any RPC method#162ryanrasti wants to merge 1 commit intocloudflare:mainfrom
Conversation
|
|
All contributors have signed the CLA ✍️ ✅ |
|
I have read the CLA Document and I hereby sign the CLA |
|
Hmm. Restricting this to only work inside a |
Sure thing. And yes // Table definitions:
class Post extends RpcTarget {
get id() { return this.column('id') }
get userId() { return this.column('user_id') }
get content() { return this.column('content') }
}
class User extends RpcTarget {
get id() { return this.column('id') }
posts() { return Post.from().where(({posts}) => posts.userId['='](this.id)) }
}
// Main stub:
class Api extends RpcTarget {
userForToken(token: string) {
const userId = validateToken(token)
return User.from().where(({users}) => users.id['='](userId))
}
db(): Database { ... }
}
// Actual usage:
const getNumPosts = (api: RpcStub<Api>) => {
const token = tokenFromContext(...)
const results = api.map(_ =>
api
.userForToken(token)
.select(({users}) => ({
id: users.id,
numPosts: users.posts().groupBy().select(({posts}) => posts.id.count())
}))
.execute(api.db())
)
return results[0]?.numPosts ?? 0
}The shape I'm envisioning: wrap the entire query once in a |
<stub>.map(fn)already recordsfnlocally, emits a["remap", …]instruction, and replays it on the receiver. This generalizes the mechanism so any user-defined method on anRpcTargetcan accept callbacks that serialize the same way.Motivation: I'm building typegres which uses capnweb to expose a capability-based query builder:
The callbacks should be interpreted server-side (not exported as a stub and sent back to client).
Key design decisions
mapand general closures: I chose to re-use the most code possible but maintain distinct wire formats forremapandclosure.Potential follow-ons (not in this PR):
RpcPayload.deliverResolvealways wraps in one, even when nothing needs awaiting. Async closures are already rejected at serialize time.(Opening as a draft to get your read on the design -- happy to rework anything.)