Fixing single threads for API threading strategy.

This commit is contained in:
Burak Kaan Köse
2024-08-29 23:43:49 +02:00
parent 3016f70349
commit 8db34289a7
5 changed files with 47 additions and 10 deletions

View File

@@ -1,6 +1,7 @@
using System.Collections.Generic; using System.Collections.Generic;
using System.Threading.Tasks; using System.Threading.Tasks;
using Wino.Core.Domain.Entities; using Wino.Core.Domain.Entities;
using Wino.Core.Domain.Models.Folders;
using Wino.Core.Domain.Models.MailItem; using Wino.Core.Domain.Models.MailItem;
namespace Wino.Core.Domain.Interfaces namespace Wino.Core.Domain.Interfaces
@@ -12,7 +13,7 @@ namespace Wino.Core.Domain.Interfaces
/// </summary> /// </summary>
/// <param name="items">Original mails.</param> /// <param name="items">Original mails.</param>
/// <returns>Original mails with thread mails.</returns> /// <returns>Original mails with thread mails.</returns>
Task<List<IMailItem>> ThreadItemsAsync(List<MailCopy> items); Task<List<IMailItem>> ThreadItemsAsync(List<MailCopy> items, IMailItemFolder threadingForFolder);
bool ShouldThreadWithItem(IMailItem originalItem, IMailItem targetItem); bool ShouldThreadWithItem(IMailItem originalItem, IMailItem targetItem);
} }
} }

View File

@@ -14,19 +14,19 @@ namespace Wino.Core.Domain.Models.MailItem
public IMailItem LatestMailItem => ThreadItems.LastOrDefault(); public IMailItem LatestMailItem => ThreadItems.LastOrDefault();
public IMailItem FirstMailItem => ThreadItems.FirstOrDefault(); public IMailItem FirstMailItem => ThreadItems.FirstOrDefault();
public void AddThreadItem(IMailItem item) public bool AddThreadItem(IMailItem item)
{ {
if (item == null) return; if (item == null) return false;
if (ThreadItems.Any(a => a.Id == item.Id)) if (ThreadItems.Any(a => a.Id == item.Id))
{ {
return; return false;
} }
if (item != null && item.IsDraft) if (item != null && item.IsDraft)
{ {
ThreadItems.Insert(0, item); ThreadItems.Insert(0, item);
return; return true;
} }
var insertItem = ThreadItems.FirstOrDefault(a => !a.IsDraft && a.CreationDate < item.CreationDate); var insertItem = ThreadItems.FirstOrDefault(a => !a.IsDraft && a.CreationDate < item.CreationDate);
@@ -39,6 +39,8 @@ namespace Wino.Core.Domain.Models.MailItem
ThreadItems.Insert(index, item); ThreadItems.Insert(index, item);
} }
return true;
} }
public IEnumerable<Guid> GetContainingIds() => ThreadItems?.Select(a => a.UniqueId) ?? default; public IEnumerable<Guid> GetContainingIds() => ThreadItems?.Select(a => a.UniqueId) ?? default;

View File

@@ -5,6 +5,7 @@ using System.Threading.Tasks;
using Wino.Core.Domain.Entities; using Wino.Core.Domain.Entities;
using Wino.Core.Domain.Enums; using Wino.Core.Domain.Enums;
using Wino.Core.Domain.Interfaces; using Wino.Core.Domain.Interfaces;
using Wino.Core.Domain.Models.Folders;
using Wino.Core.Domain.Models.MailItem; using Wino.Core.Domain.Models.MailItem;
using Wino.Core.Services; using Wino.Core.Services;
@@ -27,7 +28,7 @@ namespace Wino.Core.Integration.Threading
} }
///<inheritdoc/> ///<inheritdoc/>
public async Task<List<IMailItem>> ThreadItemsAsync(List<MailCopy> items) public async Task<List<IMailItem>> ThreadItemsAsync(List<MailCopy> items, IMailItemFolder threadingForFolder)
{ {
var assignedAccount = items[0].AssignedAccount; var assignedAccount = items[0].AssignedAccount;
@@ -62,11 +63,43 @@ namespace Wino.Core.Integration.Threading
} }
var thread = new ThreadMailItem(); var thread = new ThreadMailItem();
foreach (var childThreadItem in threadItem) foreach (var childThreadItem in threadItem)
{ {
thread.AddThreadItem(childThreadItem); if (thread.ThreadItems.Any(a => a.Id == childThreadItem.Id))
{
// Mail already exist in the thread.
// There should be only 1 instance of the mail in the thread.
// Make sure we add the correct one.
// Add the one with threading folder.
var threadingFolderItem = threadItem.FirstOrDefault(a => a.Id == childThreadItem.Id && a.FolderId == threadingForFolder.Id);
if (threadingFolderItem == null) continue;
// Remove the existing one.
thread.ThreadItems.Remove(thread.ThreadItems.First(a => a.Id == childThreadItem.Id));
// Add the correct one for listing.
thread.AddThreadItem(threadingFolderItem);
}
else
{
thread.AddThreadItem(childThreadItem);
}
}
if (thread.ThreadItems.Count > 1)
{
resultList.Add(thread);
}
else
{
// Don't make threads if the thread has only one item.
// Gmail has may have multiple assignments for the same item.
resultList.Add(thread.ThreadItems.First());
} }
resultList.Add(thread);
} }
} }

View File

@@ -5,6 +5,7 @@ using System.Threading.Tasks;
using SqlKata; using SqlKata;
using Wino.Core.Domain.Entities; using Wino.Core.Domain.Entities;
using Wino.Core.Domain.Interfaces; using Wino.Core.Domain.Interfaces;
using Wino.Core.Domain.Models.Folders;
using Wino.Core.Domain.Models.MailItem; using Wino.Core.Domain.Models.MailItem;
using Wino.Core.Extensions; using Wino.Core.Extensions;
using Wino.Core.Services; using Wino.Core.Services;
@@ -58,7 +59,7 @@ namespace Wino.Core.Integration.Threading
return _databaseService.Connection.FindWithQueryAsync<MailCopy>(query.GetRawQuery()); return _databaseService.Connection.FindWithQueryAsync<MailCopy>(query.GetRawQuery());
} }
public async Task<List<IMailItem>> ThreadItemsAsync(List<MailCopy> items) public async Task<List<IMailItem>> ThreadItemsAsync(List<MailCopy> items, IMailItemFolder threadingForFolder)
{ {
var threads = new List<ThreadMailItem>(); var threads = new List<ThreadMailItem>();

View File

@@ -241,7 +241,7 @@ namespace Wino.Core.Services
// Only thread items from Draft and Sent folders must present here. // Only thread items from Draft and Sent folders must present here.
// Otherwise this strategy will fetch the items that are in Deleted folder as well. // Otherwise this strategy will fetch the items that are in Deleted folder as well.
var accountThreadedItems = await threadingStrategy.ThreadItemsAsync([.. group]); var accountThreadedItems = await threadingStrategy.ThreadItemsAsync([.. group], options.Folders.First());
// Populate threaded items with folder and account assignments. // Populate threaded items with folder and account assignments.
// Almost everything already should be in cache from initial population. // Almost everything already should be in cache from initial population.