tncrazvan / sveltekit-sse

Server Sent Events with SvelteKit
https://www.npmjs.com/package/sveltekit-sse
MIT License
204 stars 7 forks source link

docs: Explain requirement for all logic within `start()` #36

Closed oscarhermoso closed 3 weeks ago

oscarhermoso commented 4 weeks ago

On the README page, it states that on the server, all logic must be contained within the events::start call:

Due to how the beacon api works, you must write all your logic within the start() function while on the server.

Would it be possible to explain the reason and consequences of not following this?

tncrazvan commented 4 weeks ago

When you invoke source("/events") you create an http request to POST /events which upgrades to an sse request. The http response of the server will contain a header X-SSE-ID, which identifies the sse stream. At the same time, the server will schedule the given event to be closed and destroyed after some T milliseconds.

While all of that is going on on the server, on the client side, every T milliseconds, you browser will send a beacon request to POST /events?x-sse-id=some-id-given-by-the-server, which, as you can see, contains the same stream id as a query string.

[!NOTE] We should probably use a header instead of a query string in the future.\ This will probably be the next update I'll make.\ Scratch that, beacon api doesn't allow even headers to be set, according to the W3C standard.

The server will validate this id.\ If it is correct, meaning it is internally mapped, it will clear the old schedule for destroying the stream, and create a new one.

This how we detect that a user has closed the stream on their side.

Both beacon and sse request share the same endpoint /events. If you put your logic in the body of the POST function, instead of within the start() callback, then that code will be executed every T milliseconds, which is a waste of resources, because beacon request don't need and don't even wait for the server to respond. They're meant to be lightweight requests, mainly used for analytics.

Beacon requests are a hack, because SvelteKit doesn't have an API that informs us, the userland, when a client has canceled an http request, unlike other frameworks like dotnet for example, which has a very specific solution for this. Hopefully we'll get something like that in SvelteKit some day.

The reason the beacon and the sse stream share the same endpoint is because this library promises easy use of sse. Requiring the userland to manage their own streams timeout is not exactly "easy to use".

oscarhermoso commented 3 weeks ago

Thank you, that makes a lot of sense now