Skip to content

Commit e263fad

Browse files
committed
feat: add retry handling for comp stats connection failures
1 parent a439b56 commit e263fad

File tree

2 files changed

+79
-12
lines changed

2 files changed

+79
-12
lines changed

Hearthstone Deck Tracker/Controls/Overlay/Battlegrounds/Session/BattlegroundsSession.xaml

Lines changed: 13 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -190,17 +190,19 @@
190190
Visibility="{Binding CompStatsWaitingMsgVisibility, FallbackValue=Collapsed}"
191191
Margin="0 26 0 26"
192192
/>
193-
<TextBlock
194-
Text="{lex:Loc Battlegrounds_Session_CompStats_ErrorMessage}"
195-
Foreground="#FFFFFF"
196-
Opacity=".5"
197-
TextWrapping="WrapWithOverflow"
198-
TextAlignment="Center"
199-
HorizontalAlignment="Center"
200-
VerticalAlignment="Center"
201-
Visibility="{Binding CompStatsErrorVisibility, FallbackValue=Collapsed}"
202-
Margin="0 26 0 26"
203-
/>
193+
<StackPanel Orientation="Vertical" Visibility="{Binding CompStatsErrorVisibility, FallbackValue=Collapsed}" VerticalAlignment="Center" HorizontalAlignment="Center" Margin="0 16 0 16">
194+
<TextBlock
195+
Text="{lex:Loc Battlegrounds_Session_CompStats_ErrorMessage}"
196+
Foreground="#FFFFFF"
197+
Opacity=".5"
198+
TextWrapping="WrapWithOverflow"
199+
TextAlignment="Center"
200+
HorizontalAlignment="Center"
201+
Margin="4 0 4 8"
202+
/>
203+
<Button Content="Retry" Command="{Binding RetryCompStatsCommand}" Width="64" HorizontalAlignment="Center" Style="{StaticResource Tier7ButtonStyle}" Cursor="Hand" />
204+
<TextBlock Text="{Binding CompStatsDebugInfo}" Visibility="{Binding CompStatsDebugVisibility, FallbackValue=Collapsed}" Foreground="#FFFFFF" Opacity=".6" FontSize="10" TextWrapping="Wrap" Margin="6,6,6,0" />
205+
</StackPanel>
204206
</Grid>
205207
</StackPanel>
206208
</StackPanel>

Hearthstone Deck Tracker/Controls/Overlay/Battlegrounds/Session/BattlegroundsSessionViewModel.xaml.cs

Lines changed: 66 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,17 +20,24 @@
2020
using Hearthstone_Deck_Tracker.Utility.Logging;
2121
using Hearthstone_Deck_Tracker.Utility.MVVM;
2222
using Hearthstone_Deck_Tracker.Utility.RemoteData;
23+
using Hearthstone_Deck_Tracker.Commands;
2324
using HSReplay.Requests;
2425
using HSReplay.Responses;
2526
using Newtonsoft.Json;
2627
using static Hearthstone_Deck_Tracker.Utility.Battlegrounds.BattlegroundsLastGames;
28+
using System.Windows.Input;
2729

2830
namespace Hearthstone_Deck_Tracker.Controls.Overlay.Battlegrounds.Session;
2931

3032
public class BattlegroundsSessionViewModel : ViewModel
3133
{
3234
private readonly BattlegroundsDb _db = BattlegroundsDbSingleton.Instance;
3335

36+
public BattlegroundsSessionViewModel()
37+
{
38+
RetryCompStatsCommand = new Command(async () => await RetryCompStats());
39+
}
40+
3441
public ObservableCollection<Race> AvailableMinionTypes { get; } = new();
3542
public ObservableCollection<Race> BannedMinionTypes { get; } = new();
3643
public ObservableCollection<BattlegroundsGameViewModel> SessionGames { get; } = new();
@@ -50,6 +57,8 @@ public void OnGameEnd()
5057

5158
private readonly SemaphoreSlim _updateCompStatsSemaphore = new SemaphoreSlim(1, 1);
5259

60+
public ICommand RetryCompStatsCommand { get; }
61+
5362

5463
public async void Update()
5564
{
@@ -187,6 +196,20 @@ private void UpdateMinionTypes()
187196

188197
var availableRaces = BattlegroundsUtils.GetAvailableRaces();
189198

199+
// Retry logic: game state may not be ready immediately
200+
if(availableRaces == null)
201+
{
202+
Log.Info("[Tier7CompStats] Available races not ready, retrying after delay...");
203+
await Task.Delay(2000);
204+
availableRaces = BattlegroundsUtils.GetAvailableRaces();
205+
206+
if(availableRaces == null)
207+
{
208+
await Task.Delay(3000);
209+
availableRaces = BattlegroundsUtils.GetAvailableRaces();
210+
}
211+
}
212+
190213
if(availableRaces == null)
191214
throw new CompositionStatsException("Unable to get available races");
192215

@@ -288,18 +311,28 @@ private async Task TrySetCompStats()
288311
catch(Exception e)
289312
{
290313
HandleCompStatsError(e);
314+
return;
291315
}
292316

293317
if(battlegroundsCompStats is BattlegroundsCompStats compStats)
294318
{
295319
var firstPlaceComps = compStats.Data?.FirstPlaceCompsLobbyRaces;
296-
if(firstPlaceComps != null)
320+
if(firstPlaceComps != null && firstPlaceComps.Count > 0)
297321
{
322+
Log.Info($"[Tier7CompStats] Success: received {firstPlaceComps.Count} compositions");
298323
SetBattlegroundsCompositionStatsViewModel(
299324
firstPlaceComps
300325
);
301326
ShowCompositionStats();
302327
}
328+
else
329+
{
330+
Log.Warn($"[Tier7CompStats] API returned null or empty compositions. compStats.Data={compStats.Data}, firstPlaceComps.Count={firstPlaceComps?.Count ?? 0}");
331+
}
332+
}
333+
else
334+
{
335+
Log.Warn($"[Tier7CompStats] Received null from API");
303336
}
304337
}
305338

@@ -315,6 +348,7 @@ public void HideCompStatsOnError()
315348
private void HandleCompStatsError(Exception error)
316349
{
317350
Influx.OnGetBattlegroundsCompositionStatsError(error.GetType().Name, error.Message);
351+
Log.Error($"[Tier7CompStats] error: {error.GetType().Name} - {error.Message}; debug={CompStatsDebugInfo ?? "<none>"}");
318352

319353
var beforeHeroPicked = (Core.Game.GameEntity?.GetTag(GameTag.STEP) ?? 0) <= (int)Step.BEGIN_MULLIGAN;
320354
if(!beforeHeroPicked)
@@ -332,6 +366,23 @@ private void HandleCompStatsError(Exception error)
332366
CompStatsWaitingMsgVisibility = Visibility.Hidden;
333367
}
334368

369+
private async Task RetryCompStats()
370+
{
371+
CompStatsErrorVisibility = Visibility.Hidden;
372+
CompStatsBodyVisibility = Visibility.Hidden;
373+
CompStatsWaitingMsgVisibility = Visibility.Visible;
374+
375+
try
376+
{
377+
await _updateCompStatsSemaphore.WaitAsync();
378+
await TrySetCompStats();
379+
}
380+
finally
381+
{
382+
_updateCompStatsSemaphore.Release();
383+
}
384+
}
385+
335386
private async Task<GameItem?> UpdateLatestGames()
336387
{
337388
var sortedGames = (await Instance.PlayerGames(IsDuos))
@@ -529,6 +580,20 @@ public Visibility CompStatsErrorVisibility
529580
}
530581
}
531582

583+
private string? _compStatsDebugInfo;
584+
public string? CompStatsDebugInfo
585+
{
586+
get => _compStatsDebugInfo;
587+
set
588+
{
589+
_compStatsDebugInfo = value;
590+
OnPropertyChanged();
591+
OnPropertyChanged(nameof(CompStatsDebugVisibility));
592+
}
593+
}
594+
595+
public Visibility CompStatsDebugVisibility => string.IsNullOrWhiteSpace(_compStatsDebugInfo) ? Visibility.Collapsed : Visibility.Visible;
596+
532597
private Visibility _compStatsWaitingMsgVisibility;
533598
public Visibility CompStatsWaitingMsgVisibility
534599
{

0 commit comments

Comments
 (0)