omni_orchestrator/schemas/v1/db/queries/
deployment.rs1use crate::models::deployment::Deployment;
3use anyhow::Context;
4use sqlx::{MySql, Pool};
5
6pub 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
35pub 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
45pub 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
56pub 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
76pub 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
89pub 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 let mut tx = pool.begin().await?;
105
106 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 tx.commit().await?;
130
131 Ok(deployment)
133}
134
135pub 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 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
182pub 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}