Skip to main content

oxigeo_distributed/
lib.rs

1//! OxiGeo Distributed Processing
2//!
3//! This crate provides distributed processing capabilities for large-scale geospatial
4//! workflows using Apache Arrow Flight for zero-copy data transfer.
5//!
6//! # Features
7//!
8//! - **Arrow Flight RPC**: Zero-copy data transfer between nodes
9//! - **Worker Nodes**: Execute processing tasks with resource management
10//! - **Coordinator**: Schedule and manage distributed execution
11//! - **Data Partitioning**: Spatial, hash, range, and load-balanced partitioning
12//! - **Shuffle Operations**: Efficient data redistribution for group-by and joins
13//! - **Fault Tolerance**: Automatic retry and failure recovery
14//! - **Progress Monitoring**: Real-time tracking of distributed execution
15//!
16//! # Architecture
17//!
18//! ```text
19//! ┌─────────────┐
20//! │ Coordinator │ ──── Schedules tasks
21//! └──────┬──────┘
22//!        │
23//!   ┌────┴────┐
24//!   │  Flight │
25//!   │  Server │
26//!   └────┬────┘
27//!        │
28//!   ┌────┴────────────────┐
29//!   │                     │
30//! ┌─▼──────┐         ┌───▼─────┐
31//! │ Worker │         │ Worker  │
32//! │ Node 1 │         │ Node 2  │
33//! └────────┘         └─────────┘
34//! ```
35//!
36//! # Example: Distributed NDVI Calculation
37//!
38//! ```rust,no_run
39//! use oxigeo_distributed::*;
40//! # async fn example() -> std::result::Result<(), Box<dyn std::error::Error>> {
41//!
42//! // Create coordinator
43//! let config = CoordinatorConfig::new("localhost:50051".to_string());
44//! let coordinator = Coordinator::new(config);
45//!
46//! // Add workers
47//! coordinator.add_worker("worker-1".to_string(), "localhost:50052".to_string())?;
48//! coordinator.add_worker("worker-2".to_string(), "localhost:50053".to_string())?;
49//!
50//! // Partition data spatially
51//! let extent = SpatialExtent::new(0.0, 0.0, 1000.0, 1000.0)?;
52//! let partitioner = TilePartitioner::new(extent, 4, 4)?;
53//! let partitions = partitioner.partition();
54//!
55//! // Submit tasks for each partition
56//! for partition in partitions {
57//!     coordinator.submit_task(
58//!         partition.id,
59//!         TaskOperation::CalculateIndex {
60//!             index_type: "NDVI".to_string(),
61//!             bands: vec![3, 4], // Red and NIR
62//!         },
63//!     )?;
64//! }
65//!
66//! // Monitor progress
67//! while !coordinator.is_complete() {
68//!     let progress = coordinator.get_progress()?;
69//!     println!(
70//!         "Progress: {}/{} completed",
71//!         progress.completed_tasks,
72//!         progress.total_tasks()
73//!     );
74//!     tokio::time::sleep(tokio::time::Duration::from_secs(1)).await;
75//! }
76//!
77//! // Collect results
78//! let results = coordinator.collect_results()?;
79//! println!("Processing complete: {} results", results.len());
80//! # Ok(())
81//! # }
82//! ```
83//!
84//! # Example: Custom Processing with Workers
85//!
86//! ```rust,no_run
87//! use oxigeo_distributed::*;
88//! # async fn example() -> std::result::Result<(), Box<dyn std::error::Error>> {
89//!
90//! // Create worker
91//! let config = WorkerConfig::new("worker-1".to_string())
92//!     .with_max_concurrent_tasks(4)
93//!     .with_memory_limit(8 * 1024 * 1024 * 1024); // 8 GB
94//!
95//! let worker = Worker::new(config);
96//!
97//! // Serve the worker over Arrow Flight so a coordinator can dispatch tasks to
98//! // it end-to-end via `Coordinator::dispatch_task_to_worker` (which ships the
99//! // task + its input partition through the `execute_task` Flight action):
100//! let flight_server = FlightServer::new().with_worker(std::sync::Arc::new(worker));
101//! let _service = flight_server.into_service();
102//! // tonic::transport::Server::builder().add_service(_service).serve(addr).await?;
103//! # Ok(())
104//! # }
105//! ```
106//!
107//! # Example: Data Shuffle
108//!
109//! ```rust,no_run
110//! use oxigeo_distributed::*;
111//! use arrow::array::{Int32Array, StringArray};
112//! use arrow::datatypes::{DataType, Field, Schema};
113//! use arrow::record_batch::RecordBatch;
114//! use std::sync::Arc;
115//!
116//! # fn example() -> std::result::Result<(), Box<dyn std::error::Error>> {
117//! // Create test data
118//! let schema = Arc::new(Schema::new(vec![
119//!     Field::new("id", DataType::Int32, false),
120//!     Field::new("name", DataType::Utf8, false),
121//! ]));
122//!
123//! let batch = RecordBatch::try_new(
124//!     schema,
125//!     vec![
126//!         Arc::new(Int32Array::from(vec![1, 2, 3, 4, 5])),
127//!         Arc::new(StringArray::from(vec!["a", "b", "c", "d", "e"])),
128//!     ],
129//! )?;
130//!
131//! // Hash shuffle by ID column
132//! let shuffle = HashShuffle::new("id".to_string(), 2)?;
133//! let partitions = shuffle.shuffle(&batch)?;
134//!
135//! println!("Data shuffled into {} partitions", partitions.len());
136//! # Ok(())
137//! # }
138//! ```
139
140#![deny(clippy::unwrap_used)]
141#![deny(clippy::panic)]
142#![warn(missing_docs)]
143#![warn(clippy::expect_used)]
144
145pub mod coordinator;
146pub mod error;
147pub mod flight;
148pub mod operations;
149pub mod partition;
150pub mod shuffle;
151pub mod task;
152pub mod worker;
153
154// Re-export main types
155pub use coordinator::{Coordinator, CoordinatorConfig, CoordinatorProgress, WorkerInfo};
156pub use error::{DistributedError, Result};
157pub use flight::{FlightClient, FlightServer};
158pub use partition::{
159    HashPartitioner, LoadBalancedPartitioner, Partition, PartitionStrategy, RangePartitioner,
160    SpatialExtent, StripPartitioner, TilePartitioner,
161};
162pub use shuffle::{
163    BroadcastShuffle, HashShuffle, RangeShuffle, ShuffleConfig, ShuffleKey, ShuffleResult,
164    ShuffleStats, ShuffleType,
165};
166pub use task::{
167    PartitionId, Task, TaskContext, TaskId, TaskOperation, TaskResult, TaskScheduler, TaskStatus,
168};
169pub use worker::{Worker, WorkerConfig, WorkerHealthCheck, WorkerMetrics, WorkerStatus};
170
171#[cfg(test)]
172mod tests {
173    use super::*;
174
175    #[test]
176    fn test_exports() {
177        // Verify that main types are exported
178        let _config: CoordinatorConfig;
179        let _worker_config: WorkerConfig;
180        let _task_id: TaskId;
181        let _partition_id: PartitionId;
182    }
183}