Skip to main content

drasi_lib/config/
snapshot.rs

1// Copyright 2025 The Drasi Authors.
2//
3// Licensed under the Apache License, Version 2.0 (the "License");
4// you may not use this file except in compliance with the License.
5// You may obtain a copy of the License at
6//
7//     http://www.apache.org/licenses/LICENSE-2.0
8//
9// Unless required by applicable law or agreed to in writing, software
10// distributed under the License is distributed on an "AS IS" BASIS,
11// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12// See the License for the specific language governing permissions and
13// limitations under the License.
14
15//! Configuration snapshot types for capturing point-in-time instance state.
16//!
17//! A [`ConfigurationSnapshot`] captures the full topology, status, and configuration
18//! properties of all components in a drasi-lib instance. Hosts can serialize this
19//! snapshot to store it, and later use it to reconstruct an equivalent instance.
20//!
21//! **Important:** Sources and reactions are trait objects — their properties are
22//! captured but they cannot be automatically deserialized back into instances.
23//! The host must supply the appropriate plugin factories to reconstruct them.
24
25use std::collections::HashMap;
26
27use serde::{Deserialize, Serialize};
28
29use crate::channels::ComponentStatus;
30use crate::component_graph::GraphEdge;
31use crate::config::schema::QueryConfig;
32
33/// A point-in-time snapshot of the full drasi-lib instance configuration.
34///
35/// Contains the topology (components and dependency edges), lifecycle status,
36/// and configuration properties of every source, query, and reaction.
37///
38/// # Serialization
39///
40/// This type implements `Serialize` and `Deserialize`, so it can be stored
41/// as JSON, YAML, or any serde-compatible format.
42///
43/// # Example
44///
45/// ```no_run
46/// # use drasi_lib::DrasiLib;
47/// # async fn example(core: &DrasiLib) -> Result<(), Box<dyn std::error::Error>> {
48/// let snapshot = core.snapshot_configuration().await?;
49/// let json = serde_json::to_string_pretty(&snapshot)?;
50/// std::fs::write("config-snapshot.json", &json)?;
51/// # Ok(())
52/// # }
53/// ```
54#[derive(Debug, Clone, Serialize, Deserialize)]
55pub struct ConfigurationSnapshot {
56    /// Unique identifier of the drasi-lib instance
57    pub instance_id: String,
58    /// ISO 8601 timestamp when the snapshot was captured
59    pub timestamp: String,
60    /// All source components with their configuration properties
61    pub sources: Vec<SourceSnapshot>,
62    /// All query components with their full query configurations
63    pub queries: Vec<QuerySnapshot>,
64    /// All reaction components with their configuration properties
65    pub reactions: Vec<ReactionSnapshot>,
66    /// Dependency edges between components (source→query, query→reaction)
67    pub edges: Vec<GraphEdge>,
68}
69
70/// Snapshot of a source component's configuration.
71#[derive(Debug, Clone, Serialize, Deserialize)]
72pub struct SourceSnapshot {
73    /// Source component identifier
74    pub id: String,
75    /// Plugin type identifier (e.g., "postgres", "http", "grpc")
76    pub source_type: String,
77    /// Lifecycle status at the time of snapshot
78    pub status: ComponentStatus,
79    /// Whether the source was configured to auto-start
80    pub auto_start: bool,
81    /// Configuration properties from [`Source::properties()`], including secrets.
82    ///
83    /// This is the authoritative config used to persist and recreate the source.
84    /// It intentionally contains sensitive values — see the persistence contract
85    /// on [`Source::properties()`] for details.
86    pub properties: HashMap<String, serde_json::Value>,
87    /// Bootstrap provider configuration, if one is attached to this source
88    pub bootstrap_provider: Option<BootstrapSnapshot>,
89}
90
91/// Snapshot of a bootstrap provider's configuration.
92#[derive(Debug, Clone, Serialize, Deserialize)]
93pub struct BootstrapSnapshot {
94    /// Bootstrap provider kind (e.g., "postgres", "scriptfile", "noop")
95    pub kind: String,
96    /// Configuration properties for the bootstrap provider, including secrets.
97    pub properties: HashMap<String, serde_json::Value>,
98}
99
100/// Snapshot of a query component's configuration.
101#[derive(Debug, Clone, Serialize, Deserialize)]
102pub struct QuerySnapshot {
103    /// Query component identifier
104    pub id: String,
105    /// Full query configuration (query string, source subscriptions, joins, etc.)
106    pub config: QueryConfig,
107    /// Lifecycle status at the time of snapshot
108    pub status: ComponentStatus,
109}
110
111/// Snapshot of a reaction component's configuration.
112#[derive(Debug, Clone, Serialize, Deserialize)]
113pub struct ReactionSnapshot {
114    /// Reaction component identifier
115    pub id: String,
116    /// Plugin type identifier (e.g., "log", "http", "grpc")
117    pub reaction_type: String,
118    /// Lifecycle status at the time of snapshot
119    pub status: ComponentStatus,
120    /// Whether the reaction was configured to auto-start
121    pub auto_start: bool,
122    /// Query IDs this reaction subscribes to
123    pub queries: Vec<String>,
124    /// Configuration properties from [`Reaction::properties()`], including secrets.
125    ///
126    /// This is the authoritative config used to persist and recreate the reaction.
127    /// It intentionally contains sensitive values — see the persistence contract
128    /// on [`Reaction::properties()`] for details.
129    pub properties: HashMap<String, serde_json::Value>,
130}