Auto sync trigger and cancellation support.

This commit is contained in:
Burak Kaan Köse
2026-02-11 14:50:59 +01:00
parent 96d2efb3f0
commit 96dcdc8e03
4 changed files with 205 additions and 8 deletions
+60 -2
View File
@@ -26,6 +26,7 @@ public class SynchronizationManager : ISynchronizationManager
public static SynchronizationManager Instance => _instance.Value;
private readonly ConcurrentDictionary<Guid, IWinoSynchronizerBase> _synchronizerCache = new();
private readonly ConcurrentDictionary<Guid, CancellationTokenSource> _accountSynchronizationCancellationSources = new();
private readonly SemaphoreSlim _initializationSemaphore = new(1, 1);
private readonly ILogger _logger = Log.ForContext<SynchronizationManager>();
@@ -141,9 +142,14 @@ public class SynchronizationManager : ISynchronizationManager
_logger.Information("Starting mail synchronization for account {AccountId} with type {SyncType}",
options.AccountId, options.Type);
var accountCancellationSource = _accountSynchronizationCancellationSources.GetOrAdd(options.AccountId, _ => new CancellationTokenSource());
using var linkedCancellationTokenSource = CancellationTokenSource.CreateLinkedTokenSource(
cancellationToken,
accountCancellationSource.Token);
try
{
var result = await synchronizer.SynchronizeMailsAsync(options, cancellationToken);
var result = await synchronizer.SynchronizeMailsAsync(options, linkedCancellationTokenSource.Token);
_logger.Information("Mail synchronization completed for account {AccountId} with state {State}",
options.AccountId, result.CompletedState);
@@ -156,6 +162,11 @@ public class SynchronizationManager : ISynchronizationManager
return result;
}
catch (OperationCanceledException)
{
_logger.Information("Mail synchronization canceled for account {AccountId}", options.AccountId);
return MailSynchronizationResult.Canceled;
}
catch (AuthenticationAttentionException authEx)
{
_logger.Warning("Account {AccountId} requires attention due to authentication issues", options.AccountId);
@@ -350,9 +361,14 @@ public class SynchronizationManager : ISynchronizationManager
_logger.Information("Starting calendar synchronization for account {AccountId} with type {SyncType}",
options.AccountId, options.Type);
var accountCancellationSource = _accountSynchronizationCancellationSources.GetOrAdd(options.AccountId, _ => new CancellationTokenSource());
using var linkedCancellationTokenSource = CancellationTokenSource.CreateLinkedTokenSource(
cancellationToken,
accountCancellationSource.Token);
try
{
var result = await synchronizer.SynchronizeCalendarEventsAsync(options, cancellationToken);
var result = await synchronizer.SynchronizeCalendarEventsAsync(options, linkedCancellationTokenSource.Token);
_logger.Information("Calendar synchronization completed for account {AccountId} with state {State}",
options.AccountId, result.CompletedState);
@@ -363,6 +379,11 @@ public class SynchronizationManager : ISynchronizationManager
return result;
}
catch (OperationCanceledException)
{
_logger.Information("Calendar synchronization canceled for account {AccountId}", options.AccountId);
return CalendarSynchronizationResult.Canceled;
}
catch (AuthenticationAttentionException authEx)
{
_logger.Warning("Account {AccountId} requires attention due to authentication issues", options.AccountId);
@@ -491,6 +512,38 @@ public class SynchronizationManager : ISynchronizationManager
}
}
/// <summary>
/// Cancels all in-flight synchronizations for the given account.
/// </summary>
/// <param name="accountId">Account ID to cancel synchronizations for</param>
public Task CancelSynchronizationsAsync(Guid accountId)
{
EnsureInitialized();
if (_accountSynchronizationCancellationSources.TryRemove(accountId, out var cancellationSource))
{
try
{
if (!cancellationSource.IsCancellationRequested)
{
cancellationSource.Cancel();
}
}
catch (ObjectDisposedException)
{
// no-op
}
finally
{
cancellationSource.Dispose();
}
_logger.Information("Canceled ongoing synchronizations for account {AccountId}", accountId);
}
return Task.CompletedTask;
}
/// <summary>
/// Destroys the synchronizer for the given account.
/// </summary>
@@ -498,6 +551,7 @@ public class SynchronizationManager : ISynchronizationManager
public async Task DestroySynchronizerAsync(Guid accountId)
{
EnsureInitialized();
await CancelSynchronizationsAsync(accountId);
if (_synchronizerCache.TryRemove(accountId, out var synchronizer))
{
@@ -506,6 +560,10 @@ public class SynchronizationManager : ISynchronizationManager
await synchronizer.KillSynchronizerAsync();
_logger.Information("Destroyed synchronizer for account {AccountId}", accountId);
}
catch (OperationCanceledException)
{
_logger.Information("Synchronizer destruction canceled for account {AccountId}", accountId);
}
catch (Exception ex)
{
_logger.Error(ex, "Failed to destroy synchronizer for account {AccountId}", accountId);