Awaiting on static data

112 Views Asked by At

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()
});
1

There are 1 best solutions below

0
On BEST ANSWER

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()
});