1use std::path::Path;
2
3use osmic_core::error::{OsmicError, OsmicResult};
4use serde::{Deserialize, Serialize};
5
6#[derive(Debug, Clone, Serialize, Deserialize)]
8pub struct ReplicationState {
9 pub sequence_number: u64,
10 pub timestamp: String,
11 pub base_url: String,
12}
13
14impl ReplicationState {
15 pub fn load(state_dir: &Path) -> OsmicResult<Self> {
17 let path = state_dir.join("state.json");
18 let data = std::fs::read_to_string(&path)
19 .map_err(|e| OsmicError::Other(format!("Failed to read state: {e}")))?;
20 serde_json::from_str(&data)
21 .map_err(|e| OsmicError::Other(format!("Failed to parse state: {e}")))
22 }
23
24 pub fn save(&self, state_dir: &Path) -> OsmicResult<()> {
26 std::fs::create_dir_all(state_dir)
27 .map_err(|e| OsmicError::Other(format!("Failed to create state dir: {e}")))?;
28 let path = state_dir.join("state.json");
29 let data = serde_json::to_string_pretty(self)
30 .map_err(|e| OsmicError::Other(format!("Failed to serialize state: {e}")))?;
31 std::fs::write(&path, data)
32 .map_err(|e| OsmicError::Other(format!("Failed to write state: {e}")))
33 }
34
35 pub fn next_osc_url(&self) -> String {
40 let seq = self.sequence_number + 1;
41 let a = seq / 1_000_000;
42 let b = (seq / 1_000) % 1_000;
43 let c = seq % 1_000;
44 format!(
45 "{}/{:03}/{:03}/{:03}.osc.gz",
46 self.base_url.trim_end_matches('/'),
47 a,
48 b,
49 c
50 )
51 }
52
53 pub fn init(base_url: &str, sequence_number: u64) -> Self {
55 Self {
56 sequence_number,
57 timestamp: String::new(),
58 base_url: base_url.to_string(),
59 }
60 }
61}