-
Notifications
You must be signed in to change notification settings - Fork 1.1k
Description
Describe the bug
In MqttClient in reconnect scenarios it happens, that after a successful reconnect, the IsConnect flag stays false.
That leads to a loop of reconnects in our code, which sometimes go on for several minutes until IsConnected finally transitions to true.
Which component is your bug related to?
- Client
- Server (maybe?)
To Reproduce
MQTTnet v5.0.1
MQTTnet.Server v5.0.1
MQTTnet.Server is running as broker in the same process, connected via tcp loopback adapter.
Running under Windows, with .NET 8
We have a reconnect mechanism in place, as suggested in the samples, using an endless loop and Task.Delay.
This issue never happens at initial disconnect, only at reconnect.
The client object is reused after a connection loss.
it does not happen everytime!
It's pretty hard to reproduce while productive use.
Expected behavior
IsConnected should be true when connect states successfull.
OR ConnectResult should not return Success, when IsConnected was not set to true.
Additional context / logging
when reconnection:
- Connecting event from client gets fired (which is expected)
- ClientDisconnected event from broker (for this client) get fired. DiconnectType: Takeover (which is expected IMO)
- "Disconnected" log from client (not expected IMO)
- "Client '...' Connection stopped" log from server (I guess this is from the "old" ConnectedClient, due to session takeover)
Code example
client options:
var options = ConfigureClientOptions(clientOptionsBuilder
.WithClientId("someClientIdString")
.WithKeepAlivePeriod(Timespan.FromSeconds(10))
.WithCleanStart()
.WithSessionExpiryInterval(0)
.Build();we save that options in a variable and pass it as parameter for connect and reconnect.
how we (re-)connect, and the Debug.Assert which fails:
var result = await Client.ConnectAsync(options, combinedCts.Token);
if (result.ResultCode != MqttClientConnectResultCode.Success)
{
_logger.LogCritical(
"MqttClient {mqttClientId} failed to connect to broker! ResultCode: {resultCode}, Reason: {reason}.",
ClientId, result.ResultCode, result.ReasonString);
return MqttConnectResult.FailedOrCancelled;
}
Debug.Assert(Client.IsConnected);
return MqttConnectResult.Success;Testing/reproduce code
Tryining to reproduce it (and sometimes successful), we put this code in our reconnect loop:
while (!_disposed && !stopSignal.IsCancellationRequested)
{
// test-code starts
// -----------
// sidenote: in productive environments we wait for 500ms until we check IsConnected
await Task.Delay(TimeSpan.FromSeconds(20), stopSignal);
await Client.DisconnectAsync(reason: MqttClientDisconnectOptionsReason.AdministrativeAction, cancellationToken: stopSignal);
await Task.Delay(TimeSpan.FromSeconds(2), stopSignal);
// ----------
// end of test code
if (Client.IsConnected)
{
continue;
}
var connectResult = await InternalConnectMethodAsync(options, stopSignal);
}as already said, most of the time the reconnect works without problems.