Repository: TabbyML/tabby
File: ee/tabby-db/src/job_runs.rs (Rust)

Code before:
            job_id,
        ).execute(&self.pool).await?;
        Ok(())
    }

    pub async fn get_latest_job_run(&self, command: String) -> Option<JobRunDAO> {
        sqlx::query_as(
            r#"SELECT * FROM job_runs WHERE command = ? ORDER BY created_at DESC LIMIT 1"#,
        )
        .bind(command)
        .fetch_optional(&self.pool)
        .await
        .ok()
        .flatten()
    }

    pub async fn delete_pending_job_run(&self, command: &str) -> Result<usize> {
        // Delete jobs that are not started and doesn't have an exit code.
        let num_deleted = query!("UPDATE job_runs SET exit_code = -1, end_ts = datetime('now'), updated_at = datetime('now') WHERE exit_code IS NULL AND started_at IS NULL AND command = ?", command)
            .execute(&self.pool)
            .await?.rows_affected();

        Ok(num_deleted as usize)
    }

    pub async fn delete_jobs_before(&self, before: DateTime<Utc>) -> Result<usize> {
        let before = before.as_sqlite_datetime();
        let num_deleted = query!(
            "delete FROM job_runs WHERE updated_at < ? AND exit_code IS NOT NULL",
            before,
        )
        .execute(&self.pool)
        .await?
        .rows_affected();

        Ok(num_deleted as usize)
    }

    pub async fn list_job_runs_with_filter(
        &self,
        ids: Option<Vec<i32>>,
        jobs: Option<Vec<String>>,
        limit: Option<usize>,
        skip_id: Option<i32>,
        backwards: bool,
    ) -> Result<Vec<JobRunDAO>> {
        let mut conditions = vec![];

        if let Some(ids) = ids {
            let ids: Vec<String> = ids.iter().map(i32::to_string).collect();
            let ids = ids.join(", ");

Review comment (suggestion):
```suggestion
    pub async fn delete_job_run_before_three_months(&self) -> Result<usize> {
```

Code after:
            job_id,
        ).execute(&self.pool).await?;
        Ok(())
    }

    pub async fn get_latest_job_run(&self, command: String) -> Option<JobRunDAO> {
        sqlx::query_as(
            r#"SELECT * FROM job_runs WHERE command = ? ORDER BY created_at DESC LIMIT 1"#,
        )
        .bind(command)
        .fetch_optional(&self.pool)
        .await
        .ok()
        .flatten()
    }

    pub async fn delete_pending_job_run(&self, command: &str) -> Result<usize> {
        // Delete jobs that are not started and doesn't have an exit code.
        let num_deleted = query!("UPDATE job_runs SET exit_code = -1, end_ts = datetime('now'), updated_at = datetime('now') WHERE exit_code IS NULL AND started_at IS NULL AND command = ?", command)
            .execute(&self.pool)
            .await?.rows_affected();

        Ok(num_deleted as usize)
    }

    pub async fn delete_job_run_before_three_months(&self, now: DateTime<Utc>) -> Result<usize> {
        if let Some(three_months_ago) = now.checked_sub_months(Months::new(3)) {
            let three_months_ago = three_months_ago.as_sqlite_datetime();
            let num_deleted = query!(
                "delete FROM job_runs WHERE updated_at < ? AND exit_code IS NOT NULL",
                three_months_ago,
            )
            .execute(&self.pool)
            .await?
            .rows_affected();

            Ok(num_deleted as usize)
        } else {
            Ok(0)
        }
    }

    pub async fn list_job_runs_with_filter(
        &self,
        ids: Option<Vec<i32>>,
        jobs: Option<Vec<String>>,
        limit: Option<usize>,
        skip_id: Option<i32>,
        backwards: bool,
    ) -> Result<Vec<JobRunDAO>> {
        let mut conditions = vec![];