mockforge_recorder/
sync_snapshots.rs

1//! Shadow Snapshot Mode - Store canonical before/after datasets per endpoint scenario
2//!
3//! This module provides functionality to store snapshots of API responses before and after
4//! sync operations, enabling timeline visualization of how endpoints evolve over time.
5
6use crate::diff::ComparisonResult;
7use chrono::{DateTime, Utc};
8use serde::{Deserialize, Serialize};
9use serde_json::Value;
10use std::collections::HashMap;
11
12/// Snapshot data for a single point in time
13#[derive(Debug, Clone, Serialize, Deserialize)]
14pub struct SnapshotData {
15    /// HTTP status code
16    pub status_code: u16,
17    /// Response headers
18    pub headers: HashMap<String, String>,
19    /// Response body as raw bytes
20    pub body: Vec<u8>,
21    /// Response body as parsed JSON (if applicable)
22    pub body_json: Option<Value>,
23}
24
25/// Sync snapshot capturing before/after state for an endpoint
26#[derive(Debug, Clone, Serialize, Deserialize)]
27pub struct SyncSnapshot {
28    /// Unique snapshot ID
29    pub id: String,
30    /// Endpoint path (e.g., "/api/users/{id}")
31    pub endpoint: String,
32    /// HTTP method (e.g., "GET", "POST")
33    pub method: String,
34    /// Sync cycle ID (groups snapshots from the same sync operation)
35    pub sync_cycle_id: String,
36    /// Timestamp when snapshot was created
37    pub timestamp: DateTime<Utc>,
38    /// Original fixture data (before sync)
39    pub before: SnapshotData,
40    /// New upstream response (after sync)
41    pub after: SnapshotData,
42    /// Comparison result showing differences
43    pub changes: ComparisonResult,
44    /// Response time before sync (milliseconds)
45    pub response_time_before: Option<u64>,
46    /// Response time after sync (milliseconds)
47    pub response_time_after: Option<u64>,
48}
49
50impl SyncSnapshot {
51    /// Create a new sync snapshot
52    pub fn new(
53        endpoint: String,
54        method: String,
55        sync_cycle_id: String,
56        before: SnapshotData,
57        after: SnapshotData,
58        changes: ComparisonResult,
59        response_time_before: Option<u64>,
60        response_time_after: Option<u64>,
61    ) -> Self {
62        let id = format!(
63            "snapshot_{}_{}_{}",
64            endpoint.replace('/', "_").replace('{', "").replace('}', ""),
65            method.to_lowercase(),
66            uuid::Uuid::new_v4().to_string()[..8].to_string()
67        );
68
69        Self {
70            id,
71            endpoint,
72            method,
73            sync_cycle_id,
74            timestamp: Utc::now(),
75            before,
76            after,
77            changes,
78            response_time_before,
79            response_time_after,
80        }
81    }
82}
83
84/// Timeline data for visualizing endpoint evolution
85#[derive(Debug, Clone, Serialize, Deserialize)]
86pub struct EndpointTimeline {
87    /// Endpoint path
88    pub endpoint: String,
89    /// HTTP method
90    pub method: String,
91    /// List of snapshots in chronological order
92    pub snapshots: Vec<SyncSnapshot>,
93    /// Response time trends (timestamp -> response_time_ms)
94    pub response_time_trends: Vec<(DateTime<Utc>, Option<u64>)>,
95    /// Status code changes over time (timestamp -> status_code)
96    pub status_code_history: Vec<(DateTime<Utc>, u16)>,
97    /// Common error patterns detected
98    pub error_patterns: Vec<ErrorPattern>,
99}
100
101/// Error pattern detected in response history
102#[derive(Debug, Clone, Serialize, Deserialize)]
103pub struct ErrorPattern {
104    /// Status code
105    pub status_code: u16,
106    /// Error message pattern (if extractable)
107    pub message_pattern: Option<String>,
108    /// Number of occurrences
109    pub occurrences: usize,
110    /// First occurrence timestamp
111    pub first_seen: DateTime<Utc>,
112    /// Last occurrence timestamp
113    pub last_seen: DateTime<Utc>,
114}
115
116/// Summary statistics for endpoint evolution
117#[derive(Debug, Clone, Serialize, Deserialize)]
118pub struct EndpointEvolutionSummary {
119    /// Endpoint path
120    pub endpoint: String,
121    /// HTTP method
122    pub method: String,
123    /// Total number of snapshots
124    pub total_snapshots: usize,
125    /// Number of changes detected
126    pub total_changes: usize,
127    /// Average response time (milliseconds)
128    pub avg_response_time: Option<f64>,
129    /// Most common status code
130    pub most_common_status: Option<u16>,
131    /// Field-level change frequency (field_path -> count)
132    pub field_change_frequency: HashMap<String, usize>,
133}