workerd
workerd copied to clipboard
Implement EventSource (experimental)
SHIP-9206
~~This is just a draft proposal at the moment, but it should be functional for folks who want to give it a try.~~ Had a couple of folks ask me about this over the past few months so figured I'd go ahead and see about an actual implementation. The format is simple enough that it really doesn't require bringing in any dependencies.
Implements the web platform standard EventSource API (https://developer.mozilla.org/en-US/docs/Web/API/EventSource).
There are two three-standard extensions implemented to the API:
- Passing in a custom fetcher
const ev = new EventSource('https://...', { fetcher: env.myfetcher });
- Creating an
EventSourcefrom an existingReadableStream
const ev = EventSource.from(readableStream);
- The
EventSourceimplements ERMSymbol.dispose(which simply defers to callingeventsource.close()
See the sample for an example.
Note that each time EventStream connects it counts as a subrequest and is subject to all of the same characteristics/limitations as other subrequests. Concurrent subrequest limits will apply.
~~This PR will need tests before it could land.~~
refs https://github.com/cloudflare/workerd/discussions/1640
Sorry to ask this after all this code is written, but why not implement this in JavaScript? Seems like a good candidate: not widely used, not too complicated, contains hairy parsing code that would benefit from memory safety.
Could be done either way. One bit I like about the c++ implementation is that it makes use of the optimized pumpTo when going from the fetch response stream to the EventSourceSink that actually performs the parsing, only popping back into JS to schedule emitting the message events. In other words, this approach should be pretty low overhead. But doing the implementation in JavaScript is also feasible. Implementation time is about the same either way.