Skip to main content

cognee_http_server/dto/
sync.rs

1//! DTOs for `/api/v1/sync` and `/api/v1/sync/status`.
2//!
3//! All envelope shapes match Python — including the deviation from the
4//! canonical `{"detail": ...}` envelope. The 4xx/5xx body for these
5//! endpoints is `{"error": "..."}`, never `{"detail": ...}`.
6
7use serde::{Deserialize, Serialize};
8use utoipa::ToSchema;
9use uuid::Uuid;
10
11/// `POST /api/v1/sync` request body.
12///
13/// Pydantic: `dataset_ids: Optional[List[UUID]] = None`. Inherits `InDTO`,
14/// so the wire is camelCase (`datasetIds`); snake_case is accepted as an
15/// inbound alias.
16#[derive(Debug, Clone, Default, Deserialize, ToSchema)]
17#[serde(rename_all = "camelCase")]
18pub struct SyncRequestDTO {
19    /// `None` or `[]` means "all writable datasets for the caller".
20    #[serde(default, alias = "dataset_ids")]
21    pub dataset_ids: Option<Vec<Uuid>>,
22}
23
24/// 200 response body for `POST /api/v1/sync`.
25///
26/// `run_id` stays `String` (not `Uuid`) so the wire shape matches Python's
27/// `str` annotation byte-for-byte.
28#[derive(Debug, Clone, Serialize, ToSchema)]
29#[serde(rename_all = "snake_case")]
30pub struct SyncResponseDTO {
31    pub run_id: String,
32    pub status: String,
33    pub dataset_ids: Vec<String>,
34    pub dataset_names: Vec<String>,
35    pub message: String,
36    pub timestamp: String,
37    pub user_id: String,
38}
39
40/// 409 body when another sync is already running for the user.
41#[derive(Debug, Clone, Serialize, ToSchema)]
42#[serde(rename_all = "snake_case")]
43pub struct SyncConflictDTO {
44    pub error: String,
45    pub details: SyncConflictDetailsDTO,
46}
47
48#[derive(Debug, Clone, Serialize, ToSchema)]
49#[serde(rename_all = "snake_case")]
50pub struct SyncConflictDetailsDTO {
51    pub run_id: String,
52    pub status: String,
53    pub dataset_ids: Vec<Uuid>,
54    pub dataset_names: Vec<String>,
55    pub message: String,
56    pub timestamp: String,
57    pub progress_percentage: u32,
58}
59
60/// 200 response body for `GET /api/v1/sync/status`.
61#[derive(Debug, Clone, Serialize, ToSchema)]
62#[serde(rename_all = "snake_case")]
63pub struct SyncStatusOverviewDTO {
64    pub has_running_sync: bool,
65    pub running_sync_count: usize,
66    #[serde(skip_serializing_if = "Option::is_none")]
67    pub latest_running_sync: Option<LatestRunningSyncDTO>,
68}
69
70#[derive(Debug, Clone, Serialize, ToSchema)]
71#[serde(rename_all = "snake_case")]
72pub struct LatestRunningSyncDTO {
73    pub run_id: String,
74    pub dataset_ids: Vec<Uuid>,
75    pub dataset_names: Vec<String>,
76    pub progress_percentage: u32,
77    pub created_at: Option<String>,
78}
79
80/// `{"error": "..."}` envelope used by the simpler error paths in this router.
81///
82/// Differs from the canonical `{"detail": "..."}` envelope on purpose.
83#[derive(Debug, Clone, Serialize, ToSchema)]
84#[serde(rename_all = "snake_case")]
85pub struct SyncErrorDTO {
86    pub error: String,
87}