persistence_lifecycle/
persistence_lifecycle.rs1use spatio::{Config, DBBuilder, Point, SetOptions, Spatio, SyncPolicy};
12use std::time::Duration;
13
14fn main() -> Result<(), Box<dyn std::error::Error>> {
15 println!("=== SpatioLite Persistence Lifecycle Demo ===\n");
16
17 demo_basic_persistence()?;
19
20 demo_custom_aof_path()?;
22
23 demo_spatial_persistence()?;
25
26 demo_graceful_shutdown()?;
28
29 demo_config_based_persistence()?;
31
32 println!("\n=== All demos completed successfully! ===");
33 Ok(())
34}
35
36fn demo_basic_persistence() -> Result<(), Box<dyn std::error::Error>> {
38 println!("--- Demo 1: Basic Persistence ---");
39
40 let db_path = "/tmp/spatio_demo_basic.db";
41
42 {
44 println!("Session 1: Writing data...");
45 let db = Spatio::open(db_path)?;
46
47 db.insert("user:001", b"Alice Johnson", None)?;
48 db.insert("user:002", b"Bob Smith", None)?;
49 db.insert("counter", b"42", None)?;
50
51 println!(" ✓ Inserted 3 keys");
52 println!(" ✓ Database will automatically sync on drop");
53
54 }
56
57 {
59 println!("Session 2: Reading data (automatic startup replay)...");
60 let db = Spatio::open(db_path)?;
61
62 let alice = db.get("user:001")?.unwrap();
63 let bob = db.get("user:002")?.unwrap();
64 let counter = db.get("counter")?.unwrap();
65
66 println!(
67 " ✓ Retrieved user:001: {:?}",
68 String::from_utf8_lossy(&alice)
69 );
70 println!(
71 " ✓ Retrieved user:002: {:?}",
72 String::from_utf8_lossy(&bob)
73 );
74 println!(
75 " ✓ Retrieved counter: {:?}",
76 String::from_utf8_lossy(&counter)
77 );
78
79 let stats = db.stats()?;
80 println!(" ✓ Total keys: {}", stats.key_count);
81 }
82
83 println!();
84 Ok(())
85}
86
87fn demo_custom_aof_path() -> Result<(), Box<dyn std::error::Error>> {
89 println!("--- Demo 2: Custom AOF Path ---");
90
91 let aof_path = "/tmp/spatio_custom.aof";
92
93 {
95 println!("Session 1: Creating database with custom AOF path...");
96 let db = DBBuilder::new().aof_path(aof_path).build()?;
97
98 db.insert("config:version", b"1.0.0", None)?;
99 db.insert("config:environment", b"production", None)?;
100
101 println!(" ✓ AOF file: {}", aof_path);
102 println!(" ✓ Inserted configuration data");
103
104 db.sync()?;
106 println!(" ✓ Manually synced to disk");
107 }
108
109 {
111 println!("Session 2: Reopening database...");
112 let db = DBBuilder::new().aof_path(aof_path).build()?;
113
114 let version = db.get("config:version")?.unwrap();
115 let environment = db.get("config:environment")?.unwrap();
116
117 println!(" ✓ Version: {}", String::from_utf8_lossy(&version));
118 println!(" ✓ Environment: {}", String::from_utf8_lossy(&environment));
119 }
120
121 println!();
122 Ok(())
123}
124
125fn demo_spatial_persistence() -> Result<(), Box<dyn std::error::Error>> {
127 println!("--- Demo 3: Spatial Data Persistence ---");
128
129 let db_path = "/tmp/spatio_demo_spatial.db";
130
131 {
133 println!("Session 1: Inserting spatial data...");
134 let db = Spatio::open(db_path)?;
135
136 let cities = vec![
138 ("New York", Point::new(40.7128, -74.0060)),
139 ("Los Angeles", Point::new(34.0522, -118.2437)),
140 ("Chicago", Point::new(41.8781, -87.6298)),
141 ("Houston", Point::new(29.7604, -95.3698)),
142 ("Phoenix", Point::new(33.4484, -112.0740)),
143 ];
144
145 for (name, point) in cities {
146 db.insert_point("cities", &point, name.as_bytes(), None)?;
147 println!(" ✓ Inserted city: {}", name);
148 }
149
150 let stats = db.stats()?;
151 println!(" ✓ Total keys: {}", stats.key_count);
152 }
153
154 {
156 println!("Session 2: Querying spatial data (indexes rebuilt)...");
157 let db = Spatio::open(db_path)?;
158
159 let nyc = Point::new(40.7128, -74.0060);
161 let nearby = db.query_within_radius("cities", &nyc, 500_000.0, 10)?; println!(
164 " ✓ Found {} cities within 500km of New York:",
165 nearby.len()
166 );
167 for (point, data) in nearby {
168 let name = String::from_utf8_lossy(&data);
169 println!(" - {} at ({:.4}, {:.4})", name, point.lat, point.lon);
170 }
171
172 let count = db.count_within_radius("cities", &nyc, 500_000.0)?;
174 println!(" ✓ Count verification: {} cities", count);
175 }
176
177 println!();
178 Ok(())
179}
180
181fn demo_graceful_shutdown() -> Result<(), Box<dyn std::error::Error>> {
183 println!("--- Demo 4: Graceful Shutdown ---");
184
185 let db_path = "/tmp/spatio_demo_shutdown.db";
186
187 println!("Creating database and inserting critical data...");
188 let mut db = Spatio::open(db_path)?;
189
190 db.insert("transaction:001", b"payment_processed", None)?;
192 db.insert("transaction:002", b"refund_pending", None)?;
193
194 println!(" ✓ Critical data inserted");
195
196 db.sync()?;
198 println!(" ✓ Forced sync to disk");
199
200 let opts = SetOptions::with_ttl(Duration::from_secs(300));
202 db.insert("session:xyz", b"temporary_session", Some(opts))?;
203 println!(" ✓ Added temporary session with 5-minute TTL");
204
205 println!("Performing explicit graceful shutdown...");
207 match db.close() {
208 Ok(_) => println!(" ✓ Database closed successfully"),
209 Err(e) => {
210 eprintln!(" ✗ Error during close: {}", e);
211 return Err(e.into());
212 }
213 }
214
215 match db.insert("should_fail", b"data", None) {
217 Err(e) => println!(" ✓ Correctly rejected operation on closed database: {}", e),
218 Ok(_) => println!(" ✗ Unexpectedly accepted operation on closed database"),
219 }
220
221 println!();
222 Ok(())
223}
224
225fn demo_config_based_persistence() -> Result<(), Box<dyn std::error::Error>> {
227 println!("--- Demo 5: Configuration-Based Persistence ---");
228
229 {
231 println!("Config 1: Always sync (maximum durability)");
232 let config = Config::default().with_sync_policy(SyncPolicy::Always);
233
234 let db = DBBuilder::new()
235 .aof_path("/tmp/spatio_always_sync.aof")
236 .config(config)
237 .build()?;
238
239 db.insert("critical:data", b"financial_transaction", None)?;
240 println!(" ✓ Every write immediately synced to disk");
241 }
242
243 {
245 println!("Config 2: Sync every second (recommended)");
246 let config = Config::with_geohash_precision(10)
247 .with_sync_policy(SyncPolicy::EverySecond)
248 .with_default_ttl(Duration::from_secs(3600));
249
250 let db = DBBuilder::new()
251 .aof_path("/tmp/spatio_balanced.aof")
252 .config(config)
253 .build()?;
254
255 db.insert("balanced:data", b"application_data", None)?;
256 println!(" ✓ High precision (10) with periodic sync");
257 println!(" ✓ Default TTL: 1 hour");
258 }
259
260 {
262 println!("Config 3: In-memory (no persistence)");
263 let db = DBBuilder::new().in_memory().build()?;
264
265 db.insert("cache:key", b"temporary_value", None)?;
266 println!(" ✓ Fast in-memory storage, no disk I/O");
267 }
268
269 println!();
270 Ok(())
271}