2026-08-25 15:46:39 +03:00
|
|
|
use crate::data::Id;
|
2026-08-31 14:35:11 +03:00
|
|
|
use crate::data::entities::{EntityData, EntityHandle, WordData};
|
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-09-02 00:19:58 +03:00
|
|
|
use std::ops::{Deref, Index, IndexMut};
|
2026-08-31 14:50:21 +03:00
|
|
|
use std::rc::Rc;
|
2026-09-02 00:19:58 +03:00
|
|
|
use std::slice::Iter;
|
2026-08-25 15:46:39 +03:00
|
|
|
use std::sync::Arc;
|
2026-08-31 12:12:14 +03:00
|
|
|
use crate::data_provider::sqlite::SqliteConnection;
|
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>;
|
2026-09-02 00:19:58 +03:00
|
|
|
fn get_static(&self, handle: EntityHandle<T>) -> Option<T>;
|
|
|
|
|
fn get_ref_static(&self, handle: EntityHandle<T>) -> Option<&T>;
|
|
|
|
|
fn get_mut_static(&mut self, handle: EntityHandle<T>) -> Option<&mut T>;
|
2026-08-26 17:53:09 +03:00
|
|
|
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;
|
2026-08-31 14:35:11 +03:00
|
|
|
fn find<F>(&self, predicate: F) -> Option<EntityHandle<T>> where F : Fn(&T) -> bool;
|
2026-08-26 17:53:09 +03:00
|
|
|
fn init(&mut self) -> MaybeError;
|
2026-08-30 23:35:32 +03:00
|
|
|
fn start(&mut self) -> MaybeError;
|
2026-08-26 17:53:09 +03:00
|
|
|
fn reload(&mut self) -> MaybeError;
|
2026-08-31 14:35:11 +03:00
|
|
|
fn shifts(&self) -> usize;
|
2026-09-02 00:19:58 +03:00
|
|
|
fn iter<'a>(&'a self) -> impl Iterator<Item = &'a T> where T: 'a;
|
|
|
|
|
fn iter_mut<'a>(&'a mut self) -> impl Iterator<Item = &'a mut T> where T: 'a;
|
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-31 14:50:21 +03:00
|
|
|
|
|
|
|
|
#[derive(Clone)]
|
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-31 14:50:21 +03:00
|
|
|
rule: Arc<dyn Fn(&T) -> bool + Send + Sync>,
|
2026-08-28 16:52:48 +03:00
|
|
|
parallel: bool,
|
2026-08-27 14:51:35 +03:00
|
|
|
_marker: PhantomData<(R, D)>,
|
2026-08-31 14:35:11 +03:00
|
|
|
shift_stamp: usize,
|
2026-08-27 14:05:05 +03:00
|
|
|
}
|
|
|
|
|
|
2026-08-31 14:35:11 +03:00
|
|
|
impl<T: EntityData + Clone + Send + Sync, R: Repository<T, D>, D: DbLayer<T>> Query<T, R, D> {
|
|
|
|
|
pub fn iter<'a>(&mut self, data_repository_inner: &'a DataRepositoryInner<T, D>) -> impl Iterator<Item = &'a T>
|
2026-08-27 14:51:35 +03:00
|
|
|
where
|
|
|
|
|
T: 'a,
|
|
|
|
|
{
|
2026-08-31 14:35:11 +03:00
|
|
|
if self.shift_stamp != data_repository_inner.shifts() {
|
|
|
|
|
self.load(data_repository_inner);
|
|
|
|
|
}
|
2026-08-27 14:51:35 +03:00
|
|
|
self.cache
|
|
|
|
|
.iter_mut()
|
|
|
|
|
.filter_map(move |e| data_repository_inner.get_ref(e))
|
|
|
|
|
}
|
|
|
|
|
|
2026-09-02 00:19:58 +03:00
|
|
|
pub fn iter_with_handles<'a>(&mut self, data_repository_inner: &'a DataRepositoryInner<T, D>) -> impl Iterator<Item = (&'a T, EntityHandle<T>)>
|
|
|
|
|
where
|
|
|
|
|
T: 'a,
|
|
|
|
|
{
|
|
|
|
|
if self.shift_stamp != data_repository_inner.shifts() {
|
|
|
|
|
self.load(data_repository_inner);
|
|
|
|
|
}
|
|
|
|
|
self.cache
|
|
|
|
|
.iter_mut()
|
|
|
|
|
.filter_map(move |e| Some((data_repository_inner.get_ref(e)?, e.clone())))
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
pub fn for_each_mut<F>(&mut self, repo: &mut DataRepositoryInner<T, D>, mut f: F)
|
2026-08-27 14:51:35 +03:00
|
|
|
where
|
|
|
|
|
F: FnMut(&mut T),
|
|
|
|
|
{
|
2026-09-02 00:19:58 +03:00
|
|
|
if self.shift_stamp != repo.shifts() {
|
|
|
|
|
self.load(repo);
|
|
|
|
|
}
|
2026-08-27 14:51:35 +03:00
|
|
|
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()
|
2026-08-31 14:50:21 +03:00
|
|
|
.filter(|(_, entity)| self.rule.as_ref()(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-09-02 00:19:58 +03:00
|
|
|
|
2026-09-04 11:18:23 +03:00
|
|
|
pub fn handles(&self) -> impl Iterator<Item = EntityHandle<T>> {
|
2026-09-02 00:19:58 +03:00
|
|
|
self.cache.iter().cloned()
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
pub fn len(&self) -> usize {
|
|
|
|
|
self.cache.len()
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
impl<T: EntityData + Clone + Send + Sync, R: Repository<T, D>, D: DbLayer<T>> Index<usize> for Query<T, R, D> {
|
|
|
|
|
type Output = EntityHandle<T>;
|
|
|
|
|
|
|
|
|
|
fn index(&self, index: usize) -> &Self::Output {
|
|
|
|
|
&self.cache[index]
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
impl<T: EntityData + Clone + Send + Sync, R: Repository<T, D>, D: DbLayer<T>> IndexMut<usize> for Query<T, R, D> {
|
|
|
|
|
fn index_mut(&mut self, index: usize) -> &mut Self::Output {
|
|
|
|
|
&mut self.cache[index]
|
|
|
|
|
}
|
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
|
|
|
{
|
2026-09-04 11:18:23 +03:00
|
|
|
fn create_now_many(&mut self, entities: &mut [T]) -> Result<Vec<EntityHandle<T>>, NotificationData>;
|
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-09-04 11:18:23 +03:00
|
|
|
pub struct DataRepository<T: 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-09-04 11:18:23 +03:00
|
|
|
pub struct DataRepositoryInner<T: 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-09-04 11:37:19 +03:00
|
|
|
connection: Arc<Mutex<SqliteConnection>>,
|
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-31 14:35:11 +03:00
|
|
|
shifts: usize,
|
2026-08-26 17:53:09 +03:00
|
|
|
}
|
|
|
|
|
|
2026-09-04 11:18:23 +03:00
|
|
|
impl<T: Clone + EntityData, D: DbLayer<T> + Default> DataRepository<T, D> {
|
2026-09-04 11:37:19 +03:00
|
|
|
pub fn new(connection: Arc<Mutex<SqliteConnection>>) -> DataRepository<T, D> {
|
2026-08-31 12:12:14 +03:00
|
|
|
Self{
|
|
|
|
|
inner: Arc::new(RwLock::new(DataRepositoryInner{
|
|
|
|
|
cache: vec![],
|
|
|
|
|
temporal: vec![],
|
|
|
|
|
next_temporal: 0,
|
|
|
|
|
connection,
|
|
|
|
|
data_layer: Default::default(),
|
|
|
|
|
query_manger: QueryManger { queries: vec![] },
|
|
|
|
|
version: 0,
|
|
|
|
|
shifts: 0,
|
|
|
|
|
})),
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
2026-09-04 11:18:23 +03:00
|
|
|
impl<T: 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,
|
2026-08-31 14:50:21 +03:00
|
|
|
rule: Arc<dyn Fn(&T) -> bool + Send + Sync>,
|
2026-08-27 14:51:35 +03:00
|
|
|
) -> 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,
|
2026-09-04 11:18:23 +03:00
|
|
|
rule: Arc<dyn Fn(& T) -> bool + Send + Sync>,
|
2026-08-29 22:41:11 +03:00
|
|
|
) -> 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-09-02 00:19:58 +03:00
|
|
|
|
|
|
|
|
pub fn empty_query(&self) -> Query<T, DataRepositoryInner<T, D>, D> {
|
|
|
|
|
Query{
|
|
|
|
|
cache: vec![],
|
|
|
|
|
rule: Arc::new(|_| false),
|
|
|
|
|
parallel: false,
|
|
|
|
|
_marker: Default::default(),
|
|
|
|
|
shift_stamp: 0,
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
pub fn empty_query_par(&self) -> Query<T, DataRepositoryInner<T, D>, D> {
|
|
|
|
|
Query{
|
|
|
|
|
cache: vec![],
|
|
|
|
|
rule: Arc::new(|_| false),
|
|
|
|
|
parallel: true,
|
|
|
|
|
_marker: Default::default(),
|
|
|
|
|
shift_stamp: 0,
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
pub fn len(&self) -> usize {
|
|
|
|
|
self.cache.len() + self.temporal.len()
|
|
|
|
|
}
|
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-09-02 00:19:58 +03:00
|
|
|
fn get_static(&self, mut handle: EntityHandle<T>) -> Option<T> {
|
|
|
|
|
self.get(&mut handle)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
fn get_ref_static(&self, mut handle: EntityHandle<T>) -> Option<&T> {
|
|
|
|
|
self.get_ref(&mut handle)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
fn get_mut_static(&mut self, mut handle: EntityHandle<T>) -> Option<&mut T> {
|
|
|
|
|
self.get_mut(&mut handle)
|
|
|
|
|
}
|
|
|
|
|
|
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> {
|
2026-08-31 11:26:05 +03:00
|
|
|
self.data_layer
|
2026-09-04 11:37:19 +03:00
|
|
|
.add_entity(&mut new, &self.connection.lock())?;
|
2026-08-30 19:30:43 +03:00
|
|
|
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-09-04 11:37:19 +03:00
|
|
|
.write_entity(data, &self.connection.lock())?;
|
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-09-04 11:37:19 +03:00
|
|
|
.add_entity(&mut data, &self.connection.lock())?;
|
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-09-04 11:37:19 +03:00
|
|
|
.delete_entity(handle.id, &self.connection.lock())?;
|
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(())
|
|
|
|
|
}
|
|
|
|
|
|
2026-08-31 14:35:11 +03:00
|
|
|
fn find<F>(&self, predicate: F) -> Option<EntityHandle<T>>
|
|
|
|
|
where
|
|
|
|
|
F: Fn(&T) -> bool
|
|
|
|
|
{
|
|
|
|
|
if let Some(index) = self.cache.iter().position(|entity| predicate(entity)){
|
|
|
|
|
let value = &self.cache[index];
|
|
|
|
|
return Some(EntityHandle::new(value.id(), index, true))
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if let Some(index) = self.temporal.iter().position(|entity| predicate(entity)){
|
|
|
|
|
let value = &self.temporal[index];
|
|
|
|
|
return Some(EntityHandle::new(value.id(), index, false))
|
|
|
|
|
}
|
|
|
|
|
None
|
|
|
|
|
}
|
|
|
|
|
|
2026-08-26 17:53:09 +03:00
|
|
|
fn init(&mut self) -> MaybeError {
|
2026-08-26 19:48:22 +03:00
|
|
|
self.data_layer
|
2026-09-04 11:37:19 +03:00
|
|
|
.load_all(&mut self.cache, &self.connection.lock())?;
|
2026-08-29 22:41:11 +03:00
|
|
|
self.version += 1;
|
2026-08-26 17:53:09 +03:00
|
|
|
Ok(())
|
|
|
|
|
}
|
|
|
|
|
|
2026-08-30 23:35:32 +03:00
|
|
|
fn start(&mut self) -> MaybeError {
|
|
|
|
|
if self.version != 0 {
|
2026-08-31 11:26:05 +03:00
|
|
|
return Ok(());
|
2026-08-30 23:35:32 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
self.init()?;
|
|
|
|
|
Ok(())
|
|
|
|
|
}
|
|
|
|
|
|
2026-08-26 17:53:09 +03:00
|
|
|
fn reload(&mut self) -> MaybeError {
|
|
|
|
|
self.cache.clear();
|
|
|
|
|
self.temporal.clear();
|
|
|
|
|
self.init()?;
|
|
|
|
|
Ok(())
|
|
|
|
|
}
|
2026-08-31 14:35:11 +03:00
|
|
|
|
|
|
|
|
fn shifts(&self) -> usize {
|
|
|
|
|
self.shifts
|
|
|
|
|
}
|
2026-09-02 00:19:58 +03:00
|
|
|
|
|
|
|
|
fn iter<'a>(&'a self) -> impl Iterator<Item=&'a T>
|
|
|
|
|
where
|
|
|
|
|
T: 'a
|
|
|
|
|
{
|
|
|
|
|
self.cache.iter().chain(self.temporal.iter())
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
fn iter_mut<'a>(&'a mut self) -> impl Iterator<Item=&'a mut T>
|
|
|
|
|
where
|
|
|
|
|
T: 'a
|
|
|
|
|
{
|
|
|
|
|
self.cache.iter_mut().chain(self.temporal.iter_mut())
|
|
|
|
|
}
|
2026-08-26 17:53:09 +03:00
|
|
|
}
|
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-09-04 11:18:23 +03:00
|
|
|
fn create_now_many(&mut self, entities: &mut [T]) -> Result<Vec<EntityHandle<T>>, NotificationData> {
|
2026-09-04 11:37:19 +03:00
|
|
|
self.data_layer.add_many_entities(entities, &mut self.connection.lock())?;
|
2026-09-04 11:18:23 +03:00
|
|
|
let len = self.cache.len();
|
|
|
|
|
let handles = entities.iter().enumerate().map(|(index, entity)| {EntityHandle::new(entity.id(), index + len, true)}).collect();
|
|
|
|
|
self.cache.extend(entities.to_vec());
|
|
|
|
|
Ok(handles)
|
|
|
|
|
}
|
|
|
|
|
|
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-09-04 11:37:19 +03:00
|
|
|
.add_many_entities(&mut temp_values, &mut self.connection.lock())?;
|
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-09-04 11:37:19 +03:00
|
|
|
.write_entity(&self.cache[idx], &self.connection.lock())?;
|
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-09-04 11:37:19 +03:00
|
|
|
.delete_many_entities(cached.as_slice(), &mut self.connection.lock())?;
|
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
|
|
|
}
|