Datastar automatically retries sse connections in many cases. It does not not retry in cases that should normally signal the end of a stream. i.e. Error responses from the server or graceful disconnects by the server. We can use the tools that Datastar gives us to retry even in those cases.
Before proceeding: Datastar probably already does what you want. Connections are automatically retried when interrupted, or if the server is not responding. The situations it does not retry are: the server responds with an error (status code >=400,) or if the server gracefully closes the connection. Most of the time you do not want the client to retry in these situations. If you are certain you want the client to keep retrying the connection forever you can use this technique to achieve that.
Persist an SSE connection from the server through events such as server restarts and temporary error responses. Notify the user if the connection is currently active or not.
The data-on-interval attribute can be used to repeat. An action on an
interval. We can use this to repeatedly keep connecting to the server. The leading modifier can be used to make the
first attempt immidiately rather than after the first interval. The caveat is that we need to make sure it does not
initiate duplicate connections. The data-indicator attribute will set a
signal to true while a connection is trying to connect, or is connected. We can use both of these together to only
attempt the reconnection if there is not already one active.
<div data-indicator="_connecting"
data-on-interval__duration.30s.leading="!$_connecting && @get('/updates')">
</div>This will attempt to start a new connection within 30 seconds after the previous connection has returned an errored or ended.
To notify the user when the connection is active we need to listen to the
datastar-fetch emitted during this connection process. We can create a signal
_disconnected and set its value to 'true' when we hear an event that indicates that the stream is not connected, and
set it to 'false' when we hear a datastar- event (e.g. datastar-patch-elements) indicating that the connection is
up and working. Events can come from any of the SSE connections being initiated on the page, so we also need to check
whether the event is coming from a connection initiated on the same element as our intended long-lived connection.
The _disconnected signal can then be used in any way we wish to indicate to the user when the stream is disconnected.
<div data-signals-_disconnected="false"
data-indicator="_connecting"
data-on-interval__duration.30s.leading="!$_connecting && @get('/updates')"
data-on-datastar-fetch="el === evt.detail.el &&
((evt.detail.type.startsWith('datastar') && ($_disconnected = false)) ||
(['retrying', 'error', 'finished'].includes(evt.detail.type) && ($_disconnected = true)));">
</div>
<div data-show="$_disconnected">Warning: Not connected to server.</div>This will keep trying to reconnect the SSE and show a div with a warning to the user whenever it is disconnected.
The default Datastar retry semantics are usually best, but when we want to retry even through clear indications that the connection should be over it is possible.