Files
Wino-Mail/Wino.Core/Synchronizers/Errors/Outlook/DeltaTokenExpiredHandler.cs
T

68 lines
2.9 KiB
C#

using System.Threading.Tasks;
using Microsoft.Graph.Models.ODataErrors;
using Microsoft.Kiota.Abstractions;
using Serilog;
using Wino.Core.Domain.Interfaces;
using Wino.Core.Domain.Models.Synchronization;
using Wino.Core.Integration.Processors;
namespace Wino.Core.Synchronizers.Errors.Outlook;
/// <summary>
/// Handles 410 Gone errors for Outlook synchronization, which indicates that delta tokens have expired.
/// When this occurs, all local mail cache should be deleted and initial synchronization should be reset.
/// </summary>
public class DeltaTokenExpiredHandler : ISynchronizerErrorHandler
{
private readonly ILogger _logger = Log.ForContext<DeltaTokenExpiredHandler>();
private readonly IOutlookChangeProcessor _outlookChangeProcessor;
public DeltaTokenExpiredHandler(IOutlookChangeProcessor outlookChangeProcessor)
{
_outlookChangeProcessor = outlookChangeProcessor;
}
public bool CanHandle(SynchronizerErrorContext error)
{
// Handle 410 Gone responses which indicate delta token expiration
return error.ErrorCode == 410 ||
(error.Exception is ODataError oDataError && oDataError.ResponseStatusCode == 410) ||
(error.Exception is ApiException apiException && apiException.ResponseStatusCode == 410);
}
public async Task<bool> HandleAsync(SynchronizerErrorContext error)
{
_logger.Warning("Delta token has expired for account {AccountName} ({AccountId}). Deleting all local mail cache and resetting synchronization.",
error.Account.Name, error.Account.Id);
try
{
// Delete all local mail cache for the account
await _outlookChangeProcessor.DeleteUserMailCacheAsync(error.Account.Id).ConfigureAwait(false);
// Reset the account's delta synchronization identifier
await _outlookChangeProcessor.UpdateAccountDeltaSynchronizationIdentifierAsync(error.Account.Id, string.Empty).ConfigureAwait(false);
// Get all folders for the account and reset their delta tokens
var folders = await _outlookChangeProcessor.GetLocalFoldersAsync(error.Account.Id).ConfigureAwait(false);
foreach (var folder in folders)
{
// Reset folder delta token to force full re-sync (last 30 days)
await _outlookChangeProcessor.UpdateFolderDeltaSynchronizationIdentifierAsync(folder.Id, string.Empty).ConfigureAwait(false);
}
_logger.Information("Successfully reset synchronization state for account {AccountName} ({AccountId}). Next sync will download last 30 days.",
error.Account.Name, error.Account.Id);
return true;
}
catch (System.Exception ex)
{
_logger.Error(ex, "Failed to handle delta token expiration for account {AccountName} ({AccountId})",
error.Account.Name, error.Account.Id);
return false;
}
}
}