statsig_rust/specs_adapter/
specs_adapter_trait.rs1use crate::statsig_err::StatsigErr;
2use crate::StatsigRuntime;
3use async_trait::async_trait;
4use serde::Deserialize;
5use serde::Serialize;
6use std::fmt::{self, Debug};
7use std::sync::Arc;
8use tokio::time::Duration;
9
10#[repr(u8)]
11#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
12pub enum SpecsSource {
13 Uninitialized = 0,
14 NoValues,
15 Error,
16 Loading,
17 Network,
18 Bootstrap,
19 Adapter(String),
20}
21
22impl fmt::Display for SpecsSource {
23 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
24 let s = match self {
25 SpecsSource::Adapter(name) => {
26 let type_name = format!("Adapter{name}");
27 type_name
28 }
29 SpecsSource::Uninitialized => "Uninitialized".to_string(),
30 SpecsSource::NoValues => "NoValues".to_string(),
31 SpecsSource::Error => "Error".to_string(),
32 SpecsSource::Loading => "Loading".to_string(),
33 SpecsSource::Network => "Network".to_string(),
34 SpecsSource::Bootstrap => "Bootstrap".to_string(),
35 };
36 write!(f, "{s}")
37 }
38}
39
40#[async_trait]
41pub trait SpecsAdapter: Send + Sync {
42 fn initialize(&self, listener: Arc<dyn SpecsUpdateListener>);
43
44 async fn start(
45 self: Arc<Self>,
46 statsig_runtime: &Arc<StatsigRuntime>,
47 ) -> Result<(), StatsigErr>;
48
49 async fn shutdown(
50 &self,
51 timeout: Duration,
52 statsig_runtime: &Arc<StatsigRuntime>,
53 ) -> Result<(), StatsigErr>;
54
55 async fn schedule_background_sync(
56 self: Arc<Self>,
57 statsig_runtime: &Arc<StatsigRuntime>,
58 ) -> Result<(), StatsigErr>;
59
60 fn get_type_name(&self) -> String;
61}
62
63pub struct SpecsUpdate {
64 pub data: String,
65 pub source: SpecsSource,
66 pub received_at: u64,
67}
68
69#[repr(C)]
70#[derive(Serialize, Deserialize, Debug)]
71pub struct SpecsInfo {
72 pub lcut: Option<u64>,
73 pub checksum: Option<String>,
74 pub source: SpecsSource,
75}
76
77impl SpecsInfo {
78 #[must_use]
79 pub fn empty() -> Self {
80 Self {
81 lcut: None,
82 checksum: None,
83 source: SpecsSource::NoValues,
84 }
85 }
86
87 #[must_use]
88 pub fn error() -> Self {
89 Self {
90 lcut: None,
91 checksum: None,
92 source: SpecsSource::Error,
93 }
94 }
95}
96
97pub trait SpecsUpdateListener: Send + Sync {
98 fn did_receive_specs_update(&self, update: SpecsUpdate) -> Result<(), StatsigErr>;
99
100 fn get_current_specs_info(&self) -> SpecsInfo;
101}
102
103impl fmt::Debug for dyn SpecsAdapter {
104 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
105 write!(f, "{}", self.get_type_name())
106 }
107}