diff --git a/services/blob/src/database/mod.rs b/services/blob/src/database/mod.rs --- a/services/blob/src/database/mod.rs +++ b/services/blob/src/database/mod.rs @@ -1,2 +1,3 @@ pub mod errors; pub mod old; +pub mod types; diff --git a/services/blob/src/database/types.rs b/services/blob/src/database/types.rs new file mode 100644 --- /dev/null +++ b/services/blob/src/database/types.rs @@ -0,0 +1,160 @@ +use aws_sdk_dynamodb::types::AttributeValue; +use chrono::{DateTime, Utc}; +use derive_more::Constructor; +use std::collections::HashMap; + +use crate::{ + constants::{db::*, BLOB_S3_BUCKET_NAME}, + s3::S3Path, +}; + +use super::errors::Error as DBError; + +/// Represents a database row in the DynamoDB SDK format +pub(super) type RawAttributes = HashMap; +/// A convenience Result type for database operations +pub(super) type DBResult = Result; + +/// Represents a type-safe version of a DynamoDB blob table item. +/// Each row can be either a blob item or a holder assignment. +/// +/// It implements the `TryFrom` trait to convert from raw DynamoDB +/// `AttributeValue`s to the type-safe version. +pub enum DBRow { + BlobItem(BlobItemRow), + HolderAssignment(HolderAssignmentRow), +} + +impl TryFrom for DBRow { + type Error = DBError; + + #[allow(unused)] + fn try_from(attributes: RawAttributes) -> Result { + todo!() + } +} + +/// Represents an input payload for inserting a blob item into the database. +/// This contains only the business logic related attributes +#[derive(Debug)] +pub struct BlobItemInput { + pub blob_hash: String, + pub s3_path: S3Path, +} + +impl BlobItemInput { + pub fn new(blob_hash: impl Into) -> Self { + let blob_hash: String = blob_hash.into(); + BlobItemInput { + blob_hash: blob_hash.clone(), + s3_path: S3Path { + bucket_name: BLOB_S3_BUCKET_NAME.into(), + object_name: blob_hash, + }, + } + } +} + +/// A struct representing a blob item row in the table in a type-safe way +/// +/// It implements the `TryFrom` trait to convert from raw DynamoDB +/// `AttributeValue`s to the type-safe version. +#[derive(Debug)] +pub struct BlobItemRow { + pub blob_hash: String, + pub s3_path: S3Path, + pub unchecked: bool, + pub created_at: DateTime, + pub last_modified: DateTime, +} + +impl TryFrom for BlobItemRow { + type Error = DBError; + + #[allow(unused)] + fn try_from(mut attributes: RawAttributes) -> Result { + todo!() + } +} + +/// A struct representing a holder assignment table row in a type-safe way +/// +/// It implements the `TryFrom` trait to convert from raw DynamoDB +/// `AttributeValue`s to the type-safe version. +#[derive(Debug)] +pub struct HolderAssignmentRow { + pub blob_hash: String, + pub holder: String, + pub unchecked: bool, + pub created_at: DateTime, + pub last_modified: DateTime, +} + +impl TryFrom for HolderAssignmentRow { + type Error = DBError; + + #[allow(unused)] + fn try_from(mut attributes: RawAttributes) -> Result { + todo!() + } +} + +/// Represents a composite primary key for a DynamoDB table row +/// +/// It implements `TryFrom` and `Into` traits to conveniently use it +/// in DynamoDB queries +#[derive(Clone, Constructor, Debug)] +pub struct PrimaryKey { + pub blob_hash: String, + pub holder: String, +} + +impl PrimaryKey { + /// Creates a primary key for a row containing a blob item data + /// Rows queried by primary keys created by this function will + /// be of type `BlobItemRow` + pub fn for_blob_item(blob_hash: impl Into) -> Self { + PrimaryKey { + blob_hash: blob_hash.into(), + holder: BLOB_ITEM_ROW_HOLDER_VALUE.to_string(), + } + } +} + +impl TryFrom for PrimaryKey { + type Error = DBError; + + #[allow(unused)] + fn try_from(mut attributes: RawAttributes) -> Result { + todo!() + } +} + +// useful for convenient calls: +// ddb.get_item().set_key(Some(partition_key.into())) +impl Into for PrimaryKey { + fn into(self) -> RawAttributes { + todo!() + } +} + +/// Represents possible values for the `unchecked` attribute value +pub enum UncheckedKind { + Blob, + Holder, +} + +impl UncheckedKind { + pub fn str_value(&self) -> &'static str { + match self { + UncheckedKind::Blob => "blob", + UncheckedKind::Holder => "holder", + } + } +} + +impl Into for UncheckedKind { + fn into(self) -> AttributeValue { + AttributeValue::S(self.str_value().to_string()) + } +}