Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

how do I reestablish a connection if my server restarts? #55

Open
karimcambridge opened this issue May 24, 2024 · 5 comments
Open

how do I reestablish a connection if my server restarts? #55

karimcambridge opened this issue May 24, 2024 · 5 comments

Comments

@karimcambridge
Copy link

when my server restarts this doesn't seem to reestablish my connection, how do I detect that the connection was closed?

@EmilJunker
Copy link
Contributor

This question has been asked before (see #37). I didn't understand it then and I don't understand it now. Could you be more specific about what you mean?

When the server closes the HTTP connection, react-native-sse will automatically reopen it. But I guess when the server just restarts abruptly, it won't try to reconnect. And I honestly don't see a reason why one would expect it to do that, but maybe I'm missing something?

@karimcambridge
Copy link
Author

karimcambridge commented May 24, 2024

We need it to automatically reconnect, lets say we restart the servers and clients are online on their mobile device. react-native-sse is not automaticaly reconnecting.

Right now I added a useeffect dependency with my socket.connected from socket.io to trigger a reconnect and if status is closed. This is my hook example;

import { useEffect, useRef, useState } from 'react';
import EventSource from 'react-native-sse';

import { getServerApiUrl } from '../../api/config';

type EventSourceConstructor = {
	new(url: string, eventSourceInitDict?: EventSourceInit): EventSource
};

export type EventSourceStatus = 'init' | 'open' | 'closed' | 'error';

export type EventSourceEvent = Event & { data: string };

export const useEventSource = (user, serverConnection, withCredentials: boolean = false, ESClass: EventSourceConstructor = EventSource) => {
	const source = useRef<EventSource | null>(null);
	const [status, setStatus] = useState<EventSourceStatus>('init');

	useEffect(() => {
		if(user && status === 'closed') {
			const es = new ESClass(getServerApiUrl() + '/v1/sse/rider/' + user?.id, { withCredentials });
			source.current = es;

			es.addEventListener('open', () => {
				setStatus('open');
				console.log('[sse]: connected to ' + getServerApiUrl() + '/v1/sse/rider/' + user.id);
			});
			es.addEventListener('error', () => {
				setStatus('error');
				console.log('[sse; error]: connecting to ' + getServerApiUrl() + '/v1/sse/rider/' + user.id);
			});

			return () => {
				source.current = null;
				es.removeAllEventListeners();
				es.close();
			};
		}
		setStatus('closed');

		return undefined;
	}, [serverConnection, withCredentials, ESClass]);

	return [source.current, status] as const;
};

export function useEventSourceListener(
	source: EventSource | null,
	types: string[],
	listener: (e: EventSourceEvent) => void,
	dependencies: any[] = []
) {
	useEffect(() => {
		if(source) {
			types.forEach((type) => source.addEventListener(type, listener as any));
			return () => types.forEach((type) => source.removeEventListener(type, listener as any));
		}
		return undefined;
		// eslint-disable-next-line react-hooks/exhaustive-deps
	}, [source, ...dependencies]);
}

@EmilJunker
Copy link
Contributor

You could simply add logic to automatically reconnect when no SSE event messages come in for x seconds, e.g. using setTimeout. That would usually imply that the connection is dead.

Maybe there would also be a way to handle this in the react-native-sse library itself, but I'm not sure about that.

@karimcambridge
Copy link
Author

karimcambridge commented May 24, 2024

would probably need to implement a heartbeat, it can work but unnecessary load.

i thought sses could detect when they lose connection, like we should have the readyState exposed for us to read.

@EmilJunker
Copy link
Contributor

i thought sses could detect when they lose connection, like we should have the readyState exposed for us to read.

We already do an automatic reconnect when the readyState switches to DONE. I think the problem is that the client doesn't event receive a new readyState when the server is abruptly shut down. Thus, there is no direct way for the client to know that the connection is gone. If you find one, please let us know.

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

No branches or pull requests

2 participants