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 std::{collections::BTreeMap, sync::Arc};
|
||||||
|
|
||||||
use ahash::AHashMap;
|
use ahash::AHashMap;
|
||||||
use common::{listener::SessionStream, NextMailboxState};
|
use common::{NextMailboxState, listener::SessionStream};
|
||||||
use email::mailbox::UidMailbox;
|
use email::mailbox::UidMailbox;
|
||||||
use imap_proto::protocol::{expunge, select::Exists, Sequence};
|
use imap_proto::protocol::{Sequence, expunge, select::Exists};
|
||||||
use jmap_proto::{
|
use jmap_proto::{
|
||||||
object::Object,
|
object::Object,
|
||||||
types::{collection::Collection, property::Property, value::Value},
|
types::{collection::Collection, property::Property, value::Value},
|
||||||
};
|
};
|
||||||
use store::write::assert::HashedValue;
|
use store::{
|
||||||
|
ValueKey,
|
||||||
|
write::{ValueClass, assert::HashedValue},
|
||||||
|
};
|
||||||
use trc::AddContext;
|
use trc::AddContext;
|
||||||
|
|
||||||
use crate::core::ImapId;
|
use crate::core::ImapId;
|
||||||
@@ -37,8 +40,9 @@ impl<T: SessionStream> SessionData<T> {
|
|||||||
.await?
|
.await?
|
||||||
.unwrap_or_default();
|
.unwrap_or_default();
|
||||||
|
|
||||||
// Obtain UID validity
|
// Obtain UID validity and UID next
|
||||||
let uid_validity = self.get_uid_validity(mailbox).await?;
|
let uid_validity = self.get_uid_validity(mailbox).await?;
|
||||||
|
let uid_next = self.get_uid_next(mailbox).await?;
|
||||||
|
|
||||||
// Obtain current state
|
// Obtain current state
|
||||||
let modseq = self
|
let modseq = self
|
||||||
@@ -104,7 +108,7 @@ impl<T: SessionStream> SessionData<T> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
let mut state = MailboxState {
|
let mut state = MailboxState {
|
||||||
uid_next: uid_max + 1,
|
uid_next,
|
||||||
uid_validity,
|
uid_validity,
|
||||||
total_messages: id_to_imap.len(),
|
total_messages: id_to_imap.len(),
|
||||||
id_to_imap,
|
id_to_imap,
|
||||||
@@ -245,6 +249,21 @@ impl<T: SessionStream> SessionData<T> {
|
|||||||
})
|
})
|
||||||
.map(|v| v as u32)
|
.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 {
|
impl SelectedMailbox {
|
||||||
|
|||||||
@@ -11,24 +11,22 @@ use crate::{
|
|||||||
op::ImapContext,
|
op::ImapContext,
|
||||||
spawn_op,
|
spawn_op,
|
||||||
};
|
};
|
||||||
use common::{listener::SessionStream, Mailbox};
|
use common::{Mailbox, listener::SessionStream};
|
||||||
use directory::Permission;
|
use directory::Permission;
|
||||||
use imap_proto::{
|
use imap_proto::{
|
||||||
|
Command, ResponseCode, StatusResponse,
|
||||||
parser::PushUnique,
|
parser::PushUnique,
|
||||||
protocol::status::{Status, StatusItem, StatusItemType},
|
protocol::status::{Status, StatusItem, StatusItemType},
|
||||||
receiver::Request,
|
receiver::Request,
|
||||||
Command, ResponseCode, StatusResponse,
|
|
||||||
};
|
};
|
||||||
use jmap_proto::{
|
use jmap_proto::{
|
||||||
object::Object,
|
object::Object,
|
||||||
types::{collection::Collection, id::Id, keyword::Keyword, property::Property, value::Value},
|
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::{Deserialize, U32_LEN};
|
||||||
|
use store::{
|
||||||
|
IndexKeyPrefix, IterateParams, roaring::RoaringBitmap, write::key::DeserializeBigEndian,
|
||||||
|
};
|
||||||
use trc::AddContext;
|
use trc::AddContext;
|
||||||
|
|
||||||
use super::ToModSeq;
|
use super::ToModSeq;
|
||||||
@@ -251,22 +249,10 @@ impl<T: SessionStream> SessionData<T> {
|
|||||||
for item in items_update {
|
for item in items_update {
|
||||||
let result = match item {
|
let result = match item {
|
||||||
Status::Messages => mailbox_message_ids.as_ref().map(|v| v.len()).unwrap_or(0),
|
Status::Messages => mailbox_message_ids.as_ref().map(|v| v.len()).unwrap_or(0),
|
||||||
Status::UidNext => {
|
Status::UidNext => self
|
||||||
(self
|
.get_uid_next(&mailbox)
|
||||||
.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
|
.await
|
||||||
.caused_by(trc::location!())?
|
.caused_by(trc::location!())? as u64,
|
||||||
+ 1) as u64
|
|
||||||
}
|
|
||||||
Status::UidValidity => self
|
Status::UidValidity => self
|
||||||
.server
|
.server
|
||||||
.get_property::<Object<Value>>(
|
.get_property::<Object<Value>>(
|
||||||
|
|||||||
Reference in New Issue
Block a user