diff --git a/src/NetPulse.Cli/Program.cs b/src/NetPulse.Cli/Program.cs index d1f4954..3219d1b 100644 --- a/src/NetPulse.Cli/Program.cs +++ b/src/NetPulse.Cli/Program.cs @@ -1,5 +1,6 @@ using System.Net.NetworkInformation; using NetPulse.Core.Domain; +using NetPulse.Core.Services; if (args.Length == 0) { @@ -18,15 +19,32 @@ switch (command) return; } - var target = args[1]; - await RunPingAsync(target); + var service = new PingService(); + var result = await service.RunAsync(Guid.Empty, args[1]); + Console.WriteLine(result.Success + ? $"Success: {result.LatencyMs} ms" + : $"Failed: {result.ErrorMessage}"); + if (!result.Success && result.InnerErrorMessage is not null) + { + Console.WriteLine($"Inner error: {result.InnerErrorMessage}"); + } + break; - - default: - Console.WriteLine($"Unkown command: {command}"); - break; } +/* +=========================================================== +ARCHIVE NOTE — Old Ping Logic (Lesson 2 → Pre-Service Layer) +Keeping this for reference only. Not compiled. Not used. +This was the original inline/local-function ping approach +before we migrated to the proper PingService architecture. + +Useful for: +- remembering how PingResult was initially populated +- comparing exception handling approaches +- seeing the progression of the codebase over lessons +- nostalgia (optional but valid) +=========================================================== static async Task RunPingAsync(string target) { using var pinger = new Ping(); @@ -61,6 +79,7 @@ static async Task RunPingAsync(string target) } } + static void SaveMockResult(PingResult result) { Console.WriteLine(" --- Saved Result ---"); @@ -69,3 +88,7 @@ static void SaveMockResult(PingResult result) Console.WriteLine($"Latency: {result.LatencyMs}"); Console.WriteLine($"Error: {result.ErrorMessage}"); } +=========================================================== +End of Archive Block +=========================================================== +*/ \ No newline at end of file diff --git a/src/NetPulse.Core/Domain/PingResult.cs b/src/NetPulse.Core/Domain/PingResult.cs index ad0c729..21459dd 100644 --- a/src/NetPulse.Core/Domain/PingResult.cs +++ b/src/NetPulse.Core/Domain/PingResult.cs @@ -31,4 +31,9 @@ public class PingResult /// Error detail if the pin failed. /// public string? ErrorMessage { get; init; } + + /// + /// InnerErrorMessage for error handling + /// + public string? InnerErrorMessage { get; init; } } \ No newline at end of file diff --git a/src/NetPulse.Core/Services/PingService.cs b/src/NetPulse.Core/Services/PingService.cs new file mode 100644 index 0000000..b44e3b7 --- /dev/null +++ b/src/NetPulse.Core/Services/PingService.cs @@ -0,0 +1,61 @@ +using System.Net.NetworkInformation; +using NetPulse.Core.Domain; + +namespace NetPulse.Core.Services; + +public class PingService +{ + private readonly Ping _pinger = new(); + + public async Task RunAsync(Guid targetId, string host) + { + try + { + var reply = await _pinger.SendPingAsync(host, 2000); + + if (reply.Status == IPStatus.Success) + { + return new PingResult + { + TargetId = targetId, + Timestamputc = DateTime.UtcNow, + Success = true, + LatencyMs = reply.RoundtripTime, + ErrorMessage = null + }; + } + + return new PingResult + { + TargetId = targetId, + Timestamputc = DateTime.UtcNow, + Success = false, + LatencyMs = null, + ErrorMessage = $"Ping failed with status: {reply.Status}" + }; + } + catch (PingException ex) + { + return new PingResult + { + TargetId = targetId, + Timestamputc = DateTime.UtcNow, + Success = false, + LatencyMs = null, + ErrorMessage = ex.Message, + InnerErrorMessage = ex.InnerException?.Message + }; + } + catch (Exception ex) + { + return new PingResult + { + TargetId = targetId, + Timestamputc = DateTime.UtcNow, + Success = false, + LatencyMs = null, + ErrorMessage = ex.Message + }; + } + } +} \ No newline at end of file