I am connecting to a database. Once the credentials are inserted, the connector gives me back a (client, connection)
tuple. Afterwards, a procedural macro must access some "global location", retrieves the credentials from there and wires the data into the generated code.
I tried something like this:
pub static RUNTIME_DATA: RuntimeData<'static> = RuntimeData::new().await;
struct RuntimeData<'a> {
db_credentials: DatabaseConnection<'static>,
phantom: PhantomData<&'a RuntimeData<'a>>
}
unsafe impl Send for RuntimeData<'_> {}
unsafe impl Sync for RuntimeData<'_> {}
impl<'a> RuntimeData<'a> {
pub async fn new() -> RuntimeData<'a> {
Self {
db_credentials: DatabaseConnection::new().await.unwrap(),
phantom: PhantomData,
}
}
}
I can't .await
in static contexts. Is there a workaround to hold the data of RuntimeData
on RUNTIME_DATA
?
I am trying to avoid calling DatabaseConnection::new()
on every proc-macro use as it parses the credentials from a config file and wires them into the instance. I see that Rust does this really fast, even if I think that it's quite inefficient. If I can store the credentials once in a static context, I can avoid allocating multiple instances for every proc-macro use.
My database handler is:
pub struct DatabaseConnection<'a> {
pub client: Client,
pub connection: Connection<Socket, NoTlsStream>,
pub phantom: &'a PhantomData<DatabaseConnection<'a>>
}
unsafe impl Send for DatabaseConnection<'_> {}
unsafe impl Sync for DatabaseConnection<'_> {}
impl<'a> DatabaseConnection<'a> {
pub async fn new() -> Result<DatabaseConnection<'a>, Error> {
let credentials = DatabaseCredentials::new();
let (new_client, new_connection) =
tokio_postgres::connect(
&format!(
"postgres://{user}:{pswd}@localhost/{db}",
user = credentials.username,
pswd = credentials.password,
db = credentials.db_name
)[..],
NoTls)
.await?;
Ok(Self {
client: new_client,
connection: new_connection,
phantom: &PhantomData
})
}
}
Edit for clarifiyin PitaJ
approach:
pub static lazy: Lazy<RuntimeData<'static>> = Lazy::new(|| async {
block_on(RuntimeData::new()).await.unwrap()
});
As pointed out, solution it's to use the block_on(...)
method.
pub static lazy: Lazy<RuntimeData<'static>> = Lazy::new(|| async {
block_on(RuntimeData::new()).await.unwrap()
});