68 lines
2.9 KiB
C#
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;
|
|
}
|
|
}
|
|
} |