This is just an example of an (still incomplete) real-world project written in Rust using a clean architecture: GitHub - frederikhors/rust-clean-architecture-with-db-transactions.
Goals
My intent is to have an app build in 4 layers:
-
entities
:- some call this layer "domain", not important for now, just the minimum
-
services
:- some call this layer "use cases", this is where business logic lives (just CRUD methods for now)
-
repositories
:- some call this layer "adapters", this is where concrete implementation of DB/cache/mail drivers lives
-
ports
:-
some call this layer "controllers or presenters", still not present and not important for now, I'm using
main.rs
for this
-
some call this layer "controllers or presenters", still not present and not important for now, I'm using
Reproduction
The issue
If you open the main.rs
file you can see the issue:
// This obviously works if alone:
// let db_repo = Arc::new(repositories::in_memory::Repo::new());
// This obviously works if alone:
// let pg_pool = Arc::new(sqlx::PgPool::connect("postgres://postgres:postgres@localhost:5432/postgres").await.unwrap());
// let db_repo = Arc::new(repositories::postgres::Repo::new(pg_pool));
// This doesn't work instead:
let db_repo = if use_postgres {
let pg_pool = Arc::new(sqlx::PgPool::connect("postgres://postgres:postgres@localhost:5432/postgres").await.unwrap());
Arc::new(repositories::postgres::Repo::new(pg_pool))
} else {
Arc::new(repositories::in_memory::Repo::new())
};
My intent here is to change repository in use based on a variable, but Rust doesn't like it, this is the error:
Expand the error
error[E0308]: `if` and `else` have incompatible types
--> src\main.rs:37:9
|
28 | let db_repo = if use_postgres {
| ___________________-
29 | | let pg_pool = Arc::new(
30 | | sqlx::PgPool::connect("postgres://postgres:postgres@localhost:5432/postgres")
31 | | .await
... |
35 | | Arc::new(repositories::postgres::Repo::new(pg_pool))
| | ---------------------------------------------------- expected because of this
36 | | } else {
37 | | Arc::new(repositories::in_memory::Repo::new())
| | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected struct `repositories::postgres::Repo`, found struct `in_memory::Repo`
38 | | };
| |_____- `if` and `else` have incompatible types
|
= note: struct `in_memory::Repo` and struct `repositories::postgres::Repo` have similar names, but are actually distinct types
note: struct `in_memory::Repo` is defined in module `crate::repositories::in_memory` of the current crate
--> src\repositories\in_memory\mod.rs:6:1
|
6 | pub struct Repo {
| ^^^^^^^^^^^^^^^
note: struct `repositories::postgres::Repo` is defined in module `crate::repositories::postgres` of the current crate
--> src\repositories\postgres\mod.rs:6:1
|
6 | pub struct Repo {
| ^^^^^^^^^^^^^^^
How can I fix this?
I would prefer a static dispatch method.