Skip to content

Commit 2cec45d

Browse files
committed
Refactor health check and disposal logic, update versions
Refactored health check extension methods to use ArgumentNullException.ThrowIfNull and simplified path handling. Updated HealthCheckResult and FunctionalHealthCheck to use primary constructors. Standardized ObjectDisposedException.ThrowIf usage for .NET version compatibility in ConnectionTracker and SmtpServer. Updated project versions in Zetian and Zetian.HealthCheck csproj files. Improved test assertion in SmtpServerRaceConditionTests for clarity.
1 parent 87d70de commit 2cec45d

9 files changed

Lines changed: 38 additions & 67 deletions

File tree

.pages/app/layout.tsx

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -20,11 +20,13 @@ export const metadata: Metadata = {
2020
".NET",
2121
"C#",
2222
"mail server",
23+
"smtp server",
2324
"TLS",
2425
"authentication",
2526
"rate limiting",
2627
"async",
2728
"dotnet",
29+
"health check",
2830
],
2931
authors: [{ name: "Taiizor", url: "https://github.com/Taiizor" }],
3032
creator: "Taiizor",
@@ -40,8 +42,8 @@ export const metadata: Metadata = {
4042
images: [
4143
{
4244
url: "/Logo.png",
43-
width: 1200,
44-
height: 630,
45+
width: 512,
46+
height: 512,
4547
alt: "Zetian SMTP Server",
4648
},
4749
],

src/Zetian.HealthCheck/Extensions/HealthCheckExtensions.cs

Lines changed: 12 additions & 39 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,4 @@
11
using System;
2-
using System.Collections.Generic;
32
using System.Net;
43
using System.Net.Sockets;
54
using System.Threading;
@@ -42,25 +41,22 @@ public static HealthCheckService EnableHealthCheck(
4241
int port,
4342
string path = "/health/")
4443
{
45-
if (server == null)
46-
{
47-
throw new ArgumentNullException(nameof(server));
48-
}
44+
ArgumentNullException.ThrowIfNull(server);
4945

5046
if (string.IsNullOrWhiteSpace(hostname))
5147
{
5248
throw new ArgumentNullException(nameof(hostname));
5349
}
5450

5551
// Ensure path ends with /
56-
if (!path.EndsWith("/"))
52+
if (!path.EndsWith('/'))
5753
{
58-
path += "/";
54+
path += '/';
5955
}
6056

6157
HealthCheckServiceOptions options = new()
6258
{
63-
Prefixes = new List<string> { $"http://{hostname}:{port}{path}" }
59+
Prefixes = new() { $"http://{hostname}:{port}{path}" }
6460
};
6561

6662
HealthCheckService service = new(options, server.Configuration.LoggerFactory);
@@ -86,15 +82,9 @@ public static HealthCheckService EnableHealthCheck(
8682
int port,
8783
string path = "/health/")
8884
{
89-
if (server == null)
90-
{
91-
throw new ArgumentNullException(nameof(server));
92-
}
85+
ArgumentNullException.ThrowIfNull(server);
9386

94-
if (ipAddress == null)
95-
{
96-
throw new ArgumentNullException(nameof(ipAddress));
97-
}
87+
ArgumentNullException.ThrowIfNull(ipAddress);
9888

9989
string hostname = ipAddress.ToString();
10090
if (ipAddress.AddressFamily == AddressFamily.InterNetworkV6)
@@ -117,15 +107,9 @@ public static HealthCheckService EnableHealthCheck(
117107
HealthCheckServiceOptions serviceOptions,
118108
SmtpHealthCheckOptions? healthCheckOptions = null)
119109
{
120-
if (server == null)
121-
{
122-
throw new ArgumentNullException(nameof(server));
123-
}
110+
ArgumentNullException.ThrowIfNull(server);
124111

125-
if (serviceOptions == null)
126-
{
127-
throw new ArgumentNullException(nameof(serviceOptions));
128-
}
112+
ArgumentNullException.ThrowIfNull(serviceOptions);
129113

130114
HealthCheckService service = new(serviceOptions, server.Configuration.LoggerFactory);
131115

@@ -218,20 +202,14 @@ public static HealthCheckService AddHealthCheck(
218202
string name,
219203
Func<CancellationToken, Task<HealthCheckResult>> healthCheckFunc)
220204
{
221-
if (service == null)
222-
{
223-
throw new ArgumentNullException(nameof(service));
224-
}
205+
ArgumentNullException.ThrowIfNull(service);
225206

226207
if (string.IsNullOrWhiteSpace(name))
227208
{
228209
throw new ArgumentNullException(nameof(name));
229210
}
230211

231-
if (healthCheckFunc == null)
232-
{
233-
throw new ArgumentNullException(nameof(healthCheckFunc));
234-
}
212+
ArgumentNullException.ThrowIfNull(healthCheckFunc);
235213

236214
FunctionalHealthCheck functionalHealthCheck = new(healthCheckFunc);
237215
service.AddHealthCheck(name, functionalHealthCheck);
@@ -243,14 +221,9 @@ public static HealthCheckService AddHealthCheck(
243221
/// <summary>
244222
/// Functional health check implementation
245223
/// </summary>
246-
internal class FunctionalHealthCheck : IHealthCheck
224+
internal class FunctionalHealthCheck(Func<CancellationToken, Task<HealthCheckResult>> checkFunc) : IHealthCheck
247225
{
248-
private readonly Func<CancellationToken, Task<HealthCheckResult>> _checkFunc;
249-
250-
public FunctionalHealthCheck(Func<CancellationToken, Task<HealthCheckResult>> checkFunc)
251-
{
252-
_checkFunc = checkFunc ?? throw new ArgumentNullException(nameof(checkFunc));
253-
}
226+
private readonly Func<CancellationToken, Task<HealthCheckResult>> _checkFunc = checkFunc ?? throw new ArgumentNullException(nameof(checkFunc));
254227

255228
public Task<HealthCheckResult> CheckHealthAsync(CancellationToken cancellationToken = default)
256229
{

src/Zetian.HealthCheck/HealthCheck/HealthCheckResult.cs

Lines changed: 8 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -6,38 +6,30 @@ namespace Zetian.HealthCheck
66
/// <summary>
77
/// Represents the result of a health check
88
/// </summary>
9-
public class HealthCheckResult
9+
/// <remarks>
10+
/// Initializes a new instance of HealthCheckResult
11+
/// </remarks>
12+
public class HealthCheckResult(HealthStatus status, string? description = null, Exception? exception = null, Dictionary<string, object>? data = null)
1013
{
11-
/// <summary>
12-
/// Initializes a new instance of HealthCheckResult
13-
/// </summary>
14-
public HealthCheckResult(HealthStatus status, string? description = null, Exception? exception = null, Dictionary<string, object>? data = null)
15-
{
16-
Status = status;
17-
Description = description;
18-
Exception = exception;
19-
Data = data ?? new();
20-
}
21-
2214
/// <summary>
2315
/// Gets the health status
2416
/// </summary>
25-
public HealthStatus Status { get; }
17+
public HealthStatus Status { get; } = status;
2618

2719
/// <summary>
2820
/// Gets the description
2921
/// </summary>
30-
public string? Description { get; }
22+
public string? Description { get; } = description;
3123

3224
/// <summary>
3325
/// Gets the exception if any
3426
/// </summary>
35-
public Exception? Exception { get; }
27+
public Exception? Exception { get; } = exception;
3628

3729
/// <summary>
3830
/// Gets additional data
3931
/// </summary>
40-
public Dictionary<string, object> Data { get; }
32+
public Dictionary<string, object> Data { get; } = data ?? new();
4133

4234
/// <summary>
4335
/// Creates a healthy result

src/Zetian.HealthCheck/HealthCheck/HealthCheckService.cs

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -59,10 +59,14 @@ public void AddHealthCheck(string name, IHealthCheck healthCheck)
5959
/// </summary>
6060
public async Task StartAsync(CancellationToken cancellationToken = default)
6161
{
62+
#if NET6_0
6263
if (_disposed)
6364
{
6465
throw new ObjectDisposedException(nameof(HealthCheckService));
6566
}
67+
#else
68+
ObjectDisposedException.ThrowIf(_disposed, this);
69+
#endif
6670

6771
if (IsRunning)
6872
{
@@ -182,7 +186,7 @@ private async Task HandleRequestAsync(HttpListenerContext context, CancellationT
182186
{
183187
// Extract the path after the prefix
184188
effectivePath = fullPath[prefixPath.Length..];
185-
if (!effectivePath.StartsWith("/"))
189+
if (!effectivePath.StartsWith('/'))
186190
{
187191
effectivePath = "/" + effectivePath;
188192
}
@@ -305,7 +309,7 @@ private async Task WriteJsonResponse(HttpListenerResponse response, object data)
305309
byte[] buffer = Encoding.UTF8.GetBytes(json);
306310
response.ContentLength64 = buffer.Length;
307311

308-
await response.OutputStream.WriteAsync(buffer, 0, buffer.Length);
312+
await response.OutputStream.WriteAsync(buffer);
309313
response.Close();
310314
}
311315

src/Zetian.HealthCheck/Zetian.HealthCheck.csproj

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@
1111

1212
<PropertyGroup>
1313
<ApplicationIcon>Resources\Zetian.ico</ApplicationIcon>
14-
<Version>1.0.2</Version>
14+
<Version>1.0.3</Version>
1515
<AssemblyVersion>$(Version)</AssemblyVersion>
1616
<GeneratePackageOnBuild>true</GeneratePackageOnBuild>
1717
<Title>Zetian.HealthCheck</Title>

src/Zetian/Internal/ConnectionTracker.cs

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -299,8 +299,8 @@ public Task LockAsync(CancellationToken cancellationToken = default)
299299
{
300300
throw new ObjectDisposedException(nameof(ConnectionInfo));
301301
}
302-
#elif NET7_0_OR_GREATER
303-
ObjectDisposedException.ThrowIf(_disposed, nameof(ConnectionInfo));
302+
#else
303+
ObjectDisposedException.ThrowIf(_disposed, this);
304304
#endif
305305
return _syncLock.WaitAsync(cancellationToken);
306306
}
@@ -315,8 +315,8 @@ public void Lock()
315315
{
316316
throw new ObjectDisposedException(nameof(ConnectionInfo));
317317
}
318-
#elif NET7_0_OR_GREATER
319-
ObjectDisposedException.ThrowIf(_disposed, nameof(ConnectionInfo));
318+
#else
319+
ObjectDisposedException.ThrowIf(_disposed, this);
320320
#endif
321321
_syncLock.Wait();
322322
}

src/Zetian/SmtpServer.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -413,7 +413,7 @@ private void ThrowIfDisposed()
413413
{
414414
throw new ObjectDisposedException(GetType().FullName);
415415
}
416-
#elif NET7_0_OR_GREATER
416+
#else
417417
ObjectDisposedException.ThrowIf(_disposed, this);
418418
#endif
419419
}

src/Zetian/Zetian.csproj

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@
1111

1212
<PropertyGroup>
1313
<ApplicationIcon>Resources\Zetian.ico</ApplicationIcon>
14-
<Version>1.0.9</Version>
14+
<Version>1.0.10</Version>
1515
<AssemblyVersion>$(Version)</AssemblyVersion>
1616
<GeneratePackageOnBuild>true</GeneratePackageOnBuild>
1717
<Title>Zetian</Title>

tests/Zetian.Tests/SmtpServerRaceConditionTests.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -264,7 +264,7 @@ public async Task SmtpServer_ShouldHandleConcurrentSmtpClients()
264264
if (successCount == 0)
265265
{
266266
string errorDetails = string.Join("\n", failureMessages.Take(5));
267-
Assert.True(false, $"No connections succeeded. Sample errors:\n{errorDetails}");
267+
Assert.Fail($"No connections succeeded. Sample errors:\n{errorDetails}");
268268
}
269269
Assert.True(successCount > 0, "At least some connections should succeed");
270270
}

0 commit comments

Comments
 (0)