mqtt5_client
mqtt5_client copied to clipboard
Getting 'Bad State' exception when disconnecting a connection in mid auto-reconnect
I have a situation where I am creating a websocket IoT connection to AWS via Cognito credentials. I have auto reconnect, and resubscribeOnAutoReconnect set to true, keepalive set to 5 seconds.
I have a scenario where, when I get new AWS Cognito credentials (due to the activity token expiring, or the wifi goes off and then back on again, etc.), I want to stop the old connection, and start a new one with the new AWS Cognito credentials. What is happening is that the old connection is in the background trying to autoreconnect. So, even though I call disconnect() on the old connection, when that connect call completes and it tries to run the code in mqtt_connection_handler_base.dart that follows, it gets the following exception:
The exception: "Bad state: Cannot add new events after calling close" The throwing source: ...mqtt5_client-4.5.0/lib/src/connectionhandling/mqtt_connection_handler_base.dart
Tracing through the timeline:
- I'm connected with connection A, and everything is happy.
- I turn wifi off and wait for a bit for the connection to go down.
- Connection A detects the loss of keepalive heartbeats, it goes into it's autoreconnect state.
- I turn wifi back on.
- My code detects the wifi state is on again, and regenerates cognito credentials - callbacks are called to notify clients of this.
- The code that's managing the IoT connections gets this callback and reacts by trying to create a brand new connection:
- It then calls disconnect() on connection A, and stops the listener of the connection A stream
- It creates a brand new IoT connection, connection B, with new Cognito credentials and connects
- Connection B connects, starts listening, etc. Everything with Connection B is happy.
- Eventually, Connection A's autoreconnect call (to connect()) times out, and then it goes to this else case in mqtt_connection_handler_base:
connectionStatus = await connect(server, port, connectionMessage);
autoReconnectInProgress = false;
if (connectionStatus.state == MqttConnectionState.connected) {
[REDACTED]
} else {
MqttLogger.log(
'MqttConnectionHandlerBase::autoReconnect - auto reconnect failed - re trying');
clientEventBus!.fire(MqttAutoReconnect());
}
It is here where I believe it's trying to fire on the clientEventBus, and since the connection has been disconnected/closed, it's going down.
This results in an unhandled exception. It's not causing any major issues (like a tree falling in the forest where there's no one around to hear it), but I'd like to clean this up, if possible.
Maybe this line: clientEventBus!.fire(MqttAutoReconnect());
should use a "?" instead of a "!" so that it quietly fails instead of throws? Or maybe there's some other API that I'm not seeing that I can call to allow connection A to finish cleaning up before creating B (undesirable, as I don't want to block for seconds)?
Thank you in advance. Sorry if this isn't following some GitHub etiquette, I haven't entered many issues.
TLDR Details: Deploying/running on an Android Pixel 7 Building with Android Studio Koala 2024.1.1 Patch 1 Using the MQTT 5 library, version: mqtt5_client: ^4.5.0