Improve PingAsync timeout handling.

This commit is contained in:
Christian
2022-09-14 14:17:59 +02:00
parent d4dad4860a
commit d23bbf7bf3
6 changed files with 496 additions and 444 deletions
+1
View File
@@ -1,4 +1,5 @@
* [Core] MQTT Packets being sent over web socket transport are now setting the web socket frame boundaries correctly (#1499). * [Core] MQTT Packets being sent over web socket transport are now setting the web socket frame boundaries correctly (#1499).
* [Client] Keep alive mechanism now uses the configured timeout value from the options (thanks to @Stannieman, #1495). * [Client] Keep alive mechanism now uses the configured timeout value from the options (thanks to @Stannieman, #1495).
* [Client] The _PingAsync_ will fallback to the timeout specified in the client options when the cancellation token cannot be cancelled.
* [Server] A DISCONNECT packet is no longer sent to MQTT clients < 5.0.0 (thanks to @logicaloud, #1506). * [Server] A DISCONNECT packet is no longer sent to MQTT clients < 5.0.0 (thanks to @logicaloud, #1506).
* [Server] Improved "take over" process handling. * [Server] Improved "take over" process handling.
+2 -4
View File
@@ -321,14 +321,12 @@ public static class Client_Connection_Samples
{ {
try try
{ {
// This code will also do the very first connect! So no call to _ConnectAsync_ is required // This code will also do the very first connect! So no call to _ConnectAsync_ is required in the first place.
// in the first place. if (!await mqttClient.TryPingAsync())
if (!mqttClient.IsConnected)
{ {
await mqttClient.ConnectAsync(mqttClientOptions, CancellationToken.None); await mqttClient.ConnectAsync(mqttClientOptions, CancellationToken.None);
// Subscribe to topics when session is clean etc. // Subscribe to topics when session is clean etc.
Console.WriteLine("The MQTT client is connected."); Console.WriteLine("The MQTT client is connected.");
} }
} }
+21 -16
View File
@@ -19,10 +19,12 @@ using MQTTnet.Packets;
using MQTTnet.Protocol; using MQTTnet.Protocol;
using MQTTnet.Tests.Mockups; using MQTTnet.Tests.Mockups;
// ReSharper disable InconsistentNaming
namespace MQTTnet.Tests.Client namespace MQTTnet.Tests.Client
{ {
[TestClass] [TestClass]
public sealed class Client_Tests : BaseTestClass public sealed class MqttClient_Tests : BaseTestClass
{ {
[DataTestMethod] [DataTestMethod]
[DataRow(MqttQualityOfServiceLevel.ExactlyOnce)] [DataRow(MqttQualityOfServiceLevel.ExactlyOnce)]
@@ -145,6 +147,7 @@ namespace MQTTnet.Tests.Client
} }
catch catch
{ {
// Ignore errors.
} }
await Task.Delay(500); await Task.Delay(500);
@@ -239,10 +242,10 @@ namespace MQTTnet.Tests.Client
for (var i = 0; i < 98; i++) for (var i = 0; i < 98; i++)
{ {
Assert.IsFalse(clients[i].IsConnected, $"clients[{i}] is not connected"); Assert.IsFalse(clients[i].TryPingAsync().GetAwaiter().GetResult(), $"clients[{i}] is not connected");
} }
Assert.IsTrue(clients[99].IsConnected); Assert.IsTrue(clients[99].TryPingAsync().GetAwaiter().GetResult());
Assert.AreEqual(1, clientStatus.Count); Assert.AreEqual(1, clientStatus.Count);
Assert.AreEqual(1, sessionStatus.Count); Assert.AreEqual(1, sessionStatus.Count);
@@ -332,7 +335,7 @@ namespace MQTTnet.Tests.Client
var client = await testEnvironment.ConnectClient(); var client = await testEnvironment.ConnectClient();
Assert.IsTrue(client.IsConnected); Assert.IsTrue(client.TryPingAsync().GetAwaiter().GetResult());
} }
} }
@@ -343,11 +346,11 @@ namespace MQTTnet.Tests.Client
{ {
await testEnvironment.StartServer(); await testEnvironment.StartServer();
var client = await testEnvironment.ConnectClient(); var client = await testEnvironment.ConnectClient();
Assert.IsTrue(client.IsConnected); Assert.IsTrue(client.TryPingAsync().GetAwaiter().GetResult());
await client.DisconnectAsync(); await client.DisconnectAsync();
Assert.IsFalse(client.IsConnected); Assert.IsFalse(client.TryPingAsync().GetAwaiter().GetResult());
} }
} }
@@ -591,17 +594,17 @@ namespace MQTTnet.Tests.Client
var client = await testEnvironment.ConnectClient(); var client = await testEnvironment.ConnectClient();
await Task.Delay(500); await Task.Delay(500);
Assert.IsTrue(client.IsConnected); Assert.IsTrue(await client.TryPingAsync());
await server.StopAsync(); await server.StopAsync();
await Task.Delay(500); await Task.Delay(500);
Assert.IsFalse(client.IsConnected); Assert.IsFalse(await client.TryPingAsync());
await server.StartAsync(); await server.StartAsync();
await Task.Delay(500); await Task.Delay(500);
await client.ConnectAsync(new MqttClientOptionsBuilder().WithTcpServer("127.0.0.1", testEnvironment.ServerPort).Build()); await client.ConnectAsync(new MqttClientOptionsBuilder().WithTcpServer("127.0.0.1", testEnvironment.ServerPort).Build());
Assert.IsTrue(client.IsConnected); Assert.IsTrue(await client.TryPingAsync());
} }
} }
@@ -637,6 +640,7 @@ namespace MQTTnet.Tests.Client
} }
catch catch
{ {
// Ignore errors.
} }
SpinWait.SpinUntil(() => tries >= maxTries, 10000); SpinWait.SpinUntil(() => tries >= maxTries, 10000);
@@ -656,11 +660,11 @@ namespace MQTTnet.Tests.Client
var client = await testEnvironment.ConnectClient(); var client = await testEnvironment.ConnectClient();
await Task.Delay(500); await Task.Delay(500);
Assert.IsTrue(client.IsConnected); Assert.IsTrue(client.TryPingAsync().GetAwaiter().GetResult());
await server.StopAsync(); await server.StopAsync();
await Task.Delay(500); await Task.Delay(500);
Assert.IsFalse(client.IsConnected); Assert.IsFalse(client.TryPingAsync().GetAwaiter().GetResult());
for (var i = 0; i < 5; i++) for (var i = 0; i < 5; i++)
{ {
@@ -671,6 +675,7 @@ namespace MQTTnet.Tests.Client
} }
catch catch
{ {
// Ignore errors.
} }
} }
@@ -678,7 +683,7 @@ namespace MQTTnet.Tests.Client
await Task.Delay(500); await Task.Delay(500);
await client.ConnectAsync(new MqttClientOptionsBuilder().WithTcpServer("127.0.0.1", testEnvironment.ServerPort).Build()); await client.ConnectAsync(new MqttClientOptionsBuilder().WithTcpServer("127.0.0.1", testEnvironment.ServerPort).Build());
Assert.IsTrue(client.IsConnected); await client.PingAsync();
} }
} }
@@ -828,10 +833,10 @@ namespace MQTTnet.Tests.Client
{ {
using (var testEnvironment = new TestEnvironment(TestContext)) using (var testEnvironment = new TestEnvironment(TestContext))
{ {
var server = await testEnvironment.StartServer(); await testEnvironment.StartServer();
var client = await testEnvironment.ConnectClient(); var client = await testEnvironment.ConnectClient();
Assert.IsTrue(client.IsConnected); Assert.IsTrue(client.TryPingAsync().GetAwaiter().GetResult());
client.DisconnectedAsync += e => client.DisconnectedAsync += e =>
{ {
Assert.IsTrue(e.ClientWasConnected); Assert.IsTrue(e.ClientWasConnected);
@@ -851,7 +856,7 @@ namespace MQTTnet.Tests.Client
var server = await testEnvironment.StartServer(); var server = await testEnvironment.StartServer();
var client = await testEnvironment.ConnectClient(); var client = await testEnvironment.ConnectClient();
Assert.IsTrue(client.IsConnected); Assert.IsTrue(client.TryPingAsync().GetAwaiter().GetResult());
client.DisconnectedAsync += e => client.DisconnectedAsync += e =>
{ {
Assert.IsTrue(e.ClientWasConnected); Assert.IsTrue(e.ClientWasConnected);
@@ -941,7 +946,7 @@ namespace MQTTnet.Tests.Client
await Task.Delay(500); await Task.Delay(500);
Assert.IsTrue(messageReceived); Assert.IsTrue(messageReceived);
Assert.IsTrue(client1.IsConnected); Assert.IsTrue(client1.TryPingAsync().GetAwaiter().GetResult());
Assert.IsFalse(disconnectedFired); Assert.IsFalse(disconnectedFired);
} }
} }
+18 -19
View File
@@ -7,32 +7,31 @@ namespace MQTTnet.Client
{ {
public interface IMqttClient : IDisposable public interface IMqttClient : IDisposable
{ {
event Func<MqttClientConnectedEventArgs, Task> ConnectedAsync;
event Func<MqttClientConnectingEventArgs, Task> ConnectingAsync;
event Func<MqttClientDisconnectedEventArgs, Task> DisconnectedAsync;
event Func<MqttApplicationMessageReceivedEventArgs, Task> ApplicationMessageReceivedAsync; event Func<MqttApplicationMessageReceivedEventArgs, Task> ApplicationMessageReceivedAsync;
event Func<MqttClientConnectedEventArgs, Task> ConnectedAsync;
event Func<MqttClientConnectingEventArgs, Task> ConnectingAsync;
event Func<MqttClientDisconnectedEventArgs, Task> DisconnectedAsync;
event Func<InspectMqttPacketEventArgs, Task> InspectPackage; event Func<InspectMqttPacketEventArgs, Task> InspectPackage;
bool IsConnected { get; } bool IsConnected { get; }
MqttClientOptions Options { get; } MqttClientOptions Options { get; }
Task<MqttClientConnectResult> ConnectAsync(MqttClientOptions options, CancellationToken cancellationToken = default); Task<MqttClientConnectResult> ConnectAsync(MqttClientOptions options, CancellationToken cancellationToken = default);
Task DisconnectAsync(MqttClientDisconnectOptions options, CancellationToken cancellationToken = default); Task DisconnectAsync(MqttClientDisconnectOptions options, CancellationToken cancellationToken = default);
Task PingAsync(CancellationToken cancellationToken = default); Task PingAsync(CancellationToken cancellationToken = default);
Task SendExtendedAuthenticationExchangeDataAsync(MqttExtendedAuthenticationExchangeData data, CancellationToken cancellationToken = default);
Task<MqttClientSubscribeResult> SubscribeAsync(MqttClientSubscribeOptions options, CancellationToken cancellationToken = default);
Task<MqttClientUnsubscribeResult> UnsubscribeAsync(MqttClientUnsubscribeOptions options, CancellationToken cancellationToken = default);
Task<MqttClientPublishResult> PublishAsync(MqttApplicationMessage applicationMessage, CancellationToken cancellationToken = default); Task<MqttClientPublishResult> PublishAsync(MqttApplicationMessage applicationMessage, CancellationToken cancellationToken = default);
Task SendExtendedAuthenticationExchangeDataAsync(MqttExtendedAuthenticationExchangeData data, CancellationToken cancellationToken = default);
Task<MqttClientSubscribeResult> SubscribeAsync(MqttClientSubscribeOptions options, CancellationToken cancellationToken = default);
Task<MqttClientUnsubscribeResult> UnsubscribeAsync(MqttClientUnsubscribeOptions options, CancellationToken cancellationToken = default);
} }
} }
File diff suppressed because it is too large Load Diff
@@ -14,6 +14,26 @@ namespace MQTTnet.Client
{ {
public static class MqttClientExtensions public static class MqttClientExtensions
{ {
public static async Task<bool> TryPingAsync(this IMqttClient client, CancellationToken cancellationToken = default)
{
if (client == null)
{
throw new ArgumentNullException(nameof(client));
}
try
{
await client.PingAsync(cancellationToken).ConfigureAwait(false);
return true;
}
catch
{
// Ignore errors.
}
return false;
}
public static Task DisconnectAsync(this IMqttClient client, MqttClientDisconnectReason reason = MqttClientDisconnectReason.NormalDisconnection, string reasonString = null) public static Task DisconnectAsync(this IMqttClient client, MqttClientDisconnectReason reason = MqttClientDisconnectReason.NormalDisconnection, string reasonString = null)
{ {
if (client == null) if (client == null)