plane 0.5.5

Session backend orchestrator for ambitious browser-based apps.
Documentation
use plane_common::types::{ClusterName, NodeId};
use sqlx::query;
use sqlx::PgPool;

pub struct AcmeDatabase<'a> {
    pool: &'a PgPool,
}

impl<'a> AcmeDatabase<'a> {
    pub fn new(pool: &'a PgPool) -> Self {
        Self { pool }
    }

    pub async fn lease_cluster_dns(
        &self,
        cluster: &ClusterName,
        proxy: NodeId,
    ) -> sqlx::Result<bool> {
        let result = query!(
            r#"
            insert into acme_txt_entries (cluster, leased_at, leased_by)
            values ($1, now(), $2)
            on conflict (cluster)
            do update set
                leased_at = now(),
                leased_by = $2
            where (acme_txt_entries.leased_at + interval '1 minute') < now()
            "#,
            cluster.to_string(),
            proxy.as_i32(),
        )
        .execute(self.pool)
        .await?;

        Ok(result.rows_affected() == 1)
    }

    pub async fn set_cluster_dns(
        &self,
        cluster: &ClusterName,
        proxy: NodeId,
        txt_value: &str,
    ) -> sqlx::Result<bool> {
        let result = query!(
            r#"
            update acme_txt_entries set
                txt_value = $3
            where cluster = $1
            and leased_by = $2
            "#,
            cluster.to_string(),
            proxy.as_i32(),
            txt_value,
        )
        .execute(self.pool)
        .await?;

        Ok(result.rows_affected() == 1)
    }

    pub async fn txt_record_for_cluster(
        &self,
        cluster: &ClusterName,
    ) -> sqlx::Result<Option<String>> {
        let result = query!(
            r#"
            select txt_value
            from acme_txt_entries
            where cluster = $1
            "#,
            cluster.to_string(),
        )
        .fetch_optional(self.pool)
        .await?;

        Ok(result.and_then(|r| r.txt_value))
    }

    pub async fn release_cluster_lease(
        &self,
        cluster: &ClusterName,
        proxy: NodeId,
    ) -> sqlx::Result<()> {
        query!(
            r#"
            delete from acme_txt_entries
            where cluster = $1
            and leased_by = $2
            "#,
            cluster.to_string(),
            proxy.as_i32(),
        )
        .execute(self.pool)
        .await?;

        Ok(())
    }
}