Add support for node list synchronization
Signed-off-by: trivernis <trivernis@protonmail.com>pull/1/head
parent
4635e24a43
commit
3630941962
@ -0,0 +1,26 @@
|
||||
use std::path::PathBuf;
|
||||
use serde::{Serialize, Deserialize};
|
||||
use std::time::Duration;
|
||||
|
||||
#[derive(Serialize, Deserialize, Clone, Debug)]
|
||||
pub struct HeartbeatSettings {
|
||||
pub output_file: Option<PathBuf>,
|
||||
pub interval_ms: u64,
|
||||
pub max_record_history: usize,
|
||||
}
|
||||
|
||||
impl Default for HeartbeatSettings {
|
||||
fn default() -> Self {
|
||||
Self {
|
||||
output_file: None,
|
||||
interval_ms: 10000,
|
||||
max_record_history: 10,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl HeartbeatSettings {
|
||||
pub fn interval(&self) -> Duration {
|
||||
Duration::from_millis(self.interval_ms as u64)
|
||||
}
|
||||
}
|
@ -0,0 +1,121 @@
|
||||
use crate::modules::Module;
|
||||
use vented::result::VentedResult;
|
||||
use vented::server::VentedServer;
|
||||
use crate::utils::result::SnekcloudResult;
|
||||
use scheduled_thread_pool::ScheduledThreadPool;
|
||||
use vented::server::server_events::{ NodeListPayload};
|
||||
use vented::server::data::Node;
|
||||
use std::sync::Arc;
|
||||
use parking_lot::Mutex;
|
||||
use std::collections::{HashMap};
|
||||
use std::sync::atomic::{AtomicBool, Ordering};
|
||||
use vented::crypto::PublicKey;
|
||||
use std::time::{Instant, Duration, UNIX_EPOCH};
|
||||
use crate::utils::settings::get_settings;
|
||||
use crate::data::node_data::NodeData;
|
||||
use std::path::PathBuf;
|
||||
use crate::modules::nodes_refresh::settings::NodesRefreshSettings;
|
||||
|
||||
pub mod settings;
|
||||
|
||||
pub struct NodesRefreshModule {
|
||||
nodes: Arc<Mutex<HashMap<String, Node>>>,
|
||||
update_required: Arc<AtomicBool>,
|
||||
last_request: Instant,
|
||||
settings: NodesRefreshSettings,
|
||||
}
|
||||
|
||||
impl Module for NodesRefreshModule {
|
||||
|
||||
fn name(&self) -> String {
|
||||
"node_list_refresh".to_string()
|
||||
}
|
||||
|
||||
fn init(&mut self, server: &mut VentedServer, pool: &mut ScheduledThreadPool) -> SnekcloudResult<()> {
|
||||
{
|
||||
let mut node_list = self.nodes.lock();
|
||||
for node in server.nodes() {
|
||||
node_list.insert(node.id.clone(), node);
|
||||
}
|
||||
}
|
||||
server.on("conn:node_list", {
|
||||
let nodes = Arc::clone(&self.nodes);
|
||||
let update_required = Arc::clone(&self.update_required);
|
||||
|
||||
move |event| {
|
||||
let mut nodes = nodes.lock();
|
||||
let mut new_nodes = false;
|
||||
|
||||
for node in event.get_payload::<NodeListPayload>().ok()?.nodes {
|
||||
if !nodes.contains_key(&node.id) {
|
||||
nodes.insert(node.id.clone(), Node {
|
||||
id: node.id,
|
||||
trusted: false,
|
||||
public_key: PublicKey::from(node.public_key),
|
||||
address: node.address,
|
||||
});
|
||||
new_nodes = true;
|
||||
}
|
||||
}
|
||||
|
||||
if new_nodes {
|
||||
update_required.store(true, Ordering::Relaxed)
|
||||
}
|
||||
None
|
||||
}
|
||||
});
|
||||
pool.execute_at_fixed_rate(Duration::from_secs(10), self.settings.update_interval(), {
|
||||
let nodes = Arc::clone(&self.nodes);
|
||||
let update_required = Arc::clone(&self.update_required);
|
||||
|
||||
move || {
|
||||
if update_required.load(Ordering::Relaxed) {
|
||||
let nodes_folder = get_settings().node_data_dir;
|
||||
nodes.lock().values().cloned().map(|node| {
|
||||
if let Some(address) = node.address {
|
||||
NodeData::with_addresses(node.id, vec![address], node.public_key)
|
||||
} else {
|
||||
NodeData::new(node.id, node.public_key)
|
||||
}
|
||||
}).for_each(|data| {
|
||||
let mut path = nodes_folder.clone();
|
||||
path.push(PathBuf::from(format!("{}.toml", data.id)));
|
||||
|
||||
if let Err(e) = data.write_to_file(path) {
|
||||
log::error!("Failed to write updated node data: {}", e);
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn boxed(self) -> Box<dyn Module> {
|
||||
Box::new(self)
|
||||
}
|
||||
|
||||
fn tick(&mut self, server: &mut VentedServer, _: &mut ScheduledThreadPool) -> VentedResult<()> {
|
||||
if self.last_request.elapsed() > self.settings.update_interval() {
|
||||
if let Err(e) = server.request_node_list() {
|
||||
log::debug!("Failed to refresh node list: {}", e);
|
||||
}
|
||||
self.last_request = Instant::now();
|
||||
}
|
||||
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
impl NodesRefreshModule {
|
||||
pub fn new() -> Self {
|
||||
let null_time = Instant::now() - UNIX_EPOCH.elapsed().unwrap();
|
||||
Self {
|
||||
nodes: Arc::new(Mutex::new(HashMap::new())),
|
||||
settings: get_settings().modules.nodes_refresh,
|
||||
last_request: null_time,
|
||||
update_required: Arc::new(AtomicBool::new(false))
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,21 @@
|
||||
use serde::{Serialize, Deserialize};
|
||||
use std::time::Duration;
|
||||
|
||||
#[derive(Clone, Debug, Serialize, Deserialize)]
|
||||
pub struct NodesRefreshSettings {
|
||||
pub update_interval_ms: u64,
|
||||
}
|
||||
|
||||
impl Default for NodesRefreshSettings {
|
||||
fn default() -> Self {
|
||||
Self {
|
||||
update_interval_ms: 3600000
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl NodesRefreshSettings {
|
||||
pub fn update_interval(&self) -> Duration {
|
||||
Duration::from_millis(self.update_interval_ms)
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue