| | 1 | | using Microsoft.Extensions.Logging; |
| | 2 | | using NostrSure.Infrastructure.Client.Abstractions; |
| | 3 | | using System.Net.Sockets; |
| | 4 | | using System.Net.WebSockets; |
| | 5 | |
|
| | 6 | | namespace NostrSure.Infrastructure.Client.Implementation; |
| | 7 | |
|
| | 8 | | /// <summary> |
| | 9 | | /// Centralized error handling for WebSocket connections |
| | 10 | | /// </summary> |
| | 11 | | public sealed class ConnectionErrorHandler : IConnectionErrorHandler |
| | 12 | | { |
| | 13 | | private readonly ILogger<ConnectionErrorHandler>? _logger; |
| | 14 | |
|
| 8 | 15 | | public ConnectionErrorHandler(ILogger<ConnectionErrorHandler>? logger = null) |
| 8 | 16 | | { |
| 8 | 17 | | _logger = logger; |
| 8 | 18 | | } |
| | 19 | |
|
| | 20 | | public event EventHandler<Exception>? ErrorOccurred; |
| | 21 | |
|
| | 22 | | public async Task HandleErrorAsync(Exception exception, string context) |
| 1 | 23 | | { |
| 1 | 24 | | _logger?.LogError(exception, "WebSocket error in {Context}: {Message}", context, exception.Message); |
| | 25 | |
|
| | 26 | | // Fire error event |
| 1 | 27 | | ErrorOccurred?.Invoke(this, exception); |
| | 28 | |
|
| | 29 | | // Allow for async error handling if needed |
| 1 | 30 | | await Task.CompletedTask; |
| 1 | 31 | | } |
| | 32 | |
|
| | 33 | | public bool ShouldReconnect(Exception exception) |
| 16 | 34 | | { |
| 16 | 35 | | return exception switch |
| 16 | 36 | | { |
| 16 | 37 | | // Network-related exceptions that warrant retry |
| 1 | 38 | | HttpRequestException => true, |
| 1 | 39 | | SocketException => true, |
| 1 | 40 | | TimeoutException => true, |
| 16 | 41 | |
|
| 16 | 42 | | // WebSocket-specific exceptions |
| 9 | 43 | | WebSocketException wsEx => wsEx.WebSocketErrorCode switch |
| 9 | 44 | | { |
| 1 | 45 | | WebSocketError.ConnectionClosedPrematurely => true, |
| 0 | 46 | | WebSocketError.Faulted => true, |
| 1 | 47 | | WebSocketError.HeaderError => false, // Don't retry on header errors |
| 1 | 48 | | WebSocketError.InvalidMessageType => false, // Don't retry on invalid message types |
| 1 | 49 | | WebSocketError.InvalidState => false, // Don't retry on invalid state |
| 1 | 50 | | WebSocketError.NativeError => true, |
| 1 | 51 | | WebSocketError.NotAWebSocket => false, // Don't retry if not a WebSocket |
| 1 | 52 | | WebSocketError.Success => false, // This shouldn't be an error |
| 1 | 53 | | WebSocketError.UnsupportedProtocol => false, // Don't retry on protocol mismatch |
| 1 | 54 | | WebSocketError.UnsupportedVersion => false, // Don't retry on version mismatch |
| 0 | 55 | | _ => true // Default to retry for unknown WebSocket errors |
| 9 | 56 | | }, |
| 16 | 57 | |
|
| 16 | 58 | | // Operation cancelled - usually intentional, don't retry |
| 1 | 59 | | OperationCanceledException => false, |
| 16 | 60 | |
|
| 16 | 61 | | // Invalid operations - usually programming errors, don't retry |
| 1 | 62 | | InvalidOperationException => false, |
| 1 | 63 | | ArgumentException => false, |
| 16 | 64 | |
|
| 16 | 65 | | // Default to retry for unknown exceptions |
| 1 | 66 | | _ => true |
| 16 | 67 | | }; |
| 16 | 68 | | } |
| | 69 | | } |