Files
flux-releaser/crates/flux-releaser/src/services/artifacts_db.rs
kjuulh cb7f01e85d
All checks were successful
continuous-integration/drone/push Build is passing
chore: replace axum republish of async trait with actual async trait
2025-01-10 00:02:50 +01:00

130 lines
3.0 KiB
Rust

use std::sync::Arc;
use sqlx::{prelude::FromRow, PgPool};
use self::defaults::DefaultArtifactsDB;
#[derive(Clone, Debug)]
pub struct AddCommitArtifact {
pub app: String,
pub branch: String,
pub artifact_id: uuid::Uuid,
}
#[derive(Clone, Debug, FromRow)]
pub struct Artifact {
pub app: String,
pub branch: String,
pub artifact_id: uuid::Uuid,
pub created_at: chrono::NaiveDateTime,
}
#[derive(Clone, Debug)]
pub struct GetLatestArtifact {
pub app: String,
pub branch: String,
}
pub mod traits {
use super::{AddCommitArtifact, Artifact, GetLatestArtifact};
#[async_trait::async_trait]
pub trait ArtifactsDB {
async fn commit_artifact(&self, commit_artifact: AddCommitArtifact) -> anyhow::Result<()>;
async fn get_latest_artifact(
&self,
get_latest_artifact: GetLatestArtifact,
) -> anyhow::Result<Artifact>;
}
}
pub mod defaults {
use sqlx::PgPool;
use super::{traits, AddCommitArtifact, Artifact, GetLatestArtifact};
pub struct DefaultArtifactsDB {
db: PgPool,
}
impl DefaultArtifactsDB {
pub fn new(db: PgPool) -> Self {
Self { db }
}
}
#[async_trait::async_trait]
impl traits::ArtifactsDB for DefaultArtifactsDB {
async fn commit_artifact(&self, commit_artifact: AddCommitArtifact) -> anyhow::Result<()> {
sqlx::query("INSERT INTO artifacts (app, branch, artifact_id) VALUES ($1, $2, $3)")
.bind(commit_artifact.app)
.bind(commit_artifact.branch)
.bind(commit_artifact.artifact_id)
.execute(&self.db)
.await?;
Ok(())
}
async fn get_latest_artifact(
&self,
get_latest_artifact: GetLatestArtifact,
) -> anyhow::Result<Artifact> {
let artifact = sqlx::query_as::<_, Artifact>(
"SELECT
*
FROM
artifacts
WHERE
app = $1 AND
branch = $2
ORDER BY created_at DESC
LIMIT 1",
)
.bind(get_latest_artifact.app)
.bind(get_latest_artifact.branch)
.fetch_one(&self.db)
.await?;
Ok(artifact)
}
}
}
#[derive(Clone)]
pub struct ArtifactsDB {
inner: Arc<dyn traits::ArtifactsDB + Send + Sync>,
}
impl ArtifactsDB {
pub fn new(db: PgPool) -> Self {
Self {
inner: Arc::new(DefaultArtifactsDB::new(db)),
}
}
}
impl std::ops::Deref for ArtifactsDB {
type Target = Arc<dyn traits::ArtifactsDB + Send + Sync>;
fn deref(&self) -> &Self::Target {
&self.inner
}
}
pub mod extensions {
use crate::app::App;
use super::ArtifactsDB;
pub trait ArtifactsDBExt {
fn artifacts_db(&self) -> ArtifactsDB;
}
impl ArtifactsDBExt for App {
fn artifacts_db(&self) -> ArtifactsDB {
ArtifactsDB::new(self.database.clone())
}
}
}