Skip to content

Conversation

@kevin-dp
Copy link
Contributor

@kevin-dp kevin-dp commented May 26, 2025

This is a follow up PR on #2546 and #2544. It solves a bug related with 409s (must refetch) in SSE mode and it replaces the EventSource browser API by the fetch-event-source library. I refactored the ShapeStream.#start method which was becoming very big and complex. To this end, i split the logic into helper methods that handle the different parts that need to happen (building the shape URL, making the request, parsing the response headers, handling the response body, etc.).

I had to patch the fetch-event-source library because it relies on browser-specific features such as document and window (cf. Azure/fetch-event-source#41). But we want our client to also work in server-side JS environments.

I also had to patch the fetch-event-source library because it does not abort the fetch when you pass an already aborted signal. A complete description of the bug and the fix can be found here: Azure/fetch-event-source#98.

To use, add experimentalLiveSSE to your shape options e.g.

useShape({
   url,
   experimentalLiveSSE: true
 })

EXPERIMENTAL_LIVE_SSE_QUERY_PARAM,
} from './constants'
import {
EventSourceMessage,
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Let's not load this node polyfill in the browser. It can make behavior inconsistent and it's extra code. We can detect when we're in node and conditionally load the polyfill.

Copy link
Contributor Author

@kevin-dp kevin-dp May 26, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is not a node polyfill. This is a library that implements SSE via standard fetch rather than via the browser's EventSource API which is very limited. We always use this library (in the browser, on node, etc.)

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hmm yeah ok. So looking closer this is a good thing as all the fetch options still work when we shift from http to SSE.

Have we looked at how SSE will work in a proxy?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@KyleAMathews I don't think anyone has looked into how SSE will work with a proxy. It will likely be more complicated than the current proxy pattern but it should be feasible to accept incoming SSE requests, then use fetch-event-source to proxy it through, and then in the onopen, onmessage, and onclose handlers forward those SSE events to the user.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If the proxy is just passing the headers and streaming the response through then it should just work™️. I.e.: the fact that the connection stays open and the response streams through in parts should be transparent to most proxies?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yeah I did some research and there's good support. And given this will always be an optional "fast" mode — electric will always work in basic http long-polling.

* The LSN is only present in the up-to-date control message when in SSE mode.
* If we are not in SSE mode this function will return undefined.
*/
export function getOffset(message: ControlMessage): Offset | undefined {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm not sure we should be using the LSN to compute an offset in the client. This is an internal server side implementation detail that is quite likely to change.

Would it be better to include the offset on each message from the server when in sse mode?

Copy link
Contributor Author

@kevin-dp kevin-dp Jun 3, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

That would indeed be better. However, this is what @thruflo documented the client should do in #2544 (comment) and you also did this in your original implementation: #2546. Do you want me to change the server such that the server returns an electric-offset in the body rather than the current global_last_seen_lsn ? (cc @samwillis @thruflo)

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Would this require additional deserialisation / serialisation? As in, to special case it for the SSE? Where are we on providing this info generally -- perhaps we can push the change out of scope and revisit the SSE implementation when we firm up how we expose the offset generally?

Copy link
Contributor

@KyleAMathews KyleAMathews left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Great work! I suspect we'll learn some more as we test building things on this but you've taken this a long way & I'm excited to get this out there!

@kevin-dp kevin-dp merged commit 572a935 into samwillis/experimental-live-sse Jun 9, 2025
30 checks passed
@kevin-dp kevin-dp deleted the kevin/live-sse branch June 9, 2025 13:02
@wadefletch
Copy link

Is there a timeline or plan for releasing this functionality, even if behind a flag?

@alco
Copy link
Member

alco commented Jun 25, 2025

@kevin-dp I suspect this was supposed to be merged into main but it ended up getting merged into @samwillis's branch and never made its way to main. Though it is a bit odd there's no changeset in this PR.

@KyleAMathews
Copy link
Contributor

Oh I thought this was released — @kevin-dp what's the next step here?

@kevin-dp
Copy link
Contributor Author

That's odd. Let's re-open @samwillis' PR in which we merged this one and then merge that one into main? @KyleAMathews

@KyleAMathews
Copy link
Contributor

👍 yeah sounds good :shipit:

@kevin-dp
Copy link
Contributor Author

kevin-dp commented Jul 8, 2025

@wadefletch I merged SSE support into main last week, cf. #2856

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

7 participants