use energyml_core::registry::DynObject;
use crate::array::{ArrayData, ArrayLocation, ArrayMetadata};
use crate::error::{Error, Result};
use crate::raw::RawObject;
use crate::storage::EnergymlStorage;
use async_trait::async_trait;
#[derive(Debug, Clone, Default, PartialEq, Eq)]
#[non_exhaustive]
pub struct TransactionRequest {
pub dataspaces: Vec<String>,
pub read_only: bool,
pub message: String,
}
impl TransactionRequest {
pub fn new() -> Self {
Self::default()
}
pub fn read_only(mut self) -> Self {
self.read_only = true;
self
}
pub fn with_message(mut self, message: impl Into<String>) -> Self {
self.message = message.into();
self
}
pub fn over(mut self, dataspaces: impl IntoIterator<Item = impl Into<String>>) -> Self {
self.dataspaces = dataspaces.into_iter().map(Into::into).collect();
self
}
}
#[derive(Debug, Clone, PartialEq, Eq)]
#[non_exhaustive]
pub struct Transaction {
pub id: String,
pub request: TransactionRequest,
}
impl Transaction {
pub fn new(id: impl Into<String>, request: TransactionRequest) -> Self {
Self {
id: id.into(),
request,
}
}
}
#[derive(Debug, Clone, Default, PartialEq, Eq)]
#[non_exhaustive]
pub struct Put {
pub uri: String,
pub created_contained: Vec<String>,
pub deleted_contained: Vec<String>,
pub joined_contained: Vec<String>,
pub unjoined_contained: Vec<String>,
}
impl Put {
pub fn new(uri: impl Into<String>) -> Self {
Self {
uri: uri.into(),
..Self::default()
}
}
}
#[allow(clippy::double_must_use)]
#[cfg_attr(not(target_arch = "wasm32"), async_trait)]
#[cfg_attr(target_arch = "wasm32", async_trait(?Send))]
pub trait EnergymlWriter: EnergymlStorage {
async fn put_objects(
&mut self,
objects: Vec<Box<dyn DynObject>>,
prune_contained: bool,
) -> Vec<Result<Put>>;
async fn put_raw(&mut self, objects: Vec<RawObject>, prune_contained: bool) -> Vec<Result<Put>> {
let _ = prune_contained;
objects
.iter()
.map(|_| {
Err(Error::Unsupported {
operation: "writing objects as bytes",
store: self.store_kind(),
})
})
.collect()
}
async fn delete_objects(&mut self, uris: &[String], prune_contained: bool) -> Vec<Result<Vec<String>>>;
async fn begin(&mut self, request: TransactionRequest) -> Result<Transaction>;
async fn commit(&mut self, transaction: &Transaction) -> Result<()>;
async fn rollback(&mut self, transaction: &Transaction) -> Result<()>;
fn open_transaction(&self) -> Option<Transaction>;
async fn declare_arrays(&mut self, arrays: &[(ArrayLocation, ArrayMetadata)]) -> Vec<Result<()>> {
arrays
.iter()
.map(|_| {
Err(Error::Unsupported {
operation: "declaring an array before writing it",
store: self.store_kind(),
})
})
.collect()
}
async fn put_arrays(&mut self, arrays: &[(ArrayLocation, ArrayData)]) -> Vec<Result<()>>;
}
pub fn check_open(open: Option<&Transaction>, given: &Transaction, store: &'static str) -> Result<()> {
match open {
Some(open) if open.id == given.id => Ok(()),
Some(open) => Err(Error::Transaction {
store,
reason: format!(
"transaction `{}` is not the open one (`{}` is)",
given.id, open.id
),
}),
None => Err(Error::Transaction {
store,
reason: format!("transaction `{}` is not open (no transaction is)", given.id),
}),
}
}