autopulse_database/
models.rs1use autopulse_utils::{generate_uuid, Rewrite};
2use chrono::NaiveDateTime;
3use diesel::prelude::*;
4use serde::Serialize;
5use std::fmt::Display;
6
7#[derive(Serialize)]
9pub enum ProcessStatus {
10 Pending,
11 Complete,
12 Retry,
13 Failed,
14}
15
16#[derive(Serialize)]
20pub enum FoundStatus {
21 Found,
22 NotFound,
23 HashMismatch,
24}
25
26impl Display for FoundStatus {
27 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
28 let status = match self {
29 Self::Found => "found",
30 Self::NotFound => "not_found",
31 Self::HashMismatch => "hash_mismatch",
32 };
33
34 write!(f, "{status}")
35 }
36}
37
38impl From<FoundStatus> for String {
39 fn from(val: FoundStatus) -> Self {
40 val.to_string()
41 }
42}
43
44impl From<ProcessStatus> for String {
45 fn from(val: ProcessStatus) -> Self {
46 match val {
47 ProcessStatus::Pending => "pending",
48 ProcessStatus::Complete => "complete",
49 ProcessStatus::Retry => "retry",
50 ProcessStatus::Failed => "failed",
51 }
52 .to_string()
53 }
54}
55
56#[derive(
60 Queryable, Selectable, Serialize, Clone, Debug, AsChangeset, Identifiable, Hash, Eq, PartialEq,
61)]
62#[diesel(table_name = crate::schema::scan_events)]
63pub struct ScanEvent {
64 pub id: String,
66
67 pub event_source: String,
69 pub event_timestamp: NaiveDateTime,
71
72 pub file_path: String,
74 pub file_hash: Option<String>,
76 pub process_status: String,
78 pub found_status: String,
80
81 pub failed_times: i32,
83 pub next_retry_at: Option<chrono::NaiveDateTime>,
85
86 pub targets_hit: String,
88
89 pub found_at: Option<chrono::NaiveDateTime>,
91 pub processed_at: Option<chrono::NaiveDateTime>,
93
94 pub created_at: NaiveDateTime,
96 pub updated_at: NaiveDateTime,
98
99 pub can_process: NaiveDateTime,
101}
102
103impl ScanEvent {
104 pub fn get_targets_hit(&self) -> Vec<String> {
105 self.targets_hit
106 .split(',')
107 .map(|s| s.to_string())
108 .filter(|s| !s.is_empty())
109 .collect()
110 }
111
112 pub fn add_target_hit(&mut self, target: &str) {
113 let mut targets = self.get_targets_hit();
114 targets.push(target.to_string());
115 targets.sort();
116 targets.dedup();
117 self.targets_hit = targets.join(",");
118 }
119
120 pub fn get_path(&self, rewrite: &Option<Rewrite>) -> String {
121 rewrite.as_ref().map_or_else(
122 || self.file_path.clone(),
123 |rewrite| rewrite.rewrite_path(self.file_path.clone()),
124 )
125 }
126}
127
128#[derive(Insertable)]
129#[diesel(table_name = crate::schema::scan_events)]
130#[doc(hidden)]
131pub struct NewScanEvent {
132 pub id: String,
133 pub event_source: String,
134
135 pub file_path: String,
136 pub file_hash: Option<String>,
137
138 pub found_status: String,
139 pub can_process: NaiveDateTime,
140}
141
142impl Default for NewScanEvent {
143 fn default() -> Self {
144 Self {
145 id: generate_uuid(),
146 event_source: "unknown".to_string(),
147 file_path: "unknown".to_string(),
148 file_hash: None,
149 found_status: FoundStatus::NotFound.into(),
150 can_process: chrono::Utc::now().naive_utc(),
151 }
152 }
153}