Closed numfin closed 8 months ago
The issue comes from the fact that the provider does not know how to inject sqlx::Pool<Postgres>
.
You can solve your issue like so (I used Sqlite
instead of Postgres
, but it should be similar):
use nject::{injectable, provider};
use sqlx::Sqlite;
#[injectable]
pub struct DBProvider<T: sqlx::Database> {
pub pool: sqlx::Pool<T>,
}
#[injectable]
pub struct UserService<T: sqlx::Database> {
db: DBProvider<T>,
}
#[provider]
#[provide(sqlx::pool::Pool::<Sqlite>, sqlx::pool::Pool::<Sqlite>::connect_lazy("addr").expect("Invalid db addr"))]
struct Provider;
fn main() {
let _f: UserService<Sqlite> = Provider.provide();
}
You can also refer to the actix example for a use case using sqlx
.
If you wanted the type to be generic up to the provider, you can do:
use nject::{injectable, provider};
use sqlx::Sqlite;
#[injectable]
pub struct DBProvider<T: sqlx::Database> {
pub pool: sqlx::Pool<T>,
}
#[injectable]
pub struct UserService<T: sqlx::Database> {
db: DBProvider<T>,
}
#[provider]
#[provide(sqlx::pool::Pool::<T>, sqlx::pool::Pool::<T>::connect_lazy("addr").expect("Invalid db addr"))]
struct Provider<T: sqlx::Database>(PhantomData<T>);
fn main() {
let provider = Provider(PhantomData);
let _f: UserService<Sqlite> = provider.provide();
}
@nicolascotton thank you for answer. Your advice helped me!
hm, is it possible to implement provider
by hand so we don't have to rely on macro?
I imagine api like:
struct Provider;
impl DependencyProvider<Dep1> for Provider {
type Error = ();
async fn create_async(&self) -> Result<Dep1, Self::Error>;
fn create(&self) -> Result<Dep1, Self::Error>;
}
I don't know for the API you are trying to make, but you can expand the provider macro and see what it is doing under the hood. For the previous example, the provider macro can be substituted by:
// From the provider attribute
impl<'prov, T: sqlx::Database, Value> nject::Provider<'prov, Value> for Provider<T>
where
Value: nject::Injectable<'prov, Value, Provider<T>>,
{
fn provide(&'prov self) -> Value {
Value::inject(self)
}
}
// From the provide attribute
impl<'prov, T: sqlx::Database> nject::Provider<'prov, sqlx::pool::Pool<T>> for Provider<T> {
fn provide(&'prov self) -> sqlx::pool::Pool<T> {
sqlx::pool::Pool::<T>::connect_lazy("addr").expect("Invalid db addr")
}
}
Could you please help me figure out What i want:
What i get: