use anyhow::{Ok, Result};
use common::database::{CommandUnitOfWork, QueryUnitOfWork};
use common::database::{db_context::DbContext, transactions::Transaction};
use common::direct_access::repository_factory;
use common::direct_access::table::TableRelationshipField;
use common::direct_access::use_cases;
use common::entities::Table;
use common::event::{AllEvent, DirectAccessEntity, Event, EventBuffer, EventHub, Origin};
use common::snapshot::EntityTreeSnapshot;
use common::types;
use common::types::EntityId;
use std::cell::RefCell;
use std::sync::Arc;
pub struct TableWriteUoW {
context: DbContext,
transaction: Option<Transaction>,
event_hub: Arc<EventHub>,
event_buffer: RefCell<EventBuffer>,
}
impl TableWriteUoW {
pub fn new(db_context: &DbContext, event_hub: &Arc<EventHub>) -> Self {
TableWriteUoW {
context: db_context.clone(),
transaction: None,
event_hub: event_hub.clone(),
event_buffer: RefCell::new(EventBuffer::new()),
}
}
}
impl CommandUnitOfWork for TableWriteUoW {
fn begin_transaction(&mut self) -> Result<()> {
self.transaction = Some(Transaction::begin_write_transaction(&self.context)?);
self.event_buffer.get_mut().begin_buffering();
Ok(())
}
fn commit(&mut self) -> Result<()> {
self.transaction.take().unwrap().commit()?;
for event in self.event_buffer.get_mut().flush() {
self.event_hub.send_event(event);
}
Ok(())
}
fn rollback(&mut self) -> Result<()> {
self.transaction.take().unwrap().rollback()?;
self.event_buffer.get_mut().discard();
Ok(())
}
fn create_savepoint(&self) -> Result<types::Savepoint> {
self.transaction.as_ref().unwrap().create_savepoint()
}
fn restore_to_savepoint(&mut self, savepoint: types::Savepoint) -> Result<()> {
let mut transaction = self.transaction.take().unwrap();
transaction.restore_to_savepoint(savepoint)?;
self.event_buffer.get_mut().discard();
self.event_hub.send_event(Event {
origin: Origin::DirectAccess(DirectAccessEntity::All(AllEvent::Reset)),
ids: vec![],
data: None,
});
self.transaction = Some(transaction);
Ok(())
}
}
impl use_cases::WriteUoW for TableWriteUoW {
type Entity = Table;
fn get(&self, id: &EntityId) -> Result<Option<Table>> {
let transaction = self.transaction.as_ref().expect("Transaction not started");
let repo = repository_factory::write::create_table_repository(transaction);
Ok(repo.get(id)?)
}
fn get_multi(&self, ids: &[EntityId]) -> Result<Vec<Option<Table>>> {
let transaction = self.transaction.as_ref().expect("Transaction not started");
let repo = repository_factory::write::create_table_repository(transaction);
Ok(repo.get_multi(ids)?)
}
fn get_all(&self) -> Result<Vec<Table>> {
let transaction = self.transaction.as_ref().expect("Transaction not started");
let repo = repository_factory::write::create_table_repository(transaction);
Ok(repo.get_all()?)
}
fn create_orphan_multi(&self, entities: &[Table]) -> Result<Vec<Table>> {
let transaction = self.transaction.as_ref().expect("Transaction not started");
let mut repo = repository_factory::write::create_table_repository(transaction);
let mut event_buffer = self.event_buffer.borrow_mut();
Ok(repo.create_orphan_multi(&mut event_buffer, entities)?)
}
fn update_multi(&self, entities: &[Table]) -> Result<Vec<Table>> {
let transaction = self.transaction.as_ref().expect("Transaction not started");
let mut repo = repository_factory::write::create_table_repository(transaction);
let mut event_buffer = self.event_buffer.borrow_mut();
Ok(repo.update_multi(&mut event_buffer, entities)?)
}
fn update_with_relationships_multi(&self, entities: &[Table]) -> Result<Vec<Table>> {
let transaction = self.transaction.as_ref().expect("Transaction not started");
let mut repo = repository_factory::write::create_table_repository(transaction);
let mut event_buffer = self.event_buffer.borrow_mut();
Ok(repo.update_with_relationships_multi(&mut event_buffer, entities)?)
}
fn remove(&self, id: &EntityId) -> Result<()> {
let transaction = self.transaction.as_ref().expect("Transaction not started");
let mut repo = repository_factory::write::create_table_repository(transaction);
let mut event_buffer = self.event_buffer.borrow_mut();
Ok(repo.remove(&mut event_buffer, id)?)
}
fn remove_multi(&self, ids: &[EntityId]) -> Result<()> {
let transaction = self.transaction.as_ref().expect("Transaction not started");
let mut repo = repository_factory::write::create_table_repository(transaction);
let mut event_buffer = self.event_buffer.borrow_mut();
Ok(repo.remove_multi(&mut event_buffer, ids)?)
}
fn snapshot(&self, ids: &[EntityId]) -> Result<EntityTreeSnapshot> {
let transaction = self.transaction.as_ref().expect("Transaction not started");
let repo = repository_factory::write::create_table_repository(transaction);
Ok(repo.snapshot(ids)?)
}
fn restore(&self, snap: &EntityTreeSnapshot) -> Result<()> {
let transaction = self.transaction.as_ref().expect("Transaction not started");
let mut repo = repository_factory::write::create_table_repository(transaction);
let mut event_buffer = self.event_buffer.borrow_mut();
Ok(repo.restore(&mut event_buffer, snap)?)
}
}
impl use_cases::OwnedWriteUoW for TableWriteUoW {
fn create_multi(
&self,
entities: &[Table],
owner_id: EntityId,
index: i32,
) -> Result<Vec<Table>> {
let transaction = self.transaction.as_ref().expect("Transaction not started");
let mut repo = repository_factory::write::create_table_repository(transaction);
let mut event_buffer = self.event_buffer.borrow_mut();
Ok(repo.create_multi(&mut event_buffer, entities, owner_id, index)?)
}
fn get_relationships_from_owner(&self, owner_id: &EntityId) -> Result<Vec<EntityId>> {
let transaction = self.transaction.as_ref().expect("Transaction not started");
let repo = repository_factory::write::create_table_repository(transaction);
Ok(repo.get_relationships_from_owner(owner_id)?)
}
fn set_relationships_in_owner(&self, owner_id: &EntityId, ids: &[EntityId]) -> Result<()> {
let transaction = self.transaction.as_ref().expect("Transaction not started");
let mut repo = repository_factory::write::create_table_repository(transaction);
let mut event_buffer = self.event_buffer.borrow_mut();
repo.set_relationships_in_owner(&mut event_buffer, owner_id, ids)?;
Ok(())
}
}
impl use_cases::WriteRelUoW<TableRelationshipField> for TableWriteUoW {
fn set_relationship(
&self,
id: &EntityId,
field: &TableRelationshipField,
right_ids: &[EntityId],
) -> Result<()> {
let transaction = self.transaction.as_ref().expect("Transaction not started");
let mut repo = repository_factory::write::create_table_repository(transaction);
let mut event_buffer = self.event_buffer.borrow_mut();
repo.set_relationship(&mut event_buffer, id, field, right_ids)?;
Ok(())
}
fn move_relationship(
&self,
id: &EntityId,
field: &TableRelationshipField,
ids_to_move: &[EntityId],
new_index: i32,
) -> Result<Vec<EntityId>> {
let transaction = self.transaction.as_ref().expect("Transaction not started");
let mut repo = repository_factory::write::create_table_repository(transaction);
let mut event_buffer = self.event_buffer.borrow_mut();
Ok(repo.move_relationship_ids(&mut event_buffer, id, field, ids_to_move, new_index)?)
}
}
pub struct TableWriteUoWFactory {
context: DbContext,
event_hub: Arc<EventHub>,
}
impl TableWriteUoWFactory {
pub fn new(db_context: &DbContext, event_hub: &Arc<EventHub>) -> Self {
TableWriteUoWFactory {
context: db_context.clone(),
event_hub: event_hub.clone(),
}
}
}
impl use_cases::WriteUoWFactory for TableWriteUoWFactory {
type Entity = Table;
fn create(&self) -> Box<dyn use_cases::WriteUoW<Entity = Table>> {
Box::new(TableWriteUoW::new(&self.context, &self.event_hub))
}
}
impl use_cases::OwnedWriteUoWFactory for TableWriteUoWFactory {
type Entity = Table;
fn create(&self) -> Box<dyn use_cases::OwnedWriteUoW<Entity = Table>> {
Box::new(TableWriteUoW::new(&self.context, &self.event_hub))
}
}
impl use_cases::WriteRelUoWFactory<TableRelationshipField> for TableWriteUoWFactory {
fn create(&self) -> Box<dyn use_cases::WriteRelUoW<TableRelationshipField>> {
Box::new(TableWriteUoW::new(&self.context, &self.event_hub))
}
}
pub struct TableReadUoW {
context: DbContext,
transaction: RefCell<Option<Transaction>>,
}
impl TableReadUoW {
pub fn new(db_context: &DbContext) -> Self {
TableReadUoW {
context: db_context.clone(),
transaction: RefCell::new(None),
}
}
}
impl QueryUnitOfWork for TableReadUoW {
fn begin_transaction(&self) -> Result<()> {
self.transaction
.replace(Some(Transaction::begin_read_transaction(&self.context)?));
Ok(())
}
fn end_transaction(&self) -> Result<()> {
self.transaction.take().unwrap().end_read_transaction()?;
Ok(())
}
}
impl use_cases::ReadUoW for TableReadUoW {
type Entity = Table;
fn get(&self, id: &EntityId) -> Result<Option<Table>> {
let transaction = self.transaction.borrow();
let repo = repository_factory::read::create_table_repository(transaction.as_ref().unwrap());
Ok(repo.get(id)?)
}
fn get_multi(&self, ids: &[EntityId]) -> Result<Vec<Option<Table>>> {
let transaction = self.transaction.borrow();
let repo = repository_factory::read::create_table_repository(transaction.as_ref().unwrap());
Ok(repo.get_multi(ids)?)
}
fn get_all(&self) -> Result<Vec<Table>> {
let transaction = self.transaction.borrow();
let repo = repository_factory::read::create_table_repository(transaction.as_ref().unwrap());
Ok(repo.get_all()?)
}
}
impl use_cases::ReadRelUoW<TableRelationshipField> for TableReadUoW {
fn get_relationship(
&self,
id: &EntityId,
field: &TableRelationshipField,
) -> Result<Vec<EntityId>> {
let transaction = self.transaction.borrow();
let repo = repository_factory::read::create_table_repository(transaction.as_ref().unwrap());
Ok(repo.get_relationship(id, field)?)
}
fn get_relationship_many(
&self,
ids: &[EntityId],
field: &TableRelationshipField,
) -> Result<std::collections::HashMap<EntityId, Vec<EntityId>>> {
let transaction = self.transaction.borrow();
let repo = repository_factory::read::create_table_repository(transaction.as_ref().unwrap());
Ok(repo.get_relationship_many(ids, field)?)
}
fn get_relationship_count(
&self,
id: &EntityId,
field: &TableRelationshipField,
) -> Result<usize> {
let transaction = self.transaction.borrow();
let repo = repository_factory::read::create_table_repository(transaction.as_ref().unwrap());
Ok(repo.get_relationship_count(id, field)?)
}
fn get_relationship_in_range(
&self,
id: &EntityId,
field: &TableRelationshipField,
offset: usize,
limit: usize,
) -> Result<Vec<EntityId>> {
let transaction = self.transaction.borrow();
let repo = repository_factory::read::create_table_repository(transaction.as_ref().unwrap());
Ok(repo.get_relationship_in_range(id, field, offset, limit)?)
}
}
pub struct TableReadUoWFactory {
context: DbContext,
}
impl TableReadUoWFactory {
pub fn new(db_context: &DbContext) -> Self {
TableReadUoWFactory {
context: db_context.clone(),
}
}
}
impl use_cases::ReadUoWFactory for TableReadUoWFactory {
type Entity = Table;
fn create(&self) -> Box<dyn use_cases::ReadUoW<Entity = Table>> {
Box::new(TableReadUoW::new(&self.context))
}
}
impl use_cases::ReadRelUoWFactory<TableRelationshipField> for TableReadUoWFactory {
fn create(&self) -> Box<dyn use_cases::ReadRelUoW<TableRelationshipField>> {
Box::new(TableReadUoW::new(&self.context))
}
}