Improved outlook online search even more and removed redundant methods from ChangeProcessor (#586)
This commit is contained in:
@@ -40,16 +40,6 @@ public interface IDefaultChangeProcessor
|
||||
Task<bool> MapLocalDraftAsync(Guid accountId, Guid localDraftCopyUniqueId, string newMailCopyId, string newDraftId, string newThreadId);
|
||||
Task UpdateFolderLastSyncDateAsync(Guid folderId);
|
||||
Task UpdateRemoteAliasInformationAsync(MailAccount account, List<RemoteAccountAlias> remoteAccountAliases);
|
||||
|
||||
/// <summary>
|
||||
/// Interrupted initial synchronization may cause downloaded mails to be saved in the database twice.
|
||||
/// Since downloading mime is costly in Outlook, we need to check if the actual copy of the message has been saved before.
|
||||
/// This is also used in online search to prevent duplicate mails.
|
||||
/// </summary>
|
||||
/// <param name="messageId">MailCopyId of the message.</param>
|
||||
/// <returns>Whether mail exists or not.</returns>
|
||||
Task<bool> IsMailExistsAsync(string messageId);
|
||||
|
||||
// Calendar
|
||||
Task<List<AccountCalendar>> GetAccountCalendarsAsync(Guid accountId);
|
||||
|
||||
@@ -60,7 +50,6 @@ public interface IDefaultChangeProcessor
|
||||
Task UpdateAccountCalendarAsync(AccountCalendar accountCalendar);
|
||||
|
||||
Task UpdateCalendarDeltaSynchronizationToken(Guid calendarId, string deltaToken);
|
||||
Task<MailCopy> GetMailCopyAsync(string mailCopyId);
|
||||
Task<List<MailCopy>> GetMailCopiesAsync(IEnumerable<string> mailCopyIds);
|
||||
Task CreateMailRawAsync(MailAccount account, MailItemFolder mailItemFolder, NewMailItemPackage package);
|
||||
Task DeleteUserMailCacheAsync(Guid accountId);
|
||||
@@ -138,15 +127,9 @@ public class DefaultChangeProcessor(IDatabaseService databaseService,
|
||||
public Task ChangeFlagStatusAsync(string mailCopyId, bool isFlagged)
|
||||
=> MailService.ChangeFlagStatusAsync(mailCopyId, isFlagged);
|
||||
|
||||
public Task<bool> IsMailExistsAsync(string messageId)
|
||||
=> MailService.IsMailExistsAsync(messageId);
|
||||
|
||||
public Task<List<string>> AreMailsExistsAsync(IEnumerable<string> mailCopyIds)
|
||||
=> MailService.AreMailsExistsAsync(mailCopyIds);
|
||||
|
||||
public Task<MailCopy> GetMailCopyAsync(string mailCopyId)
|
||||
=> MailService.GetSingleMailItemAsync(mailCopyId);
|
||||
|
||||
public Task<List<MailCopy>> GetMailCopiesAsync(IEnumerable<string> mailCopyIds)
|
||||
=> MailService.GetMailItemsAsync(mailCopyIds);
|
||||
|
||||
|
||||
@@ -967,12 +967,10 @@ public class OutlookSynchronizer : WinoSynchronizer<RequestInformation, Message,
|
||||
|
||||
public override async Task<List<MailCopy>> OnlineSearchAsync(string queryText, List<IMailItemFolder> folders, CancellationToken cancellationToken = default)
|
||||
{
|
||||
bool isFoldersIncluded = folders?.Any() ?? false;
|
||||
|
||||
var messagesToDownload = new List<Message>();
|
||||
List<Message> messagesReturnedByApi = [];
|
||||
|
||||
// Perform search for each folder separately.
|
||||
if (isFoldersIncluded)
|
||||
if (folders?.Count > 0)
|
||||
{
|
||||
var folderIds = folders.Select(a => a.RemoteFolderId);
|
||||
|
||||
@@ -990,9 +988,9 @@ public class OutlookSynchronizer : WinoSynchronizer<RequestInformation, Message,
|
||||
|
||||
if (result?.Value != null)
|
||||
{
|
||||
lock (messagesToDownload)
|
||||
lock (messagesReturnedByApi)
|
||||
{
|
||||
messagesToDownload.AddRange(result.Value);
|
||||
messagesReturnedByApi.AddRange(result.Value);
|
||||
}
|
||||
}
|
||||
});
|
||||
@@ -1008,59 +1006,60 @@ public class OutlookSynchronizer : WinoSynchronizer<RequestInformation, Message,
|
||||
requestConfig.QueryParameters.Search = $"\"{queryText}\"";
|
||||
requestConfig.QueryParameters.Select = ["Id, ParentFolderId"];
|
||||
requestConfig.QueryParameters.Top = 1000;
|
||||
});
|
||||
}, cancellationToken);
|
||||
|
||||
var result = await mailQuery;
|
||||
|
||||
if (result?.Value != null)
|
||||
{
|
||||
lock (messagesToDownload)
|
||||
{
|
||||
messagesToDownload.AddRange(result.Value);
|
||||
}
|
||||
messagesReturnedByApi.AddRange(result.Value);
|
||||
}
|
||||
}
|
||||
|
||||
// Do not download messages that exists, but return them for listing.
|
||||
if (messagesReturnedByApi.Count == 0) return [];
|
||||
|
||||
var localFolders = await _outlookChangeProcessor.GetLocalFoldersAsync(Account.Id).ConfigureAwait(false);
|
||||
var localFolders = (await _outlookChangeProcessor.GetLocalFoldersAsync(Account.Id).ConfigureAwait(false))
|
||||
.ToDictionary(x => x.RemoteFolderId);
|
||||
|
||||
var existingMessageIds = new List<string>();
|
||||
var messagesDictionary = messagesReturnedByApi.ToDictionary(a => a.Id);
|
||||
|
||||
//Download missing messages.
|
||||
foreach (var message in messagesToDownload)
|
||||
// Contains a list of message ids that potentially can be downloaded.
|
||||
List<string> messageIdsWithKnownFolder = [];
|
||||
|
||||
// Validate that all messages are in a known folder.
|
||||
foreach (var message in messagesReturnedByApi)
|
||||
{
|
||||
var messageId = message.Id;
|
||||
var parentFolderId = message.ParentFolderId;
|
||||
|
||||
if (!localFolders.Any(a => a.RemoteFolderId == parentFolderId))
|
||||
if (!localFolders.ContainsKey(message.ParentFolderId))
|
||||
{
|
||||
Log.Warning($"Search result returned a message from a folder that is not synchronized.");
|
||||
Log.Warning("Search result returned a message from a folder that is not synchronized.");
|
||||
continue;
|
||||
}
|
||||
|
||||
existingMessageIds.Add(messageId);
|
||||
messageIdsWithKnownFolder.Add(message.Id);
|
||||
}
|
||||
|
||||
var exists = await _outlookChangeProcessor.IsMailExistsAsync(messageId).ConfigureAwait(false);
|
||||
var locallyExistingMails = await _outlookChangeProcessor.AreMailsExistsAsync(messageIdsWithKnownFolder).ConfigureAwait(false);
|
||||
|
||||
if (!exists)
|
||||
{
|
||||
// Check if folder exists. We can't download a mail without existing folder.
|
||||
// Find messages that are not downloaded yet.
|
||||
List<Message> messagesToDownload = [];
|
||||
foreach (var id in messagesDictionary.Keys.Except(locallyExistingMails))
|
||||
{
|
||||
messagesToDownload.Add(messagesDictionary[id]);
|
||||
}
|
||||
|
||||
var localFolder = localFolders.Find(a => a.RemoteFolderId == parentFolderId);
|
||||
|
||||
await DownloadSearchResultMessageAsync(messageId, localFolder, cancellationToken).ConfigureAwait(false);
|
||||
}
|
||||
foreach (var message in messagesToDownload)
|
||||
{
|
||||
await DownloadSearchResultMessageAsync(message.Id, localFolders[message.ParentFolderId], cancellationToken).ConfigureAwait(false);
|
||||
}
|
||||
|
||||
// Get results from database and return.
|
||||
return await _outlookChangeProcessor.GetMailCopiesAsync(existingMessageIds);
|
||||
return await _outlookChangeProcessor.GetMailCopiesAsync(messageIdsWithKnownFolder).ConfigureAwait(false);
|
||||
}
|
||||
|
||||
private async Task<MimeMessage> DownloadMimeMessageAsync(string messageId, CancellationToken cancellationToken = default)
|
||||
{
|
||||
var mimeContentStream = await _graphClient.Me.Messages[messageId].Content.GetAsync(null, cancellationToken).ConfigureAwait(false);
|
||||
return await MimeMessage.LoadAsync(mimeContentStream).ConfigureAwait(false);
|
||||
return await MimeMessage.LoadAsync(mimeContentStream, cancellationToken).ConfigureAwait(false);
|
||||
}
|
||||
|
||||
public override async Task<List<NewMailItemPackage>> CreateNewMailPackagesAsync(Message message, MailItemFolder assignedFolder, CancellationToken cancellationToken = default)
|
||||
|
||||
Reference in New Issue
Block a user