Skip to content

Commit

Permalink
add repositories
Browse files Browse the repository at this point in the history
Signed-off-by: simonsan <[email protected]>
  • Loading branch information
simonsan committed Apr 2, 2024
1 parent ad25fc7 commit e78195c
Show file tree
Hide file tree
Showing 8 changed files with 315 additions and 21 deletions.
20 changes: 20 additions & 0 deletions crates/error/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -293,6 +293,26 @@ pub enum DatabaseStorageErrorKind {
#[source]
source: sea_orm::error::SqlErr,
},

/// Failed to read item {item_type}::{item_id} from database: {source}
RepositoryReadFailed {
source: sea_orm::DbErr,
item_type: String,
item_id: String,
},

/// Failed to delete item {item_type}::{item_id} from database: {source}
RepositoryDeleteFailed {
source: sea_orm::prelude::DbErr,
item_type: String,
item_id: String,
},

/// Failed to create item {item_type} in database: {source}
RepositoryCreateFailed {
source: sea_orm::prelude::DbErr,
item_type: String,
},
}

/// [`TomlFileStorageErrorKind`] describes the errors that can happen while dealing with the Toml file storage.
Expand Down
20 changes: 20 additions & 0 deletions crates/storage/src/migration/m20240325_000001_create_activities.rs
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,26 @@ impl MigrationTrait for Migration {
)
.to_owned(),

Check warning on line 46 in crates/storage/src/migration/m20240325_000001_create_activities.rs

View check run for this annotation

Codecov / codecov/patch

crates/storage/src/migration/m20240325_000001_create_activities.rs#L46

Added line #L46 was not covered by tests
)
.await?;

Check warning on line 48 in crates/storage/src/migration/m20240325_000001_create_activities.rs

View check run for this annotation

Codecov / codecov/patch

crates/storage/src/migration/m20240325_000001_create_activities.rs#L48

Added line #L48 was not covered by tests

manager

Check warning on line 50 in crates/storage/src/migration/m20240325_000001_create_activities.rs

View check run for this annotation

Codecov / codecov/patch

crates/storage/src/migration/m20240325_000001_create_activities.rs#L50

Added line #L50 was not covered by tests
.create_index(
Index::create()
.table(Activities::Table)
.name("idx_activities_parent_guid")
.col(Activities::ParentGuid)
.to_owned(),

Check warning on line 56 in crates/storage/src/migration/m20240325_000001_create_activities.rs

View check run for this annotation

Codecov / codecov/patch

crates/storage/src/migration/m20240325_000001_create_activities.rs#L52-L56

Added lines #L52 - L56 were not covered by tests
)
.await?;

Check warning on line 58 in crates/storage/src/migration/m20240325_000001_create_activities.rs

View check run for this annotation

Codecov / codecov/patch

crates/storage/src/migration/m20240325_000001_create_activities.rs#L58

Added line #L58 was not covered by tests

manager

Check warning on line 60 in crates/storage/src/migration/m20240325_000001_create_activities.rs

View check run for this annotation

Codecov / codecov/patch

crates/storage/src/migration/m20240325_000001_create_activities.rs#L60

Added line #L60 was not covered by tests
.create_index(
Index::create()
.table(Activities::Table)
.name("idx_activities_description")
.col(Activities::Description)
.to_owned(),

Check warning on line 66 in crates/storage/src/migration/m20240325_000001_create_activities.rs

View check run for this annotation

Codecov / codecov/patch

crates/storage/src/migration/m20240325_000001_create_activities.rs#L62-L66

Added lines #L62 - L66 were not covered by tests
)
.await

Check warning on line 68 in crates/storage/src/migration/m20240325_000001_create_activities.rs

View check run for this annotation

Codecov / codecov/patch

crates/storage/src/migration/m20240325_000001_create_activities.rs#L68

Added line #L68 was not covered by tests
}

Expand Down
10 changes: 10 additions & 0 deletions crates/storage/src/migration/m20240326_000001_create_tags.rs
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,16 @@ impl MigrationTrait for Migration {
.col(ColumnDef::new(Tags::Tag).text().not_null())
.to_owned(),

Check warning on line 18 in crates/storage/src/migration/m20240326_000001_create_tags.rs

View check run for this annotation

Codecov / codecov/patch

crates/storage/src/migration/m20240326_000001_create_tags.rs#L13-L18

Added lines #L13 - L18 were not covered by tests
)
.await?;

Check warning on line 20 in crates/storage/src/migration/m20240326_000001_create_tags.rs

View check run for this annotation

Codecov / codecov/patch

crates/storage/src/migration/m20240326_000001_create_tags.rs#L20

Added line #L20 was not covered by tests

manager

Check warning on line 22 in crates/storage/src/migration/m20240326_000001_create_tags.rs

View check run for this annotation

Codecov / codecov/patch

crates/storage/src/migration/m20240326_000001_create_tags.rs#L22

Added line #L22 was not covered by tests
.create_index(
Index::create()
.table(Tags::Table)
.name("idx_tags_tag")
.col(Tags::Tag)
.to_owned(),

Check warning on line 28 in crates/storage/src/migration/m20240326_000001_create_tags.rs

View check run for this annotation

Codecov / codecov/patch

crates/storage/src/migration/m20240326_000001_create_tags.rs#L24-L28

Added lines #L24 - L28 were not covered by tests
)
.await

Check warning on line 30 in crates/storage/src/migration/m20240326_000001_create_tags.rs

View check run for this annotation

Codecov / codecov/patch

crates/storage/src/migration/m20240326_000001_create_tags.rs#L30

Added line #L30 was not covered by tests
}

Expand Down
10 changes: 10 additions & 0 deletions crates/storage/src/migration/m20240326_000002_create_categories.rs
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,16 @@ impl MigrationTrait for Migration {
.col(ColumnDef::new(Categories::Description).text().null())
.to_owned(),

Check warning on line 24 in crates/storage/src/migration/m20240326_000002_create_categories.rs

View check run for this annotation

Codecov / codecov/patch

crates/storage/src/migration/m20240326_000002_create_categories.rs#L22-L24

Added lines #L22 - L24 were not covered by tests
)
.await?;

Check warning on line 26 in crates/storage/src/migration/m20240326_000002_create_categories.rs

View check run for this annotation

Codecov / codecov/patch

crates/storage/src/migration/m20240326_000002_create_categories.rs#L26

Added line #L26 was not covered by tests

manager

Check warning on line 28 in crates/storage/src/migration/m20240326_000002_create_categories.rs

View check run for this annotation

Codecov / codecov/patch

crates/storage/src/migration/m20240326_000002_create_categories.rs#L28

Added line #L28 was not covered by tests
.create_index(
Index::create()
.table(Categories::Table)
.name("idx_categories_category")
.col(Categories::Category)
.to_owned(),

Check warning on line 34 in crates/storage/src/migration/m20240326_000002_create_categories.rs

View check run for this annotation

Codecov / codecov/patch

crates/storage/src/migration/m20240326_000002_create_categories.rs#L30-L34

Added lines #L30 - L34 were not covered by tests
)
.await

Check warning on line 36 in crates/storage/src/migration/m20240326_000002_create_categories.rs

View check run for this annotation

Codecov / codecov/patch

crates/storage/src/migration/m20240326_000002_create_categories.rs#L36

Added line #L36 was not covered by tests
}

Expand Down
35 changes: 29 additions & 6 deletions crates/storage/src/repository.rs
Original file line number Diff line number Diff line change
@@ -1,8 +1,10 @@
pub mod activity;
pub mod category;
pub mod tag;

use pace_error::{PaceOptResult, PaceResult};

pub trait Repository<T> {
pub(crate) trait Repository<T> {
/// Read a single entity by its id.
///
/// # Arguments
Expand All @@ -16,7 +18,7 @@ pub trait Repository<T> {
/// # Returns
///
/// Returns the entity if it exists or None if it does not.
fn read(&self, id: &str) -> PaceOptResult<T>;
async fn read(&self, id: &str) -> PaceOptResult<T>;

/// Read all entities of a given type.
///
Expand All @@ -28,7 +30,7 @@ pub trait Repository<T> {
///
/// Returns a vector of all entities of the given type or an
/// empty vector if there are none.
fn read_all(&self) -> PaceOptResult<Vec<T>>;
async fn read_all(&self) -> PaceOptResult<Vec<T>>;

/// Create a new entity of a given type.
///
Expand All @@ -43,7 +45,7 @@ pub trait Repository<T> {
/// # Returns
///
/// Returns the id of the created entity.
fn create(&self, entity: &T) -> PaceResult<String>;
async fn create(&self, model: &T) -> PaceResult<String>;

/// Update an existing entity of a given type.
///
Expand All @@ -59,7 +61,7 @@ pub trait Repository<T> {
/// # Returns
///
/// Returns nothing if the entity was updated successfully.
fn update(&self, id: &str, entity: &T) -> PaceResult<()>;
async fn update(&self, id: &str, model: &T) -> PaceResult<()>;

/// Delete an existing entity of a given type.
///
Expand All @@ -70,5 +72,26 @@ pub trait Repository<T> {
/// # Errors
///
/// Returns an error if there was a problem deleting the entity.
fn delete(&self, id: &str) -> PaceResult<()>;
///
/// # Returns
///
/// Returns the deleted entity if it exists.
async fn delete(&self, id: &str) -> PaceOptResult<T>;
}

pub struct SeaOrmRepository<'conn> {
activity: activity::ActivityRepository<'conn, sea_orm::DatabaseConnection>,
category: category::CategoryRepository<'conn, sea_orm::DatabaseConnection>,
tag: tag::TagRepository<'conn, sea_orm::DatabaseConnection>,
}

impl<'conn> SeaOrmRepository<'conn> {
#[must_use]
pub const fn new(connection: &'conn sea_orm::DatabaseConnection) -> Self {

Check warning on line 90 in crates/storage/src/repository.rs

View check run for this annotation

Codecov / codecov/patch

crates/storage/src/repository.rs#L90

Added line #L90 was not covered by tests
Self {
activity: activity::ActivityRepository::new(connection),
category: category::CategoryRepository::new(connection),
tag: tag::TagRepository::new(connection),

Check warning on line 94 in crates/storage/src/repository.rs

View check run for this annotation

Codecov / codecov/patch

crates/storage/src/repository.rs#L92-L94

Added lines #L92 - L94 were not covered by tests
}
}
}
81 changes: 81 additions & 0 deletions crates/storage/src/repository/activity.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,81 @@
use pace_error::{DatabaseStorageErrorKind, PaceOptResult, PaceResult};
use sea_orm::{EntityTrait, IntoActiveModel};

use crate::entity::activities::{Entity as ActivityEntity, Model as ActivityModel};
use crate::repository::Repository;

pub struct ActivityRepository<'conn, C> {
connection: &'conn C,
}

impl<'conn, C> ActivityRepository<'conn, C> {
pub const fn new(connection: &'conn C) -> Self {

Check warning on line 12 in crates/storage/src/repository/activity.rs

View check run for this annotation

Codecov / codecov/patch

crates/storage/src/repository/activity.rs#L12

Added line #L12 was not covered by tests
Self { connection }
}
}

impl<'conn> Repository<ActivityModel> for ActivityRepository<'conn, sea_orm::DatabaseConnection> {
async fn read(&self, id: &str) -> PaceOptResult<ActivityModel> {
Ok(ActivityEntity::find_by_id(id)
.one(self.connection)
.await
.map_err(|source| DatabaseStorageErrorKind::RepositoryReadFailed {
source,
item_type: "activity".to_string(),
item_id: id.to_string(),

Check warning on line 25 in crates/storage/src/repository/activity.rs

View check run for this annotation

Codecov / codecov/patch

crates/storage/src/repository/activity.rs#L18-L25

Added lines #L18 - L25 were not covered by tests
})?)
}

async fn read_all(&self) -> PaceOptResult<Vec<ActivityModel>> {
let items = ActivityEntity::find()
.all(self.connection)
.await
.map_err(|source| DatabaseStorageErrorKind::RepositoryReadFailed {
source,
item_type: "activity".to_string(),
item_id: "all".to_string(),

Check warning on line 36 in crates/storage/src/repository/activity.rs

View check run for this annotation

Codecov / codecov/patch

crates/storage/src/repository/activity.rs#L29-L36

Added lines #L29 - L36 were not covered by tests
})?;

if items.is_empty() {
return Ok(None);

Check warning on line 40 in crates/storage/src/repository/activity.rs

View check run for this annotation

Codecov / codecov/patch

crates/storage/src/repository/activity.rs#L39-L40

Added lines #L39 - L40 were not covered by tests
}

Ok(Some(items))

Check warning on line 43 in crates/storage/src/repository/activity.rs

View check run for this annotation

Codecov / codecov/patch

crates/storage/src/repository/activity.rs#L43

Added line #L43 was not covered by tests
}

async fn create(&self, model: &ActivityModel) -> PaceResult<String> {

Check warning on line 46 in crates/storage/src/repository/activity.rs

View check run for this annotation

Codecov / codecov/patch

crates/storage/src/repository/activity.rs#L46

Added line #L46 was not covered by tests
// TODO: What else should we do with ActiveModel here?
let active_model = model.clone().into_active_model();

Check warning on line 48 in crates/storage/src/repository/activity.rs

View check run for this annotation

Codecov / codecov/patch

crates/storage/src/repository/activity.rs#L48

Added line #L48 was not covered by tests

let id = ActivityEntity::insert(active_model)
.exec(self.connection)
.await
.map_err(|source| DatabaseStorageErrorKind::RepositoryCreateFailed {
source,
item_type: "activity".to_string(),

Check warning on line 55 in crates/storage/src/repository/activity.rs

View check run for this annotation

Codecov / codecov/patch

crates/storage/src/repository/activity.rs#L50-L55

Added lines #L50 - L55 were not covered by tests
})?
.last_insert_id;

Check warning on line 57 in crates/storage/src/repository/activity.rs

View check run for this annotation

Codecov / codecov/patch

crates/storage/src/repository/activity.rs#L57

Added line #L57 was not covered by tests

Ok(id)

Check warning on line 59 in crates/storage/src/repository/activity.rs

View check run for this annotation

Codecov / codecov/patch

crates/storage/src/repository/activity.rs#L59

Added line #L59 was not covered by tests
}

async fn update(&self, id: &str, model: &ActivityModel) -> PaceResult<()> {

Check warning on line 62 in crates/storage/src/repository/activity.rs

View check run for this annotation

Codecov / codecov/patch

crates/storage/src/repository/activity.rs#L62

Added line #L62 was not covered by tests
unimplemented!()
}

async fn delete(&self, id: &str) -> PaceOptResult<ActivityModel> {
let item = self.read(id).await?;

Check warning on line 67 in crates/storage/src/repository/activity.rs

View check run for this annotation

Codecov / codecov/patch

crates/storage/src/repository/activity.rs#L66-L67

Added lines #L66 - L67 were not covered by tests

// TODO: Unused result here, what should we do with the rows affected?
_ = ActivityEntity::delete_by_id(id)
.exec(self.connection)
.await
.map_err(|source| DatabaseStorageErrorKind::RepositoryDeleteFailed {
source,
item_type: "activity".to_string(),
item_id: id.to_string(),

Check warning on line 76 in crates/storage/src/repository/activity.rs

View check run for this annotation

Codecov / codecov/patch

crates/storage/src/repository/activity.rs#L70-L76

Added lines #L70 - L76 were not covered by tests
})?;

Ok(item)

Check warning on line 79 in crates/storage/src/repository/activity.rs

View check run for this annotation

Codecov / codecov/patch

crates/storage/src/repository/activity.rs#L79

Added line #L79 was not covered by tests
}
}
79 changes: 64 additions & 15 deletions crates/storage/src/repository/category.rs
Original file line number Diff line number Diff line change
@@ -1,32 +1,81 @@
use pace_error::{PaceOptResult, PaceResult};
use sea_orm::{sea_query::Query, DatabaseConnection};
use pace_error::{DatabaseStorageErrorKind, PaceOptResult, PaceResult};
use sea_orm::{EntityTrait, IntoActiveModel};

use crate::entity::categories::{Entity as CategoryEntity, Model as CategoryModel};
use crate::entity::tags::Entity as TagEntity;
use crate::repository::Repository;

pub struct CategoryRepository {
connection: DatabaseConnection,
pub struct CategoryRepository<'conn, C> {
connection: &'conn C,
}

impl Repository<CategoryEntity> for CategoryRepository {
fn read(&self, id: &str) -> PaceOptResult<CategoryEntity> {
unimplemented!()
impl<'conn, C> CategoryRepository<'conn, C> {
pub const fn new(connection: &'conn C) -> Self {

Check warning on line 12 in crates/storage/src/repository/category.rs

View check run for this annotation

Codecov / codecov/patch

crates/storage/src/repository/category.rs#L12

Added line #L12 was not covered by tests
Self { connection }
}
}

fn read_all(&self) -> PaceOptResult<Vec<CategoryEntity>> {
unimplemented!()
impl<'conn> Repository<CategoryModel> for CategoryRepository<'conn, sea_orm::DatabaseConnection> {
async fn read(&self, id: &str) -> PaceOptResult<CategoryModel> {
Ok(CategoryEntity::find_by_id(id)
.one(self.connection)
.await
.map_err(|source| DatabaseStorageErrorKind::RepositoryReadFailed {
source,
item_type: "category".to_string(),
item_id: id.to_string(),

Check warning on line 25 in crates/storage/src/repository/category.rs

View check run for this annotation

Codecov / codecov/patch

crates/storage/src/repository/category.rs#L18-L25

Added lines #L18 - L25 were not covered by tests
})?)
}

fn create(&self, entity: &CategoryEntity) -> PaceResult<String> {
unimplemented!()
async fn read_all(&self) -> PaceOptResult<Vec<CategoryModel>> {
let items = CategoryEntity::find()
.all(self.connection)
.await
.map_err(|source| DatabaseStorageErrorKind::RepositoryReadFailed {
source,
item_type: "category".to_string(),
item_id: "all".to_string(),

Check warning on line 36 in crates/storage/src/repository/category.rs

View check run for this annotation

Codecov / codecov/patch

crates/storage/src/repository/category.rs#L29-L36

Added lines #L29 - L36 were not covered by tests
})?;

if items.is_empty() {
return Ok(None);

Check warning on line 40 in crates/storage/src/repository/category.rs

View check run for this annotation

Codecov / codecov/patch

crates/storage/src/repository/category.rs#L39-L40

Added lines #L39 - L40 were not covered by tests
}

Ok(Some(items))

Check warning on line 43 in crates/storage/src/repository/category.rs

View check run for this annotation

Codecov / codecov/patch

crates/storage/src/repository/category.rs#L43

Added line #L43 was not covered by tests
}

fn update(&self, id: &str, entity: &CategoryEntity) -> PaceResult<()> {
unimplemented!()
async fn create(&self, model: &CategoryModel) -> PaceResult<String> {

Check warning on line 46 in crates/storage/src/repository/category.rs

View check run for this annotation

Codecov / codecov/patch

crates/storage/src/repository/category.rs#L46

Added line #L46 was not covered by tests
// TODO: What else should we do with ActiveModel here?
let active_model = model.clone().into_active_model();

Check warning on line 48 in crates/storage/src/repository/category.rs

View check run for this annotation

Codecov / codecov/patch

crates/storage/src/repository/category.rs#L48

Added line #L48 was not covered by tests

let id = CategoryEntity::insert(active_model)
.exec(self.connection)
.await
.map_err(|source| DatabaseStorageErrorKind::RepositoryCreateFailed {
source,
item_type: "category".to_string(),

Check warning on line 55 in crates/storage/src/repository/category.rs

View check run for this annotation

Codecov / codecov/patch

crates/storage/src/repository/category.rs#L50-L55

Added lines #L50 - L55 were not covered by tests
})?
.last_insert_id;

Check warning on line 57 in crates/storage/src/repository/category.rs

View check run for this annotation

Codecov / codecov/patch

crates/storage/src/repository/category.rs#L57

Added line #L57 was not covered by tests

Ok(id)

Check warning on line 59 in crates/storage/src/repository/category.rs

View check run for this annotation

Codecov / codecov/patch

crates/storage/src/repository/category.rs#L59

Added line #L59 was not covered by tests
}

fn delete(&self, id: &str) -> PaceResult<()> {
async fn update(&self, id: &str, model: &CategoryModel) -> PaceResult<()> {

Check warning on line 62 in crates/storage/src/repository/category.rs

View check run for this annotation

Codecov / codecov/patch

crates/storage/src/repository/category.rs#L62

Added line #L62 was not covered by tests
unimplemented!()
}

async fn delete(&self, id: &str) -> PaceOptResult<CategoryModel> {
let item = self.read(id).await?;

Check warning on line 67 in crates/storage/src/repository/category.rs

View check run for this annotation

Codecov / codecov/patch

crates/storage/src/repository/category.rs#L66-L67

Added lines #L66 - L67 were not covered by tests

// TODO: Unused result here, what should we do with the rows affected?
_ = CategoryEntity::delete_by_id(id)
.exec(self.connection)
.await
.map_err(|source| DatabaseStorageErrorKind::RepositoryDeleteFailed {
source,
item_type: "category".to_string(),
item_id: id.to_string(),

Check warning on line 76 in crates/storage/src/repository/category.rs

View check run for this annotation

Codecov / codecov/patch

crates/storage/src/repository/category.rs#L70-L76

Added lines #L70 - L76 were not covered by tests
})?;

Ok(item)

Check warning on line 79 in crates/storage/src/repository/category.rs

View check run for this annotation

Codecov / codecov/patch

crates/storage/src/repository/category.rs#L79

Added line #L79 was not covered by tests
}
}
Loading

0 comments on commit e78195c

Please sign in to comment.