2020
2121"""
2222
23+ import itertools
2324from collections import OrderedDict
2425from datetime import datetime , timedelta
2526from threading import Semaphore
@@ -173,7 +174,7 @@ def initial_sync_impl(self, crispin_client: "CrispinClient") -> None:
173174 # schedule change_poller to die
174175 change_poller .kill ()
175176
176- def resync_uids_impl (self ) -> None :
177+ def resync_uids_impl (self , chunk_size : int = 1000 ) -> None :
177178 with session_scope (self .namespace_id ) as db_session :
178179 imap_folder_info_entry = (
179180 db_session .query (ImapFolderInfo )
@@ -188,6 +189,7 @@ def resync_uids_impl(self) -> None:
188189 self .folder_name , lambda * args : True
189190 )
190191 uidvalidity = crispin_client .selected_uidvalidity
192+ remote_uidnext = crispin_client .selected_uidnext
191193 if uidvalidity <= imap_folder_info_entry .uidvalidity :
192194 # if the remote UIDVALIDITY is less than or equal to -
193195 # from my (siro) understanding it should not be less than -
@@ -221,8 +223,7 @@ def resync_uids_impl(self) -> None:
221223 "FORCE INDEX (ix_imapuid_account_id_folder_id_msg_uid_desc)" ,
222224 )
223225 )
224-
225- chunk_size = 1000
226+ imap_uids_to_delete = []
226227 for entry in imap_uid_entries .yield_per (chunk_size ):
227228 if entry .message .g_msgid in mapping :
228229 log .debug (
@@ -234,14 +235,22 @@ def resync_uids_impl(self) -> None:
234235 )
235236 entry .msg_uid = mapping [entry .message .g_msgid ]
236237 else :
237- db_session . delete (entry )
238+ imap_uids_to_delete . append (entry . msg_uid )
238239 log .debug (
239240 "UIDVALIDITY from {} to {}" .format ( # noqa: G001
240241 imap_folder_info_entry .uidvalidity , uidvalidity
241242 )
242243 )
244+ for uid_batch in itertools .batched (
245+ imap_uids_to_delete , chunk_size
246+ ):
247+ for uid_to_delete in db_session .query (ImapUid ).filter (
248+ ImapUid .msg_uid .in_ (uid_batch )
249+ ):
250+ db_session .delete (uid_to_delete )
243251 imap_folder_info_entry .uidvalidity = uidvalidity
244252 imap_folder_info_entry .highestmodseq = None
253+ imap_folder_info_entry .uidnext = remote_uidnext
245254 db_session .commit ()
246255
247256 def __deduplicate_message_object_creation ( # type: ignore[no-untyped-def]
@@ -470,15 +479,15 @@ def g_msgids(namespace_id, session, in_): # type: ignore[no-untyped-def] # noq
470479 .filter (Message .namespace_id == namespace_id )
471480 .all ()
472481 )
473- return sorted (g_msgid for g_msgid , in query if g_msgid in in_ )
482+ return sorted (g_msgid for ( g_msgid ,) in query if g_msgid in in_ )
474483 # But in the normal case that in_ only has a few elements, it's way better
475484 # to not fetch a bunch of values from MySQL only to return a few of them.
476485 query = (
477486 session .query (Message .g_msgid )
478487 .filter (Message .namespace_id == namespace_id , Message .g_msgid .in_ (in_ ))
479488 .all ()
480489 )
481- return {g_msgid for g_msgid , in query }
490+ return {g_msgid for ( g_msgid ,) in query }
482491
483492
484493class GmailSyncMonitor (ImapSyncMonitor ):
0 commit comments