Browse Source

Async traits

main
Julio Biason 3 years ago
parent
commit
2bec0c0fd0
  1. 12
      Cargo.lock
  2. 1
      lib/Cargo.toml
  3. 4
      lib/src/database.rs
  4. 13
      lib/src/domain/command.rs
  5. 8
      lib/src/domain/project/create.rs
  6. 8
      lib/src/domain/project/repository.rs

12
Cargo.lock generated

@ -28,6 +28,17 @@ version = "0.5.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "23b62fc65de8e4e7f52534fb52b0f3ed04746ae267519eef2a83941e8085068b"
[[package]]
name = "async-trait"
version = "0.1.51"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "44318e776df68115a881de9a8fd1b9e53368d7a4a5ce4cc48517da3393233a5e"
dependencies = [
"proc-macro2",
"quote",
"syn",
]
[[package]]
name = "atoi"
version = "0.4.0"
@ -455,6 +466,7 @@ dependencies = [
name = "lib"
version = "0.1.0"
dependencies = [
"async-trait",
"directories",
"sqlx",
"tokio",

1
lib/Cargo.toml

@ -7,3 +7,4 @@ edition = "2018"
directories = "3.0"
sqlx = { version = "0.5", default-features = false, features = [ "sqlite", "chrono", "macros", "migrate", "runtime-tokio-rustls"] }
tokio = { version = "1.6", features = [ "rt", "macros" ] }
async-trait = "0.1"

4
lib/src/database.rs

@ -25,11 +25,11 @@ use sqlx::sqlite::SqliteConnectOptions;
use sqlx::sqlite::SqlitePoolOptions;
use sqlx::Pool;
async fn connect() -> Result<Pool<Sqlite>, sqlx::Error> {
pub async fn connect() -> Result<Pool<Sqlite>, sqlx::Error> {
connect_with(&default_filename()).await
}
async fn connect_with(filename: &Path) -> Result<Pool<Sqlite>, sqlx::Error> {
pub async fn connect_with(filename: &Path) -> Result<Pool<Sqlite>, sqlx::Error> {
let pool = SqlitePoolOptions::new()
.connect_with(
SqliteConnectOptions::new()

13
lib/src/domain/command.rs

@ -16,16 +16,27 @@
along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
use async_trait::async_trait;
/// Trait/tag for DTOs
pub trait Dto {}
/// Trait that all commands must implement.
#[async_trait]
pub trait Command<T: Dto> {
async fn execute(self) -> Result<T, CommandError>;
async fn execute(&self) -> Result<&T, CommandError>;
}
/// Errors produced by invalid commands
pub enum CommandError {
/// The request identified used in the command is already used.
IdentifierAlreadyUsed(String),
/// Erro with the database
DatabaseError,
}
impl From<sqlx::Error> for CommandError {
fn from(_error: sqlx::Error) -> Self {
Self::DatabaseError
}
}

8
lib/src/domain/project/create.rs

@ -16,6 +16,8 @@
along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
use async_trait::async_trait;
use super::dto::Project;
use super::repository::Repository;
use crate::database;
@ -30,11 +32,13 @@ impl Create {
}
}
#[async_trait]
impl Command<Project> for Create {
async fn execute(self) -> Result<Project, CommandError> {
async fn execute(&self) -> Result<&Project, CommandError> {
let pool = database::connect().await?;
let repo = Repository::new(&pool);
Ok(self.0)
repo.save(&self.0).await?;
Ok(&self.0)
}
}

8
lib/src/domain/project/repository.rs

@ -21,21 +21,21 @@ use sqlx::Pool;
use super::dto::Project;
struct Repository<'a> {
pub struct Repository<'a> {
pool: &'a Pool<Sqlite>,
}
impl<'a> Repository<'a> {
fn new(pool: &'a Pool<Sqlite>) -> Self {
pub fn new(pool: &'a Pool<Sqlite>) -> Self {
Self { pool }
}
async fn save(&self, project: Project) -> Result<Project, sqlx::Error> {
pub async fn save(&self, project: &Project) -> Result<(), sqlx::Error> {
sqlx::query(r#"INSERT INTO project (code, name) VALUES (?, ?)"#)
.bind(&project.code())
.bind(&project.name())
.execute(self.pool)
.await?;
Ok(project)
Ok(())
}
}

Loading…
Cancel
Save