Import upstream v0.16.22, stripped
Upstream commit: 474dd0229cb20cf513036619781ed97bd8073c3f Enterprise-only files removed or emptied: 63 Enterprise-only snippets removed: 117 in 50 files Dangling module declarations removed: 5 Cargo edits turning enterprise off: 14 Verification: clean Enterprise feature gates left for rebuilt features: 19 in 18 files Produced by tools/fork/strip.py. The full report is in docs/fork/strip-reports/ on main.
This commit is contained in:
@@ -0,0 +1,198 @@
|
||||
/*
|
||||
* SPDX-FileCopyrightText: 2020 Stalwart Labs LLC <[email protected]>
|
||||
*
|
||||
* SPDX-License-Identifier: AGPL-3.0-only OR LicenseRef-SEL
|
||||
*/
|
||||
|
||||
use crate::{Server, ipc::PushNotification};
|
||||
use std::time::Duration;
|
||||
use store::{
|
||||
IterateParams, Key, LogKey, SUBSPACE_LOGS, U64_LEN,
|
||||
write::{AnyClass, AssignedIds, BatchBuilder, ValueClass, key::DeserializeBigEndian},
|
||||
};
|
||||
use trc::AddContext;
|
||||
use types::{
|
||||
collection::SyncCollection,
|
||||
type_state::{DataType, StateChange},
|
||||
};
|
||||
use utils::{map::bitmap::Bitmap, snowflake::SnowflakeIdGenerator};
|
||||
|
||||
impl Server {
|
||||
pub async fn commit_batch(&self, mut builder: BatchBuilder) -> trc::Result<AssignedIds> {
|
||||
let mut assigned_ids = AssignedIds::default();
|
||||
let mut commit_points = builder.commit_points();
|
||||
|
||||
for commit_point in commit_points.iter() {
|
||||
let batch = builder.build_one(commit_point);
|
||||
assigned_ids
|
||||
.ids
|
||||
.extend(self.store().write(batch).await?.ids);
|
||||
}
|
||||
|
||||
if let Some(changes) = builder.changes() {
|
||||
for (account_id, changed_collections) in changes {
|
||||
let mut state_change = StateChange::new(account_id);
|
||||
for changed_collection in changed_collections.changed_containers {
|
||||
if let Some(data_type) = DataType::try_from_sync(changed_collection, true) {
|
||||
state_change.set_change(data_type);
|
||||
}
|
||||
}
|
||||
for changed_collection in changed_collections.changed_items {
|
||||
if let Some(data_type) = DataType::try_from_sync(changed_collection, false) {
|
||||
state_change.set_change(data_type);
|
||||
}
|
||||
}
|
||||
if state_change.has_changes() {
|
||||
self.broadcast_push_notification(PushNotification::StateChange(
|
||||
state_change.with_change_id(assigned_ids.last_change_id(account_id)?),
|
||||
))
|
||||
.await;
|
||||
}
|
||||
if let Some(change_id) = changed_collections.share_notification_id {
|
||||
self.broadcast_push_notification(PushNotification::StateChange(StateChange {
|
||||
account_id,
|
||||
change_id,
|
||||
types: Bitmap::from_iter([DataType::ShareNotification]),
|
||||
}))
|
||||
.await;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Ok(assigned_ids)
|
||||
}
|
||||
|
||||
pub async fn delete_changes(
|
||||
&self,
|
||||
account_id: u32,
|
||||
max_entries: Option<usize>,
|
||||
max_duration: Option<Duration>,
|
||||
) -> trc::Result<()> {
|
||||
if let Some(max_entries) = max_entries {
|
||||
for sync_collection in [
|
||||
SyncCollection::Email,
|
||||
SyncCollection::Thread,
|
||||
SyncCollection::Identity,
|
||||
SyncCollection::EmailSubmission,
|
||||
SyncCollection::SieveScript,
|
||||
SyncCollection::FileNode,
|
||||
SyncCollection::AddressBook,
|
||||
SyncCollection::Calendar,
|
||||
SyncCollection::CalendarEventNotification,
|
||||
] {
|
||||
let collection = sync_collection.into();
|
||||
let from_key = LogKey {
|
||||
account_id,
|
||||
collection,
|
||||
change_id: 0,
|
||||
};
|
||||
let to_key = LogKey {
|
||||
account_id,
|
||||
collection,
|
||||
change_id: u64::MAX,
|
||||
};
|
||||
|
||||
let mut first_change_id = 0;
|
||||
let mut num_changes = 0;
|
||||
|
||||
self.store()
|
||||
.iterate(
|
||||
IterateParams::new(from_key, to_key)
|
||||
.descending()
|
||||
.no_values(),
|
||||
|key, _| {
|
||||
first_change_id = key.deserialize_be_u64(key.len() - U64_LEN)?;
|
||||
num_changes += 1;
|
||||
|
||||
Ok(num_changes <= max_entries)
|
||||
},
|
||||
)
|
||||
.await
|
||||
.caused_by(trc::location!())?;
|
||||
|
||||
if num_changes > max_entries {
|
||||
self.store()
|
||||
.delete_range(
|
||||
LogKey {
|
||||
account_id,
|
||||
collection,
|
||||
change_id: 0,
|
||||
},
|
||||
LogKey {
|
||||
account_id,
|
||||
collection,
|
||||
change_id: first_change_id,
|
||||
},
|
||||
)
|
||||
.await
|
||||
.caused_by(trc::location!())?;
|
||||
|
||||
// Delete vanished items
|
||||
if let Some(vanished_collection) =
|
||||
sync_collection.vanished_collection().map(u8::from)
|
||||
{
|
||||
self.store()
|
||||
.delete_range(
|
||||
LogKey {
|
||||
account_id,
|
||||
collection: vanished_collection,
|
||||
change_id: 0,
|
||||
},
|
||||
LogKey {
|
||||
account_id,
|
||||
collection: vanished_collection,
|
||||
change_id: first_change_id,
|
||||
},
|
||||
)
|
||||
.await
|
||||
.caused_by(trc::location!())?;
|
||||
}
|
||||
|
||||
// Write truncation entry for cache
|
||||
let mut batch = BatchBuilder::new();
|
||||
batch.with_account_id(account_id).set(
|
||||
ValueClass::Any(AnyClass {
|
||||
subspace: SUBSPACE_LOGS,
|
||||
key: LogKey {
|
||||
account_id,
|
||||
collection,
|
||||
change_id: first_change_id,
|
||||
}
|
||||
.serialize(0),
|
||||
}),
|
||||
Vec::new(),
|
||||
);
|
||||
self.store()
|
||||
.write(batch.build_all())
|
||||
.await
|
||||
.caused_by(trc::location!())?;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if let Some(max_duration) = max_duration {
|
||||
self.store()
|
||||
.delete_range(
|
||||
LogKey {
|
||||
account_id,
|
||||
collection: SyncCollection::ShareNotification.into(),
|
||||
change_id: 0,
|
||||
},
|
||||
LogKey {
|
||||
account_id,
|
||||
collection: SyncCollection::ShareNotification.into(),
|
||||
change_id: SnowflakeIdGenerator::from_duration(max_duration)
|
||||
.unwrap_or_default(),
|
||||
},
|
||||
)
|
||||
.await
|
||||
.caused_by(trc::location!())?;
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
|
||||
#[inline(always)]
|
||||
pub fn generate_snowflake_id(&self) -> u64 {
|
||||
self.inner.data.jmap_id_gen.generate()
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user