Skip to main content

context69_contracts/
tasks.rs

1use chrono::{DateTime, Utc};
2use schemars::JsonSchema;
3use serde::{Deserialize, Serialize};
4use serde_json::Value;
5use utoipa::{IntoParams, ToSchema};
6use uuid::Uuid;
7
8use crate::{
9    GroupResponse, ImportLibraryFileFromUrlRequest, LibraryFileUploadMetadata,
10    UpsertLibraryTextRequest,
11};
12
13#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize, ToSchema, JsonSchema)]
14#[serde(rename_all = "snake_case")]
15pub enum TaskKind {
16    SourceSync,
17    TextBatch,
18    FileBatch,
19    UrlBatch,
20    DeleteBatch,
21    Translation,
22    VectorRebuild,
23}
24
25impl TaskKind {
26    pub fn as_str(self) -> &'static str {
27        match self {
28            Self::SourceSync => "source_sync",
29            Self::TextBatch => "text_batch",
30            Self::FileBatch => "file_batch",
31            Self::UrlBatch => "url_batch",
32            Self::DeleteBatch => "delete_batch",
33            Self::Translation => "translation",
34            Self::VectorRebuild => "vector_rebuild",
35        }
36    }
37}
38
39#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize, ToSchema, JsonSchema)]
40#[serde(rename_all = "snake_case")]
41pub enum TaskStatus {
42    Queued,
43    Running,
44    Waiting,
45    Succeeded,
46    Failed,
47    Cancelled,
48}
49
50impl TaskStatus {
51    pub fn as_str(self) -> &'static str {
52        match self {
53            Self::Queued => "queued",
54            Self::Running => "running",
55            Self::Waiting => "waiting",
56            Self::Succeeded => "succeeded",
57            Self::Failed => "failed",
58            Self::Cancelled => "cancelled",
59        }
60    }
61}
62
63#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize, ToSchema, JsonSchema)]
64#[serde(rename_all = "snake_case")]
65pub enum TaskItemStatus {
66    Queued,
67    Running,
68    Waiting,
69    Succeeded,
70    Failed,
71    Cancelled,
72}
73
74impl TaskItemStatus {
75    pub fn as_str(self) -> &'static str {
76        match self {
77            Self::Queued => "queued",
78            Self::Running => "running",
79            Self::Waiting => "waiting",
80            Self::Succeeded => "succeeded",
81            Self::Failed => "failed",
82            Self::Cancelled => "cancelled",
83        }
84    }
85}
86
87#[derive(Debug, Clone, Serialize, Deserialize, ToSchema, JsonSchema)]
88pub struct TaskRef {
89    pub task_id: Uuid,
90    #[serde(default)]
91    pub item_ids: Vec<Uuid>,
92}
93
94#[derive(Debug, Clone, Serialize, Deserialize, ToSchema, JsonSchema)]
95pub struct TaskProgress {
96    pub total: i64,
97    pub queued: i64,
98    pub running: i64,
99    pub waiting: i64,
100    pub succeeded: i64,
101    pub failed: i64,
102    pub cancelled: i64,
103}
104
105#[derive(Debug, Clone, Serialize, Deserialize, ToSchema, JsonSchema)]
106pub struct TaskResponse {
107    pub task_id: Uuid,
108    pub kind: TaskKind,
109    pub status: TaskStatus,
110    pub group_path: Option<String>,
111    pub source_key: Option<String>,
112    pub stage: Option<String>,
113    pub waiting_reason: Option<String>,
114    pub dependency_key: Option<String>,
115    pub progress: TaskProgress,
116    pub failure_stage: Option<String>,
117    pub error_summary: Option<String>,
118    pub eta_seconds: Option<i64>,
119    pub created_at: DateTime<Utc>,
120    pub started_at: Option<DateTime<Utc>>,
121    pub finished_at: Option<DateTime<Utc>>,
122    pub updated_at: DateTime<Utc>,
123}
124
125#[derive(Debug, Clone, Serialize, Deserialize, ToSchema, JsonSchema)]
126pub struct TaskItemResponse {
127    pub item_id: Uuid,
128    pub ordinal: i32,
129    pub status: TaskItemStatus,
130    pub resource_id: Option<String>,
131    pub file_id: Option<Uuid>,
132    pub stage: Option<String>,
133    pub waiting_reason: Option<String>,
134    pub dependency_key: Option<String>,
135    pub next_attempt_at: Option<DateTime<Utc>>,
136    pub failure_stage: Option<String>,
137    pub error_message: Option<String>,
138    pub attempt_count: i32,
139    pub retryable: bool,
140    pub created_at: DateTime<Utc>,
141    pub started_at: Option<DateTime<Utc>>,
142    pub finished_at: Option<DateTime<Utc>>,
143}
144
145#[derive(Debug, Clone, Serialize, Deserialize, IntoParams, ToSchema)]
146#[into_params(parameter_in = Query)]
147pub struct TaskListQuery {
148    #[serde(default = "default_page")]
149    pub page: u32,
150    #[serde(default = "default_page_size")]
151    pub page_size: u32,
152    #[serde(default)]
153    pub query: Option<String>,
154    #[serde(default)]
155    pub kind: Option<TaskKind>,
156    #[serde(default)]
157    pub status: Option<TaskStatus>,
158    #[serde(default)]
159    pub stage: Option<String>,
160    #[serde(default)]
161    pub waiting_reason: Option<String>,
162    #[serde(default)]
163    pub dependency_key: Option<String>,
164}
165
166#[derive(Debug, Clone, Serialize, Deserialize, ToSchema, JsonSchema)]
167pub struct TaskPageResponse {
168    pub items: Vec<TaskResponse>,
169    pub pagination: crate::Pagination,
170}
171
172#[derive(Debug, Clone, Serialize, Deserialize, ToSchema, JsonSchema)]
173pub struct TaskItemsResponse {
174    pub items: Vec<TaskItemResponse>,
175    pub next_cursor: Option<String>,
176}
177
178#[derive(Debug, Clone, Serialize, Deserialize, IntoParams, ToSchema)]
179#[into_params(parameter_in = Query)]
180pub struct TaskItemsQuery {
181    #[serde(default = "default_item_limit")]
182    pub limit: u32,
183    #[serde(default)]
184    pub cursor: Option<String>,
185}
186
187#[derive(Debug, Clone, Serialize, Deserialize, ToSchema, JsonSchema)]
188pub struct ScopeSpec {
189    pub group_path: String,
190    pub name: String,
191    pub visibility: crate::Visibility,
192    #[serde(default)]
193    pub kind: Option<crate::GroupKind>,
194    #[serde(default)]
195    pub metadata_indexes: Vec<ScopeMetadataIndex>,
196}
197
198#[derive(Debug, Clone, Serialize, Deserialize, ToSchema, JsonSchema)]
199pub struct ScopeMetadataIndex {
200    pub source_key: String,
201    #[serde(flatten)]
202    pub definition: crate::CreateMetadataIndexRequest,
203}
204
205#[derive(Debug, Clone, Serialize, Deserialize, ToSchema)]
206pub struct EnsureScopeResponse {
207    pub group: GroupResponse,
208    pub metadata_indexes: Vec<crate::MetadataIndexResponse>,
209}
210
211#[derive(Debug, Clone, Serialize, Deserialize, ToSchema)]
212pub struct TextBatchRequest {
213    pub items: Vec<UpsertLibraryTextRequest>,
214}
215
216#[derive(Debug, Clone, Serialize, Deserialize, ToSchema)]
217pub struct UrlBatchRequest {
218    pub items: Vec<ImportLibraryFileFromUrlRequest>,
219}
220
221#[derive(Debug, Clone, Serialize, Deserialize, ToSchema)]
222pub struct DeleteBatchRequest {
223    pub items: Vec<crate::DocumentKey>,
224}
225
226#[derive(Debug, Clone, Serialize, Deserialize, ToSchema)]
227pub struct FileBatchItem {
228    pub filename: String,
229    pub media_type: String,
230    pub content_base64: String,
231    #[serde(default, skip_serializing_if = "Option::is_none")]
232    pub declared_sha256: Option<String>,
233    #[serde(default)]
234    pub folder_id: Option<Uuid>,
235    #[serde(default)]
236    pub metadata: Option<LibraryFileUploadMetadata>,
237    #[serde(default)]
238    pub translation: Option<crate::TranslationDirective>,
239}
240
241#[derive(Debug, Clone, Serialize, Deserialize, ToSchema)]
242pub struct FileBatchRequest {
243    pub items: Vec<FileBatchItem>,
244}
245
246#[derive(Debug, Clone, Serialize, Deserialize, ToSchema, JsonSchema)]
247pub struct GenericTaskRequest {
248    pub kind: TaskKind,
249    #[serde(default)]
250    pub group_path: Option<String>,
251    #[serde(default)]
252    pub source_key: Option<String>,
253    #[serde(default)]
254    pub items: Vec<Value>,
255}
256
257#[derive(Debug, Clone, Serialize, Deserialize, ToSchema, JsonSchema)]
258pub struct TaskRetryResponse {
259    pub task: TaskRef,
260    pub retried_items: i64,
261}
262
263#[derive(Debug, Clone, Serialize, Deserialize, ToSchema, JsonSchema)]
264pub struct RerunTaskResponse {
265    pub task: TaskRef,
266}
267
268#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize, ToSchema, JsonSchema)]
269#[serde(rename_all = "snake_case")]
270pub enum TaskPurgeMode {
271    Expired,
272    AllTerminal,
273}
274
275#[derive(Debug, Clone, Serialize, Deserialize, ToSchema, JsonSchema)]
276pub struct TaskMaintenanceSettings {
277    pub cleanup_enabled: bool,
278    pub retention_days: i64,
279    pub updated_at: DateTime<Utc>,
280}
281
282#[derive(Debug, Clone, Serialize, Deserialize, ToSchema, JsonSchema)]
283pub struct TaskMaintenanceStats {
284    pub total: i64,
285    pub queued: i64,
286    pub running: i64,
287    pub waiting: i64,
288    pub succeeded: i64,
289    pub failed: i64,
290    pub cancelled: i64,
291    pub active: i64,
292    pub expired_terminal: i64,
293}
294
295#[derive(Debug, Clone, Serialize, Deserialize, ToSchema, JsonSchema)]
296pub struct TaskMaintenanceOverview {
297    pub settings: TaskMaintenanceSettings,
298    pub stats: TaskMaintenanceStats,
299}
300
301#[derive(Debug, Clone, Serialize, Deserialize, ToSchema, JsonSchema)]
302pub struct UpdateTaskMaintenanceSettingsRequest {
303    pub cleanup_enabled: bool,
304    pub retention_days: i64,
305}
306
307#[derive(Debug, Clone, Serialize, Deserialize, ToSchema, JsonSchema)]
308pub struct CancelActiveTasksResponse {
309    pub cancelled_tasks: i64,
310}
311
312#[derive(Debug, Clone, Serialize, Deserialize, ToSchema, JsonSchema)]
313pub struct PurgeTasksRequest {
314    pub mode: TaskPurgeMode,
315}
316
317#[derive(Debug, Clone, Serialize, Deserialize, ToSchema, JsonSchema)]
318pub struct PurgeTasksResponse {
319    pub deleted_tasks: i64,
320}
321
322fn default_page() -> u32 {
323    1
324}
325
326fn default_page_size() -> u32 {
327    50
328}
329
330fn default_item_limit() -> u32 {
331    100
332}