diff --git a/GamesDat.Demo/Program.cs b/GamesDat.Demo/Program.cs index e0bca59..dfa87af 100644 --- a/GamesDat.Demo/Program.cs +++ b/GamesDat.Demo/Program.cs @@ -21,26 +21,43 @@ static async Task Main(string[] args) static async Task CaptureWarThunderSession() { var cts = new CancellationTokenSource(); - Console.CancelKeyPress += (s, e) => + ConsoleCancelEventHandler handler = (s, e) => { e.Cancel = true; cts.Cancel(); }; + Console.CancelKeyPress += handler; - var session = new GameSession() - .AddSource( - WarThunderSources.CreateStateSource() - .UseWriter(new BinarySessionWriter()) - .OutputTo($"./sessions/warthunder_{DateTime.UtcNow:yyyyMMdd_HHmmss}.bin")) - .OnData(data => - { - Console.WriteLine($"Altitude: {data.Altitude} | Speed {data.TrueAirspeed} | Throttle {data.Throttle}"); - }); + try + { + var session = new GameSession() + .AddSource( + WarThunderSources.CreateStateSource() + .UseWriter(new BinarySessionWriter()) + .OutputTo($"./sessions/warthunder_{DateTime.UtcNow:yyyyMMdd_HHmmss}.bin")) + .OnData(data => + { + Console.WriteLine($"Altitude: {data.Altitude} | Speed {data.TrueAirspeed} | Throttle {data.Throttle}"); + }); - await session.StartAsync(cts.Token); + await session.StartAsync(cts.Token); - // Session is now running, wait for cancellation - await Task.Delay(Timeout.Infinite, cts.Token); + // Session is now running, wait for cancellation + await Task.Delay(Timeout.Infinite, cts.Token); + } + catch (FileNotFoundException) + { + Console.WriteLine("\nError: War Thunder is not running. Start War Thunder and try again."); + } + catch (OperationCanceledException) + { + Console.WriteLine("\nCapture stopped by user."); + } + finally + { + Console.CancelKeyPress -= handler; + cts.Dispose(); + } } #endregion diff --git a/GamesDat/Telemetry/Sources/HttpPollingSourceBase.cs b/GamesDat/Telemetry/Sources/HttpPollingSourceBase.cs index 440e037..561bc3c 100644 --- a/GamesDat/Telemetry/Sources/HttpPollingSourceBase.cs +++ b/GamesDat/Telemetry/Sources/HttpPollingSourceBase.cs @@ -98,12 +98,33 @@ public override async IAsyncEnumerable ReadContinuousAsync( // JSON parse errors are logged but don't trigger aggressive retry Console.WriteLine($"[{GetType().Name}] JSON parse error (skipping frame): {ex.Message}"); } - catch (OperationCanceledException) + catch (OperationCanceledException ex) { - // Clean cancellation - yield break; + if (cancellationToken.IsCancellationRequested) + { + // Clean cancellation requested by caller + yield break; + } + + // Timeout cancellation from linkedCts (request timeout) - treat as connection error + _consecutiveErrors++; + + if (firstError) + { + Console.WriteLine($"[{GetType().Name}] Connection error: {ex.Message}"); + Console.WriteLine($"[{GetType().Name}] Retrying with exponential backoff..."); + firstError = false; + } + + if (_consecutiveErrors >= _options.MaxConsecutiveErrors) + { + errorToThrow = new InvalidOperationException( + $"Failed to connect after {_consecutiveErrors} consecutive attempts. " + + $"Ensure the game is running and the API is accessible at {fullUrl}", + ex); + } } - catch (Exception ex) when (ex is HttpRequestException or TaskCanceledException) + catch (HttpRequestException ex) { // Connection/timeout errors - use exponential backoff _consecutiveErrors++; diff --git a/GamesDat/Telemetry/Sources/HttpPollingSourceOptions.cs b/GamesDat/Telemetry/Sources/HttpPollingSourceOptions.cs index a9eca37..92422d3 100644 --- a/GamesDat/Telemetry/Sources/HttpPollingSourceOptions.cs +++ b/GamesDat/Telemetry/Sources/HttpPollingSourceOptions.cs @@ -1,3 +1,7 @@ +using System; +using System.Collections.Generic; +using System.Linq; + namespace GamesDat.Core.Telemetry.Sources; /// diff --git a/docs/WarThunder.md b/docs/WarThunder.md index 45d4c43..96de098 100644 --- a/docs/WarThunder.md +++ b/docs/WarThunder.md @@ -370,5 +370,5 @@ War Thunder API documentation and community tools: ## See Also - [Creating Custom Sources](CREATING_SOURCES.md) -- [GameSession API Reference](API_REFERENCE.md) -- [Performance Tuning Guide](PERFORMANCE.md) +- GameSession API Reference (coming soon) +- Performance Tuning Guide (coming soon)