scout_rs 0.95.95

A Rust client for the synchornizing state with the Scout database
Documentation
use serde::{Deserialize, Serialize};

#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
#[serde(rename_all = "snake_case")]
pub enum AnalysisWorkStatus {
    Waiting,
    Cancelled,
    Processing,
    Failed,
    Success,
}

impl Default for AnalysisWorkStatus {
    fn default() -> Self {
        Self::Waiting
    }
}

impl AnalysisWorkStatus {
    pub const fn as_str(self) -> &'static str {
        match self {
            Self::Waiting => "waiting",
            Self::Cancelled => "cancelled",
            Self::Processing => "processing",
            Self::Failed => "failed",
            Self::Success => "success",
        }
    }
}

/// Annotation/review workflow state (analysis_jobs.review_status / analysis_tasks.review_status).
#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
#[serde(rename_all = "snake_case")]
pub enum ReviewStatus {
    Pending,
    Annotating,
    InReview,
    Completed,
    Rejected,
}

impl Default for ReviewStatus {
    fn default() -> Self {
        Self::Pending
    }
}

impl ReviewStatus {
    pub const fn as_str(self) -> &'static str {
        match self {
            Self::Pending => "pending",
            Self::Annotating => "annotating",
            Self::InReview => "in_review",
            Self::Completed => "completed",
            Self::Rejected => "rejected",
        }
    }
}

#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
pub struct AnalysisJob {
    #[serde(skip_serializing_if = "Option::is_none")]
    pub id: Option<i64>,
    #[serde(skip_serializing_if = "Option::is_none")]
    pub timestamp_requested: Option<String>,
    #[serde(skip_serializing_if = "Option::is_none")]
    pub timestamp_started: Option<String>,
    #[serde(skip_serializing_if = "Option::is_none")]
    pub timestamp_finished: Option<String>,
    #[serde(skip_serializing_if = "Option::is_none")]
    pub inserted_at: Option<String>,
    /// Matches `analysis_jobs.job_type` (NOT NULL in DB; default `''`). Default allows JSON without this key.
    #[serde(default, skip_serializing_if = "Option::is_none")]
    pub job_type: Option<String>,
    #[serde(skip_serializing_if = "Option::is_none")]
    pub status: Option<AnalysisWorkStatus>,
    /// Annotation/review workflow state; independent of `status` (execution).
    #[serde(default, skip_serializing_if = "Option::is_none")]
    pub review_status: Option<ReviewStatus>,
    #[serde(default, skip_serializing_if = "Option::is_none")]
    pub assignee_user_id: Option<String>,
    #[serde(default, skip_serializing_if = "Option::is_none")]
    pub reviewer_user_id: Option<String>,
}

impl Default for AnalysisJob {
    fn default() -> Self {
        Self {
            id: None,
            timestamp_requested: None,
            timestamp_started: None,
            timestamp_finished: None,
            inserted_at: None,
            job_type: None,
            status: None,
            review_status: None,
            assignee_user_id: None,
            reviewer_user_id: None,
        }
    }
}

#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
pub struct AnalysisTask {
    #[serde(skip_serializing_if = "Option::is_none")]
    pub id: Option<i64>,
    #[serde(skip_serializing_if = "Option::is_none")]
    pub job_id: Option<i64>,
    #[serde(skip_serializing_if = "Option::is_none")]
    pub time_started: Option<String>,
    #[serde(skip_serializing_if = "Option::is_none")]
    pub time_finished: Option<String>,
    #[serde(skip_serializing_if = "Option::is_none")]
    pub status: Option<AnalysisWorkStatus>,
    #[serde(skip_serializing_if = "Option::is_none")]
    pub event_id: Option<i64>,
    #[serde(skip_serializing_if = "Option::is_none")]
    pub artifact_id: Option<i64>,
    #[serde(skip_serializing_if = "Option::is_none")]
    pub execution_environment: Option<String>,
    #[serde(skip_serializing_if = "Option::is_none")]
    pub task_type: Option<String>,
    #[serde(skip_serializing_if = "Option::is_none")]
    pub gpu_seconds: Option<f64>,
    #[serde(skip_serializing_if = "Option::is_none")]
    pub gpu_memory_peak: Option<i64>,
    #[serde(skip_serializing_if = "Option::is_none")]
    pub cpu_core_seconds: Option<f64>,
    #[serde(skip_serializing_if = "Option::is_none")]
    pub cpu_memory_avg: Option<f64>,
    #[serde(skip_serializing_if = "Option::is_none")]
    pub frames_processed: Option<i64>,
    #[serde(skip_serializing_if = "Option::is_none")]
    pub model_id: Option<i64>,
    /// Annotation/review workflow state; independent of `status` (execution).
    #[serde(default, skip_serializing_if = "Option::is_none")]
    pub review_status: Option<ReviewStatus>,
    #[serde(default, skip_serializing_if = "Option::is_none")]
    pub assignee_user_id: Option<String>,
    #[serde(default, skip_serializing_if = "Option::is_none")]
    pub reviewer_user_id: Option<String>,
}

impl AnalysisTask {
    pub fn new(
        job_id: i64,
        execution_environment: impl Into<String>,
        task_type: impl Into<String>,
    ) -> Self {
        Self {
            id: None,
            job_id: Some(job_id),
            time_started: None,
            time_finished: None,
            status: None,
            event_id: None,
            artifact_id: None,
            execution_environment: Some(execution_environment.into()),
            task_type: Some(task_type.into()),
            gpu_seconds: None,
            gpu_memory_peak: None,
            cpu_core_seconds: None,
            cpu_memory_avg: None,
            frames_processed: None,
            model_id: None,
            review_status: None,
            assignee_user_id: None,
            reviewer_user_id: None,
        }
    }
}