Add initial mail sync range selection

This commit is contained in:
Burak Kaan Köse
2026-04-14 00:03:48 +02:00
parent 2e36772a4c
commit c622858d2d
21 changed files with 378 additions and 73 deletions
+11 -14
View File
@@ -81,9 +81,8 @@ public class GmailSynchronizer : WinoSynchronizer<IClientServiceRequest, Message
public override uint BatchModificationSize => 1000;
/// <summary>
/// Maximum messages to fetch per folder during initial sync (1500).
/// All messages are downloaded with METADATA ONLY - no raw MIME content.
/// Uses Gmail API's Metadata format which includes headers, labels, and snippet but NOT full message body.
/// Legacy page size hint kept for compatibility with shared synchronizer contracts.
/// Gmail initial sync now downloads all messages inside the selected cutoff window.
/// </summary>
public override uint InitialMessageDownloadCountPerFolder => 1500;
@@ -304,13 +303,18 @@ public class GmailSynchronizer : WinoSynchronizer<IClientServiceRequest, Message
/// <summary>
/// Performs initial synchronization by downloading messages per-folder.
/// Each folder gets up to 1500 messages, but we track already downloaded message IDs globally
/// to avoid downloading the same message multiple times (Gmail messages can have multiple labels).
/// Messages are filtered by the account's configured initial synchronization cutoff date when present,
/// and duplicates are avoided globally because Gmail messages can have multiple labels.
/// </summary>
private async Task<List<string>> PerformInitialSyncAsync(CancellationToken cancellationToken)
{
// Track all downloaded message IDs globally to avoid duplicate downloads
var downloadedMessageIds = new HashSet<string>();
var referenceDateUtc = Account.CreatedAt ?? DateTime.UtcNow;
var initialSynchronizationCutoffDateUtc = Account.InitialSynchronizationRange.ToCutoffDateUtc(referenceDateUtc);
var queryText = initialSynchronizationCutoffDateUtc.HasValue
? $"after:{initialSynchronizationCutoffDateUtc.Value.ToUniversalTime():yyyy/MM/dd}"
: null;
_logger.Information("Performing initial sync for {Name} - downloading messages per folder", Account.Name);
@@ -337,7 +341,6 @@ public class GmailSynchronizer : WinoSynchronizer<IClientServiceRequest, Message
var folderDownloaded = 0;
string pageToken = null;
var remainingToDownload = (int)InitialMessageDownloadCountPerFolder;
do
{
@@ -345,8 +348,9 @@ public class GmailSynchronizer : WinoSynchronizer<IClientServiceRequest, Message
var request = _gmailService.Users.Messages.List("me");
request.LabelIds = new Google.Apis.Util.Repeatable<string>(new[] { folder.RemoteFolderId });
request.MaxResults = Math.Min(remainingToDownload, 500); // API max is 500
request.MaxResults = 500; // API max is 500
request.PageToken = pageToken;
request.Q = queryText;
var response = await request.ExecuteAsync(cancellationToken);
@@ -373,19 +377,12 @@ public class GmailSynchronizer : WinoSynchronizer<IClientServiceRequest, Message
totalMessagesDownloaded += newMessageIds.Count;
}
// Count all messages (including duplicates) toward the folder limit
remainingToDownload -= response.Messages.Count;
_logger.Debug("Folder {FolderName}: Downloaded {New} new messages ({Total} total in folder)",
folder.FolderName, newMessageIds.Count, folderDownloaded);
}
pageToken = response.NextPageToken;
// Stop if we've processed enough messages for this folder or no more pages
if (remainingToDownload <= 0 || string.IsNullOrEmpty(pageToken))
break;
} while (!string.IsNullOrEmpty(pageToken));
_logger.Information("Folder {FolderName}: Downloaded {Count} messages", folder.FolderName, folderDownloaded);