omni_orchestrator/schemas/v1/db/queries/
deployment.rs

1// db/queries/deployment.rs
2use crate::models::deployment::Deployment;
3use anyhow::Context;
4use sqlx::{MySql, Pool};
5
6/// Retrieves a paginated list of deployments from the database.
7pub async fn list_deployments(pool: &Pool<MySql>, page: i64, per_page: i64) -> anyhow::Result<Vec<Deployment>> {
8    println!("Attempting to fetch deployments from database...");
9
10    let result = sqlx::query_as::<_, Deployment>(
11        r#"
12        SELECT *
13        FROM deployments
14        ORDER BY created_at DESC
15        LIMIT ? OFFSET ?
16        "#,
17    )
18    .bind(per_page)
19    .bind(page * per_page)
20    .fetch_all(pool)
21    .await;
22
23    match result {
24        Ok(deployments) => {
25            println!("Successfully fetched {} deployments", deployments.len());
26            Ok(deployments)
27        }
28        Err(e) => {
29            eprintln!("Error fetching deployments: {:#?}", e);
30            Err(anyhow::Error::new(e).context("Failed to fetch deployments"))
31        }
32    }
33}
34
35/// Counts the total number of deployments in the database.
36pub async fn count_deployments(pool: &Pool<MySql>) -> anyhow::Result<i64> {
37    let count = sqlx::query_scalar::<_, i64>("SELECT COUNT(*) FROM deployments")
38        .fetch_one(pool)
39        .await
40        .context("Failed to count deployments")?;
41
42    Ok(count)
43}
44
45/// Retrieves a specific deployment by its unique identifier.
46pub async fn get_deployment_by_id(pool: &Pool<MySql>, id: i64) -> anyhow::Result<Deployment> {
47    let deployment = sqlx::query_as::<_, Deployment>("SELECT * FROM deployments WHERE id = ?")
48        .bind(id)
49        .fetch_one(pool)
50        .await
51        .context("Failed to fetch deployment")?;
52
53    Ok(deployment)
54}
55
56/// Retrieves all deployments for a specific application with pagination.
57pub async fn list_deployments_by_app(
58    pool: &Pool<MySql>, 
59    app_id: i64, 
60    page: i64, 
61    per_page: i64
62) -> anyhow::Result<Vec<Deployment>> {
63    let deployments = sqlx::query_as::<_, Deployment>(
64        "SELECT * FROM deployments WHERE app_id = ? ORDER BY created_at DESC LIMIT ? OFFSET ?"
65    )
66        .bind(app_id)
67        .bind(per_page)
68        .bind(page * per_page)
69        .fetch_all(pool)
70        .await
71        .context("Failed to fetch app deployments")?;
72
73    Ok(deployments)
74}
75
76/// Counts the number of deployments for a specific application.
77pub async fn count_deployments_by_app(pool: &Pool<MySql>, app_id: i64) -> anyhow::Result<i64> {
78    let count = sqlx::query_scalar::<_, i64>(
79        "SELECT COUNT(*) FROM deployments WHERE app_id = ?"
80    )
81    .bind(app_id)
82    .fetch_one(pool)
83    .await
84    .context("Failed to count deployments by app_id")?;
85
86    Ok(count)
87}
88
89/// Creates a new deployment in the database.
90pub async fn create_deployment(
91    pool: &Pool<MySql>,
92    app_id: i64,
93    build_id: i64,
94    version: &str,
95    deployment_strategy: &str,
96    previous_deployment_id: Option<i64>,
97    canary_percentage: Option<i64>,
98    environment_variables: Option<serde_json::Value>,
99    annotations: Option<serde_json::Value>,
100    labels: Option<serde_json::Value>,
101    created_by: Option<i64>,
102) -> anyhow::Result<Deployment> {
103    // Begin transaction
104    let mut tx = pool.begin().await?;
105
106    // Insert new deployment
107    let deployment = sqlx::query_as::<_, Deployment>(
108        r#"INSERT INTO deployments (
109            app_id, build_id, version, status, deployment_strategy, 
110            previous_deployment_id, canary_percentage, environment_variables,
111            annotations, labels, created_at, created_by
112        ) VALUES (?, ?, ?, 'pending', ?, ?, ?, ?, ?, ?, CURRENT_TIMESTAMP, ?)"#,
113    )
114    .bind(app_id)
115    .bind(build_id)
116    .bind(version)
117    .bind(deployment_strategy)
118    .bind(previous_deployment_id)
119    .bind(canary_percentage)
120    .bind(environment_variables)
121    .bind(annotations)
122    .bind(labels)
123    .bind(created_by)
124    .fetch_one(&mut *tx)
125    .await
126    .context("Failed to create deployment")?;
127
128    // Commit transaction
129    tx.commit().await?;
130
131    // Return newly created deployment
132    Ok(deployment)
133}
134
135/// Updates the status of an existing deployment.
136pub async fn update_deployment_status(
137    pool: &Pool<MySql>,
138    id: i64,
139    status: &str,
140    error_message: Option<&str>,
141) -> anyhow::Result<Deployment> {
142    let mut tx = pool.begin().await?;
143
144    // Update fields based on the new status
145    let deployment = match status {
146        "in_progress" => {
147            sqlx::query_as::<_, Deployment>(
148                "UPDATE deployments SET status = ?, started_at = CURRENT_TIMESTAMP WHERE id = ?"
149            )
150            .bind(status)
151            .bind(id)
152            .fetch_one(&mut *tx)
153            .await
154        },
155        "deployed" | "failed" | "canceled" => {
156            sqlx::query_as::<_, Deployment>(
157                "UPDATE deployments SET status = ?, completed_at = CURRENT_TIMESTAMP, 
158                deployment_duration = TIMESTAMPDIFF(SECOND, started_at, CURRENT_TIMESTAMP),
159                error_message = ? WHERE id = ?"
160            )
161            .bind(status)
162            .bind(error_message)
163            .bind(id)
164            .fetch_one(&mut *tx)
165            .await
166        },
167        _ => {
168            sqlx::query_as::<_, Deployment>(
169                "UPDATE deployments SET status = ? WHERE id = ?"
170            )
171            .bind(status)
172            .bind(id)
173            .fetch_one(&mut *tx)
174            .await
175        }
176    }.context("Failed to update deployment status")?;
177
178    tx.commit().await?;
179    Ok(deployment)
180}
181
182/// Deletes a deployment from the database.
183pub async fn delete_deployment(pool: &Pool<MySql>, id: i64) -> anyhow::Result<()> {
184    let mut tx = pool.begin().await?;
185
186    sqlx::query("DELETE FROM deployments WHERE id = ?")
187        .bind(id)
188        .execute(&mut *tx)
189        .await
190        .context("Failed to delete deployment")?;
191
192    tx.commit().await?;
193    Ok(())
194}