2026-08-25 15:46:39 +03:00
|
|
|
use crate::data::Id;
|
2026-08-26 19:48:22 +03:00
|
|
|
use crate::data::entities::{EntityData, EntityHandle};
|
2026-08-28 16:52:48 +03:00
|
|
|
use crate::helpers::into_result;
|
|
|
|
|
use crate::notification::{MaybeError, NotificationData};
|
2026-08-25 15:46:39 +03:00
|
|
|
use parking_lot::{Mutex, RwLock};
|
2026-08-27 14:51:35 +03:00
|
|
|
use rayon::iter::IndexedParallelIterator;
|
|
|
|
|
use rayon::iter::IntoParallelRefIterator;
|
|
|
|
|
use rayon::iter::ParallelIterator;
|
2026-08-25 15:46:39 +03:00
|
|
|
use rusqlite::Connection;
|
|
|
|
|
use std::marker::PhantomData;
|
2026-08-26 19:48:22 +03:00
|
|
|
use std::ops::Deref;
|
2026-08-25 15:46:39 +03:00
|
|
|
use std::sync::Arc;
|
2026-08-26 17:53:09 +03:00
|
|
|
|
2026-08-26 19:48:22 +03:00
|
|
|
pub trait Repository<T, D>
|
|
|
|
|
where
|
|
|
|
|
D: DbLayer<T>,
|
|
|
|
|
{
|
2026-08-26 17:53:09 +03:00
|
|
|
fn get(&self, handle: &mut EntityHandle<T>) -> Option<T>;
|
|
|
|
|
fn get_ref(&self, handle: &mut EntityHandle<T>) -> Option<&T>;
|
|
|
|
|
fn get_mut(&mut self, handle: &mut EntityHandle<T>) -> Option<&mut T>;
|
|
|
|
|
fn handle_by_id(&self, id: Id) -> EntityHandle<T>;
|
|
|
|
|
fn create(&mut self, new: T) -> EntityHandle<T>;
|
2026-08-30 19:30:43 +03:00
|
|
|
fn create_now(&mut self, new: T) -> Result<EntityHandle<T>, NotificationData>;
|
2026-08-26 17:53:09 +03:00
|
|
|
fn save(&mut self, entity: &mut EntityHandle<T>) -> MaybeError;
|
|
|
|
|
fn delete(&mut self, handle: EntityHandle<T>) -> MaybeError;
|
|
|
|
|
fn init(&mut self) -> MaybeError;
|
|
|
|
|
fn reload(&mut self) -> MaybeError;
|
2026-08-27 14:05:05 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
struct QueryManger<T, R, D>
|
|
|
|
|
where
|
|
|
|
|
R: Repository<T, D>,
|
|
|
|
|
D: DbLayer<T>,
|
|
|
|
|
{
|
2026-08-28 16:52:48 +03:00
|
|
|
queries: Vec<Arc<Mutex<Query<T, R, D>>>>,
|
2026-08-27 14:05:05 +03:00
|
|
|
}
|
|
|
|
|
|
2026-08-28 16:52:48 +03:00
|
|
|
impl<T, R, D> QueryManger<T, R, D>
|
|
|
|
|
where
|
|
|
|
|
R: Repository<T, D>,
|
|
|
|
|
D: DbLayer<T>,
|
|
|
|
|
T: EntityData,
|
|
|
|
|
{
|
|
|
|
|
pub(crate) fn handle_save(&self, old: EntityHandle<T>, new: &mut EntityHandle<T>, data: &T) {
|
2026-08-29 23:10:57 +03:00
|
|
|
return;
|
2026-08-29 22:41:11 +03:00
|
|
|
if old.real() && new.real() {
|
2026-08-28 16:52:48 +03:00
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
let affected = self.get_affected_queries(data);
|
|
|
|
|
for q in affected {
|
|
|
|
|
let mut query = self.queries[q].lock();
|
|
|
|
|
let index = query.cache.binary_search(&old).unwrap();
|
|
|
|
|
query.cache.remove(index);
|
2026-08-29 22:41:11 +03:00
|
|
|
let real_end = query.cache.iter().rposition(|r| r.real()).unwrap() + 1;
|
2026-08-28 16:52:48 +03:00
|
|
|
query.cache.insert(real_end, new.clone());
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
pub(crate) fn handle_delete(&self, handle: &EntityHandle<T>, data: &T) {
|
2026-08-29 23:10:57 +03:00
|
|
|
return;
|
2026-08-28 16:52:48 +03:00
|
|
|
let affected = self.get_affected_queries(data);
|
|
|
|
|
for q in affected {
|
|
|
|
|
let mut query = self.queries[q].lock();
|
|
|
|
|
let slice = query.cache.as_slice();
|
|
|
|
|
if let Ok(index) = slice.binary_search(&handle) {
|
|
|
|
|
query.cache.remove(index);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
fn get_affected_queries(&self, data: &T) -> Vec<usize> {
|
|
|
|
|
self.queries
|
|
|
|
|
.iter()
|
|
|
|
|
.enumerate()
|
|
|
|
|
.filter(|(_, q)| {
|
|
|
|
|
let query = q.lock();
|
|
|
|
|
let rule = &query.rule;
|
|
|
|
|
return rule(data);
|
|
|
|
|
|
|
|
|
|
false
|
|
|
|
|
})
|
|
|
|
|
.map(|(i, _)| i)
|
|
|
|
|
.collect()
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
fn reload_queries(&mut self, data_repository: impl Repository<T, D>) {
|
|
|
|
|
for q in &self.queries {
|
|
|
|
|
let mut query = q.lock();
|
|
|
|
|
query.cache.clear();
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
2026-08-27 14:05:05 +03:00
|
|
|
pub struct Query<T, R, D>
|
|
|
|
|
where
|
2026-08-27 14:51:35 +03:00
|
|
|
R: Repository<T, D>,
|
|
|
|
|
D: DbLayer<T>,
|
2026-08-27 14:05:05 +03:00
|
|
|
{
|
|
|
|
|
cache: Vec<EntityHandle<T>>,
|
2026-08-28 16:52:48 +03:00
|
|
|
rule: Box<dyn Fn(&T) -> bool + Send + Sync>,
|
|
|
|
|
parallel: bool,
|
2026-08-27 14:51:35 +03:00
|
|
|
_marker: PhantomData<(R, D)>,
|
2026-08-30 19:22:28 +03:00
|
|
|
shift_stamp: u16,
|
2026-08-27 14:05:05 +03:00
|
|
|
}
|
|
|
|
|
|
2026-08-28 16:52:48 +03:00
|
|
|
impl<T: EntityData + Clone, R: Repository<T, D>, D: DbLayer<T>> Query<T, R, D> {
|
2026-08-27 14:51:35 +03:00
|
|
|
pub fn iter<'a>(&mut self, data_repository_inner: &'a R) -> impl Iterator<Item = &'a T>
|
|
|
|
|
where
|
|
|
|
|
T: 'a,
|
|
|
|
|
{
|
|
|
|
|
self.cache
|
|
|
|
|
.iter_mut()
|
|
|
|
|
.filter_map(move |e| data_repository_inner.get_ref(e))
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
pub fn for_each_mut<F>(&mut self, repo: &mut R, mut f: F)
|
|
|
|
|
where
|
|
|
|
|
F: FnMut(&mut T),
|
|
|
|
|
{
|
|
|
|
|
for handle in &mut self.cache {
|
|
|
|
|
if let Some(entity) = repo.get_mut(handle) {
|
|
|
|
|
f(entity);
|
|
|
|
|
}
|
|
|
|
|
}
|
2026-08-27 14:05:05 +03:00
|
|
|
}
|
2026-08-28 16:52:48 +03:00
|
|
|
|
2026-08-29 22:41:11 +03:00
|
|
|
pub fn load(&mut self, data_repository: &DataRepositoryInner<T, D>)
|
|
|
|
|
where
|
|
|
|
|
T: Send + Sync,
|
|
|
|
|
{
|
2026-08-28 16:52:48 +03:00
|
|
|
self.cache.clear();
|
|
|
|
|
if self.parallel {
|
2026-08-28 17:15:16 +03:00
|
|
|
self.cache = data_repository
|
2026-08-28 16:52:48 +03:00
|
|
|
.cache
|
|
|
|
|
.par_iter()
|
|
|
|
|
.enumerate()
|
|
|
|
|
.filter(|(_, entity)| (self.rule)(entity))
|
2026-08-29 22:41:11 +03:00
|
|
|
.map(|(i, entity)| EntityHandle::new(entity.id(), i, true))
|
2026-08-28 16:52:48 +03:00
|
|
|
.collect();
|
2026-08-29 22:41:11 +03:00
|
|
|
} else {
|
2026-08-28 17:15:16 +03:00
|
|
|
self.cache = data_repository
|
|
|
|
|
.cache
|
|
|
|
|
.iter()
|
|
|
|
|
.enumerate()
|
|
|
|
|
.filter(|(_, entity)| (self.rule)(entity))
|
2026-08-29 22:41:11 +03:00
|
|
|
.map(|(i, entity)| EntityHandle::new(entity.id(), i, true))
|
2026-08-28 17:15:16 +03:00
|
|
|
.collect();
|
2026-08-28 16:52:48 +03:00
|
|
|
}
|
2026-08-28 17:15:16 +03:00
|
|
|
|
|
|
|
|
self.cache.extend(
|
|
|
|
|
data_repository
|
|
|
|
|
.temporal
|
|
|
|
|
.iter()
|
|
|
|
|
.enumerate()
|
|
|
|
|
.filter(|(_, entity)| (self.rule)(entity))
|
2026-08-29 22:41:11 +03:00
|
|
|
.map(|(i, entity)| EntityHandle::new(entity.id(), i, false))
|
2026-08-28 17:15:16 +03:00
|
|
|
.collect::<Vec<_>>(),
|
|
|
|
|
);
|
2026-08-28 16:52:48 +03:00
|
|
|
}
|
2026-08-26 17:53:09 +03:00
|
|
|
}
|
|
|
|
|
|
2026-08-26 19:48:22 +03:00
|
|
|
pub trait BatchedRepository<T, D>
|
|
|
|
|
where
|
|
|
|
|
D: BatchedDbLayer<T>,
|
|
|
|
|
T: EntityData,
|
2026-08-26 17:53:09 +03:00
|
|
|
{
|
|
|
|
|
fn save_many(&mut self, handles: &mut [EntityHandle<T>]) -> MaybeError;
|
|
|
|
|
fn delete_many(&mut self, handles: &mut [EntityHandle<T>]) -> MaybeError;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
pub trait DbLayer<T> {
|
|
|
|
|
fn write_entity(&self, entity: &T, connection: &Connection) -> MaybeError;
|
|
|
|
|
fn add_entity(&mut self, entity: &mut T, connection: &Connection) -> MaybeError;
|
|
|
|
|
fn delete_entity(&mut self, id: Id, connection: &Connection) -> MaybeError;
|
2026-08-26 19:48:22 +03:00
|
|
|
fn load_all(&self, storage: &mut Vec<T>, connection: &Connection) -> MaybeError;
|
2026-08-26 17:53:09 +03:00
|
|
|
}
|
|
|
|
|
|
2026-08-26 19:48:22 +03:00
|
|
|
pub trait BatchedDbLayer<T>
|
|
|
|
|
where
|
|
|
|
|
T: EntityData,
|
|
|
|
|
{
|
2026-08-30 20:32:16 +03:00
|
|
|
fn delete_many_entities(&mut self, ids: &[Id], connection: &mut Connection) -> MaybeError;
|
|
|
|
|
fn add_many_entities(&mut self, entity: &mut [T], connection: &mut Connection) -> MaybeError;
|
2026-08-26 17:53:09 +03:00
|
|
|
}
|
|
|
|
|
|
2026-08-25 15:46:39 +03:00
|
|
|
#[derive(Clone)]
|
2026-08-27 14:05:05 +03:00
|
|
|
pub struct DataRepository<T: std::clone::Clone + EntityData, D: DbLayer<T>> {
|
2026-08-26 17:53:09 +03:00
|
|
|
inner: Arc<RwLock<DataRepositoryInner<T, D>>>,
|
2026-08-25 15:46:39 +03:00
|
|
|
}
|
|
|
|
|
|
2026-08-27 14:05:05 +03:00
|
|
|
pub struct DataRepositoryInner<T: std::clone::Clone + EntityData, D: DbLayer<T>> {
|
2026-08-26 17:53:09 +03:00
|
|
|
cache: Vec<T>,
|
|
|
|
|
temporal: Vec<T>,
|
2026-08-25 15:46:39 +03:00
|
|
|
next_temporal: u32,
|
2026-08-29 23:10:57 +03:00
|
|
|
connection: Arc<RwLock<Connection>>,
|
2026-08-26 17:53:09 +03:00
|
|
|
data_layer: D,
|
2026-08-27 14:51:35 +03:00
|
|
|
query_manger: QueryManger<T, Self, D>,
|
2026-08-29 23:10:57 +03:00
|
|
|
version: u16,
|
2026-08-29 23:15:22 +03:00
|
|
|
shifts: u16,
|
2026-08-26 17:53:09 +03:00
|
|
|
}
|
|
|
|
|
|
2026-08-27 14:05:05 +03:00
|
|
|
impl<T: std::clone::Clone + EntityData, D: DbLayer<T>> Deref for DataRepository<T, D> {
|
2026-08-26 17:53:09 +03:00
|
|
|
type Target = Arc<RwLock<DataRepositoryInner<T, D>>>;
|
|
|
|
|
|
|
|
|
|
fn deref(&self) -> &Self::Target {
|
|
|
|
|
&self.inner
|
|
|
|
|
}
|
2026-08-25 15:46:39 +03:00
|
|
|
}
|
|
|
|
|
|
2026-08-29 23:10:57 +03:00
|
|
|
impl<T: EntityData + Clone, D: DbLayer<T>> DataRepositoryInner<T, D> {
|
2026-08-27 14:51:35 +03:00
|
|
|
pub fn query_par(
|
|
|
|
|
&self,
|
|
|
|
|
rule: Box<dyn Fn(&T) -> bool + Send + Sync>,
|
|
|
|
|
) -> Query<T, DataRepositoryInner<T, D>, D>
|
|
|
|
|
where
|
|
|
|
|
T: Send + Sync,
|
|
|
|
|
{
|
2026-08-29 23:10:57 +03:00
|
|
|
let mut cache: Vec<EntityHandle<T>> = self
|
2026-08-27 14:51:35 +03:00
|
|
|
.cache
|
|
|
|
|
.par_iter()
|
|
|
|
|
.enumerate()
|
|
|
|
|
.filter(|(_, entity)| rule(entity))
|
2026-08-29 22:41:11 +03:00
|
|
|
.map(|(i, entity)| EntityHandle::new(entity.id(), i, true))
|
2026-08-27 14:51:35 +03:00
|
|
|
.collect();
|
|
|
|
|
|
2026-08-28 16:52:48 +03:00
|
|
|
cache.extend(
|
2026-08-29 23:10:57 +03:00
|
|
|
self.temporal
|
2026-08-28 16:52:48 +03:00
|
|
|
.iter()
|
|
|
|
|
.enumerate()
|
|
|
|
|
.filter(|(_, entity)| rule(entity))
|
2026-08-29 22:41:11 +03:00
|
|
|
.map(|(i, entity)| EntityHandle::new(entity.id(), i, false))
|
2026-08-28 16:52:48 +03:00
|
|
|
.collect::<Vec<_>>(),
|
|
|
|
|
);
|
2026-08-27 14:51:35 +03:00
|
|
|
|
|
|
|
|
Query {
|
|
|
|
|
cache,
|
|
|
|
|
rule,
|
2026-08-28 16:52:48 +03:00
|
|
|
parallel: true,
|
2026-08-27 14:51:35 +03:00
|
|
|
_marker: PhantomData,
|
2026-08-29 23:15:22 +03:00
|
|
|
shift_stamp: self.shifts,
|
2026-08-27 14:51:35 +03:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2026-08-29 22:41:11 +03:00
|
|
|
pub fn query(
|
|
|
|
|
&self,
|
|
|
|
|
rule: Box<dyn Fn(&T) -> bool + Send + Sync>,
|
|
|
|
|
) -> Query<T, DataRepositoryInner<T, D>, D>
|
2026-08-27 14:51:35 +03:00
|
|
|
where
|
|
|
|
|
T: Send + Sync,
|
|
|
|
|
{
|
2026-08-29 23:10:57 +03:00
|
|
|
let mut cache: Vec<EntityHandle<T>> = self
|
2026-08-27 14:51:35 +03:00
|
|
|
.cache
|
|
|
|
|
.iter()
|
|
|
|
|
.enumerate()
|
|
|
|
|
.filter(|(_, entity)| rule(entity))
|
2026-08-29 22:41:11 +03:00
|
|
|
.map(|(i, entity)| EntityHandle::new(entity.id(), i, true))
|
2026-08-27 14:51:35 +03:00
|
|
|
.collect();
|
|
|
|
|
|
2026-08-28 16:52:48 +03:00
|
|
|
cache.extend(
|
2026-08-29 23:10:57 +03:00
|
|
|
self.temporal
|
2026-08-28 16:52:48 +03:00
|
|
|
.iter()
|
|
|
|
|
.enumerate()
|
|
|
|
|
.filter(|(_, entity)| rule(entity))
|
2026-08-29 22:41:11 +03:00
|
|
|
.map(|(i, entity)| EntityHandle::new(entity.id(), i, false))
|
2026-08-28 16:52:48 +03:00
|
|
|
.collect::<Vec<_>>(),
|
|
|
|
|
);
|
2026-08-27 14:51:35 +03:00
|
|
|
|
|
|
|
|
Query {
|
|
|
|
|
cache,
|
|
|
|
|
rule,
|
2026-08-28 16:52:48 +03:00
|
|
|
parallel: false,
|
2026-08-27 14:51:35 +03:00
|
|
|
_marker: PhantomData,
|
2026-08-29 23:15:22 +03:00
|
|
|
shift_stamp: self.shifts,
|
2026-08-27 14:51:35 +03:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2026-08-26 17:53:09 +03:00
|
|
|
impl<T: EntityData + Clone, D: DbLayer<T>> Repository<T, D> for DataRepositoryInner<T, D> {
|
|
|
|
|
fn get(&self, handle: &mut EntityHandle<T>) -> Option<T> {
|
2026-08-29 22:41:11 +03:00
|
|
|
let slice = if handle.real() {
|
2026-08-26 17:53:09 +03:00
|
|
|
self.cache.as_slice()
|
|
|
|
|
} else {
|
|
|
|
|
self.temporal.as_slice()
|
|
|
|
|
};
|
|
|
|
|
let index = fast_position_of(slice, handle)?;
|
|
|
|
|
Some(slice[index].clone())
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
fn get_ref(&self, handle: &mut EntityHandle<T>) -> Option<&T> {
|
2026-08-29 22:41:11 +03:00
|
|
|
let slice = if handle.real() {
|
2026-08-26 17:53:09 +03:00
|
|
|
self.cache.as_slice()
|
|
|
|
|
} else {
|
|
|
|
|
self.temporal.as_slice()
|
|
|
|
|
};
|
|
|
|
|
let index = fast_position_of(slice, handle)?;
|
|
|
|
|
Some(&slice[index])
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
fn get_mut(&mut self, handle: &mut EntityHandle<T>) -> Option<&mut T> {
|
2026-08-29 22:41:11 +03:00
|
|
|
let slice = if handle.real() {
|
2026-08-26 17:53:09 +03:00
|
|
|
self.cache.as_mut_slice()
|
|
|
|
|
} else {
|
|
|
|
|
self.temporal.as_mut_slice()
|
|
|
|
|
};
|
|
|
|
|
let index = fast_position_of(slice, handle)?;
|
|
|
|
|
Some(&mut slice[index])
|
2026-08-25 15:46:39 +03:00
|
|
|
}
|
|
|
|
|
|
2026-08-26 17:53:09 +03:00
|
|
|
fn handle_by_id(&self, id: Id) -> EntityHandle<T> {
|
2026-08-29 22:50:18 +03:00
|
|
|
EntityHandle::new(id, id.0 as usize, true)
|
2026-08-26 17:53:09 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
fn create(&mut self, mut new: T) -> EntityHandle<T> {
|
|
|
|
|
let next_temporal = self.next_temporal;
|
|
|
|
|
self.next_temporal += 1;
|
2026-08-29 22:41:11 +03:00
|
|
|
let entity = EntityHandle::new(next_temporal.into(), self.temporal.len(), false);
|
2026-08-26 17:53:09 +03:00
|
|
|
new.set_id(entity.id);
|
|
|
|
|
self.temporal.push(new);
|
2026-08-25 15:46:39 +03:00
|
|
|
entity
|
|
|
|
|
}
|
|
|
|
|
|
2026-08-30 19:30:43 +03:00
|
|
|
fn create_now(&mut self, mut new: T) -> Result<EntityHandle<T>, NotificationData> {
|
|
|
|
|
self.data_layer.add_entity(&mut new, &self.connection.read())?;
|
|
|
|
|
let index = self.cache.len();
|
|
|
|
|
let handle = EntityHandle::new(new.id(), index, true);
|
|
|
|
|
self.cache.push(new);
|
|
|
|
|
Ok(handle)
|
|
|
|
|
}
|
|
|
|
|
|
2026-08-26 17:53:09 +03:00
|
|
|
fn save(&mut self, entity: &mut EntityHandle<T>) -> MaybeError {
|
2026-08-28 16:52:48 +03:00
|
|
|
let original_state = entity.clone();
|
2026-08-29 22:41:11 +03:00
|
|
|
if entity.real() {
|
2026-08-26 17:53:09 +03:00
|
|
|
let data = self.get_ref(entity).unwrap();
|
2026-08-26 19:48:22 +03:00
|
|
|
self.data_layer
|
2026-08-29 23:10:57 +03:00
|
|
|
.write_entity(data, &self.connection.read())?;
|
2026-08-26 17:53:09 +03:00
|
|
|
} else {
|
|
|
|
|
let index = fast_position_of(self.temporal.as_slice(), entity).unwrap();
|
2026-08-28 16:52:48 +03:00
|
|
|
let mut data = self.temporal.remove(index);
|
2026-08-26 19:48:22 +03:00
|
|
|
self.data_layer
|
2026-08-29 23:10:57 +03:00
|
|
|
.add_entity(&mut data, &self.connection.read())?;
|
2026-08-29 22:41:11 +03:00
|
|
|
entity.set_real(true);
|
2026-08-28 16:52:48 +03:00
|
|
|
entity.id = data.id();
|
2026-08-29 22:41:11 +03:00
|
|
|
entity.set_index(self.cache.len());
|
2026-08-28 16:52:48 +03:00
|
|
|
self.query_manger.handle_save(original_state, entity, &data);
|
|
|
|
|
|
|
|
|
|
self.cache.push(data);
|
2026-08-29 23:15:22 +03:00
|
|
|
self.shifts += 1;
|
2026-08-26 17:53:09 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
Ok(())
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
fn delete(&mut self, mut handle: EntityHandle<T>) -> MaybeError {
|
2026-08-29 22:41:11 +03:00
|
|
|
let vec = if handle.real() {
|
2026-08-26 19:48:22 +03:00
|
|
|
self.data_layer
|
2026-08-29 23:10:57 +03:00
|
|
|
.delete_entity(handle.id, &self.connection.read())?;
|
2026-08-26 17:53:09 +03:00
|
|
|
&mut self.cache
|
|
|
|
|
} else {
|
|
|
|
|
&mut self.temporal
|
|
|
|
|
};
|
|
|
|
|
|
2026-08-28 16:52:48 +03:00
|
|
|
let index = into_result(
|
|
|
|
|
fast_position_of(vec.as_slice(), &mut handle),
|
|
|
|
|
NotificationData::DbSaveError,
|
|
|
|
|
)?;
|
|
|
|
|
let value = vec.remove(index);
|
|
|
|
|
self.query_manger.handle_delete(&handle, &value);
|
2026-08-29 23:15:22 +03:00
|
|
|
self.shifts += 1;
|
2026-08-26 17:53:09 +03:00
|
|
|
Ok(())
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
fn init(&mut self) -> MaybeError {
|
2026-08-26 19:48:22 +03:00
|
|
|
self.data_layer
|
2026-08-29 23:10:57 +03:00
|
|
|
.load_all(&mut self.cache, &self.connection.read())?;
|
2026-08-29 22:41:11 +03:00
|
|
|
self.version += 1;
|
2026-08-26 17:53:09 +03:00
|
|
|
Ok(())
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
fn reload(&mut self) -> MaybeError {
|
|
|
|
|
self.cache.clear();
|
|
|
|
|
self.temporal.clear();
|
|
|
|
|
self.init()?;
|
|
|
|
|
Ok(())
|
|
|
|
|
}
|
|
|
|
|
}
|
2026-08-26 19:48:22 +03:00
|
|
|
impl<T: EntityData + Clone, D: BatchedDbLayer<T> + DbLayer<T>> BatchedRepository<T, D>
|
2026-08-27 14:05:05 +03:00
|
|
|
for DataRepositoryInner<T, D>
|
2026-08-26 19:48:22 +03:00
|
|
|
{
|
2026-08-26 17:53:09 +03:00
|
|
|
fn save_many(&mut self, handles: &mut [EntityHandle<T>]) -> MaybeError {
|
|
|
|
|
let mut temp = Vec::with_capacity(handles.len() / 2);
|
|
|
|
|
let mut cached = Vec::with_capacity(handles.len() / 2);
|
2026-08-26 19:48:22 +03:00
|
|
|
handles.sort_by_key(|a| a.id);
|
|
|
|
|
handles.iter_mut().for_each(|handle| {
|
2026-08-29 22:41:11 +03:00
|
|
|
if handle.real() {
|
2026-08-26 19:48:22 +03:00
|
|
|
cached.push(handle)
|
|
|
|
|
} else {
|
|
|
|
|
temp.push(handle)
|
|
|
|
|
}
|
|
|
|
|
});
|
|
|
|
|
|
2026-08-29 23:10:57 +03:00
|
|
|
let mut temp_values = Vec::with_capacity(temp.len());
|
2026-08-26 17:53:09 +03:00
|
|
|
let mut cell = 0;
|
2026-08-26 19:48:22 +03:00
|
|
|
let len = temp.len();
|
|
|
|
|
self.temporal.retain(|x| {
|
|
|
|
|
if cell == len {
|
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
let find = temp[cell].id;
|
|
|
|
|
let remove = x.id() == find;
|
2026-08-26 23:55:24 +03:00
|
|
|
if remove {
|
2026-08-26 19:48:22 +03:00
|
|
|
cell += 1;
|
2026-08-29 23:10:57 +03:00
|
|
|
temp_values.push(x.clone());
|
2026-08-26 19:48:22 +03:00
|
|
|
}
|
|
|
|
|
!remove
|
2026-08-26 17:53:09 +03:00
|
|
|
});
|
|
|
|
|
|
2026-08-26 19:48:22 +03:00
|
|
|
self.data_layer
|
2026-08-30 20:32:16 +03:00
|
|
|
.add_many_entities(&mut temp_values, &mut self.connection.write())?;
|
2026-08-26 19:48:22 +03:00
|
|
|
|
2026-08-26 23:55:24 +03:00
|
|
|
let start = self.cache.len();
|
|
|
|
|
|
2026-08-29 23:10:57 +03:00
|
|
|
for (i, (handle, data)) in temp.into_iter().zip(&mut temp_values).enumerate() {
|
2026-08-28 16:52:48 +03:00
|
|
|
let old = handle.clone();
|
2026-08-29 23:10:57 +03:00
|
|
|
handle.id = data.id();
|
|
|
|
|
handle.set_index(start + i);
|
|
|
|
|
handle.set_real(true);
|
|
|
|
|
self.query_manger.handle_save(old, handle, data);
|
2026-08-26 23:55:24 +03:00
|
|
|
}
|
|
|
|
|
|
2026-08-29 23:10:57 +03:00
|
|
|
self.cache.extend(temp_values);
|
2026-08-28 16:52:48 +03:00
|
|
|
|
2026-08-27 09:21:16 +03:00
|
|
|
for handle in cached.into_iter() {
|
|
|
|
|
let h = handle;
|
2026-08-26 23:55:24 +03:00
|
|
|
let idx = fast_position_of(self.cache.as_slice(), h).unwrap();
|
|
|
|
|
self.data_layer
|
2026-08-29 23:10:57 +03:00
|
|
|
.write_entity(&self.cache[idx], &self.connection.read())?;
|
2026-08-26 19:48:22 +03:00
|
|
|
}
|
2026-08-29 23:15:22 +03:00
|
|
|
self.shifts += 1;
|
2026-08-26 23:55:24 +03:00
|
|
|
|
|
|
|
|
Ok(())
|
2026-08-26 19:48:22 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
fn delete_many(&mut self, handles: &mut [EntityHandle<T>]) -> MaybeError {
|
|
|
|
|
let (cached, temp) = split_temp_real(handles, |e| e.id);
|
|
|
|
|
|
|
|
|
|
let mut cell = 0;
|
2026-08-26 17:53:09 +03:00
|
|
|
let len = temp.len();
|
|
|
|
|
self.temporal.retain(|x| {
|
2026-08-26 19:48:22 +03:00
|
|
|
if cell == len {
|
|
|
|
|
return true;
|
|
|
|
|
}
|
2026-08-26 17:53:09 +03:00
|
|
|
let find = temp[cell];
|
|
|
|
|
let remove = x.id() == find;
|
2026-08-26 23:55:24 +03:00
|
|
|
if remove {
|
2026-08-26 19:48:22 +03:00
|
|
|
cell += 1;
|
|
|
|
|
}
|
2026-08-26 17:53:09 +03:00
|
|
|
!remove
|
|
|
|
|
});
|
2026-08-26 19:48:22 +03:00
|
|
|
self.data_layer
|
2026-08-30 20:32:16 +03:00
|
|
|
.delete_many_entities(cached.as_slice(), &mut self.connection.write())?;
|
2026-08-26 17:53:09 +03:00
|
|
|
let len = cached.len();
|
|
|
|
|
cell = 0;
|
|
|
|
|
self.cache.retain(|x| {
|
2026-08-26 19:48:22 +03:00
|
|
|
if cell == len {
|
|
|
|
|
return true;
|
|
|
|
|
}
|
2026-08-26 17:53:09 +03:00
|
|
|
let find = cached[cell];
|
|
|
|
|
let remove = x.id() == find;
|
2026-08-26 23:55:24 +03:00
|
|
|
if remove {
|
2026-08-26 19:48:22 +03:00
|
|
|
cell += 1;
|
|
|
|
|
}
|
2026-08-28 16:52:48 +03:00
|
|
|
|
2026-08-26 17:53:09 +03:00
|
|
|
!remove
|
|
|
|
|
});
|
2026-08-29 23:15:22 +03:00
|
|
|
self.shifts += 1;
|
2026-08-26 17:53:09 +03:00
|
|
|
|
2026-08-26 19:48:22 +03:00
|
|
|
Ok(())
|
2026-08-26 17:53:09 +03:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2026-08-26 19:48:22 +03:00
|
|
|
fn split_temp_real<T, F, V>(handles: &mut [EntityHandle<T>], getter: F) -> (Vec<V>, Vec<V>)
|
|
|
|
|
where
|
|
|
|
|
F: Fn(&EntityHandle<T>) -> V,
|
|
|
|
|
{
|
|
|
|
|
let mut temp = Vec::with_capacity(handles.len() / 2);
|
|
|
|
|
let mut cached = Vec::with_capacity(handles.len() / 2);
|
|
|
|
|
handles.sort_by(|a, b| a.id.cmp(&b.id));
|
|
|
|
|
handles.iter().for_each(|handle| {
|
2026-08-29 22:41:11 +03:00
|
|
|
if handle.real() {
|
2026-08-26 19:48:22 +03:00
|
|
|
cached.push(getter(handle))
|
|
|
|
|
} else {
|
|
|
|
|
temp.push(getter(handle))
|
|
|
|
|
}
|
|
|
|
|
});
|
|
|
|
|
(cached, temp)
|
|
|
|
|
}
|
|
|
|
|
|
2026-08-26 17:53:09 +03:00
|
|
|
pub fn fast_position_of<E: EntityData>(
|
|
|
|
|
storage: &[E],
|
|
|
|
|
handle: &mut EntityHandle<E>,
|
|
|
|
|
) -> Option<usize> {
|
|
|
|
|
if storage.is_empty() {
|
|
|
|
|
return None;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
let max_idx = storage.len() - 1;
|
2026-08-29 22:41:11 +03:00
|
|
|
let upper = (handle.index()).min(max_idx);
|
2026-08-26 17:53:09 +03:00
|
|
|
let peek = storage[upper].id();
|
|
|
|
|
|
|
|
|
|
if peek == handle.id {
|
2026-08-29 22:41:11 +03:00
|
|
|
handle.set_index(upper);
|
2026-08-26 17:53:09 +03:00
|
|
|
return Some(upper);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if peek.0 < handle.id.0 {
|
|
|
|
|
return None;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
let target_id_val = handle.id.0 as i64;
|
|
|
|
|
let peek_val = peek.0 as i64;
|
|
|
|
|
let delta = peek_val - target_id_val;
|
|
|
|
|
|
|
|
|
|
let new_index = (upper as i64 - delta).max(0) as usize;
|
|
|
|
|
|
|
|
|
|
if storage[new_index].id() == handle.id {
|
2026-08-29 22:41:11 +03:00
|
|
|
handle.set_index(new_index);
|
2026-08-26 17:53:09 +03:00
|
|
|
return Some(new_index);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if new_index == upper {
|
|
|
|
|
return None;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
let index = storage[new_index..upper]
|
|
|
|
|
.binary_search_by(|e| e.id().cmp(&handle.id))
|
|
|
|
|
.ok()?
|
|
|
|
|
+ new_index;
|
|
|
|
|
|
2026-08-29 22:41:11 +03:00
|
|
|
handle.set_index(index);
|
2026-08-26 17:53:09 +03:00
|
|
|
Some(index)
|
2026-08-25 15:46:39 +03:00
|
|
|
}
|