Fix incorrect UID NEXT when mailbox is empty (#1201)
This commit is contained in:
@@ -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 {
|
||||
|
||||
@@ -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()),
|
||||
})
|
||||
Status::UidNext => self
|
||||
.get_uid_next(&mailbox)
|
||||
.await
|
||||
.caused_by(trc::location!())?
|
||||
+ 1) as u64
|
||||
}
|
||||
.caused_by(trc::location!())? as u64,
|
||||
Status::UidValidity => self
|
||||
.server
|
||||
.get_property::<Object<Value>>(
|
||||
|
||||
Reference in New Issue
Block a user