/* * SPDX-FileCopyrightText: 2020 Stalwart Labs Ltd * * SPDX-License-Identifier: AGPL-3.0-only OR LicenseRef-SEL */ use std::sync::Arc; use common::{Server, Threads}; use jmap_proto::types::{collection::Collection, property::Property}; use std::future::Future; use trc::AddContext; pub trait ThreadCache: Sync + Send { fn get_cached_thread_ids( &self, account_id: u32, message_ids: impl Iterator + Send, ) -> impl Future>> + Send; } impl ThreadCache for Server { async fn get_cached_thread_ids( &self, account_id: u32, message_ids: impl Iterator + Send, ) -> trc::Result> { // Obtain current state let modseq = self .core .storage .data .get_last_change_id(account_id, Collection::Thread) .await .caused_by(trc::location!())?; // Lock the cache let thread_cache = if let Some(thread_cache) = self.inner.cache.threads.get(&account_id).and_then(|t| { if t.modseq.unwrap_or(0) >= modseq.unwrap_or(0) { Some(t) } else { None } }) { thread_cache } else { let thread_cache = Arc::new(Threads { threads: self .get_properties::( account_id, Collection::Email, &(), Property::ThreadId, ) .await? .into_iter() .collect(), modseq, }); self.inner .cache .threads .insert(account_id, thread_cache.clone()); thread_cache }; // Obtain threadIds for matching messages let mut thread_ids = Vec::with_capacity(message_ids.size_hint().0); for document_id in message_ids { if let Some(thread_id) = thread_cache.threads.get(&document_id) { thread_ids.push((document_id, *thread_id)); } } Ok(thread_ids) } }