Fix incorrect UID NEXT when mailbox is empty (#1201)

This commit is contained in:
mdecimus
2025-02-28 11:31:42 +01:00
parent 7e9a793cb6
commit d1f18d5fe8
2 changed files with 33 additions and 28 deletions

View File

@@ -7,14 +7,17 @@
use std::{collections::BTreeMap, sync::Arc};
use ahash::AHashMap;
use common::{listener::SessionStream, NextMailboxState};
use common::{NextMailboxState, listener::SessionStream};
use email::mailbox::UidMailbox;
use imap_proto::protocol::{expunge, select::Exists, Sequence};
use imap_proto::protocol::{Sequence, expunge, select::Exists};
use jmap_proto::{
object::Object,
types::{collection::Collection, property::Property, value::Value},
};
use store::write::assert::HashedValue;
use store::{
ValueKey,
write::{ValueClass, assert::HashedValue},
};
use trc::AddContext;
use crate::core::ImapId;
@@ -37,8 +40,9 @@ impl<T: SessionStream> SessionData<T> {
.await?
.unwrap_or_default();
// Obtain UID validity
// Obtain UID validity and UID next
let uid_validity = self.get_uid_validity(mailbox).await?;
let uid_next = self.get_uid_next(mailbox).await?;
// Obtain current state
let modseq = self
@@ -104,7 +108,7 @@ impl<T: SessionStream> SessionData<T> {
}
let mut state = MailboxState {
uid_next: uid_max + 1,
uid_next,
uid_validity,
total_messages: id_to_imap.len(),
id_to_imap,
@@ -245,6 +249,21 @@ impl<T: SessionStream> SessionData<T> {
})
.map(|v| v as u32)
}
pub async fn get_uid_next(&self, mailbox: &MailboxId) -> trc::Result<u32> {
self.server
.core
.storage
.data
.get_counter(ValueKey {
account_id: mailbox.account_id,
collection: Collection::Mailbox.into(),
document_id: mailbox.mailbox_id,
class: ValueClass::Property(Property::EmailIds.into()),
})
.await
.map(|v| (v + 1) as u32)
}
}
impl SelectedMailbox {

View File

@@ -11,24 +11,22 @@ use crate::{
op::ImapContext,
spawn_op,
};
use common::{listener::SessionStream, Mailbox};
use common::{Mailbox, listener::SessionStream};
use directory::Permission;
use imap_proto::{
Command, ResponseCode, StatusResponse,
parser::PushUnique,
protocol::status::{Status, StatusItem, StatusItemType},
receiver::Request,
Command, ResponseCode, StatusResponse,
};
use jmap_proto::{
object::Object,
types::{collection::Collection, id::Id, keyword::Keyword, property::Property, value::Value},
};
use store::{
roaring::RoaringBitmap,
write::{key::DeserializeBigEndian, ValueClass},
IndexKeyPrefix, IterateParams, ValueKey,
};
use store::{Deserialize, U32_LEN};
use store::{
IndexKeyPrefix, IterateParams, roaring::RoaringBitmap, write::key::DeserializeBigEndian,
};
use trc::AddContext;
use super::ToModSeq;
@@ -251,22 +249,10 @@ impl<T: SessionStream> SessionData<T> {
for item in items_update {
let result = match item {
Status::Messages => mailbox_message_ids.as_ref().map(|v| v.len()).unwrap_or(0),
Status::UidNext => {
(self
.server
.core
.storage
.data
.get_counter(ValueKey {
account_id: mailbox.account_id,
collection: Collection::Mailbox.into(),
document_id: mailbox.mailbox_id,
class: ValueClass::Property(Property::EmailIds.into()),
})
.await
.caused_by(trc::location!())?
+ 1) as u64
}
Status::UidNext => self
.get_uid_next(&mailbox)
.await
.caused_by(trc::location!())? as u64,
Status::UidValidity => self
.server
.get_property::<Object<Value>>(