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

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