Skip to content

Commit 580b99a

Browse files
authored
Add Periodic Internal Health Checks (#170)
1 parent c1b08ce commit 580b99a

File tree

1 file changed

+39
-21
lines changed

1 file changed

+39
-21
lines changed

Source/HiveMQtt/Client/HiveMQClientTrafficProcessor.cs

Lines changed: 39 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -44,13 +44,32 @@ public partial class HiveMQClient : IDisposable, IHiveMQClient
4444

4545
private readonly Stopwatch lastCommunicationTimer = new();
4646

47+
/// <summary>
48+
/// Health check method to assure that tasks haven't faulted unexpectedly.
49+
/// </summary>
50+
private async Task RunTaskHealthCheckAsync(Task? task, string taskName)
51+
{
52+
if (task is null)
53+
{
54+
Logger.Info($"{this.Options.ClientId}-(CM)- {taskName} is not running.");
55+
}
56+
else
57+
{
58+
if (task.IsFaulted)
59+
{
60+
Logger.Error($"{this.Options.ClientId}-(CM)- {taskName} Faulted: {task.Exception}");
61+
Logger.Error($"{this.Options.ClientId}-(CM)- {taskName} died. Disconnecting.");
62+
_ = await this.HandleDisconnectionAsync(false).ConfigureAwait(false);
63+
}
64+
}
65+
}
66+
4767
/// <summary>
4868
/// Asynchronous background task that monitors the connection state and sends PingReq packets when
4969
/// necessary.
5070
/// </summary>
5171
/// <param name="cancellationToken">The cancellation token.</param>
52-
/// <returns>A boolean return indicating exit state.</returns>
53-
private Task<bool> ConnectionMonitorAsync(CancellationToken cancellationToken) => Task.Run(
72+
private Task ConnectionMonitorAsync(CancellationToken cancellationToken) => Task.Run(
5473
async () =>
5574
{
5675
var keepAlivePeriod = this.Options.KeepAlive / 2;
@@ -77,34 +96,35 @@ private Task<bool> ConnectionMonitorAsync(CancellationToken cancellationToken) =
7796

7897
// Dumping Client State
7998
Logger.Trace($"{this.Options.ClientId}-(CM)- {this.ConnectState} lastCommunicationTimer:{this.lastCommunicationTimer.Elapsed}");
80-
Logger.Trace($"{this.Options.ClientId}-(CM)- SendQueue:{this.SendQueue.Count} ReceivedQueue:{this.ReceivedQueue.Count} OutgoingPublishQueue:{this.OutgoingPublishQueue.Count}");
81-
Logger.Trace($"{this.Options.ClientId}-(CM)- TransactionQueue:{this.TransactionQueue.Count}");
82-
Logger.Trace($"{this.Options.ClientId}-(CM)- - ConnectionMonitor:{this.ConnectionMonitorTask?.Status}");
83-
Logger.Trace($"{this.Options.ClientId}-(CM)- - ConnectionPublishWriter:{this.ConnectionPublishWriterTask?.Status}");
84-
Logger.Trace($"{this.Options.ClientId}-(CM)- - ConnectionWriter:{this.ConnectionWriterTask?.Status}");
85-
Logger.Trace($"{this.Options.ClientId}-(CM)- - ConnectionReader:{this.ConnectionReaderTask?.Status}");
86-
Logger.Trace($"{this.Options.ClientId}-(CM)- - ReceivedPacketsHandler:{this.ReceivedPacketsHandlerTask?.Status}");
99+
Logger.Trace($"{this.Options.ClientId}-(CM)- SendQueue:............{this.SendQueue.Count}");
100+
Logger.Trace($"{this.Options.ClientId}-(CM)- ReceivedQueue:........{this.ReceivedQueue.Count}");
101+
Logger.Trace($"{this.Options.ClientId}-(CM)- OutgoingPublishQueue:.{this.OutgoingPublishQueue.Count}");
102+
Logger.Trace($"{this.Options.ClientId}-(CM)- TransactionQueue:.....{this.TransactionQueue.Count}");
103+
Logger.Trace($"{this.Options.ClientId}-(CM)- # of Subscriptions:...{this.Subscriptions.Count}");
104+
105+
await this.RunTaskHealthCheckAsync(this.ConnectionWriterTask, "ConnectionWriter").ConfigureAwait(false);
106+
await this.RunTaskHealthCheckAsync(this.ConnectionReaderTask, "ConnectionReader").ConfigureAwait(false);
107+
await this.RunTaskHealthCheckAsync(this.ConnectionPublishWriterTask, "ConnectionPublishWriter").ConfigureAwait(false);
108+
await this.RunTaskHealthCheckAsync(this.ReceivedPacketsHandlerTask, "ReceivedPacketsHandler").ConfigureAwait(false);
87109

88110
try
89111
{
90112
await Task.Delay(2000, cancellationToken).ConfigureAwait(false);
91113
}
92114
catch (TaskCanceledException)
93115
{
94-
Logger.Trace($"{this.Options.ClientId}-(CM)- Cancelled");
95-
break;
116+
Logger.Info($"{this.Options.ClientId}-(CM)- Cancelled");
117+
return;
96118
}
97119
}
98120

99121
Logger.Trace($"{this.Options.ClientId}-(CM)- Exiting...{this.ConnectState}");
100-
101-
return true;
102122
}, cancellationToken);
103123

104124
/// <summary>
105125
/// Asynchronous background task that handles the outgoing publish packets queued in OutgoingPublishQueue.
106126
/// </summary>
107-
private Task<bool> ConnectionPublishWriterAsync(CancellationToken cancellationToken) => Task.Run(
127+
private Task ConnectionPublishWriterAsync(CancellationToken cancellationToken) => Task.Run(
108128
async () =>
109129
{
110130
this.lastCommunicationTimer.Start();
@@ -168,13 +188,12 @@ private Task<bool> ConnectionPublishWriterAsync(CancellationToken cancellationTo
168188
} // while(true)
169189

170190
Logger.Trace($"{this.Options.ClientId}-(PW)- ConnectionPublishWriter Exiting...{this.ConnectState}");
171-
return true;
172191
}, cancellationToken);
173192

174193
/// <summary>
175194
/// Asynchronous background task that handles the outgoing traffic of packets queued in the sendQueue.
176195
/// </summary>
177-
private Task<bool> ConnectionWriterAsync(CancellationToken cancellationToken) => Task.Run(
196+
private Task ConnectionWriterAsync(CancellationToken cancellationToken) => Task.Run(
178197
async () =>
179198
{
180199
this.lastCommunicationTimer.Start();
@@ -280,7 +299,7 @@ private Task<bool> ConnectionWriterAsync(CancellationToken cancellationToken) =>
280299
} // while(true)
281300

282301
Logger.Trace($"{this.Options.ClientId}-(W)- ConnectionWriter Exiting...{this.ConnectState}");
283-
return true;
302+
return;
284303
}, cancellationToken);
285304

286305
/// <summary>
@@ -383,8 +402,7 @@ private Task<bool> ConnectionReaderAsync(CancellationToken cancellationToken) =>
383402
/// Continually processes the packets queued in the receivedQueue.
384403
/// </summary>
385404
/// <param name="cancellationToken">The cancellation token to stop the task.</param>
386-
/// <returns>A fairly worthless boolean.</returns>
387-
private Task<bool> ReceivedPacketsHandlerAsync(CancellationToken cancellationToken) => Task.Run(
405+
private Task ReceivedPacketsHandlerAsync(CancellationToken cancellationToken) => Task.Run(
388406
async () =>
389407
{
390408
Logger.Trace($"{this.Options.ClientId}-(RPH)- Starting...{this.ConnectState}");
@@ -412,7 +430,7 @@ private Task<bool> ReceivedPacketsHandlerAsync(CancellationToken cancellationTok
412430
ReasonString = "Packet Too Large",
413431
};
414432
await this.DisconnectAsync(opts).ConfigureAwait(false);
415-
return false;
433+
return;
416434
}
417435
}
418436

@@ -462,7 +480,7 @@ private Task<bool> ReceivedPacketsHandlerAsync(CancellationToken cancellationTok
462480
} // while (true)
463481

464482
Logger.Trace($"{this.Options.ClientId}-(RPH)- ReceivedPacketsHandler Exiting...{this.ConnectState}");
465-
return true;
483+
return;
466484
}, cancellationToken);
467485

468486
/// <summary>

0 commit comments

Comments
 (0)