telemetry_kit/sync/
mod.rs

1//! Sync protocol implementation for telemetry-kit
2//!
3//! This module handles synchronization of local events to the telemetry-kit.dev service
4//! using HMAC-SHA256 authentication.
5
6mod auth;
7mod client;
8mod config;
9mod retry;
10
11pub use auth::HmacAuth;
12pub use client::SyncClient;
13pub use config::{SyncConfig, SyncConfigBuilder};
14pub use retry::RetryStrategy;
15
16use serde::{Deserialize, Serialize};
17
18/// Response from the sync endpoint
19#[derive(Debug, Serialize, Deserialize)]
20#[serde(tag = "status")]
21pub enum SyncResponse {
22    /// All events accepted
23    #[serde(rename = "success")]
24    Success {
25        /// Number of events accepted
26        accepted: usize,
27        /// Number of events rejected
28        rejected: usize,
29        /// Success message
30        message: String,
31    },
32
33    /// Partial success (some events rejected)
34    #[serde(rename = "partial")]
35    Partial {
36        /// Number of events accepted
37        accepted: usize,
38        /// Number of events rejected
39        rejected: usize,
40        /// Error details for rejected events
41        errors: Vec<EventError>,
42    },
43}
44
45/// Error for a specific event
46#[derive(Debug, Serialize, Deserialize)]
47pub struct EventError {
48    /// Event ID that failed
49    pub event_id: uuid::Uuid,
50    /// Error code
51    pub error: String,
52    /// Human-readable error message
53    pub message: String,
54}
55
56/// Error response from server
57#[derive(Debug, Serialize, Deserialize)]
58pub struct ErrorResponse {
59    /// Error code
60    pub error: String,
61    /// Error message
62    pub message: String,
63    /// Additional details
64    #[serde(skip_serializing_if = "Option::is_none")]
65    pub details: Option<String>,
66    /// Retry after (for 429 responses)
67    #[serde(skip_serializing_if = "Option::is_none")]
68    pub retry_after: Option<u64>,
69}
70
71impl SyncResponse {
72    /// Get the number of accepted events
73    pub fn accepted(&self) -> usize {
74        match self {
75            SyncResponse::Success { accepted, .. } => *accepted,
76            SyncResponse::Partial { accepted, .. } => *accepted,
77        }
78    }
79
80    /// Get the number of rejected events
81    pub fn rejected(&self) -> usize {
82        match self {
83            SyncResponse::Success { rejected, .. } => *rejected,
84            SyncResponse::Partial { rejected, .. } => *rejected,
85        }
86    }
87
88    /// Check if all events were accepted
89    pub fn is_success(&self) -> bool {
90        matches!(self, SyncResponse::Success { .. })
91    }
92}