Run full UID fetch in background when message_list_limit is set

This commit is contained in:
the-djmaze 2023-12-26 16:45:48 +01:00
parent ef850e37f7
commit 1a75a624cb
4 changed files with 125 additions and 86 deletions

View file

@ -435,6 +435,7 @@ class MailClient
return $aSerializedUids['ThreadsUids']; return $aSerializedUids['ThreadsUids'];
} }
} }
/*
// Idea to fetch all UID's in background // Idea to fetch all UID's in background
else if (!$bBackground) { else if (!$bBackground) {
$this->logWrite('Set MessageListThreadsMap() as background task ("'.$sFolderName.'" / '.$sSearch.')'); $this->logWrite('Set MessageListThreadsMap() as background task ("'.$sFolderName.'" / '.$sSearch.')');
@ -444,6 +445,7 @@ class MailClient
}, [$this, $oMessageCollection, $oCacher]); }, [$this, $oMessageCollection, $oCacher]);
return []; return [];
} }
*/
} }
$this->oImapClient->FolderExamine($sFolderName); $this->oImapClient->FolderExamine($sFolderName);
@ -529,15 +531,17 @@ class MailClient
* @throws \MailSo\Net\Exceptions\* * @throws \MailSo\Net\Exceptions\*
* @throws \MailSo\Imap\Exceptions\* * @throws \MailSo\Imap\Exceptions\*
*/ */
private function GetUids(MessageListParams $oParams, string $sSearch, private function GetUids(MessageListParams $oParams, FolderInformation $oInfo, bool $onlyCache = false) : array
FolderInformation $oInfo, bool $bUseSort = false) : array
{ {
$oCacher = $oParams->oCacher; $oCacher = $oParams->oCacher;
$sFolderName = $oParams->sFolderName; $sFolderName = $oParams->sFolderName;
$bUseSort = $bUseSort && $this->oImapClient->hasCapability('SORT'); $bUseSort = $oParams->bUseSort && $this->oImapClient->hasCapability('SORT');
$sSort = $bUseSort ? $oParams->sSort : ''; $aSortTypes = [];
/* TODO: Validate $sSort if ($bUseSort) {
if ($oParams->sSort) {
/* TODO: Validate $oParams->sSort
* /(REVERSE\s+)?(ARRIVAL|CC|DATE|FROM|SIZE|SUBJECT|TO|DISPLAYFROM|DISPLAYTO)/
ARRIVAL ARRIVAL
Internal date and time of the message. This differs from the Internal date and time of the message. This differs from the
ON criteria in SEARCH, which uses just the internal date. ON criteria in SEARCH, which uses just the internal date.
@ -577,11 +581,25 @@ class MailClient
$this->oImapClient->hasCapability('SORT=DISPLAY') $this->oImapClient->hasCapability('SORT=DISPLAY')
DISPLAYFROM, DISPLAYTO DISPLAYFROM, DISPLAYTO
*/ */
$aSortTypes[] = $oParams->sSort;
}
if (!\str_contains($oParams->sSort, 'DATE')) {
// Always also sort DATE descending when DATE is not defined
$aSortTypes[] = 'REVERSE DATE';
}
}
$oParams->sSort = \implode(' ', $aSortTypes);
$bUseCacheAfterSearch = $oCacher && $oCacher->IsInited(); $bUseCache = $oCacher && $oCacher->IsInited();
$sSearchCriterias = \MailSo\Imap\SearchCriterias::fromString($this->oImapClient, $sFolderName, $sSearch, $oParams->bHideDeleted, $bUseCacheAfterSearch); $sSearchCriterias = \MailSo\Imap\SearchCriterias::fromString(
$this->oImapClient,
$sFolderName,
$oParams->sSearch,
$oParams->bHideDeleted,
$bUseCache
);
// Disable? as there are many cases that change the result // Disable? as there are many cases that change the result
// $bUseCacheAfterSearch = false; // $bUseCache = false;
$bReturnUid = true; $bReturnUid = true;
if ($oParams->oSequenceSet) { if ($oParams->oSequenceSet) {
@ -591,12 +609,11 @@ class MailClient
$sSerializedHash = ''; $sSerializedHash = '';
$sSerializedLog = ''; $sSerializedLog = '';
if ($bUseCacheAfterSearch) { if ($bUseCache) {
$sSerializedHash = 'Get' $sSerializedHash = 'Get'
. ($bReturnUid ? 'UIDS/' : 'IDS/') . ($bReturnUid ? 'UIDS/' : 'IDS/')
. ($bUseSort ? 'S' . $sSort : 'N') . "{$oParams->sSort}/{$this->oImapClient->Hash()}/{$sFolderName}/{$sSearchCriterias}";
. "/{$this->oImapClient->Hash()}/{$sFolderName}/{$sSearchCriterias}"; $sSerializedLog = "\"{$sFolderName}\" / {$oParams->sSort} / {$sSearchCriterias}";
$sSerializedLog = "\"{$sFolderName}\" / {$sSort} / {$sSearchCriterias}";
$sSerialized = $oCacher->Get($sSerializedHash); $sSerialized = $oCacher->Get($sSerializedHash);
if (!empty($sSerialized)) { if (!empty($sSerialized)) {
@ -610,19 +627,14 @@ class MailClient
} }
} }
} }
if ($onlyCache) {
return [];
}
$this->oImapClient->FolderExamine($sFolderName); $this->oImapClient->FolderExamine($sFolderName);
$aResultUids = []; $aResultUids = [];
if ($bUseSort) { if ($bUseSort) {
$aSortTypes = [];
if ($sSort) {
$aSortTypes[] = $sSort;
}
if (false === \strpos($sSort, 'DATE')) {
// Always also sort DATE descending when DATE is not defined
$aSortTypes[] = 'REVERSE DATE';
}
// $this->oImapClient->hasCapability('ESORT') // $this->oImapClient->hasCapability('ESORT')
// $aResultUids = $this->oImapClient->MessageSimpleESort($aSortTypes, $sSearchCriterias)['ALL']; // $aResultUids = $this->oImapClient->MessageSimpleESort($aSortTypes, $sSearchCriterias)['ALL'];
$aResultUids = $this->oImapClient->MessageSimpleSort($aSortTypes, $sSearchCriterias, $bReturnUid); $aResultUids = $this->oImapClient->MessageSimpleSort($aSortTypes, $sSearchCriterias, $bReturnUid);
@ -632,7 +644,7 @@ class MailClient
$aResultUids = $this->oImapClient->MessageSimpleSearch($sSearchCriterias, $bReturnUid); $aResultUids = $this->oImapClient->MessageSimpleSearch($sSearchCriterias, $bReturnUid);
} }
if ($bUseCacheAfterSearch) { if ($bUseCache) {
$oCacher->Set($sSerializedHash, \json_encode(array( $oCacher->Set($sSerializedHash, \json_encode(array(
'FolderHash' => $oInfo->etag, 'FolderHash' => $oInfo->etag,
'Uids' => $aResultUids 'Uids' => $aResultUids
@ -641,6 +653,10 @@ class MailClient
$this->logWrite('Save Serialized '.($bReturnUid?'UIDS':'IDS').' to cache ('.$sSerializedLog.') [count:'.\count($aResultUids).']'); $this->logWrite('Save Serialized '.($bReturnUid?'UIDS':'IDS').' to cache ('.$sSerializedLog.') [count:'.\count($aResultUids).']');
} }
// $oSequenceSet = new SequenceSet($aResultUids, false);
// $oSequenceSet->UID = $bReturnUid;
// return $oSequenceSet;
return $aResultUids; return $aResultUids;
} }
@ -648,7 +664,7 @@ class MailClient
{ {
$oUnseenParams = new MessageListParams; $oUnseenParams = new MessageListParams;
$oUnseenParams->sFolderName = $oParams->sFolderName; $oUnseenParams->sFolderName = $oParams->sFolderName;
// $oUnseenParams->sSearch = $oParams->sSearch; $oUnseenParams->sSearch = 'unseen';
// $oUnseenParams->sSort = $oParams->sSort; // $oUnseenParams->sSort = $oParams->sSort;
$oUnseenParams->oCacher = $oParams->oCacher; $oUnseenParams->oCacher = $oParams->oCacher;
$oUnseenParams->bUseSort = false; // $oParams->bUseSort $oUnseenParams->bUseSort = false; // $oParams->bUseSort
@ -658,7 +674,7 @@ class MailClient
// $oUnseenParams->iLimit = $oParams->iLimit; // $oUnseenParams->iLimit = $oParams->iLimit;
// $oUnseenParams->iPrevUidNext = $oParams->iPrevUidNext; // $oUnseenParams->iPrevUidNext = $oParams->iPrevUidNext;
// $oUnseenParams->iThreadUid = $oParams->iThreadUid; // $oUnseenParams->iThreadUid = $oParams->iThreadUid;
return $this->GetUids($oUnseenParams, 'unseen', $oInfo); return $this->GetUids($oUnseenParams, $oInfo);
} }
/** /**
@ -688,14 +704,13 @@ class MailClient
$oMessageCollection->FolderInfo = $oInfo; $oMessageCollection->FolderInfo = $oInfo;
$oMessageCollection->totalEmails = $oInfo->MESSAGES; $oMessageCollection->totalEmails = $oInfo->MESSAGES;
$bUseThreads = $oParams->bUseThreads && $this->oImapClient->CapabilityValue('THREAD'); $oParams->bUseThreads = $oParams->bUseThreads && $this->oImapClient->CapabilityValue('THREAD');
// && ($this->oImapClient->hasCapability('THREAD=REFS') || $this->oImapClient->hasCapability('THREAD=REFERENCES') || $this->oImapClient->hasCapability('THREAD=ORDEREDSUBJECT')); // && ($this->oImapClient->hasCapability('THREAD=REFS') || $this->oImapClient->hasCapability('THREAD=REFERENCES') || $this->oImapClient->hasCapability('THREAD=ORDEREDSUBJECT'));
if ($oParams->iThreadUid && !$bUseThreads) { if ($oParams->iThreadUid && !$oParams->bUseThreads) {
throw new \InvalidArgumentException('THREAD not supported'); throw new \InvalidArgumentException('THREAD not supported');
} }
if (!$oInfo->MESSAGES) { if (!$oInfo->MESSAGES || $oParams->iOffset > $oInfo->MESSAGES) {
$this->logWrite('No messages in '.$oMessageCollection->FolderName);
return $oMessageCollection; return $oMessageCollection;
} }
@ -705,23 +720,41 @@ class MailClient
); );
} }
$bUseSort = $oParams->bUseSort || $oParams->sSort; $bUseSort = ($oParams->bUseSort || $oParams->sSort) && $this->oImapClient->hasCapability('SORT');
$oParams->bUseSort = $bUseSort;
$oParams->sSearch = $sSearch;
$aAllThreads = []; $aAllThreads = [];
$aUnseenUIDs = []; $aUnseenUIDs = [];
$aUids = []; $aUids = [];
$message_list_limit = $oParams->bIgnoreLimit ? 0 : $this->oImapClient->Settings->message_list_limit; $message_list_limit = $this->oImapClient->Settings->message_list_limit;
if (0 < $message_list_limit && $message_list_limit < $oInfo->MESSAGES) { if (100 > $message_list_limit || $message_list_limit > $oInfo->MESSAGES) {
/* $message_list_limit = 0;
// TODO: Idea to fetch all UID's in background
// Must know what is cached so needs more thought
if ($oParams->oCacher && !$oParams->iOffset && !$oParams->iThreadUid && !\strlen($sSearch)) {
\SnappyMail\Shutdown::add(function($oMailClient, $oParams) {
$oParams->bIgnoreLimit = true;
$oMailClient->MessageList($oParams);
}, [$this, $oParams]);
} }
*/ // Idea to fetch all UID's in background
$oAllParams = clone $oParams;
$oAllParams->sSearch = '';
$oAllParams->oSequenceSet = null;
if ($message_list_limit && $message_list_limit < $oInfo->MESSAGES && !$oParams->iThreadUid
&& $oParams->oCacher && $oParams->oCacher->IsInited()
) {
$aUids = $this->GetUids($oAllParams, $oInfo, true);
if ($aUids) {
$message_list_limit = 0;
$oMessageCollection->Sort = $oAllParams->sSort;
} else {
\SnappyMail\Shutdown::add(function($oMailClient, $oAllParams, $oInfo, $oMessageCollection) {
$oMailClient->GetUids($oAllParams, $oInfo);
if ($oAllParams->bUseThreads) {
$oMessageCollection->FolderInfo->MESSAGES = 0;
$oMailClient->MessageListThreadsMap($oMessageCollection, $oAllParams->oCacher, true);
}
}, [$this, $oAllParams, $oInfo, $oMessageCollection]);
}
}
if ($message_list_limit && $message_list_limit < $oInfo->MESSAGES && !$aUids) {
// if ((0 < $message_list_limit && $message_list_limit < $oInfo->MESSAGES) // if ((0 < $message_list_limit && $message_list_limit < $oInfo->MESSAGES)
// || (!$this->oImapClient->hasCapability('SORT') && !$this->oImapClient->CapabilityValue('THREAD'))) { // || (!$this->oImapClient->hasCapability('SORT') && !$this->oImapClient->CapabilityValue('THREAD'))) {
// Don't use THREAD for speed // Don't use THREAD for speed
@ -729,17 +762,15 @@ class MailClient
$this->logWrite('List optimization (count: '.$oInfo->MESSAGES.', limit:'.$message_list_limit.')'); $this->logWrite('List optimization (count: '.$oInfo->MESSAGES.', limit:'.$message_list_limit.')');
if (\strlen($sSearch)) { if (\strlen($sSearch)) {
// Don't use SORT for speed // Don't use SORT for speed
$aUids = $this->GetUids($oParams, $sSearch, $oInfo/*, $bUseSort*/); $oParams->bUseSort = false;
$aUids = $this->GetUids($oParams, $oInfo);
} else { } else {
$bUseSort = $this->oImapClient->hasCapability('SORT'); if ($bUseSort) {
if (2 > $oInfo->MESSAGES) {
$aRequestIndexes = \array_slice([1], $oParams->iOffset, 1);
} else if ($bUseSort) {
// Attempt to sort REVERSE DATE with a bigger range then $oParams->iLimit // Attempt to sort REVERSE DATE with a bigger range then $oParams->iLimit
$end = \min($oInfo->MESSAGES, \max(1, $oInfo->MESSAGES - $oParams->iOffset + $oParams->iLimit)); $end = \min($oInfo->MESSAGES, \max(1, $oInfo->MESSAGES - $oParams->iOffset + $oParams->iLimit));
$start = \max(1, $end - ($oParams->iLimit * 3) + 1); $start = \max(1, $end - ($oParams->iLimit * 3) + 1);
$oParams->oSequenceSet = new SequenceSet(\range($end, $start), false); $oParams->oSequenceSet = new SequenceSet(\range($end, $start), false);
$aRequestIndexes = $this->GetUids($oParams, '', $oInfo, $bUseSort); $aRequestIndexes = $this->GetUids($oParams, $oInfo);
// Attempt to get the correct $oParams->iLimit slice // Attempt to get the correct $oParams->iLimit slice
$aRequestIndexes = \array_slice($aRequestIndexes, $oParams->iOffset ? $oParams->iLimit : 0, $oParams->iLimit); $aRequestIndexes = \array_slice($aRequestIndexes, $oParams->iOffset ? $oParams->iLimit : 0, $oParams->iLimit);
} else { } else {
@ -750,12 +781,16 @@ class MailClient
} }
$this->MessageListByRequestIndexOrUids($oMessageCollection, new SequenceSet($aRequestIndexes, false)); $this->MessageListByRequestIndexOrUids($oMessageCollection, new SequenceSet($aRequestIndexes, false));
} }
$oMessageCollection->Sort = $oParams->sSort;
} else { } else {
$aUids = ($bUseThreads && $oParams->iThreadUid) if ($oParams->bUseThreads && $oParams->iThreadUid) {
? [$oParams->iThreadUid] $aUids = [$oParams->iThreadUid];
: $this->GetUids($oParams, '', $oInfo, $bUseSort); } else if (!$aUids) {
$aUids = $this->GetUids($oAllParams, $oInfo);
$oMessageCollection->Sort = $oAllParams->sSort;
}
if ($bUseThreads) { if ($oParams->bUseThreads) {
$aAllThreads = $this->MessageListThreadsMap($oMessageCollection, $oParams->oCacher); $aAllThreads = $this->MessageListThreadsMap($oMessageCollection, $oParams->oCacher);
$oMessageCollection->totalThreads = \count($aAllThreads); $oMessageCollection->totalThreads = \count($aAllThreads);
// $iThreadLimit = $this->oImapClient->Settings->thread_limit; // $iThreadLimit = $this->oImapClient->Settings->thread_limit;
@ -784,8 +819,9 @@ class MailClient
} }
if ($aUids && \strlen($sSearch)) { if ($aUids && \strlen($sSearch)) {
$aSearchedUids = $this->GetUids($oParams, $sSearch, $oInfo/*, $bUseSort*/); $oParams->bUseSort = false;
if ($bUseThreads && !$oParams->iThreadUid) { $aSearchedUids = $this->GetUids($oParams, $oInfo);
if ($oParams->bUseThreads && !$oParams->iThreadUid) {
$matchingThreadUids = []; $matchingThreadUids = [];
foreach ($aAllThreads as $aMap) { foreach ($aAllThreads as $aMap) {
if (\array_intersect($aSearchedUids, $aMap)) { if (\array_intersect($aSearchedUids, $aMap)) {

View file

@ -32,6 +32,8 @@ class MessageCollection extends \MailSo\Base\Collection
public string $Search = ''; public string $Search = '';
public string $Sort = '';
public int $ThreadUid = 0; public int $ThreadUid = 0;
// MailSo\Imap\FolderInformation // MailSo\Imap\FolderInformation
@ -57,7 +59,7 @@ class MessageCollection extends \MailSo\Base\Collection
#[\ReturnTypeWillChange] #[\ReturnTypeWillChange]
public function jsonSerialize() public function jsonSerialize()
{ {
return array_merge(parent::jsonSerialize(), array( return \array_merge(parent::jsonSerialize(), array(
'totalEmails' => $this->totalEmails, 'totalEmails' => $this->totalEmails,
'totalThreads' => $this->totalThreads, 'totalThreads' => $this->totalThreads,
'threadUid' => $this->ThreadUid, 'threadUid' => $this->ThreadUid,
@ -66,6 +68,7 @@ class MessageCollection extends \MailSo\Base\Collection
'offset' => $this->Offset, 'offset' => $this->Offset,
'limit' => $this->Limit, 'limit' => $this->Limit,
'search' => $this->Search, 'search' => $this->Search,
'sort' => $this->Sort,
'limited' => $this->Limited, 'limited' => $this->Limited,
'folder' => $this->FolderInfo 'folder' => $this->FolderInfo
)); ));

View file

@ -24,8 +24,7 @@ class MessageListParams
public bool public bool
$bUseSort = true, $bUseSort = true,
$bUseThreads = false, $bUseThreads = false,
$bHideDeleted = true, $bHideDeleted = true;
$bIgnoreLimit = false;
protected int protected int
$iOffset = 0, $iOffset = 0,
@ -61,7 +60,7 @@ class MessageListParams
$this->iLimit, $this->iLimit,
$this->bHideDeleted ? '1' : '0', $this->bHideDeleted ? '1' : '0',
$this->sSearch, $this->sSearch,
$this->bUseSort ? $this->sSort : '', $this->bUseSort ? $this->sSort : '0',
$this->bUseThreads ? $this->iThreadUid : '', $this->bUseThreads ? $this->iThreadUid : '',
$this->iPrevUidNext $this->iPrevUidNext
])); ]));

View file

@ -77,6 +77,7 @@ trait Messages
$oParams->oCacher = $this->Cacher($oAccount); $oParams->oCacher = $this->Cacher($oAccount);
} }
// $oParams->bUseSort = $this->ImapClient->hasCapability('SORT');
$oParams->bUseSort = true; $oParams->bUseSort = true;
$oSettingsLocal = $this->SettingsProvider(true)->Load($oAccount); $oSettingsLocal = $this->SettingsProvider(true)->Load($oAccount);