pub mod clock;
pub mod error;
#[doc(hidden)]
pub mod sql_builders;
#[cfg(any(feature = "native-sqlite", feature = "_has-encryption"))]
pub mod rusqlite_impl;
#[cfg(feature = "wasm-sqlite")]
pub mod wasm_backend;
use crate::storage::{
CreateTableMetadata, DatabaseInfo, QueryParams, ScanParams, StreamRecord, TableMetadata,
TableStats,
};
use crate::types::Tag;
pub use clock::{Clock, ManualClock, SystemClock};
pub use error::BackendError;
#[cfg(any(feature = "native-sqlite", feature = "_has-encryption"))]
pub use error::from_rusqlite;
#[doc(hidden)]
pub use sql_builders::SqlParam;
#[cfg(feature = "wasm-sqlite")]
pub use wasm_backend::WasmBridgeBackend;
#[derive(Debug, Clone)]
pub struct BaseItemRow {
pub pk: String,
pub sk: String,
pub item_json: String,
pub item_size: usize,
pub cached_at: Option<f64>,
pub hash_prefix: String,
}
#[derive(Debug, Clone)]
pub struct GsiItemRow {
pub gsi_pk: String,
pub gsi_sk: String,
pub table_pk: String,
pub table_sk: String,
pub item_json: String,
}
#[derive(Debug, Clone)]
pub enum IndexWriteOp {
DeleteGsi {
table_name: String,
index_name: String,
table_pk: String,
table_sk: String,
},
InsertGsi {
table_name: String,
index_name: String,
gsi_pk: String,
gsi_sk: String,
table_pk: String,
table_sk: String,
item_json: String,
},
DeleteLsi {
table_name: String,
index_name: String,
base_pk: String,
base_sk: String,
},
InsertLsi {
table_name: String,
index_name: String,
pk: String,
sk: String,
base_pk: String,
base_sk: String,
item_json: String,
},
}
#[allow(async_fn_in_trait)]
pub trait StorageBackend {
fn clock(&self) -> &dyn Clock;
async fn insert_table_metadata(&self, m: &CreateTableMetadata<'_>) -> Result<(), BackendError>;
async fn get_table_metadata(
&self,
table_name: &str,
) -> Result<Option<TableMetadata>, BackendError>;
async fn delete_table_metadata(&self, table_name: &str) -> Result<bool, BackendError>;
async fn update_table_metadata(
&self,
table_name: &str,
attribute_definitions: &str,
gsi_definitions: Option<&str>,
) -> Result<(), BackendError>;
async fn update_provisioned_throughput(
&self,
table_name: &str,
provisioned_throughput: &str,
) -> Result<(), BackendError>;
async fn clear_provisioned_throughput(&self, table_name: &str) -> Result<(), BackendError>;
async fn update_billing_mode(
&self,
table_name: &str,
billing_mode: &str,
) -> Result<(), BackendError>;
async fn update_table_class(
&self,
table_name: &str,
table_class: &str,
) -> Result<(), BackendError>;
async fn update_on_demand_throughput(
&self,
table_name: &str,
on_demand_throughput: &str,
) -> Result<(), BackendError>;
async fn get_tags(&self, table_name: &str) -> Result<Vec<Tag>, BackendError>;
async fn set_tags(&self, table_name: &str, new_tags: &[Tag]) -> Result<(), BackendError>;
async fn update_deletion_protection(
&self,
table_name: &str,
enabled: bool,
) -> Result<(), BackendError>;
async fn remove_tags(&self, table_name: &str, keys: &[String]) -> Result<(), BackendError>;
async fn list_table_names(&self) -> Result<Vec<String>, BackendError>;
async fn table_exists(&self, table_name: &str) -> Result<bool, BackendError>;
async fn create_data_table(&self, table_name: &str) -> Result<(), BackendError>;
async fn drop_data_table(&self, table_name: &str) -> Result<(), BackendError>;
async fn create_gsi_table(
&self,
table_name: &str,
index_name: &str,
) -> Result<(), BackendError>;
async fn drop_gsi_table(&self, table_name: &str, index_name: &str) -> Result<(), BackendError>;
async fn create_lsi_table(
&self,
table_name: &str,
index_name: &str,
) -> Result<(), BackendError>;
async fn drop_lsi_table(&self, table_name: &str, index_name: &str) -> Result<(), BackendError>;
#[allow(clippy::too_many_arguments)]
async fn insert_gsi_item(
&self,
table_name: &str,
index_name: &str,
gsi_pk: &str,
gsi_sk: &str,
table_pk: &str,
table_sk: &str,
item_json: &str,
) -> Result<(), BackendError>;
async fn insert_gsi_items(
&self,
table_name: &str,
index_name: &str,
rows: &[GsiItemRow],
) -> Result<(), BackendError>;
async fn delete_gsi_item(
&self,
table_name: &str,
index_name: &str,
table_pk: &str,
table_sk: &str,
) -> Result<(), BackendError>;
async fn query_gsi_items(
&self,
table_name: &str,
index_name: &str,
gsi_pk: &str,
params: &QueryParams<'_>,
) -> Result<Vec<(String, String, String)>, BackendError>;
async fn scan_gsi_items(
&self,
table_name: &str,
index_name: &str,
params: &ScanParams<'_>,
) -> Result<Vec<(String, String, String)>, BackendError>;
#[allow(clippy::too_many_arguments)]
async fn insert_lsi_item(
&self,
table_name: &str,
index_name: &str,
pk: &str,
sk: &str,
base_pk: &str,
base_sk: &str,
item_json: &str,
) -> Result<(), BackendError>;
async fn delete_lsi_item(
&self,
table_name: &str,
index_name: &str,
base_pk: &str,
base_sk: &str,
) -> Result<(), BackendError>;
async fn query_lsi_items(
&self,
table_name: &str,
index_name: &str,
pk: &str,
params: &QueryParams<'_>,
) -> Result<Vec<(String, String, String)>, BackendError>;
async fn scan_lsi_items(
&self,
table_name: &str,
index_name: &str,
params: &ScanParams<'_>,
) -> Result<Vec<(String, String, String)>, BackendError>;
async fn apply_index_writes(&self, ops: &[IndexWriteOp]) -> Result<(), BackendError> {
for op in ops {
match op {
IndexWriteOp::DeleteGsi {
table_name,
index_name,
table_pk,
table_sk,
} => {
self.delete_gsi_item(table_name, index_name, table_pk, table_sk)
.await?;
}
IndexWriteOp::InsertGsi {
table_name,
index_name,
gsi_pk,
gsi_sk,
table_pk,
table_sk,
item_json,
} => {
self.insert_gsi_item(
table_name, index_name, gsi_pk, gsi_sk, table_pk, table_sk, item_json,
)
.await?;
}
IndexWriteOp::DeleteLsi {
table_name,
index_name,
base_pk,
base_sk,
} => {
self.delete_lsi_item(table_name, index_name, base_pk, base_sk)
.await?;
}
IndexWriteOp::InsertLsi {
table_name,
index_name,
pk,
sk,
base_pk,
base_sk,
item_json,
} => {
self.insert_lsi_item(
table_name, index_name, pk, sk, base_pk, base_sk, item_json,
)
.await?;
}
}
}
Ok(())
}
async fn begin_transaction(&self) -> Result<(), BackendError>;
async fn commit(&self) -> Result<(), BackendError>;
async fn rollback(&self) -> Result<(), BackendError>;
async fn enable_bulk_loading(&self) -> Result<(), BackendError>;
async fn disable_bulk_loading(&self) -> Result<(), BackendError>;
async fn put_item(
&self,
table_name: &str,
pk: &str,
sk: &str,
item_json: &str,
item_size: usize,
) -> Result<Option<String>, BackendError>;
#[allow(clippy::too_many_arguments)]
async fn put_item_with_hash(
&self,
table_name: &str,
pk: &str,
sk: &str,
item_json: &str,
item_size: usize,
hash_prefix: &str,
) -> Result<Option<String>, BackendError>;
async fn put_base_items(
&self,
table_name: &str,
rows: &[BaseItemRow],
) -> Result<(), BackendError>;
async fn get_item(
&self,
table_name: &str,
pk: &str,
sk: &str,
) -> Result<Option<String>, BackendError>;
async fn get_partition_size(&self, table_name: &str, pk: &str) -> Result<i64, BackendError>;
async fn get_lsi_partition_size(
&self,
table_name: &str,
index_name: &str,
pk: &str,
) -> Result<i64, BackendError>;
async fn delete_item(
&self,
table_name: &str,
pk: &str,
sk: &str,
) -> Result<Option<String>, BackendError>;
async fn query_items(
&self,
table_name: &str,
pk: &str,
params: &QueryParams<'_>,
) -> Result<Vec<(String, String, String)>, BackendError>;
async fn scan_items(
&self,
table_name: &str,
params: &ScanParams<'_>,
) -> Result<Vec<(String, String, String)>, BackendError>;
async fn count_items(&self, table_name: &str) -> Result<i64, BackendError>;
async fn db_size_bytes(&self) -> Result<u64, BackendError>;
async fn table_count(&self) -> Result<usize, BackendError>;
async fn table_stats(&self) -> Result<Vec<TableStats>, BackendError>;
async fn database_info(&self) -> Result<DatabaseInfo, BackendError>;
async fn vacuum(&self) -> Result<(), BackendError>;
async fn enable_stream(
&self,
table_name: &str,
view_type: &str,
label: &str,
) -> Result<(), BackendError>;
async fn disable_stream(&self, table_name: &str) -> Result<(), BackendError>;
#[allow(clippy::too_many_arguments)]
async fn insert_stream_record(
&self,
table_name: &str,
event_name: &str,
keys_json: &str,
new_image: Option<&str>,
old_image: Option<&str>,
sequence_number: &str,
shard_id: &str,
created_at: i64,
) -> Result<(), BackendError>;
#[allow(clippy::too_many_arguments)]
async fn insert_stream_record_with_identity(
&self,
table_name: &str,
event_name: &str,
keys_json: &str,
new_image: Option<&str>,
old_image: Option<&str>,
sequence_number: &str,
shard_id: &str,
created_at: i64,
user_identity: Option<&str>,
) -> Result<(), BackendError>;
async fn next_stream_sequence_number(&self, table_name: &str) -> Result<i64, BackendError>;
async fn get_stream_records(
&self,
table_name: &str,
shard_id: &str,
after_sequence: i64,
limit: usize,
) -> Result<Vec<StreamRecord>, BackendError>;
async fn list_stream_enabled_tables(&self) -> Result<Vec<TableMetadata>, BackendError>;
async fn update_ttl_config(
&self,
table_name: &str,
attribute_name: Option<&str>,
enabled: bool,
) -> Result<(), BackendError>;
async fn list_ttl_enabled_tables(&self) -> Result<Vec<TableMetadata>, BackendError>;
async fn get_shard_sequence_range(
&self,
table_name: &str,
shard_id: &str,
) -> Result<(Option<String>, Option<String>), BackendError>;
async fn touch_cached_at(
&self,
table_name: &str,
pk: &str,
sk: &str,
timestamp: f64,
) -> Result<(), BackendError>;
async fn get_lru_items(
&self,
table_name: &str,
limit: usize,
) -> Result<Vec<(String, String, i64)>, BackendError>;
}