-
Notifications
You must be signed in to change notification settings - Fork 1
Submit service API proposal #21
base: master
Are you sure you want to change the base?
Conversation
Good proposal, thanks for submitting. I also want to explore RPC-focused mechanisms and long-lived execution models before we decide on anything. The HTTP-like interface can be used for RPC, but it's a bad mapping to language semantics and I'd like to explore what something built on persistent message channels (perhaps with JSON-RPC on top) looks like. |
👍 Let me know if I can help in any way.
Since long-lived execution came up multiple times, I'd like to propose to not tie this proposal to the lifetime. While I do think that committing to lifetime guarantees would be a mistake that can be a separate discussion neither RPC nor IPC imply specific lifetime guarantees so maybe it's best to have that discussion on it's own merits.
I am still not sure I understand reasoning for this claim. If you can provide some specific limitations / inconvenience that would really help and I'd love to include that into list of constraints.
On top of this proposal or as an alternative ? If that is on top of this one I can try and help with this exploration. Maybe in a branch somewhere or as separate node based server just for illustration. If you thinking of JSON-RPC as an alternative, I'm not sure I understand your motivation, HTTP is a form of RPC, according to wikipedia in reference to RPC
JSON-RPC is that except it's limited to message format being in JSON and I strongly favor to not have such limitation. |
I think it would be a good idea to look at how Worklets are structured since you could think of this as a sort of "ServiceWorklet" proposal. |
Can you provide a link ? I don't know what are you referring to ? If Service Workers it's closely based on it, except I left out some event listener awkwardness. Request / Response and lifetimes are all from ServiceWorkers spec. |
Right now worklets are aimed at being a lightweight alternative to WebWorkers which are used for stuff like rendering, layout, and audio processing. |
Ideally, we'd have RPC which looks like this: rpc.exportAPI(channel, {
foo () {
...
}
})
var api = rpc.importAPI(channel)
await api.foo() That's a really direct mapping to the programming language, because you can just export and import functions. With HTTP or HTTP-style, you use async function updateUser (hostname, userId, data) {
var response = await fetch(hostname + '/users/' + userId, {
method: "POST",
headers: {
"Content-Type": "application/json; charset=utf-8"
},
body: JSON.stringify(data)
})
return await response.json()
} Which is pretty crummy compared to an RPC solution that just maps to function calls: var api = rpc.importAPI(channel)
await api.updateUser('bob', {bio: 'Cool hacker guy'})
// ^ no boilerplate needed Writing server request-handlers is much worse, because you have to route the method and path using conditionals or some kind of mapping structure, and then you handle content-type negotiation, and then a number of other headers such as caching. If we're just doing RPC, it's much easier to simply export the RPC function. The two scenarios we're considering for Beaker right now are
Both of which favor long-lived channels, are designed for RPC, and don't currently require HTTP-like semantics. So I'm basically wondering, could we create something nicer for RPC than HTTP? JSON-RPC is just a default thought, to me, because it's relatively simple, but I'm open to discussing all the requirements of what the ideal RPC solution would have. |
Thanks for clarifying what you meant. I'd like bring up two things:
|
If all you want is RPC, I think it's reasonable to generate server / client. On the downside it does allow importing some library to do so but on the upside it allows us cases where RPC isn't ideal. |
In fact you could have same RPC generator library that could wrap either service transport or PeerSocket one which could be a benefit as well. |
I'm also not necessarily agreeing with this statement (although it depends who you were referring to with we). Things I've being trying to build are in the lines of perform this operation please, and for that I would much rather not manage connections or manage references to it. I have to admit that I might be on the fringe side as I also end up wrapping all of the DatArchive API to get out of the business of holding onto archive instances, etc.. Which reminds me of the fact that I have always wondered how does the background process drops refs for archives that are no longer in use (GC-ed) ? |
One more thing to consider is if you ever want to also allow Wasm based services JSON-RPC may not necessarily map all that well there and memory model could be very different (already case for Rust). Request / Response with a binary interface is far more flexible in that regard. |
I took a glance at the spec https://drafts.css-houdini.org/worklets/#worklet it appears to me that they are dedicated scripts that run in the same main thread just given much more limited access to the document they belong to. So I don't think it's very relevant. I'll take a deeper analyses if we end choosing to purse this approach. Although overall I don't think it would have much impact as spec intentionally omits implementation details like OS thread per worker vs thread pool and what not. |
I wasn't suggesting we'd have distributed objects. That would be a bad idea. I'm just suggesting we use a protocol that maps naturally to functions. |
I understand you were not suggesting it, but you can't prevent people from doing mistakes. I would also argue that long-lived execution model does create an expectation that things on the other end will be across multiple requests, which is also a reason why I'm advocating no lifetime guarantees beyond request lifetime and no 1:1 client / server relation that sets up more realistic expectation IMO. |
I'm not concerned. We've had JSON-RPC over WebSockets for a long time, it hasn't led to a lot people doing distributed objects.
We'll just need to explore the options here. Idle long-running background scripts may take too much resources to be feasible, but we need to know more about our requirements before I can jump to any conclusions. |
After thinking little more about it I'm realizing that it might make more sense to embrace ServiceWorkes API with a foreign fetch. If mainstream browsers would ever to adopt this it's likely the most viable option would be to just allow service workers accept requests across different origins. That being said it does'n necessarily invalidates this proposal just something worth considering. At the end of the day adapting this API to Service worker would be fairly simple would just require: self.addEventListener('fetch', event => event.respondWith(default(event.request))); Still I though it was worth pointing out. |
No description provided.