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

Connection loss handling in useIoBrokerState() etc. #9

Open
rovo89 opened this issue Aug 22, 2023 · 1 comment
Open

Connection loss handling in useIoBrokerState() etc. #9

rovo89 opened this issue Aug 22, 2023 · 1 comment

Comments

@rovo89
Copy link

rovo89 commented Aug 22, 2023

While moving around the house/town, maybe even when the site goes into the background, the websocket can get disconnected. The reconnect usually works fine, but any updates which happened in the "downtime" won't show up in the page. Subscriptions are restored automatically (probably here), so at least when the value changes again, it will show correctly. This affects at least useIoBrokerState(), but probably also useIoBrokerObject().

I looked into various ways to fix it:


In ioBroker/socket-client, there are various instructions to ensure that loadData() is only triggered for the first connect. Which probably makes sense because that client seems to be mostly stateless. Sure, system config could have changed between disconnect and reconnect, but apart from that there doesn't seem to be any "caching" of objects and values. So there is nothing that could become outdated.

In contrast to that, the hooks remember the last state/object data. Basically useIoBrokerState() would just need to call loadInitial() again after a reconnect. But for that, the Connection would need a way to subscribe to reconnects and the hooks would need to use it.

I also thought that the value from useConnection() would change when the connection disconnects (to null or undefined) or reconnects (to a new object). That would make it possible to track the connection lifecycle (e.g. display a "connected" icon) and would also trigger a re-run of all those effects which have connection in their dependencies. Looks like the most natural way to me, although various places would do unnecessary stuff then. For example, it would be pointless to unsubscribe and then resubscribe to state updates because the former necessarily happens at disconnect and the latter is done by the socket-client already, without any way to disable it. But I'm sure that there would be fairly easy ways to avoid such efforts.

Finally, it might be possible (maybe not here, but in socket-client) to request the latest state/object for all subscriptions after a reconnect. After all, someone cared to subscribe to them and they might have changed in between. The results of those requests would be handled via the usual means, just as if the value had really changed. But I guess wildcards would be a problem.


My favorite would be the one with useConnection(), but I'd like to hear your opinion.

@rovo89
Copy link
Author

rovo89 commented Aug 24, 2023

Looked this a bit more and as far as I can see, the connection can't be undefined currently as none of the child components of IoBrokerApp will be rendered before the connection has been established.

Also found that there's already a way to detect dis- and reconnects, so I came up with this custom hook:

import type { Connection } from "@iobroker/socket-client";
import { useConnection } from "iobroker-react/hooks";
import React from "react";

export function useReconnected(listener: (connection: Connection) => void): void {
	const connection = useConnection();
	React.useEffect(() => {
		const handler = (connected: boolean) => {
			if (connected) {
				listener(connection);
			}
		};
		connection.registerConnectionHandler(handler);
		return () => {
			connection.unregisterConnectionHandler(handler);
		};
	}, [connection, listener]);
}

So my current workaround is this:

useReconnected(() => {
	window.location.reload();
});

But I guess it would make more sense to add a handler to useIoBrokerState().

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

1 participant