feat: track cache changes with sequence numbers and tombstones

Signed-off-by: Sebastian Krupinski <krupinski01@gmail.com>
This commit is contained in:
2026-10-07 21:21:14 -04:00
parent c20dde6633
commit eea9b5630a
10 changed files with 511 additions and 46 deletions
+18 -8
View File
@@ -10,6 +10,7 @@ declare(strict_types=1);
namespace KTXM\ProviderImap\Service\Cache;
use KTXM\ProviderImap\Providers\EntityResource;
use KTXM\ProviderImap\Stores\MailboxStore;
use KTXM\ProviderImap\Stores\MessageFileStore;
use KTXM\ProviderImap\Stores\MessageStore;
@@ -26,28 +27,37 @@ class MessageIngestor
public function __construct(
private readonly MessageFileStore $fileStore,
private readonly MessageStore $messageStore,
private readonly MailboxStore $mailboxStore,
) {}
/**
* Cache messages of one mailbox generation.
*
* The content is written before the meta document, so an interruption leaves at
* most an orphaned file, never a meta document without content.
* most an orphaned file, never a meta document without content. Each message is
* stamped with its own change sequence, reserved per mailbox in one step.
*
* @return int[] UIDs that were cached
*/
public function ingest(string $tenantId, string $serviceId, int $uidValidity, EntityResource ...$entities): array
{
$ingested = [];
$byMailbox = [];
foreach ($entities as $entity) {
$mailbox = (string) $entity->collection();
$uid = (int) $entity->identifier();
$byMailbox[(string) $entity->collection()][] = $entity;
}
$this->fileStore->write($tenantId, $serviceId, $mailbox, $uidValidity, $uid, $entity->toCacheContent());
$this->messageStore->upsert($tenantId, $serviceId, $uidValidity, $entity);
$ingested = [];
foreach ($byMailbox as $mailbox => $group) {
$seq = $this->mailboxStore->reserveSequence($serviceId, (string) $mailbox, count($group));
$ingested[] = $uid;
foreach ($group as $entity) {
$uid = (int) $entity->identifier();
$this->fileStore->write($tenantId, $serviceId, (string) $mailbox, $uidValidity, $uid, $entity->toCacheContent());
$this->messageStore->upsert($tenantId, $serviceId, $uidValidity, $entity, $seq++);
$ingested[] = $uid;
}
}
return $ingested;