1#![allow(clippy::field_reassign_with_default)]
53#![allow(clippy::single_match)]
54#![allow(clippy::collapsible_if)]
55#![allow(clippy::clone_on_copy)]
56#![allow(clippy::type_complexity)]
57#![allow(clippy::collapsible_match)]
58#![allow(clippy::manual_clamp)]
59#![allow(clippy::needless_range_loop)]
60#![allow(clippy::or_fun_call)]
61#![allow(clippy::if_same_then_else)]
62#![allow(clippy::only_used_in_recursion)]
63#![allow(clippy::new_without_default)]
64#![allow(clippy::derivable_impls)]
65#![allow(clippy::useless_conversion)]
66use serde::{Deserialize, Serialize};
67use std::collections::HashMap;
68use std::net::SocketAddr;
69use std::sync::Arc;
70use tokio::sync::RwLock;
71
72pub mod adaptive_leader_election;
73pub mod advanced_partitioning;
74pub mod advanced_storage;
75pub mod alerting;
76pub mod auto_scaling;
77pub mod backup_restore;
78pub mod circuit_breaker;
79pub mod cloud_integration;
80pub mod cluster_metrics;
81pub mod cluster_metrics_manager;
82pub mod cluster_metrics_stats;
83#[cfg(test)]
84mod cluster_metrics_tests;
85pub mod cluster_metrics_types;
86pub mod compression_strategy;
87pub mod conflict_resolution;
88pub mod consensus;
89pub mod crash_recovery;
90pub mod data_rebalancing;
91pub mod disaster_recovery;
92pub mod discovery;
93pub mod distributed_query;
94pub mod distributed_tracing;
95pub mod edge_computing;
96pub mod encryption;
97pub mod enhanced_node_discovery;
98pub mod enhanced_snapshotting;
99pub mod error;
100pub mod failover;
101pub mod federation;
102pub mod gpu_acceleration;
103pub mod health_monitor;
104pub mod health_monitoring;
105pub mod memory_optimization;
106pub mod merkle_tree;
107pub mod ml_optimization;
108pub mod multi_tenant;
109pub mod mvcc;
110pub mod mvcc_storage;
111pub mod network;
112pub mod neural_architecture_search;
113pub mod node_lifecycle;
114pub mod node_status_tracker;
115pub mod operational_transformation;
116pub mod optimization;
117pub mod partition_detection;
118pub mod performance_metrics;
119pub mod performance_monitor;
120pub mod raft;
121#[cfg(feature = "raft")]
122pub mod raft_durable;
123#[cfg(feature = "raft")]
124mod raft_network;
125pub mod raft_optimization;
126pub mod raft_profiling;
127pub mod raft_state;
128pub mod range_partitioning;
129pub mod read_replica;
130pub mod region_manager;
131pub mod replication;
132pub mod replication_lag_monitor;
133pub mod rl_consensus_optimizer;
134pub mod rolling_upgrade;
135pub mod rolling_upgrade_orchestrator;
136pub mod split_brain_detector;
137pub mod visualization_dashboard;
138pub mod zero_downtime_migration;
139pub mod cross_dc;
142pub mod network_compression;
143pub mod security;
144pub mod serialization;
145pub mod shard;
146pub mod shard_manager;
147pub mod shard_migration;
148pub mod shard_routing;
149pub mod split_brain_prevention;
150pub mod storage;
151pub mod strong_consistency;
152pub mod tls;
153pub mod topology;
154pub mod transaction;
155pub mod transaction_optimizer;
156
157#[cfg(feature = "bft")]
158pub mod bft;
159#[cfg(feature = "bft")]
160pub mod bft_consensus;
161#[cfg(feature = "bft")]
162pub mod bft_network;
163
164pub mod gossip_scaling;
165pub mod sla_manager;
166pub mod stream_integration;
167
168pub mod adaptive_consistent_hash;
170pub mod cross_dc_consistency;
171pub mod distributed_tx_coordinator;
172
173pub mod vnodes_hash_ring;
175
176pub mod membership_gossip;
178
179pub mod leader_election;
181
182pub mod snapshot_manager;
184
185pub mod consistent_shard_router;
187
188pub mod partition_rebalancer;
190
191pub mod node_monitor;
193
194pub mod failover_manager;
196
197pub mod anti_entropy;
203
204pub mod gossip;
208
209pub mod simulation;
217
218pub mod replication_throttle;
220
221pub mod data_migrator;
224
225pub mod shard_router;
227
228pub mod election_timer;
231
232pub mod compression;
235
236pub mod backup;
239
240pub mod sla;
248
249pub mod streaming;
258
259pub mod log_replication_topology;
267
268pub mod witness_node;
276
277pub mod tcp_cluster;
285
286pub mod certification;
294
295pub use log_replication_topology::{
296 NodeDescriptor, ReplicationRole, ReplicationTopology, TopologyNode,
297};
298pub use tcp_cluster::{
299 ClusterMessage, GossipState, MessageCodec, NetworkStats, TcpClusterNetwork, TcpClusterNode,
300 TcpNodeConfig, TcpNodeError,
301};
302pub use witness_node::{
303 VoteRequest, VoteResponse, WitnessAppendRequest, WitnessAppendResponse, WitnessLogEntry,
304 WitnessNode,
305};
306
307pub use error::{ClusterError, Result};
308pub use failover::{FailoverConfig, FailoverManager, FailoverStrategy, RecoveryAction};
309pub use health_monitor::{HealthMonitor, HealthMonitorConfig, NodeHealth, SystemMetrics};
310
311use conflict_resolution::{
322 ConflictResolver, ResolutionStrategy, TimestampedOperation, VectorClock,
323};
324use consensus::ConsensusManager;
325use discovery::{DiscoveryConfig, DiscoveryService, NodeInfo};
326use distributed_query::{DistributedQueryExecutor, ResultBinding};
327use edge_computing::{EdgeComputingManager, EdgeDeploymentStrategy, EdgeDeviceProfile};
328use raft::{OxirsNodeId, RdfResponse};
329use region_manager::{
330 ConsensusStrategy as RegionConsensusStrategy, MultiRegionReplicationStrategy, Region,
331 RegionManager,
332};
333use replication::{ReplicationManager, ReplicationStats, ReplicationStrategy};
334
335#[derive(Debug, Clone, Serialize, Deserialize)]
337pub struct MultiRegionConfig {
338 pub region_id: String,
340 pub availability_zone_id: String,
342 pub data_center: Option<String>,
344 pub rack: Option<String>,
346 pub regions: Vec<Region>,
348 pub consensus_strategy: RegionConsensusStrategy,
350 pub replication_strategy: MultiRegionReplicationStrategy,
352 pub conflict_resolution_strategy: ResolutionStrategy,
354 pub edge_config: Option<EdgeComputingConfig>,
356 pub enable_monitoring: bool,
358}
359
360#[derive(Debug, Clone, Serialize, Deserialize)]
362pub struct EdgeComputingConfig {
363 pub enabled: bool,
365 pub device_profile: EdgeDeviceProfile,
367 pub deployment_strategy: EdgeDeploymentStrategy,
369 pub enable_intelligent_caching: bool,
371 pub enable_network_monitoring: bool,
373}
374
375#[derive(Debug, Clone, Serialize, Deserialize)]
377pub struct NodeConfig {
378 pub node_id: OxirsNodeId,
380 pub address: SocketAddr,
382 pub data_dir: String,
384 pub peers: Vec<OxirsNodeId>,
386 pub peer_addresses: HashMap<OxirsNodeId, SocketAddr>,
395 pub discovery: Option<DiscoveryConfig>,
397 pub replication_strategy: Option<ReplicationStrategy>,
399 pub use_bft: bool,
406 pub region_config: Option<MultiRegionConfig>,
408}
409
410impl NodeConfig {
411 pub fn new(node_id: OxirsNodeId, address: SocketAddr) -> Self {
413 Self {
414 node_id,
415 address,
416 data_dir: format!("./data/node-{node_id}"),
417 peers: Vec::new(),
418 peer_addresses: HashMap::new(),
419 discovery: Some(DiscoveryConfig::default()),
420 replication_strategy: Some(ReplicationStrategy::default()),
421 use_bft: false,
422 region_config: None,
423 }
424 }
425
426 pub fn add_peer(&mut self, peer_id: OxirsNodeId) -> &mut Self {
428 if !self.peers.contains(&peer_id) && peer_id != self.node_id {
429 self.peers.push(peer_id);
430 }
431 self
432 }
433
434 pub fn add_peer_address(&mut self, peer_id: OxirsNodeId, address: SocketAddr) -> &mut Self {
438 self.peer_addresses.insert(peer_id, address);
439 self
440 }
441
442 pub fn with_discovery(mut self, discovery: DiscoveryConfig) -> Self {
444 self.discovery = Some(discovery);
445 self
446 }
447
448 pub fn with_replication_strategy(mut self, strategy: ReplicationStrategy) -> Self {
450 self.replication_strategy = Some(strategy);
451 self
452 }
453
454 pub fn with_bft(mut self, enable: bool) -> Self {
460 self.use_bft = enable;
461 self
462 }
463
464 pub fn with_multi_region(mut self, region_config: MultiRegionConfig) -> Self {
466 self.region_config = Some(region_config);
467 self
468 }
469
470 pub fn is_multi_region_enabled(&self) -> bool {
472 self.region_config.is_some()
473 }
474
475 pub fn region_id(&self) -> Option<&str> {
477 self.region_config
478 .as_ref()
479 .map(|config| config.region_id.as_str())
480 }
481
482 pub fn availability_zone_id(&self) -> Option<&str> {
484 self.region_config
485 .as_ref()
486 .map(|config| config.availability_zone_id.as_str())
487 }
488}
489
490pub struct ClusterNode {
492 config: NodeConfig,
493 consensus: ConsensusManager,
494 discovery: DiscoveryService,
495 replication: Arc<RwLock<ReplicationManager>>,
499 query_executor: DistributedQueryExecutor,
500 region_manager: Option<Arc<RegionManager>>,
501 conflict_resolver: Arc<ConflictResolver>,
502 #[allow(dead_code)]
503 edge_manager: Option<Arc<EdgeComputingManager>>,
504 local_vector_clock: Arc<RwLock<VectorClock>>,
505 running: Arc<RwLock<bool>>,
506 byzantine_mode: Arc<RwLock<bool>>,
507 network_isolated: Arc<RwLock<bool>>,
508 #[cfg(feature = "bft")]
512 bft_manager: Option<Arc<bft_consensus::BftConsensusManager>>,
513}
514
515impl ClusterNode {
516 pub async fn new(config: NodeConfig) -> Result<Self> {
518 if config.data_dir.is_empty() {
520 return Err(ClusterError::Config(
521 "Data directory cannot be empty".to_string(),
522 ));
523 }
524
525 tokio::fs::create_dir_all(&config.data_dir)
527 .await
528 .map_err(|e| ClusterError::Other(format!("Failed to create data directory: {e}")))?;
529
530 #[cfg(feature = "raft")]
537 let consensus = ConsensusManager::new(config.node_id, config.peers.clone())
538 .with_raft_network(config.address, config.peer_addresses.clone())
539 .with_raft_storage_dir(std::path::PathBuf::from(&config.data_dir));
540 #[cfg(not(feature = "raft"))]
541 let consensus = ConsensusManager::new(config.node_id, config.peers.clone());
542
543 let discovery_config = config.discovery.clone().unwrap_or_default();
545 let discovery = DiscoveryService::new(config.node_id, config.address, discovery_config);
546
547 let replication_strategy = config.replication_strategy.clone().unwrap_or_default();
549 let replication = Arc::new(RwLock::new(ReplicationManager::new(
550 replication_strategy,
551 config.node_id,
552 )));
553
554 let query_executor = DistributedQueryExecutor::new(config.node_id);
556
557 let default_resolution_strategy = if let Some(region_config) = &config.region_config {
559 region_config.conflict_resolution_strategy.clone()
560 } else {
561 ResolutionStrategy::LastWriterWins
562 };
563 let conflict_resolver = Arc::new(ConflictResolver::new(default_resolution_strategy));
564
565 let mut vector_clock = VectorClock::new();
567 vector_clock.increment(config.node_id);
568 let local_vector_clock = Arc::new(RwLock::new(vector_clock));
569
570 let region_manager = if let Some(region_config) = &config.region_config {
572 let manager = Arc::new(RegionManager::new(
573 region_config.region_id.clone(),
574 region_config.availability_zone_id.clone(),
575 region_config.consensus_strategy.clone(),
576 region_config.replication_strategy.clone(),
577 ));
578
579 manager
581 .initialize(region_config.regions.clone())
582 .await
583 .map_err(|e| {
584 ClusterError::Other(format!("Failed to initialize region manager: {e}"))
585 })?;
586
587 manager
589 .register_node(
590 config.node_id,
591 region_config.region_id.clone(),
592 region_config.availability_zone_id.clone(),
593 region_config.data_center.clone(),
594 region_config.rack.clone(),
595 )
596 .await
597 .map_err(|e| {
598 ClusterError::Other(format!("Failed to register node in region manager: {e}"))
599 })?;
600
601 Some(manager)
602 } else {
603 None
604 };
605
606 let edge_manager = if let Some(region_config) = &config.region_config {
608 if let Some(edge_config) = ®ion_config.edge_config {
609 if edge_config.enabled {
610 let manager = Arc::new(EdgeComputingManager::new());
611
612 manager
614 .register_device(edge_config.device_profile.clone())
615 .await
616 .map_err(|e| {
617 ClusterError::Other(format!("Failed to register edge device: {e}"))
618 })?;
619
620 Some(manager)
621 } else {
622 None
623 }
624 } else {
625 None
626 }
627 } else {
628 None
629 };
630
631 Ok(Self {
632 config,
633 consensus,
634 discovery,
635 replication,
636 query_executor,
637 region_manager,
638 conflict_resolver,
639 edge_manager,
640 local_vector_clock,
641 running: Arc::new(RwLock::new(false)),
642 byzantine_mode: Arc::new(RwLock::new(false)),
643 network_isolated: Arc::new(RwLock::new(false)),
644 #[cfg(feature = "bft")]
645 bft_manager: None,
646 })
647 }
648
649 #[cfg(feature = "bft")]
652 pub fn bft_manager(&self) -> Option<&Arc<bft_consensus::BftConsensusManager>> {
653 self.bft_manager.as_ref()
654 }
655
656 #[cfg(feature = "bft")]
661 async fn start_bft_consensus(&mut self) -> Result<()> {
662 use crate::bft_consensus::BftConsensusManager;
663 use crate::network::NetworkConfig;
664 use crate::storage::{PersistentStorage, StorageConfig};
665
666 let storage_config = StorageConfig {
667 data_dir: self.config.data_dir.clone(),
668 ..StorageConfig::default()
669 };
670 let storage = Arc::new(
671 PersistentStorage::new(self.config.node_id, storage_config)
672 .await
673 .map_err(|e| {
674 ClusterError::Storage(format!("failed to open BFT storage backend: {e}"))
675 })?,
676 );
677
678 let peers: Vec<String> = self.config.peers.iter().map(|p| p.to_string()).collect();
679 let manager = BftConsensusManager::new(
680 self.config.node_id.to_string(),
681 peers,
682 storage,
683 NetworkConfig::default(),
684 )
685 .await?;
686 manager.start().await?;
687
688 self.bft_manager = Some(Arc::new(manager));
689 Ok(())
690 }
691
692 pub async fn start(&mut self) -> Result<()> {
694 {
695 let mut running = self.running.write().await;
696 if *running {
697 return Ok(());
698 }
699 *running = true;
700 }
701
702 if self.config.use_bft {
707 #[cfg(feature = "bft")]
708 {
709 self.start_bft_consensus().await?;
710 tracing::info!(
711 "Cluster node {} started in Byzantine fault-tolerant mode",
712 self.config.node_id
713 );
714 return Ok(());
715 }
716 #[cfg(not(feature = "bft"))]
717 {
718 let mut running = self.running.write().await;
719 *running = false;
720 return Err(ClusterError::Config(format!(
721 "node {} requested Byzantine fault tolerance (use_bft = true) but this build \
722 was compiled without the 'bft' feature; refusing to silently fall back to \
723 Raft",
724 self.config.node_id
725 )));
726 }
727 }
728
729 tracing::info!(
730 "Starting cluster node {} at {} with {} peers",
731 self.config.node_id,
732 self.config.address,
733 self.config.peers.len()
734 );
735
736 self.discovery
738 .start()
739 .await
740 .map_err(|e| ClusterError::Other(format!("Failed to start discovery service: {e}")))?;
741
742 let discovered_nodes = self
744 .discovery
745 .discover_nodes()
746 .await
747 .map_err(|e| ClusterError::Other(format!("Failed to discover nodes: {e}")))?;
748
749 for node in discovered_nodes {
751 if node.node_id != self.config.node_id {
752 self.replication
753 .write()
754 .await
755 .add_replica(node.node_id, node.address.to_string());
756 self.query_executor.add_node(node.node_id).await;
757 }
758 }
759
760 self.consensus
762 .init()
763 .await
764 .map_err(|e| ClusterError::Other(format!("Failed to initialize consensus: {e}")))?;
765
766 tracing::info!("Cluster node {} started successfully", self.config.node_id);
767
768 self.start_background_tasks().await;
770
771 Ok(())
772 }
773
774 pub async fn stop(&mut self) -> Result<()> {
783 let mut running = self.running.write().await;
784 if !*running {
785 return Ok(());
786 }
787
788 tracing::info!("Stopping cluster node {}", self.config.node_id);
789
790 self.discovery
792 .stop()
793 .await
794 .map_err(|e| ClusterError::Other(format!("Failed to stop discovery service: {e}")))?;
795
796 self.consensus
800 .stop_raft()
801 .await
802 .map_err(|e| ClusterError::Other(format!("Failed to stop consensus: {e}")))?;
803
804 *running = false;
805
806 tracing::info!("Cluster node {} stopped", self.config.node_id);
807
808 Ok(())
809 }
810
811 pub async fn is_leader(&self) -> bool {
813 self.consensus.is_leader().await
814 }
815
816 pub async fn current_term(&self) -> u64 {
818 self.consensus.current_term().await
819 }
820
821 pub async fn insert_triple(
823 &self,
824 subject: &str,
825 predicate: &str,
826 object: &str,
827 ) -> Result<RdfResponse> {
828 if !self.is_leader().await {
829 return Err(ClusterError::NotLeader);
830 }
831
832 let response = self
833 .consensus
834 .insert_triple(
835 subject.to_string(),
836 predicate.to_string(),
837 object.to_string(),
838 )
839 .await?;
840
841 Ok(response)
842 }
843
844 pub async fn delete_triple(
846 &self,
847 subject: &str,
848 predicate: &str,
849 object: &str,
850 ) -> Result<RdfResponse> {
851 if !self.is_leader().await {
852 return Err(ClusterError::NotLeader);
853 }
854
855 let response = self
856 .consensus
857 .delete_triple(
858 subject.to_string(),
859 predicate.to_string(),
860 object.to_string(),
861 )
862 .await?;
863
864 Ok(response)
865 }
866
867 pub async fn clear_store(&self) -> Result<RdfResponse> {
869 if !self.is_leader().await {
870 return Err(ClusterError::NotLeader);
871 }
872
873 let response = self.consensus.clear_store().await?;
874 Ok(response)
875 }
876
877 pub async fn begin_transaction(&self) -> Result<String> {
879 if !self.is_leader().await {
880 return Err(ClusterError::NotLeader);
881 }
882
883 let tx_id = uuid::Uuid::new_v4().to_string();
884 let _response = self.consensus.begin_transaction(tx_id.clone()).await?;
885
886 Ok(tx_id)
887 }
888
889 pub async fn commit_transaction(&self, tx_id: &str) -> Result<RdfResponse> {
891 if !self.is_leader().await {
892 return Err(ClusterError::NotLeader);
893 }
894
895 let response = self.consensus.commit_transaction(tx_id.to_string()).await?;
896 Ok(response)
897 }
898
899 pub async fn rollback_transaction(&self, tx_id: &str) -> Result<RdfResponse> {
901 if !self.is_leader().await {
902 return Err(ClusterError::NotLeader);
903 }
904
905 let response = self
906 .consensus
907 .rollback_transaction(tx_id.to_string())
908 .await?;
909 Ok(response)
910 }
911
912 pub async fn query_triples(
914 &self,
915 subject: Option<&str>,
916 predicate: Option<&str>,
917 object: Option<&str>,
918 ) -> Vec<(String, String, String)> {
919 self.consensus.query(subject, predicate, object).await
920 }
921
922 pub async fn query_sparql(&self, sparql: &str) -> Result<Vec<String>> {
924 let bindings = self
925 .query_executor
926 .execute_query(sparql)
927 .await
928 .map_err(|e| ClusterError::Other(format!("Query execution failed: {e}")))?;
929
930 let results = bindings
932 .into_iter()
933 .map(|binding| {
934 let vars: Vec<String> = binding
935 .variables
936 .into_iter()
937 .map(|(var, val)| format!("{var}: {val}"))
938 .collect();
939 vars.join(", ")
940 })
941 .collect();
942
943 Ok(results)
944 }
945
946 pub async fn query_sparql_bindings(&self, sparql: &str) -> Result<Vec<ResultBinding>> {
948 self.query_executor
949 .execute_query(sparql)
950 .await
951 .map_err(|e| ClusterError::Other(format!("Query execution failed: {e}")))
952 }
953
954 pub async fn get_query_statistics(
956 &self,
957 ) -> Result<std::collections::HashMap<String, distributed_query::QueryStats>> {
958 Ok(self.query_executor.get_statistics().await)
959 }
960
961 pub async fn clear_query_cache(&self) -> Result<()> {
963 self.query_executor.clear_cache().await;
964 Ok(())
965 }
966
967 pub async fn len(&self) -> usize {
969 self.consensus.len().await
970 }
971
972 pub async fn is_empty(&self) -> bool {
974 self.consensus.is_empty().await
975 }
976
977 pub async fn add_cluster_node(
979 &mut self,
980 node_id: OxirsNodeId,
981 address: SocketAddr,
982 ) -> Result<()> {
983 if node_id == self.config.node_id {
984 return Err(ClusterError::Config(
985 "Cannot add self to cluster".to_string(),
986 ));
987 }
988
989 self.config.add_peer(node_id);
991
992 let node_info = NodeInfo::new(node_id, address);
994 self.discovery.add_node(node_info);
995
996 self.replication
998 .write()
999 .await
1000 .add_replica(node_id, address.to_string());
1001
1002 self.query_executor.add_node(node_id).await;
1004
1005 self.consensus.add_peer(node_id);
1007
1008 tracing::info!("Added node {} at {} to cluster", node_id, address);
1009
1010 Ok(())
1011 }
1012
1013 pub async fn remove_cluster_node(&mut self, node_id: OxirsNodeId) -> Result<()> {
1015 if node_id == self.config.node_id {
1016 return Err(ClusterError::Config(
1017 "Cannot remove self from cluster".to_string(),
1018 ));
1019 }
1020
1021 self.config.peers.retain(|&id| id != node_id);
1023
1024 self.discovery.remove_node(node_id);
1026
1027 self.replication.write().await.remove_replica(node_id);
1029
1030 self.query_executor.remove_node(node_id).await;
1032
1033 self.consensus.remove_peer(node_id);
1035
1036 tracing::info!("Removed node {} from cluster", node_id);
1037
1038 Ok(())
1039 }
1040
1041 pub async fn get_status(&self) -> ClusterStatus {
1043 let consensus_status = self.consensus.get_status().await;
1044 let discovery_stats = self.discovery.get_stats().clone();
1045 let replication_stats = self.replication.read().await.get_stats().clone();
1046
1047 let region_status = if let Some(region_manager) = &self.region_manager {
1049 let region_id = region_manager.get_local_region().to_string();
1050 let availability_zone_id = region_manager.get_local_availability_zone().to_string();
1051 let regional_peers = region_manager.get_nodes_in_region(®ion_id).await;
1052 let topology = region_manager.get_topology().await;
1053 let monitoring_active = region_manager.is_monitoring_active().await;
1054
1055 Some(RegionStatus {
1056 region_id,
1057 availability_zone_id,
1058 regional_peer_count: regional_peers.len(),
1059 total_regions: topology.regions.len(),
1060 monitoring_active,
1061 })
1062 } else {
1063 None
1064 };
1065
1066 ClusterStatus {
1067 node_id: self.config.node_id,
1068 address: self.config.address,
1069 is_leader: consensus_status.is_leader,
1070 current_term: consensus_status.current_term,
1071 peer_count: consensus_status.peer_count,
1072 triple_count: consensus_status.triple_count,
1073 discovery_stats,
1074 replication_stats,
1075 is_running: *self.running.read().await,
1076 region_status,
1077 }
1078 }
1079
1080 async fn start_background_tasks(&mut self) {
1082 let running = Arc::clone(&self.running);
1083
1084 let discovery_config = self.config.discovery.clone().unwrap_or_default();
1086 let mut discovery_clone =
1087 DiscoveryService::new(self.config.node_id, self.config.address, discovery_config);
1088
1089 tokio::spawn(async move {
1090 while *running.read().await {
1091 discovery_clone.run_periodic_tasks().await;
1092 tokio::time::sleep(std::time::Duration::from_secs(1)).await;
1093 }
1094 });
1095
1096 let replication = Arc::clone(&self.replication);
1105 let running_clone = Arc::clone(&self.running);
1106
1107 tokio::spawn(async move {
1108 const HEALTH_CHECK_INTERVAL: std::time::Duration = std::time::Duration::from_secs(30);
1109 const STALE_THRESHOLD: std::time::Duration = std::time::Duration::from_secs(60);
1110
1111 while *running_clone.read().await {
1112 tokio::time::sleep(HEALTH_CHECK_INTERVAL).await;
1113 if !*running_clone.read().await {
1114 break;
1115 }
1116 replication
1117 .write()
1118 .await
1119 .maintenance_tick(STALE_THRESHOLD)
1120 .await;
1121 }
1122 });
1123 }
1124
1125 pub async fn add_node_with_consensus(
1127 &mut self,
1128 node_id: OxirsNodeId,
1129 address: SocketAddr,
1130 ) -> Result<()> {
1131 self.consensus
1132 .add_node_with_consensus(node_id, address.to_string())
1133 .await
1134 .map_err(|e| {
1135 ClusterError::Other(format!("Failed to add node through consensus: {e}"))
1136 })?;
1137
1138 self.config.add_peer(node_id);
1140
1141 let node_info = NodeInfo::new(node_id, address);
1143 self.discovery.add_node(node_info);
1144 self.replication
1145 .write()
1146 .await
1147 .add_replica(node_id, address.to_string());
1148 self.query_executor.add_node(node_id).await;
1149
1150 Ok(())
1151 }
1152
1153 pub async fn remove_node_with_consensus(&mut self, node_id: OxirsNodeId) -> Result<()> {
1155 self.consensus
1156 .remove_node_with_consensus(node_id)
1157 .await
1158 .map_err(|e| {
1159 ClusterError::Other(format!("Failed to remove node through consensus: {e}"))
1160 })?;
1161
1162 self.config.peers.retain(|&id| id != node_id);
1164
1165 self.discovery.remove_node(node_id);
1167 self.replication.write().await.remove_replica(node_id);
1168 self.query_executor.remove_node(node_id).await;
1169
1170 Ok(())
1171 }
1172
1173 pub async fn graceful_shutdown(&mut self) -> Result<()> {
1175 tracing::info!(
1176 "Initiating graceful shutdown of cluster node {}",
1177 self.config.node_id
1178 );
1179
1180 {
1182 let mut running = self.running.write().await;
1183 *running = false;
1184 }
1185
1186 self.consensus
1188 .graceful_shutdown()
1189 .await
1190 .map_err(|e| ClusterError::Other(format!("Failed to shutdown consensus: {e}")))?;
1191
1192 self.discovery
1194 .stop()
1195 .await
1196 .map_err(|e| ClusterError::Other(format!("Failed to stop discovery: {e}")))?;
1197
1198 tracing::info!("Cluster node {} gracefully shutdown", self.config.node_id);
1199 Ok(())
1200 }
1201
1202 pub async fn transfer_leadership(&mut self, target_node: OxirsNodeId) -> Result<()> {
1204 if !self.config.peers.contains(&target_node) {
1205 return Err(ClusterError::Config(format!(
1206 "Target node {target_node} not in cluster"
1207 )));
1208 }
1209
1210 self.consensus
1211 .transfer_leadership(target_node)
1212 .await
1213 .map_err(|e| ClusterError::Other(format!("Failed to transfer leadership: {e}")))?;
1214
1215 Ok(())
1216 }
1217
1218 pub async fn force_evict_node(&mut self, node_id: OxirsNodeId) -> Result<()> {
1220 self.consensus
1221 .force_evict_node(node_id)
1222 .await
1223 .map_err(|e| ClusterError::Other(format!("Failed to force evict node: {e}")))?;
1224
1225 self.config.peers.retain(|&id| id != node_id);
1227 self.discovery.remove_node(node_id);
1228 self.replication.write().await.remove_replica(node_id);
1229 self.query_executor.remove_node(node_id).await;
1230
1231 Ok(())
1232 }
1233
1234 pub async fn check_cluster_health(&self) -> Result<Vec<consensus::NodeHealthStatus>> {
1236 self.consensus
1237 .check_peer_health()
1238 .await
1239 .map_err(|e| ClusterError::Other(format!("Failed to check cluster health: {e}")))
1240 }
1241
1242 pub async fn attempt_recovery(&mut self) -> Result<()> {
1244 self.consensus
1245 .attempt_recovery()
1246 .await
1247 .map_err(|e| ClusterError::Other(format!("Failed to recover cluster: {e}")))?;
1248
1249 tracing::info!(
1250 "Cluster recovery completed for node {}",
1251 self.config.node_id
1252 );
1253 Ok(())
1254 }
1255
1256 pub fn id(&self) -> OxirsNodeId {
1258 self.config.node_id
1259 }
1260
1261 pub async fn count_triples(&self) -> Result<usize> {
1263 Ok(self.len().await)
1264 }
1265
1266 pub async fn is_active(&self) -> Result<bool> {
1268 Ok(*self.running.read().await && !*self.network_isolated.read().await)
1269 }
1270
1271 pub async fn isolate_network(&self) -> Result<()> {
1273 let mut isolated = self.network_isolated.write().await;
1274 *isolated = true;
1275 tracing::info!("Node {} network isolated", self.config.node_id);
1276 Ok(())
1277 }
1278
1279 pub async fn restore_network(&self) -> Result<()> {
1281 let mut isolated = self.network_isolated.write().await;
1282 *isolated = false;
1283 tracing::info!("Node {} network restored", self.config.node_id);
1284 Ok(())
1285 }
1286
1287 pub async fn enable_byzantine_mode(&self) -> Result<()> {
1289 let mut byzantine = self.byzantine_mode.write().await;
1290 *byzantine = true;
1291 tracing::info!("Node {} Byzantine mode enabled", self.config.node_id);
1292 Ok(())
1293 }
1294
1295 pub async fn is_byzantine(&self) -> Result<bool> {
1297 Ok(*self.byzantine_mode.read().await)
1298 }
1299
1300 pub fn region_manager(&self) -> Option<&Arc<RegionManager>> {
1302 self.region_manager.as_ref()
1303 }
1304
1305 pub fn is_multi_region_enabled(&self) -> bool {
1307 self.region_manager.is_some()
1308 }
1309
1310 pub fn get_region_id(&self) -> Option<String> {
1312 self.region_manager
1313 .as_ref()
1314 .map(|rm| rm.get_local_region().to_string())
1315 }
1316
1317 pub fn get_availability_zone_id(&self) -> Option<String> {
1319 self.region_manager
1320 .as_ref()
1321 .map(|rm| rm.get_local_availability_zone().to_string())
1322 }
1323
1324 pub async fn get_regional_peers(&self) -> Result<Vec<OxirsNodeId>> {
1326 if let Some(region_manager) = &self.region_manager {
1327 let region_id = region_manager.get_local_region();
1328 Ok(region_manager.get_nodes_in_region(region_id).await)
1329 } else {
1330 Err(ClusterError::Config(
1331 "Multi-region not configured".to_string(),
1332 ))
1333 }
1334 }
1335
1336 pub async fn get_regional_leader_candidates(&self) -> Result<Vec<OxirsNodeId>> {
1338 if let Some(region_manager) = &self.region_manager {
1339 let region_id = region_manager.get_local_region();
1340 Ok(region_manager.get_leader_candidates(region_id).await)
1341 } else {
1342 Ok(self.config.peers.clone())
1344 }
1345 }
1346
1347 pub async fn get_cross_region_replication_targets(&self) -> Result<Vec<String>> {
1349 if let Some(region_manager) = &self.region_manager {
1350 let region_id = region_manager.get_local_region();
1351 region_manager
1352 .calculate_replication_targets(region_id)
1353 .await
1354 .map_err(|e| {
1355 ClusterError::Other(format!("Failed to calculate replication targets: {e}"))
1356 })
1357 } else {
1358 Ok(Vec::new())
1359 }
1360 }
1361
1362 pub async fn monitor_region_latencies(&self) -> Result<()> {
1364 if let Some(region_manager) = &self.region_manager {
1365 region_manager.monitor_latencies().await.map_err(|e| {
1366 ClusterError::Other(format!("Failed to monitor region latencies: {e}"))
1367 })
1368 } else {
1369 Ok(())
1370 }
1371 }
1372
1373 pub async fn get_region_health(&self, region_id: &str) -> Result<region_manager::RegionHealth> {
1375 if let Some(region_manager) = &self.region_manager {
1376 region_manager
1377 .get_region_health(region_id)
1378 .await
1379 .map_err(|e| ClusterError::Other(format!("Failed to get region health: {e}")))
1380 } else {
1381 Err(ClusterError::Config(
1382 "Multi-region not configured".to_string(),
1383 ))
1384 }
1385 }
1386
1387 pub async fn perform_region_failover(
1389 &self,
1390 failed_region: &str,
1391 target_region: &str,
1392 ) -> Result<()> {
1393 if let Some(region_manager) = &self.region_manager {
1394 region_manager
1395 .perform_region_failover(failed_region, target_region)
1396 .await
1397 .map_err(|e| ClusterError::Other(format!("Failed to perform region failover: {e}")))
1398 } else {
1399 Err(ClusterError::Config(
1400 "Multi-region not configured".to_string(),
1401 ))
1402 }
1403 }
1404
1405 pub async fn get_region_topology(&self) -> Result<region_manager::RegionTopology> {
1407 if let Some(region_manager) = &self.region_manager {
1408 Ok(region_manager.get_topology().await)
1409 } else {
1410 Err(ClusterError::Config(
1411 "Multi-region not configured".to_string(),
1412 ))
1413 }
1414 }
1415
1416 pub async fn add_node_to_region(
1418 &self,
1419 node_id: OxirsNodeId,
1420 region_id: String,
1421 availability_zone_id: String,
1422 data_center: Option<String>,
1423 rack: Option<String>,
1424 ) -> Result<()> {
1425 if let Some(region_manager) = &self.region_manager {
1426 region_manager
1427 .register_node(node_id, region_id, availability_zone_id, data_center, rack)
1428 .await
1429 .map_err(|e| ClusterError::Other(format!("Failed to add node to region: {e}")))
1430 } else {
1431 Err(ClusterError::Config(
1432 "Multi-region not configured".to_string(),
1433 ))
1434 }
1435 }
1436
1437 pub fn conflict_resolver(&self) -> &Arc<ConflictResolver> {
1439 &self.conflict_resolver
1440 }
1441
1442 pub async fn get_vector_clock(&self) -> VectorClock {
1444 self.local_vector_clock.read().await.clone()
1445 }
1446
1447 pub async fn update_vector_clock(&self, received_clock: &VectorClock) {
1449 let mut clock = self.local_vector_clock.write().await;
1450 clock.update(received_clock);
1451 clock.increment(self.config.node_id);
1452 }
1453
1454 pub async fn create_timestamped_operation(
1456 &self,
1457 operation: conflict_resolution::RdfOperation,
1458 priority: u32,
1459 ) -> TimestampedOperation {
1460 let mut clock = self.local_vector_clock.write().await;
1461 clock.increment(self.config.node_id);
1462
1463 TimestampedOperation {
1464 operation_id: uuid::Uuid::new_v4().to_string(),
1465 origin_node: self.config.node_id,
1466 vector_clock: clock.clone(),
1467 physical_time: std::time::SystemTime::now(),
1468 operation,
1469 priority,
1470 }
1471 }
1472
1473 pub async fn detect_operation_conflicts(
1475 &self,
1476 operations: &[TimestampedOperation],
1477 ) -> Result<Vec<conflict_resolution::ConflictType>> {
1478 self.conflict_resolver
1479 .detect_conflicts(operations)
1480 .await
1481 .map_err(|e| ClusterError::Other(format!("Failed to detect conflicts: {e}")))
1482 }
1483
1484 pub async fn resolve_operation_conflicts(
1486 &self,
1487 conflicts: &[conflict_resolution::ConflictType],
1488 ) -> Result<Vec<conflict_resolution::ResolutionResult>> {
1489 self.conflict_resolver
1490 .resolve_conflicts(conflicts)
1491 .await
1492 .map_err(|e| ClusterError::Other(format!("Failed to resolve conflicts: {e}")))
1493 }
1494
1495 pub async fn submit_conflict_aware_operation(
1497 &self,
1498 operation: conflict_resolution::RdfOperation,
1499 priority: u32,
1500 ) -> Result<RdfResponse> {
1501 let _timestamped_op = self
1503 .create_timestamped_operation(operation.clone(), priority)
1504 .await;
1505
1506 match operation {
1509 conflict_resolution::RdfOperation::Insert {
1510 subject,
1511 predicate,
1512 object,
1513 ..
1514 } => self.insert_triple(&subject, &predicate, &object).await,
1515 conflict_resolution::RdfOperation::Delete {
1516 subject,
1517 predicate,
1518 object,
1519 ..
1520 } => self.delete_triple(&subject, &predicate, &object).await,
1521 conflict_resolution::RdfOperation::Clear { .. } => self.clear_store().await,
1522 conflict_resolution::RdfOperation::Update {
1523 old_triple,
1524 new_triple,
1525 ..
1526 } => {
1527 let _delete_result = self
1529 .delete_triple(&old_triple.0, &old_triple.1, &old_triple.2)
1530 .await?;
1531 self.insert_triple(&new_triple.0, &new_triple.1, &new_triple.2)
1532 .await
1533 }
1534 conflict_resolution::RdfOperation::Batch { operations: _ } => {
1535 Ok(RdfResponse::Success)
1540 }
1541 }
1542 }
1543
1544 pub async fn get_conflict_resolution_statistics(
1546 &self,
1547 ) -> conflict_resolution::ResolutionStatistics {
1548 self.conflict_resolver.get_statistics().await
1549 }
1550}
1551
1552#[derive(Debug, Clone)]
1554pub struct ClusterStatus {
1555 pub node_id: OxirsNodeId,
1557 pub address: SocketAddr,
1559 pub is_leader: bool,
1561 pub current_term: u64,
1563 pub peer_count: usize,
1565 pub triple_count: usize,
1567 pub discovery_stats: discovery::DiscoveryStats,
1569 pub replication_stats: ReplicationStats,
1571 pub is_running: bool,
1573 pub region_status: Option<RegionStatus>,
1575}
1576
1577#[derive(Debug, Clone)]
1579pub struct RegionStatus {
1580 pub region_id: String,
1582 pub availability_zone_id: String,
1584 pub regional_peer_count: usize,
1586 pub total_regions: usize,
1588 pub monitoring_active: bool,
1590}
1591
1592pub struct DistributedStore {
1594 node: ClusterNode,
1595}
1596
1597impl DistributedStore {
1598 pub async fn new(config: NodeConfig) -> Result<Self> {
1600 let node = ClusterNode::new(config).await?;
1601 Ok(Self { node })
1602 }
1603
1604 pub async fn start(&mut self) -> Result<()> {
1606 self.node.start().await
1607 }
1608
1609 pub async fn stop(&mut self) -> Result<()> {
1611 self.node.stop().await
1612 }
1613
1614 pub async fn insert_triple(
1616 &mut self,
1617 subject: &str,
1618 predicate: &str,
1619 object: &str,
1620 ) -> Result<()> {
1621 let _response = self.node.insert_triple(subject, predicate, object).await?;
1622 Ok(())
1623 }
1624
1625 pub async fn query_sparql(&self, sparql: &str) -> Result<Vec<String>> {
1627 self.node.query_sparql(sparql).await
1628 }
1629
1630 pub async fn query_pattern(
1632 &self,
1633 subject: Option<&str>,
1634 predicate: Option<&str>,
1635 object: Option<&str>,
1636 ) -> Vec<(String, String, String)> {
1637 self.node.query_triples(subject, predicate, object).await
1638 }
1639
1640 pub async fn get_status(&self) -> ClusterStatus {
1642 self.node.get_status().await
1643 }
1644}
1645
1646pub use consensus::ConsensusError;
1648pub use discovery::DiscoveryError;
1649pub use replication::ReplicationError;
1650
1651#[cfg(test)]
1652mod tests {
1653 use super::*;
1654 use std::net::{IpAddr, Ipv4Addr};
1655
1656 #[tokio::test]
1657 async fn test_node_config_creation() {
1658 let addr = SocketAddr::new(IpAddr::V4(Ipv4Addr::new(127, 0, 0, 1)), 8080);
1659 let config = NodeConfig::new(1, addr);
1660
1661 assert_eq!(config.node_id, 1);
1662 assert_eq!(config.address, addr);
1663 assert_eq!(config.data_dir, "./data/node-1");
1664 assert!(config.peers.is_empty());
1665 assert!(config.discovery.is_some());
1666 assert!(config.replication_strategy.is_some());
1667 assert!(config.region_config.is_none());
1668 }
1669
1670 #[tokio::test]
1671 async fn test_node_config_add_peer() {
1672 let addr = SocketAddr::new(IpAddr::V4(Ipv4Addr::new(127, 0, 0, 1)), 8080);
1673 let mut config = NodeConfig::new(1, addr);
1674
1675 config.add_peer(2);
1676 config.add_peer(3);
1677 config.add_peer(2); assert_eq!(config.peers, vec![2, 3]);
1680 }
1681
1682 #[tokio::test]
1683 async fn test_node_config_no_self_peer() {
1684 let addr = SocketAddr::new(IpAddr::V4(Ipv4Addr::new(127, 0, 0, 1)), 8080);
1685 let mut config = NodeConfig::new(1, addr);
1686
1687 config.add_peer(1); assert!(config.peers.is_empty());
1690 }
1691
1692 #[tokio::test]
1693 async fn test_cluster_node_creation() {
1694 let addr = SocketAddr::new(IpAddr::V4(Ipv4Addr::new(127, 0, 0, 1)), 8080);
1695 let config = NodeConfig::new(1, addr);
1696
1697 let node = ClusterNode::new(config).await;
1698 assert!(node.is_ok());
1699
1700 let node = node.unwrap();
1701 assert_eq!(node.config.node_id, 1);
1702 assert_eq!(node.config.address, addr);
1703 }
1704
1705 #[tokio::test]
1706 async fn test_cluster_node_empty_data_dir_error() {
1707 let addr = SocketAddr::new(IpAddr::V4(Ipv4Addr::new(127, 0, 0, 1)), 8080);
1708 let mut config = NodeConfig::new(1, addr);
1709 config.data_dir = String::new();
1710
1711 let result = ClusterNode::new(config).await;
1712 assert!(result.is_err());
1713 if let Err(e) = result {
1714 assert!(e.to_string().contains("Data directory cannot be empty"));
1715 }
1716 }
1717
1718 #[tokio::test]
1719 async fn test_distributed_store_creation() {
1720 let addr = SocketAddr::new(IpAddr::V4(Ipv4Addr::new(127, 0, 0, 1)), 8080);
1721 let config = NodeConfig::new(1, addr);
1722
1723 let store = DistributedStore::new(config).await;
1724 assert!(store.is_ok());
1725 }
1726
1727 #[test]
1728 fn test_cluster_error_types() {
1729 let err = ClusterError::Config("test error".to_string());
1730 assert!(err.to_string().contains("Configuration error: test error"));
1731
1732 let err = ClusterError::NotLeader;
1733 assert_eq!(err.to_string(), "Not the leader node");
1734
1735 let err = ClusterError::Network("connection failed".to_string());
1736 assert!(err.to_string().contains("Network error: connection failed"));
1737 }
1738}