Database schema optimization - part 11

This commit is contained in:
mdecimus
2025-11-12 19:09:06 +01:00
parent 3e181ae467
commit 8bbcb999d1
40 changed files with 541 additions and 493 deletions

View File

@@ -72,7 +72,7 @@ pub async fn test(params: &mut JMAPTest) {
.await;
let john_event_id = response.created(0).id().to_string();
tokio::time::sleep(std::time::Duration::from_millis(200)).await;
tokio::time::sleep(std::time::Duration::from_millis(600)).await;
// Verify Jane and Bill received the share notification
let mut jane_event_id = String::new();

View File

@@ -5,7 +5,7 @@
*/
use crate::{
jmap::{ChangeType, IntoJmapSet, JMAPTest, JmapUtils},
jmap::{ChangeType, IntoJmapSet, JMAPTest, JmapUtils, wait_for_index},
webdav::DummyWebDavClient,
};
use ahash::AHashSet;
@@ -336,6 +336,7 @@ pub async fn test(params: &mut JMAPTest) {
}));
// Query tests
wait_for_index(&params.server).await;
assert_eq!(
account
.jmap_query(

View File

@@ -40,7 +40,10 @@ use pop3::Pop3SessionManager;
use reqwest::header;
use serde::{Deserialize, Serialize, de::DeserializeOwned};
use serde_json::{Value, json};
use services::SpawnServices;
use services::{
SpawnServices,
task_manager::{Task, TaskAction},
};
use smtp::{SpawnQueueManager, core::SmtpSessionManager};
use std::{
fmt::{Debug, Display},
@@ -48,7 +51,10 @@ use std::{
sync::Arc,
time::Duration,
};
use store::{IterateParams, SUBSPACE_TASK_QUEUE, Stores, write::AnyKey};
use store::{
IterateParams, SUBSPACE_TASK_QUEUE, Stores, U32_LEN, U64_LEN,
write::{AnyKey, TaskEpoch, key::DeserializeBigEndian},
};
use tokio::sync::watch;
use types::id::Id;
use utils::config::Config;
@@ -71,7 +77,7 @@ async fn jmap_tests() {
/*mail::get::test(&mut params).await;
mail::set::test(&mut params).await;
mail::parse::test(&mut params).await;
mail::parse::test(&mut params).await;*/
mail::query::test(&mut params, delete).await;
mail::search_snippet::test(&mut params).await;
mail::changes::test(&mut params).await;
@@ -95,7 +101,7 @@ async fn jmap_tests() {
auth::limits::test(&mut params).await;
auth::oauth::test(&mut params).await;
auth::quota::test(&mut params).await;
auth::permissions::test(&params).await;*/
auth::permissions::test(&params).await;
contacts::addressbook::test(&mut params).await;
contacts::contact::test(&mut params).await;
@@ -198,7 +204,7 @@ impl Account {
pub async fn wait_for_index(server: &Server) {
let mut count = 0;
loop {
let mut has_index_tasks = false;
let mut has_index_tasks = None;
server
.core
.storage
@@ -211,12 +217,21 @@ pub async fn wait_for_index(server: &Server) {
},
AnyKey {
subspace: SUBSPACE_TASK_QUEUE,
key: vec![u8::MAX, u8::MAX, u8::MAX, u8::MAX],
key: vec![u8::MAX; 16],
},
)
.ascending(),
|_, _| {
has_index_tasks = true;
|key, value| {
has_index_tasks = Some(
Task::<TaskAction>::deserialize(key, value).unwrap_or_else(|_| Task {
due: TaskEpoch::from_inner(
key.deserialize_be_u64(key.len() - U64_LEN).unwrap(),
),
account_id: key.deserialize_be_u32(U64_LEN).unwrap(),
document_id: key.deserialize_be_u32(U64_LEN + U32_LEN + 1).unwrap(),
action: TaskAction::SendImip,
}),
);
Ok(false)
},
@@ -224,10 +239,10 @@ pub async fn wait_for_index(server: &Server) {
.await
.unwrap();
if has_index_tasks {
if let Some(task) = has_index_tasks {
count += 1;
if count % 10 == 0 {
println!("Waiting for pending index tasks...");
println!("Waiting for pending task {:?}...", task);
}
tokio::time::sleep(Duration::from_millis(300)).await;
} else {
@@ -314,6 +329,10 @@ async fn init_jmap_tests(delete_if_exists: bool) -> JMAPTest {
cache,
});
if delete_if_exists {
store.destroy().await;
}
// Parse acceptors
servers.parse_tcp_acceptors(&mut config, inner.clone());
@@ -361,10 +380,6 @@ async fn init_jmap_tests(delete_if_exists: bool) -> JMAPTest {
};
});
if delete_if_exists {
store.destroy().await;
}
// Create tables
let server = inner.build_server();
let mut accounts = AHashMap::new();

View File

@@ -16,6 +16,7 @@ use crate::{
JMAPTest, ManagementApi,
mail::delivery::{AssertResult, SmtpConnection},
server::List,
wait_for_index,
},
};
use common::{
@@ -258,9 +259,7 @@ async fn tracing(params: &mut JMAPTest) {
SearchFilter::Operator {
field: SearchField::Tracing(TracingSearchField::EventType),
op: SearchOperator::Equal,
value: SearchValue::Uint(
EventType::Smtp(SmtpEvent::ConnectionStart).id() as u64
)
value: SearchValue::Uint(EventType::Smtp(SmtpEvent::ConnectionStart).code())
}
]))
.await
@@ -285,11 +284,14 @@ async fn tracing(params: &mut JMAPTest) {
)
.await;
lmtp.quit().await;
tokio::time::sleep(Duration::from_millis(200)).await;
tokio::time::sleep(Duration::from_millis(300)).await;
params.server.notify_task_queue();
wait_for_index(&params.server).await;
// Purge should not delete anything at this point
store
.purge_spans(Duration::from_secs(1), Some(&query))
.purge_spans(Duration::from_secs(2), Some(&query))
.await
.unwrap();
@@ -303,7 +305,7 @@ async fn tracing(params: &mut JMAPTest) {
SearchFilter::Operator {
field: SearchField::Tracing(TracingSearchField::EventType),
op: SearchOperator::Equal,
value: SearchValue::Uint(span_type.id() as u64),
value: SearchValue::Uint(span_type.code()),
},
]))
.await
@@ -332,7 +334,7 @@ async fn tracing(params: &mut JMAPTest) {
.unwrap();
assert_eq!(spans.len(), 2, "keyword: {keyword}");
assert!(spans[0] > spans[1], "keyword: {keyword}");
assert!(spans[0] != spans[1], "keyword: {keyword}");
}
// Purge should delete the span entries
@@ -377,7 +379,7 @@ async fn metrics(params: &mut JMAPTest) {
);
}
async fn undelete(_params: &mut JMAPTest) {
async fn undelete(params: &mut JMAPTest) {
// Authenticate
let mut imap = ImapConnection::connect(b"_x ").await;
imap.authenticate("jdoe@example.com", "12345").await;
@@ -430,6 +432,7 @@ async fn undelete(_params: &mut JMAPTest) {
api.get::<serde_json::Value>("/api/store/purge/account/jdoe@example.com")
.await
.unwrap();
wait_for_index(&params.server).await;
tokio::time::sleep(Duration::from_millis(200)).await;
let deleted = api
.get::<List<DeletedBlob<String, String, String>>>("/api/store/undelete/jdoe@example.com")