Skip to main content

max / makenotwork

2.7 KB · 81 lines History Blame Raw
1 //! The push/pull changelog wire types, shared by personal sync and group
2 //! sync and by nothing else.
3 //!
4 //! Six types is the whole shared surface between [`super::sync`] and
5 //! [`super::groups`]; a seventh belongs in whichever of them uses it.
6
7 use chrono::{DateTime, Utc};
8 use serde::{Deserialize, Serialize};
9
10 use crate::db::{SyncDeviceId, SyncOperation};
11
12 #[derive(Deserialize, utoipa::ToSchema)]
13 pub(crate) struct PushRequest {
14 #[schema(value_type = String)]
15 pub device_id: SyncDeviceId,
16 /// Client-generated UUID for idempotent push. If a push with the same
17 /// batch_id has already been committed, the server returns the existing
18 /// cursor without re-inserting.
19 pub batch_id: uuid::Uuid,
20 pub changes: Vec<ChangeEntry>,
21 }
22
23 #[derive(Deserialize, utoipa::ToSchema)]
24 pub(crate) struct ChangeEntry {
25 pub table: String,
26 #[schema(value_type = String)]
27 pub op: SyncOperation,
28 pub row_id: String,
29 #[schema(value_type = String)]
30 pub timestamp: DateTime<Utc>,
31 pub data: Option<serde_json::Value>,
32 }
33
34 #[derive(Serialize, utoipa::ToSchema)]
35 pub(crate) struct PushResponse {
36 pub(super) cursor: i64,
37 }
38
39 #[derive(Deserialize, utoipa::ToSchema)]
40 pub(crate) struct PullRequest {
41 #[schema(value_type = String)]
42 pub device_id: SyncDeviceId,
43 pub cursor: i64,
44 /// Optional table name filter; only return entries for these tables.
45 #[serde(default)]
46 pub tables: Option<Vec<String>>,
47 /// Optional timestamp filter; only return entries at or after this time.
48 #[serde(default)]
49 #[schema(value_type = Option<String>)]
50 pub since: Option<DateTime<Utc>>,
51 }
52
53 #[derive(Serialize, utoipa::ToSchema)]
54 pub(crate) struct PullResponse {
55 pub(super) changes: Vec<PullChangeEntry>,
56 pub(super) cursor: i64,
57 pub(super) has_more: bool,
58 }
59
60 #[derive(Serialize, utoipa::ToSchema)]
61 pub(crate) struct PullChangeEntry {
62 pub(super) seq: i64,
63 #[schema(value_type = String)]
64 pub(super) device_id: SyncDeviceId,
65 pub(super) table: String,
66 pub(super) op: String,
67 pub(super) row_id: String,
68 #[schema(value_type = String)]
69 pub(super) timestamp: DateTime<Utc>,
70 pub(super) data: Option<serde_json::Value>,
71 /// Which encryption key was used. Null means key_id 1 (pre-rotation).
72 #[serde(skip_serializing_if = "Option::is_none")]
73 pub(super) key_id: Option<i32>,
74 /// For a group entry, the GCK generation its ciphertext is sealed under. The
75 /// member resolves that generation's grant to decrypt it, which is how entries
76 /// written before a rotation stay readable. Absent on personal entries, which
77 /// key off `key_id` instead.
78 #[serde(skip_serializing_if = "Option::is_none")]
79 pub(super) gck_version: Option<i32>,
80 }
81