hivemq-mqtt-client
hivemq-mqtt-client copied to clipboard
How to turn off RECONNECT?
🐛 Bug Report
Cannot call disconnect in non-CONNECTED state Unable to stop automaticReconnect in Android Device hivemq-shaded = { group = "com.hivemq", name = "hivemq-mqtt-client-shaded", version = "1.3.5" }
🔬 How To Reproduce
Steps to reproduce the behavior:
- useMqttVersion3().automaticReconnect().initialDelay(1, TimeUnit.SECONDS).maxDelay(2, TimeUnit.SECONDS).applyAutomaticReconnect()
- Turn off device network and run HiveMQ
- disconnect() 提示 com.hivemq.client.mqtt.exceptions.MqttClientStateException: MQTT client is not connected.
- AutomaticReconnect will still be executed and cannot be stopped
I had the same issue, no way to stop reconnecting, even disconnect is not working in this case.
Please consider add an API for this case
Thanks in advance.
A solution for this would be great. Mqtt3AsyncClient.disconnect() seems to be unusable with this issue.
Hi all - thanks for reporting this! I'm talking with the team about a potential fix in #724. We'll have an update soon.
Just an update that the team is a bit overloaded right now but we'll review that PR as soon as possible and make a decision.
In the meantime, feel to try that github branch (add-disconnect-gracefully) to validate that the solution works for you and provide feed back in #724.
I can't promise that it will go out in it's current state but the feedback would definitely be helpful.
That PR adds a new interface method disconnectGracefully that allows you to gracefully disconnect regardless of client state.
If there are any questions - let us know!
Was able to test the PR, but it does not solve the issue fully since the new method doesn't stop the auto-reconnect if a connection was never established successfully.
Until the issue is resolved, I basically copied the auto-reconnect logic in a DisconnectedListener adding a short circuit flag for when it should stop attempting to reconnect. Hope this helps!
public class MqttHiveClientWrapper implements MqttClientDisconnectedListener {
static final long RECONNECT_START_DELAY_NANOS = TimeUnit.SECONDS.toNanos(MqttClientAutoReconnect.DEFAULT_START_DELAY_S);
static final long RECONNECT_MAX_DELAY_NANOS = TimeUnit.SECONDS.toNanos(MqttClientAutoReconnect.DEFAULT_MAX_DELAY_S);
private Mqtt3AsyncClient hiveMqttClient;
private boolean connectionActive = false;
public void initClient() {
this.hiveMqttClient = Mqtt3Client.builder()
.addDisconnectedListener(this)
.identifier(IDENTIFIER)
.serverHost(HOST)
.serverPort(PORT)
.buildAsync();
}
public void connect() {
this.connectionActive = true;
if(this.hiveMqttClient != null && !this.hiveMqttClient.getState().isConnectedOrReconnect()) {
this.hiveMqttClient.connect();
}
}
public void disconnect() {
this.connectionActive = false;
if (this.hiveMqttClient != null) {
this.hiveMqttClient.disconnect();
}
}
@Override
public void onDisconnected(@NotNull MqttClientDisconnectedContext context) {
// Only attempt to reconnect if connect should be active
if (this.connectionActive && context.getSource() != MqttDisconnectSource.USER) {
final MqttClientReconnector reconnector = context.getReconnector();
final long delay = (long) Math.min(RECONNECT_START_DELAY_NANOS * Math.pow(2, reconnector.getAttempts()), RECONNECT_MAX_DELAY_NANOS);
final long randomDelay = (long) (delay / 4d / Integer.MAX_VALUE * ThreadLocalRandom.current().nextInt());
reconnector.reconnect(true).delay(delay + randomDelay, TimeUnit.NANOSECONDS);
}
}
}
It is a known inconvenience that the disconnect method can only be called when the client is connected but not when the client is trying to reconnect.
The current solution is to implement a disconnected listener that stops reconnecting.
// create client together with a boolean setting that stops reconnect
final AtomicBoolean stopReconnect = new AtomicBoolean(false);
final Mqtt5Client client = Mqtt5Client.builder()
// other client setup
.automaticReconnectWithDefaultConfig()
.addDisconnectedListener(context -> {
if (stopReonnect.get()) {
context.getReconnector().reconnect(false);
}
})
.build();
// when you want to disconnect finally, set stopReconnect to true in addition to calling disconnect
stopReconnect.set(true);
client.toAsync().disconnect();
@max-was-here nice for figuring out a workaround. You do not need to copy the auto-reconnect code. You can have another disconnected listener in addition to the auto-reconnect logic. See my comment above.