Skip to content

Fix fire-and-forget TriggerSyncAsync: log exceptions instead of silently discarding them#177

Open
davidortinau wants to merge 1 commit into
mainfrom
op-fix-sync-fire-and-forget
Open

Fix fire-and-forget TriggerSyncAsync: log exceptions instead of silently discarding them#177
davidortinau wants to merge 1 commit into
mainfrom
op-fix-sync-fire-and-forget

Conversation

@davidortinau

Copy link
Copy Markdown
Owner

Problem

Every repository in src/SentenceStudio.Shared/Data/ called _syncService?.TriggerSyncAsync().ConfigureAwait(false) as fire-and-forget after SaveChangesAsync(). In .NET 5+, unobserved task exceptions are silently discarded — no crash, no log. .ConfigureAwait(false) on a non-awaited Task is also a no-op. If TriggerSyncAsync threw (connection refused, auth failure, serialization error), the error was lost, the write appeared successful to the caller, and data never synced — with zero indication anything went wrong.

Fix

Added a private void TriggerSync() helper to each affected repository that runs the sync in Task.Run and catches/logs any exception via ILogger:

private void TriggerSync()
{
    if (_syncService is null) return;
    _ = Task.Run(async () =>
    {
        try { await _syncService.TriggerSyncAsync(); }
        catch (Exception ex) { _logger.LogError(ex, "Background sync trigger failed"); }
    });
}

Replaced all 29 silent call sites with TriggerSync().

Changes

File Sites replaced
LearningResourceRepository.cs 12
ScenarioRepository.cs 2
SkillProfileRepository.cs 2
StoryRepository.cs 2
StreamHistoryRepository.cs 2
UserActivityRepository.cs 2
UserProfileRepository.cs 3
VocabularyLearningContextRepository.cs 2
VocabularyProgressRepository.cs 2
Total 29

Verification

  • SentenceStudio.Shared builds clean (0 errors)
  • ✅ 452/452 unit tests pass (dotnet test tests/SentenceStudio.UnitTests)

…() helper

Replace all 29 _syncService?.TriggerSyncAsync().ConfigureAwait(false) call
sites across 9 repository files with a private TriggerSync() helper that
runs the sync in Task.Run and catches/logs any exception via ILogger.

Previously, unobserved task exceptions were silently discarded in .NET 5+.
The .ConfigureAwait(false) on a non-awaited Task was also a no-op.

Affected files:
- LearningResourceRepository.cs (12 sites)
- ScenarioRepository.cs (2 sites)
- SkillProfileRepository.cs (2 sites)
- StoryRepository.cs (2 sites)
- StreamHistoryRepository.cs (2 sites)
- UserActivityRepository.cs (2 sites)
- UserProfileRepository.cs (3 sites)
- VocabularyLearningContextRepository.cs (2 sites)
- VocabularyProgressRepository.cs (2 sites)

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant