Automated schema migration

This commit is contained in:
mdecimus
2025-05-16 16:10:21 +02:00
parent 365c87af20
commit 10bb4e5661
40 changed files with 3371 additions and 156 deletions

View File

@@ -8,7 +8,6 @@ pub mod cache;
pub mod identity;
pub mod mailbox;
pub mod message;
pub mod migration;
pub mod push;
pub mod sieve;
pub mod submission;

View File

@@ -4,6 +4,12 @@
* SPDX-License-Identifier: AGPL-3.0-only OR LicenseRef-SEL
*/
use super::{
index::{MAX_ID_LENGTH, MAX_SORT_FIELD_LENGTH, TrimTextValue, VisitText},
ingest::{EmailIngest, IngestedEmail, ThreadResult},
metadata::{MessageData, MessageMetadata},
};
use crate::mailbox::UidMailbox;
use common::{Server, auth::ResourceToken, storage::index::ObjectIndexBuilder};
use jmap_proto::{
error::set::SetError,
@@ -23,14 +29,6 @@ use store::{
};
use trc::AddContext;
use crate::{cache::MessageCacheFetch, mailbox::UidMailbox};
use super::{
index::{MAX_ID_LENGTH, MAX_SORT_FIELD_LENGTH, TrimTextValue, VisitText},
ingest::{EmailIngest, IngestedEmail, ThreadResult},
metadata::{MessageData, MessageMetadata},
};
pub trait EmailCopy: Sync + Send {
#[allow(clippy::too_many_arguments)]
fn copy_message(
@@ -145,10 +143,10 @@ impl EmailCopy for Server {
ThreadResult::Id(thread_id) => (false, thread_id),
ThreadResult::Create => (
true,
self.get_cached_messages(account_id)
self.store()
.assign_document_ids(account_id, Collection::Thread, 1)
.await
.caused_by(trc::location!())?
.assign_thread_id(subject.as_bytes(), message_id.as_bytes()),
.caused_by(trc::location!())?,
),
ThreadResult::Skip => unreachable!(),
};

View File

@@ -330,13 +330,10 @@ impl EmailIngest for Server {
ThreadResult::Id(thread_id) => thread_id,
ThreadResult::Create => {
log_thread_create = true;
self.get_cached_messages(account_id)
self.store()
.assign_document_ids(account_id, Collection::Thread, 1)
.await
.caused_by(trc::location!())?
.assign_thread_id(
subject.as_bytes(),
message_id.as_deref().unwrap_or_default().as_bytes(),
)
}
ThreadResult::Skip => {
// Duplicate message

View File

@@ -24,7 +24,7 @@ use std::{borrow::Cow, collections::VecDeque};
use store::{SERIALIZE_MESSAGE_DATA_V1, SERIALIZE_MESSAGE_METADATA_V1, SerializedVersion};
use utils::BlobHash;
#[derive(rkyv::Serialize, rkyv::Deserialize, rkyv::Archive, Debug)]
#[derive(rkyv::Serialize, rkyv::Deserialize, rkyv::Archive, Debug, Default)]
pub struct MessageData {
pub mailboxes: Vec<UidMailbox>,
pub keywords: Vec<Keyword>,

View File

@@ -1,14 +0,0 @@
use common::Server;
use jmap_proto::types::collection::Collection;
async fn migrate_email(server: &Server, account_id: u32) -> trc::Result<()> {
// Obtain email ids
let document_ids = server
.get_document_ids(account_id, Collection::Email)
.await?
.unwrap_or_default();
//TODO remove tombstones
Ok(())
}

View File

@@ -1 +0,0 @@
pub mod email;

View File

@@ -19,16 +19,17 @@ use common::{
use directory::{Permission, QueryBy};
use jmap_proto::types::{collection::Collection, id::Id, keyword::Keyword, property::Property};
use mail_parser::MessageParser;
use rkyv::util::AlignedVec;
use sieve::{Envelope, Event, Input, Mailbox, Recipient, Sieve};
use std::future::Future;
use std::{borrow::Cow, sync::Arc};
use store::{
Serialize, SerializeInfallible,
Deserialize, Serialize, SerializeInfallible,
ahash::AHashMap,
dispatch::lookup::KeyValue,
query::Filter,
write::{Archiver, BatchBuilder, BlobOp},
write::{
AlignedBytes, Archiver, BatchBuilder, BlobOp, UnversionedArchive, UnversionedArchiver,
},
};
use trc::{AddContext, SieveEvent};
use utils::config::utils::ParseValue;
@@ -636,9 +637,10 @@ impl SieveScriptIngest for Server {
// Obtain the precompiled script
if let Some(script) = script_bytes.get(script_offset..).and_then(|bytes| {
let mut abytes = AlignedVec::<16>::with_capacity(bytes.len());
abytes.extend_from_slice(bytes);
rkyv::from_bytes::<Sieve, rkyv::rancor::Error>(&abytes).ok()
<UnversionedArchive<AlignedBytes> as Deserialize>::deserialize(bytes)
.ok()?
.deserialize::<Sieve>()
.ok()
}) {
Ok(CompiledScript {
script,
@@ -657,9 +659,8 @@ impl SieveScriptIngest for Server {
) {
Ok(sieve) => {
// Store updated compiled sieve script
let compiled_bytes = rkyv::to_bytes::<rkyv::rancor::Error>(&sieve)
.map_err(Into::into)
.caused_by(trc::location!())?;
let sieve = UnversionedArchiver::new(sieve);
let compiled_bytes = sieve.serialize().caused_by(trc::location!())?;
let mut updated_sieve_bytes =
Vec::with_capacity(script_offset + compiled_bytes.len());
updated_sieve_bytes.extend_from_slice(&script_bytes[0..script_offset]);
@@ -700,7 +701,7 @@ impl SieveScriptIngest for Server {
.caused_by(trc::location!())?;
Ok(CompiledScript {
script: sieve,
script: sieve.into_inner(),
name: new_archive.into_inner().name,
hash,
})