Skip to content

Commit

Permalink
fix: duplicate uid repair job failing on postgres
Browse files Browse the repository at this point in the history
Signed-off-by: Richard Steinmetz <richard@steinmetz.cloud>
  • Loading branch information
st3iny committed Jul 8, 2024
1 parent d6a55f8 commit 48a149b
Show file tree
Hide file tree
Showing 2 changed files with 56 additions and 19 deletions.
21 changes: 13 additions & 8 deletions lib/Db/MessageMapper.php
Original file line number Diff line number Diff line change
Expand Up @@ -1662,6 +1662,8 @@ public function findMessagesToUnSnooze(int $mailboxId, int $time): array {
* Delete all duplicated cached messages.
* Some messages (with the same mailbox_id and uid) where inserted twice and this method cleans
* up the duplicated rows.
*
* @throws \OCP\DB\Exception
*/
public function deleteDuplicateUids(): void {
$qb = $this->db->getQueryBuilder();
Expand All @@ -1672,14 +1674,7 @@ public function deleteDuplicateUids(): void {
$qb->expr()->eq('t1.uid', 't2.uid', IQueryBuilder::PARAM_INT),
$qb->expr()->neq('t1.id', 't2.id', IQueryBuilder::PARAM_INT),
))
->groupBy('mailbox_id', 'uid')
->executeQuery();
$rows = $result->fetchAll();
$result->closeCursor();

if (empty($rows)) {
return;
}

$deleteQb = $this->db->getQueryBuilder();
$deleteQb->delete($this->getTableName())
Expand All @@ -1701,11 +1696,21 @@ public function deleteDuplicateUids(): void {
),
);

foreach ($rows as $row) {
$handledMailboxIdUidPairs = [];
while ($row = $result->fetch()) {
$pair = $row['mailbox_id'] . ':' . $row['uid'];
if (isset($handledMailboxIdUidPairs[$pair])) {
continue;
}

$deleteQb->setParameter('id', $row['id'], IQueryBuilder::PARAM_INT);
$deleteQb->setParameter('mailbox_id', $row['mailbox_id'], IQueryBuilder::PARAM_INT);
$deleteQb->setParameter('uid', $row['uid'], IQueryBuilder::PARAM_INT);
$deleteQb->executeStatement();

$handledMailboxIdUidPairs[$pair] = true;
}

$result->closeCursor();
}
}
54 changes: 43 additions & 11 deletions tests/Integration/Db/MessageMapperTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,20 @@ protected function setUp(): void {
$delete->executeStatement();
}

private function insertMessage(int $uid, int $mailbox_id): void {
$qb = $this->db->getQueryBuilder();
$insert = $qb->insert($this->mapper->getTableName())
->values([
'uid' => $qb->createNamedParameter($uid, IQueryBuilder::PARAM_INT),
'message_id' => $qb->createNamedParameter('<abc' . $uid . $mailbox_id . '@123.com>'),
'mailbox_id' => $qb->createNamedParameter($mailbox_id, IQueryBuilder::PARAM_INT),
'subject' => $qb->createNamedParameter('TEST'),
'sent_at' => $qb->createNamedParameter(time(), IQueryBuilder::PARAM_INT),
'in_reply_to' => $qb->createNamedParameter('<>')
]);
$insert->executeStatement();
}

public function testResetInReplyTo() : void {
$account = $this->createMock(Account::class);
$account->method('getId')->willReturn(13);
Expand Down Expand Up @@ -177,22 +191,40 @@ public function testDeleteByUid(): void {
$mailbox = new Mailbox();
$mailbox->setId(1);
array_map(function ($i) {
$qb = $this->db->getQueryBuilder();
$insert = $qb->insert($this->mapper->getTableName())
->values([
'uid' => $qb->createNamedParameter($i, IQueryBuilder::PARAM_INT),
'message_id' => $qb->createNamedParameter('<abc' . $i . '@123.com>'),
'mailbox_id' => $qb->createNamedParameter(1, IQueryBuilder::PARAM_INT),
'subject' => $qb->createNamedParameter('TEST'),
'sent_at' => $qb->createNamedParameter(time(), IQueryBuilder::PARAM_INT),
'in_reply_to' => $qb->createNamedParameter('<>')
]);
$insert->executeStatement();
$this->insertMessage($i, 1);
}, range(1, 10));

$this->mapper->deleteByUid($mailbox, 1, 5);

$messages = $this->mapper->findByUids($mailbox, range(1, 10));
self::assertCount(8, $messages);
}

public function testDeleteDuplicateUids(): void {
$mailbox1 = new Mailbox();
$mailbox1->setId(1);
$mailbox2 = new Mailbox();
$mailbox2->setId(2);
$mailbox3 = new Mailbox();
$mailbox3->setId(3);
$this->insertMessage(100, 1);
$this->insertMessage(101, 1);
$this->insertMessage(101, 1);
$this->insertMessage(102, 1);
$this->insertMessage(102, 1);
$this->insertMessage(102, 1);
$this->insertMessage(103, 2);
$this->insertMessage(104, 2);
$this->insertMessage(104, 2);
$this->insertMessage(105, 3);

$this->mapper->deleteDuplicateUids();

self::assertCount(1, $this->mapper->findByUids($mailbox1, [100]));
self::assertCount(1, $this->mapper->findByUids($mailbox1, [101]));
self::assertCount(1, $this->mapper->findByUids($mailbox1, [102]));
self::assertCount(1, $this->mapper->findByUids($mailbox2, [103]));
self::assertCount(1, $this->mapper->findByUids($mailbox2, [104]));
self::assertCount(1, $this->mapper->findByUids($mailbox3, [105]));
}
}

0 comments on commit 48a149b

Please sign in to comment.