comprehensive_demo/
comprehensive_demo.rs

1use spatio::{Point, SetOptions, Spatio, TemporalPoint};
2use std::time::{Duration, UNIX_EPOCH};
3
4fn main() -> Result<(), Box<dyn std::error::Error>> {
5    println!("=== Spatio - Comprehensive Demo ===\n");
6
7    let mut db = Spatio::memory()?;
8    println!("✓ Created in-memory database\n");
9
10    // === 1. BASIC KEY-VALUE OPERATIONS ===
11    println!("1. Basic Key-Value Operations");
12    println!("------------------------------");
13
14    db.insert("app:name", b"Spatio Demo", None)?;
15    db.insert("app:version", b"1.0.0", None)?;
16    db.insert("user:alice", b"Alice Johnson", None)?;
17
18    let app_name = db.get("app:name")?.unwrap();
19    println!("   Stored: {}", String::from_utf8_lossy(&app_name));
20
21    let count = db.stats().key_count;
22    println!("   Total keys: {}\n", count);
23
24    // === 2. TTL (TIME-TO-LIVE) ===
25    println!("2. TTL (Time-to-Live)");
26    println!("---------------------");
27
28    let session_opts = SetOptions::with_ttl(Duration::from_secs(10));
29    db.insert("session:temp", b"expires_soon", Some(session_opts))?;
30    println!("   Created session with 10-second TTL");
31
32    let cache_opts = SetOptions::with_ttl(Duration::from_secs(300));
33    db.insert("cache:weather", b"sunny, 22C", Some(cache_opts))?;
34    println!("   Cached data with 5-minute TTL\n");
35
36    // === 3. ATOMIC BATCH OPERATIONS ===
37    println!("3. Atomic Batch Operations");
38    println!("--------------------------");
39
40    db.atomic(|batch| {
41        batch.insert("sensor:temp", b"23.5", None)?;
42        batch.insert("sensor:humidity", b"68", None)?;
43        batch.insert("sensor:pressure", b"1013", None)?;
44        Ok(())
45    })?;
46    println!("   Atomically inserted 3 sensor readings\n");
47
48    // === 4. SPATIAL POINT STORAGE ===
49    println!("4. Spatial Point Storage");
50    println!("------------------------");
51
52    let cities = vec![
53        ("New York", Point::new(-74.0060, 40.7128)),
54        ("London", Point::new(-0.1278, 51.5074)),
55        ("Paris", Point::new(2.3522, 48.8566)),
56        ("Tokyo", Point::new(139.6503, 35.6762)),
57        ("Sydney", Point::new(151.2093, -33.8688)),
58    ];
59
60    for (name, point) in &cities {
61        db.insert_point("cities", point, name.as_bytes(), None)?;
62    }
63    println!("   Stored {} cities with spatial indexing", cities.len());
64
65    // Find nearby cities
66    let london = Point::new(-0.1278, 51.5074);
67    let nearby = db.query_within_radius("cities", &london, 1_000_000.0, 10)?;
68    println!("   Cities within 1000km of London: {}", nearby.len());
69    for (_, data, _) in &nearby {
70        println!("     - {}", String::from_utf8_lossy(data));
71    }
72    println!();
73
74    // === 5. SPATIAL QUERIES ===
75    println!("5. Spatial Query Methods");
76    println!("------------------------");
77
78    // Existence check
79    let has_nearby = db.intersects_radius("cities", &london, 500_000.0)?;
80    println!("   Cities within 500km of London exist: {}", has_nearby);
81
82    // Count points
83    let count = db.count_within_radius("cities", &london, 2_000_000.0)?;
84    println!("   Cities within 2000km of London: {}", count);
85
86    // Bounding box query (Europe)
87    let europe = db.find_within_bounds("cities", -10.0, 40.0, 20.0, 60.0, 10)?;
88    println!("   Cities in European bounding box: {}", europe.len());
89    for (_point, data) in europe {
90        println!("     - {}", String::from_utf8_lossy(&data));
91    }
92    println!();
93
94    // === 6. POINTS OF INTEREST ===
95    println!("6. Multiple Namespaces (POI)");
96    println!("----------------------------");
97
98    let landmarks = vec![
99        ("Big Ben", Point::new(-0.1245, 51.4994)),
100        ("Tower Bridge", Point::new(-0.0754, 51.5055)),
101        ("London Eye", Point::new(-0.1195, 51.5033)),
102    ];
103
104    for (name, point) in &landmarks {
105        db.insert_point("landmarks", point, name.as_bytes(), None)?;
106    }
107    println!("   Added {} London landmarks", landmarks.len());
108
109    // Query different namespaces
110    let nearby_landmarks = db.query_within_radius("landmarks", &london, 5_000.0, 10)?;
111    println!(
112        "   Landmarks within 5km of London: {}",
113        nearby_landmarks.len()
114    );
115    for (_, data, _) in &nearby_landmarks {
116        println!("     - {}", String::from_utf8_lossy(data));
117    }
118    println!();
119
120    // === 7. TRAJECTORY TRACKING ===
121    println!("7. Trajectory Tracking");
122    println!("----------------------");
123
124    let delivery_route = vec![
125        TemporalPoint {
126            point: Point::new(-0.1278, 51.5074),
127            timestamp: UNIX_EPOCH + Duration::from_secs(1640995200),
128        },
129        TemporalPoint {
130            point: Point::new(-0.0931, 51.5055),
131            timestamp: UNIX_EPOCH + Duration::from_secs(1640995260),
132        },
133        TemporalPoint {
134            point: Point::new(-0.0865, 51.5045),
135            timestamp: UNIX_EPOCH + Duration::from_secs(1640995320),
136        },
137        TemporalPoint {
138            point: Point::new(-0.1245, 51.4994),
139            timestamp: UNIX_EPOCH + Duration::from_secs(1640995380),
140        },
141    ];
142
143    db.insert_trajectory("delivery:truck001", &delivery_route, None)?;
144    println!(
145        "   Stored delivery trajectory ({} waypoints)",
146        delivery_route.len()
147    );
148
149    // Query trajectory for time range
150    let path = db.query_trajectory("delivery:truck001", 1640995200, 1640995320)?;
151    println!(
152        "   Retrieved {} waypoints for first 2 minutes\n",
153        path.len()
154    );
155
156    // === 8. DATA UPDATES & DELETES ===
157    println!("8. Updates and Deletes");
158    println!("----------------------");
159
160    // Update existing key
161    db.insert("app:version", b"1.0.1", None)?;
162    let new_version = db.get("app:version")?.unwrap();
163    println!(
164        "   Updated version to: {}",
165        String::from_utf8_lossy(&new_version)
166    );
167
168    // Delete key
169    let deleted = db.delete("user:alice")?;
170    println!("   Deleted key: {}", deleted.is_some());
171    println!();
172
173    // === 9. DATABASE STATISTICS ===
174    println!("9. Database Statistics");
175    println!("----------------------");
176
177    let stats = db.stats();
178    println!("   Total keys: {}", stats.key_count);
179    println!("   Total operations: {}\n", stats.operations_count);
180
181    // === 10. TTL EXPIRATION DEMO (LAZY) ===
182    println!("10. TTL Expiration (lazy deletion)");
183    println!("-----------------------------------");
184
185    std::thread::sleep(Duration::from_secs(11));
186
187    match db.get("session:temp")? {
188        Some(_) => println!("   Session still active (unexpected)"),
189        None => println!("   ✓ Session expired (lazy check on read)\n"),
190    }
191
192    // === 11. MANUAL CLEANUP ===
193    println!("11. Manual Cleanup");
194    println!("------------------");
195    let removed = db.cleanup_expired()?;
196    println!("   Removed {} expired keys from storage\n", removed);
197
198    println!("=== Comprehensive Demo Complete! ===");
199    println!("\nFeatures Demonstrated:");
200    println!("  • Key-value storage");
201    println!("  • TTL (lazy expiration + manual cleanup)");
202    println!("  • Atomic batch operations");
203    println!("  • Spatial point indexing");
204    println!("  • Radius queries");
205    println!("  • Bounding box queries");
206    println!("  • Multiple namespaces");
207    println!("  • Trajectory tracking");
208    println!("  • Updates and deletes");
209    println!("  • Manual expired key cleanup");
210
211    Ok(())
212}