Просмотр исходного кода

bin/taud: use more general Settings struct for rpc, raft, and dataset configurations

ghassmo 4 лет назад
Родитель
Сommit
53a8953ffb

+ 9 - 9
bin/tau/taud/src/jsonrpc.rs

@@ -1,4 +1,4 @@
-use std::sync::Arc;
+use std::{path::PathBuf, sync::Arc};
 
 use async_executor::Executor;
 use async_trait::async_trait;
@@ -18,11 +18,11 @@ use crate::{
     error::{to_json_result, TaudError, TaudResult},
     month_tasks::MonthTasks,
     task_info::{Comment, TaskInfo},
-    util::{Settings, Timestamp},
+    util::Timestamp,
 };
 
 pub struct JsonRpcInterface {
-    settings: Settings,
+    dataset_path: PathBuf,
     notify_queue_sender: async_channel::Sender<Option<TaskInfo>>,
 }
 
@@ -43,7 +43,7 @@ impl RequestHandler for JsonRpcInterface {
             return JsonResult::Err(jsonerr(ErrorCode::InvalidParams, None, req.id))
         }
 
-        if let Err(_) = self.notify_queue_sender.send(None).await {
+        if self.notify_queue_sender.send(None).await.is_err() {
             return JsonResult::Err(jsonerr(ErrorCode::InternalError, None, req.id))
         }
 
@@ -69,9 +69,9 @@ impl RequestHandler for JsonRpcInterface {
 impl JsonRpcInterface {
     pub fn new(
         notify_queue_sender: async_channel::Sender<Option<TaskInfo>>,
-        settings: Settings,
+        dataset_path: PathBuf,
     ) -> Self {
-        Self { notify_queue_sender, settings }
+        Self { notify_queue_sender, dataset_path }
     }
 
     // RPCAPI:
@@ -94,7 +94,7 @@ impl JsonRpcInterface {
 
         let task: BaseTaskInfo = serde_json::from_value(args[0].clone())?;
         let mut new_task: TaskInfo =
-            TaskInfo::new(&task.title, &task.desc, task.due, task.rank, &self.settings)?;
+            TaskInfo::new(&task.title, &task.desc, task.due, task.rank, &self.dataset_path)?;
         new_task.set_project(&task.project);
         new_task.set_assign(&task.assign);
 
@@ -108,7 +108,7 @@ impl JsonRpcInterface {
     // --> {"jsonrpc": "2.0", "method": "list", "params": [], "id": 1}
     // <-- {"jsonrpc": "2.0", "result": [task, ...], "id": 1}
     async fn list(&self, _params: Value) -> TaudResult<Value> {
-        let tks = MonthTasks::load_current_open_tasks(&self.settings)?;
+        let tks = MonthTasks::load_current_open_tasks(&self.dataset_path)?;
         Ok(json!(tks))
     }
 
@@ -207,7 +207,7 @@ impl JsonRpcInterface {
     fn load_task_by_id(&self, task_id: &Value) -> TaudResult<TaskInfo> {
         let task_id: u64 = serde_json::from_value(task_id.clone())?;
 
-        let tasks = MonthTasks::load_current_open_tasks(&self.settings)?;
+        let tasks = MonthTasks::load_current_open_tasks(&self.dataset_path)?;
         let task = tasks.into_iter().find(|t| (t.get_id() as u64) == task_id);
 
         task.ok_or(TaudError::InvalidId)

+ 25 - 37
bin/tau/taud/src/main.rs

@@ -1,4 +1,4 @@
-use std::{fs::create_dir_all, path::PathBuf, sync::Arc};
+use std::sync::Arc;
 
 use async_executor::Executor;
 use clap::Parser;
@@ -10,7 +10,6 @@ use darkfi::{
     rpc::rpcserver::{listen_and_serve, RpcServerConfig},
     util::{
         cli::{log_config, spawn_config, Config},
-        expand_path,
         path::get_config_path,
         sleep,
     },
@@ -30,42 +29,29 @@ use crate::{
     util::{CliTaud, Settings, TauConfig, CONFIG_FILE_CONTENTS},
 };
 
-async fn start(config: TauConfig, args: CliTaud, executor: Arc<Executor<'_>>) -> Result<()> {
-    if config.dataset_path.is_empty() {
-        return Err(Error::ParseFailed("Failed to parse dataset_path"))
-    }
-
-    let dataset_path = expand_path(&config.dataset_path)?;
-
-    // mkdir dataset_path if not exists
-    create_dir_all(dataset_path.join("month"))?;
-    create_dir_all(dataset_path.join("task"))?;
-
-    let settings = Settings { dataset_path };
-
+async fn start(settings: Settings, executor: Arc<Executor<'_>>) -> Result<()> {
     let p2p_settings = P2pSettings {
-        inbound: args.accept,
-        outbound_connections: args.slots,
-        external_addr: args.accept,
-        peers: args.connect.clone(),
-        seeds: args.seed.clone(),
+        inbound: settings.accept_address,
+        outbound_connections: settings.outbound_connections,
+        external_addr: settings.accept_address,
+        peers: settings.connect.clone(),
+        seeds: settings.seeds.clone(),
         ..Default::default()
     };
 
     //
     //Raft
     //
-    let mut raft =
-        Raft::<TaskInfo>::new(p2p_settings.inbound, PathBuf::from(config.datastore_raft))?;
+    let mut raft = Raft::<TaskInfo>::new(settings.accept_address, settings.datastore_raft.clone())?;
 
-    let raft_sender = raft.get_broadcast().clone();
-    let commits = raft.get_commits().clone();
+    let raft_sender = raft.get_broadcast();
+    let commits = raft.get_commits();
 
     //
     // RPC
     //
     let server_config = RpcServerConfig {
-        socket_addr: config.rpc_listener_url.url.parse()?,
+        socket_addr: settings.rpc_listener_url,
         use_tls: false,
         // this is all random filler that is meaningless bc tls is disabled
         identity_path: Default::default(),
@@ -74,7 +60,7 @@ async fn start(config: TauConfig, args: CliTaud, executor: Arc<Executor<'_>>) ->
 
     let (rpc_snd, rpc_rcv) = async_channel::unbounded::<Option<TaskInfo>>();
 
-    let rpc_interface = Arc::new(JsonRpcInterface::new(rpc_snd, settings));
+    let rpc_interface = Arc::new(JsonRpcInterface::new(rpc_snd, settings.dataset_path));
 
     let recv_update_from_raft: smol::Task<TaudResult<()>> = executor.spawn(async move {
         loop {
@@ -122,8 +108,10 @@ async fn main() -> Result<()> {
 
     let config: TauConfig = Config::<TauConfig>::load(config_path)?;
 
+    let settings = Settings::load(args, config)?;
+
     let ex = Arc::new(Executor::new());
-    smol::block_on(ex.run(start(config, args, ex.clone())))
+    smol::block_on(ex.run(start(settings, ex.clone())))
 }
 
 #[cfg(test)]
@@ -153,16 +141,16 @@ mod tests {
 
     #[test]
     fn load_and_save_tasks() -> TaudResult<()> {
-        let settings = Settings { dataset_path: get_path()? };
+        let dataset_path = get_path()?;
 
         // load and save TaskInfo
         ///////////////////////
 
-        let mut task = TaskInfo::new("test_title", "test_desc", None, 0.0, &settings)?;
+        let mut task = TaskInfo::new("test_title", "test_desc", None, 0.0, &dataset_path)?;
 
         task.save()?;
 
-        let t_load = TaskInfo::load(&task.get_ref_id(), &settings)?;
+        let t_load = TaskInfo::load(&task.get_ref_id(), &dataset_path)?;
 
         assert_eq!(task, t_load);
 
@@ -170,7 +158,7 @@ mod tests {
 
         task.save()?;
 
-        let t_load = TaskInfo::load(&task.get_ref_id(), &settings)?;
+        let t_load = TaskInfo::load(&task.get_ref_id(), &dataset_path)?;
 
         assert_eq!(task, t_load);
 
@@ -179,11 +167,11 @@ mod tests {
 
         let task_tks = vec![];
 
-        let mut mt = MonthTasks::new(&task_tks, &settings);
+        let mut mt = MonthTasks::new(&task_tks, &dataset_path);
 
         mt.save()?;
 
-        let mt_load = MonthTasks::load_or_create(&get_current_time(), &settings)?;
+        let mt_load = MonthTasks::load_or_create(&get_current_time(), &dataset_path)?;
 
         assert_eq!(mt, mt_load);
 
@@ -191,24 +179,24 @@ mod tests {
 
         mt.save()?;
 
-        let mt_load = MonthTasks::load_or_create(&get_current_time(), &settings)?;
+        let mt_load = MonthTasks::load_or_create(&get_current_time(), &dataset_path)?;
 
         assert_eq!(mt, mt_load);
 
         // activate task
         ///////////////////////
 
-        let task = TaskInfo::new("test_title_3", "test_desc", None, 0.0, &settings)?;
+        let task = TaskInfo::new("test_title_3", "test_desc", None, 0.0, &dataset_path)?;
 
         task.save()?;
 
-        let mt_load = MonthTasks::load_or_create(&get_current_time(), &settings)?;
+        let mt_load = MonthTasks::load_or_create(&get_current_time(), &dataset_path)?;
 
         assert!(!mt_load.get_task_tks().contains(&task.get_ref_id()));
 
         task.activate()?;
 
-        let mt_load = MonthTasks::load_or_create(&get_current_time(), &settings)?;
+        let mt_load = MonthTasks::load_or_create(&get_current_time(), &dataset_path)?;
 
         assert!(mt_load.get_task_tks().contains(&task.get_ref_id()));
 

+ 17 - 20
bin/tau/taud/src/month_tasks.rs

@@ -1,4 +1,4 @@
-use std::path::PathBuf;
+use std::path::{Path, PathBuf};
 
 use chrono::{TimeZone, Utc};
 use serde::{Deserialize, Serialize};
@@ -6,21 +6,21 @@ use serde::{Deserialize, Serialize};
 use crate::{
     error::{TaudError, TaudResult},
     task_info::TaskInfo,
-    util::{get_current_time, Settings, Timestamp},
+    util::{get_current_time, Timestamp},
 };
 
 #[derive(Clone, Debug, Serialize, Deserialize, PartialEq)]
 pub struct MonthTasks {
     created_at: Timestamp,
-    settings: Settings,
+    dataset_path: PathBuf,
     task_tks: Vec<String>,
 }
 
 impl MonthTasks {
-    pub fn new(task_tks: &[String], settings: &Settings) -> Self {
+    pub fn new(task_tks: &[String], dataset_path: &Path) -> Self {
         Self {
             created_at: get_current_time(),
-            settings: settings.clone(),
+            dataset_path: dataset_path.to_path_buf(),
             task_tks: task_tks.to_owned(),
         }
     }
@@ -33,7 +33,7 @@ impl MonthTasks {
         let mut tks: Vec<TaskInfo> = vec![];
 
         for ref_id in self.task_tks.iter() {
-            tks.push(TaskInfo::load(ref_id, &self.settings)?);
+            tks.push(TaskInfo::load(ref_id, &self.dataset_path)?);
         }
 
         Ok(tks)
@@ -45,8 +45,8 @@ impl MonthTasks {
         }
     }
 
-    pub fn set_settings(&mut self, settings: &Settings) {
-        self.settings = settings.clone();
+    pub fn set_dataset_path(&mut self, dataset_path: &Path) {
+        self.dataset_path = dataset_path.to_path_buf();
     }
 
     pub fn set_date(&mut self, date: &Timestamp) {
@@ -57,26 +57,23 @@ impl MonthTasks {
         self.task_tks.clone()
     }
 
-    fn get_path(date: &Timestamp, settings: &Settings) -> PathBuf {
-        settings
-            .dataset_path
-            .join("month")
-            .join(Utc.timestamp(date.0, 0).format("%m%y").to_string())
+    fn get_path(date: &Timestamp, dataset_path: &Path) -> PathBuf {
+        dataset_path.join("month").join(Utc.timestamp(date.0, 0).format("%m%y").to_string())
     }
 
     pub fn save(&self) -> TaudResult<()> {
-        crate::util::save::<Self>(&Self::get_path(&self.created_at, &self.settings), self)
+        crate::util::save::<Self>(&Self::get_path(&self.created_at, &self.dataset_path), self)
             .map_err(TaudError::Darkfi)
     }
 
-    pub fn load_or_create(date: &Timestamp, settings: &Settings) -> TaudResult<Self> {
-        match crate::util::load::<Self>(&Self::get_path(date, settings)) {
+    pub fn load_or_create(date: &Timestamp, dataset_path: &Path) -> TaudResult<Self> {
+        match crate::util::load::<Self>(&Self::get_path(date, dataset_path)) {
             Ok(mut mt) => {
-                mt.set_settings(settings);
+                mt.set_dataset_path(dataset_path);
                 Ok(mt)
             }
             Err(_) => {
-                let mut mt = Self::new(&[], settings);
+                let mut mt = Self::new(&[], dataset_path);
                 mt.set_date(date);
                 mt.save()?;
                 Ok(mt)
@@ -84,8 +81,8 @@ impl MonthTasks {
         }
     }
 
-    pub fn load_current_open_tasks(settings: &Settings) -> TaudResult<Vec<TaskInfo>> {
-        let mt = Self::load_or_create(&get_current_time(), settings)?;
+    pub fn load_current_open_tasks(dataset_path: &Path) -> TaudResult<Vec<TaskInfo>> {
+        let mt = Self::load_or_create(&get_current_time(), dataset_path)?;
         Ok(mt.objects()?.into_iter().filter(|t| t.get_state() != "stop").collect())
     }
 }

+ 19 - 16
bin/tau/taud/src/task_info.rs

@@ -1,4 +1,7 @@
-use std::{io, path::PathBuf};
+use std::{
+    io,
+    path::{Path, PathBuf},
+};
 
 use serde::{Deserialize, Serialize};
 
@@ -9,7 +12,7 @@ use darkfi::util::serial::VarInt;
 use crate::{
     error::{TaudError, TaudResult},
     month_tasks::MonthTasks,
-    util::{find_free_id, get_current_time, random_ref_id, Settings, Timestamp},
+    util::{find_free_id, get_current_time, random_ref_id, Timestamp},
 };
 
 #[derive(Clone, Debug, Serialize, Deserialize, SerialEncodable, SerialDecodable, PartialEq)]
@@ -60,7 +63,7 @@ pub struct TaskInfo {
     events: TaskEvents,
     comments: TaskComments,
     #[serde(skip_serializing, skip_deserializing)]
-    settings: Settings,
+    dataset_path: PathBuf,
 }
 
 impl TaskInfo {
@@ -69,7 +72,7 @@ impl TaskInfo {
         desc: &str,
         due: Option<Timestamp>,
         rank: f32,
-        settings: &Settings,
+        dataset_path: &Path,
     ) -> TaudResult<Self> {
         // generate ref_id
         let ref_id = random_ref_id();
@@ -77,7 +80,7 @@ impl TaskInfo {
         let created_at: Timestamp = get_current_time();
 
         let task_ids: Vec<u32> =
-            MonthTasks::load_current_open_tasks(settings)?.into_iter().map(|t| t.id).collect();
+            MonthTasks::load_current_open_tasks(dataset_path)?.into_iter().map(|t| t.id).collect();
 
         let id: u32 = find_free_id(&task_ids);
 
@@ -99,29 +102,29 @@ impl TaskInfo {
             created_at,
             comments: TaskComments(vec![]),
             events: TaskEvents(vec![]),
-            settings: settings.clone(),
+            dataset_path: dataset_path.to_path_buf(),
         })
     }
 
-    pub fn load(ref_id: &str, settings: &Settings) -> TaudResult<Self> {
-        let mut task = crate::util::load::<Self>(&Self::get_path(ref_id, settings))?;
-        task.set_settings(settings);
+    pub fn load(ref_id: &str, dataset_path: &Path) -> TaudResult<Self> {
+        let mut task = crate::util::load::<Self>(&Self::get_path(ref_id, dataset_path))?;
+        task.set_dataset_path(dataset_path);
         Ok(task)
     }
 
     pub fn save(&self) -> TaudResult<()> {
-        crate::util::save::<Self>(&Self::get_path(&self.ref_id, &self.settings), self)
+        crate::util::save::<Self>(&Self::get_path(&self.ref_id, &self.dataset_path), self)
             .map_err(TaudError::Darkfi)
     }
 
     pub fn activate(&self) -> TaudResult<()> {
-        let mut mt = MonthTasks::load_or_create(&self.created_at, &self.settings)?;
+        let mut mt = MonthTasks::load_or_create(&self.created_at, &self.dataset_path)?;
         mt.add(&self.ref_id);
         mt.save()
     }
 
     pub fn get_month_task(&self) -> TaudResult<MonthTasks> {
-        MonthTasks::load_or_create(&self.created_at, &self.settings)
+        MonthTasks::load_or_create(&self.created_at, &self.dataset_path)
     }
 
     pub fn get_state(&self) -> String {
@@ -132,8 +135,8 @@ impl TaskInfo {
         }
     }
 
-    fn get_path(ref_id: &str, settings: &Settings) -> PathBuf {
-        settings.dataset_path.join("task").join(ref_id)
+    fn get_path(ref_id: &str, dataset_path: &Path) -> PathBuf {
+        dataset_path.join("task").join(ref_id)
     }
 
     pub fn get_id(&self) -> u32 {
@@ -172,8 +175,8 @@ impl TaskInfo {
         self.due = d;
     }
 
-    pub fn set_settings(&mut self, settings: &Settings) {
-        self.settings = settings.clone();
+    pub fn set_dataset_path(&mut self, dataset_path: &Path) {
+        self.dataset_path = dataset_path.to_path_buf();
     }
 
     pub fn set_state(&mut self, action: &str) {

+ 73 - 8
bin/tau/taud/src/util.rs

@@ -1,5 +1,5 @@
 use std::{
-    fs::File,
+    fs::{create_dir_all, File},
     io::BufReader,
     net::SocketAddr,
     path::{Path, PathBuf},
@@ -13,9 +13,10 @@ use serde::{de::DeserializeOwned, Deserialize, Serialize};
 use darkfi::{
     util::{
         cli::UrlConfig,
+        expand_path,
         serial::{SerialDecodable, SerialEncodable},
     },
-    Result,
+    Error, Result,
 };
 
 pub const CONFIG_FILE_CONTENTS: &[u8] = include_bytes!("../taud_config.toml");
@@ -51,14 +52,72 @@ pub fn save<T: Serialize>(path: &Path, value: &T) -> Result<()> {
     Ok(())
 }
 
-#[derive(Clone, Debug, Serialize, Deserialize, SerialEncodable, SerialDecodable, PartialEq)]
+#[derive(Clone, Debug)]
 pub struct Settings {
     pub dataset_path: PathBuf,
+    pub datastore_raft: PathBuf,
+    pub rpc_listener_url: SocketAddr,
+    pub accept_address: Option<SocketAddr>,
+    pub outbound_connections: u32,
+    pub connect: Vec<SocketAddr>,
+    pub seeds: Vec<SocketAddr>,
 }
 
-impl Default for Settings {
-    fn default() -> Self {
-        Self { dataset_path: PathBuf::from("") }
+impl Settings {
+    pub fn load(args: CliTaud, config: TauConfig) -> Result<Self> {
+        if config.dataset_path.is_empty() {
+            return Err(Error::ParseFailed("Failed to parse dataset_path"))
+        }
+
+        let dataset_path = expand_path(&config.dataset_path)?;
+
+        // mkdir dataset_path if not exists
+        create_dir_all(dataset_path.join("month"))?;
+        create_dir_all(dataset_path.join("task"))?;
+
+        if config.datastore_raft.is_empty() {
+            return Err(Error::ParseFailed("Failed to parse datastore_raft path"))
+        }
+
+        let datastore_raft = expand_path(&config.datastore_raft)?;
+
+        let rpc_listener_url = SocketAddr::try_from(config.rpc_listener_url)?;
+
+        let accept_address = if args.accept.is_none() {
+            match config.accept_address {
+                Some(addr) => {
+                    let socket_addr = SocketAddr::try_from(addr)?;
+                    Some(socket_addr)
+                }
+                None => None,
+            }
+        } else {
+            args.accept
+        };
+
+        let outbound_connections =
+            if args.slots == 0 { config.outbound_connections.unwrap_or(0) } else { args.slots };
+
+        let connect = args.connect;
+
+        let config_seeds = config
+            .seeds
+            .map(|addrs| {
+                addrs.iter().filter_map(|addr| SocketAddr::try_from(addr.clone()).ok()).collect()
+            })
+            .unwrap_or_default();
+
+        let seeds = if args.seeds.is_empty() { config_seeds } else { args.seeds };
+
+        Ok(Settings {
+            dataset_path,
+            datastore_raft,
+            rpc_listener_url,
+            accept_address,
+            outbound_connections,
+            connect,
+            seeds,
+        })
     }
 }
 
@@ -77,9 +136,9 @@ pub struct CliTaud {
     /// Raft Accept address
     #[clap(short, long)]
     pub accept: Option<SocketAddr>,
-    /// Raft Seed node (repeatable)
+    /// Raft Seed nodes (repeatable)
     #[clap(short, long)]
-    pub seed: Vec<SocketAddr>,
+    pub seeds: Vec<SocketAddr>,
     /// Raft Manual connection (repeatable)
     #[clap(short, long)]
     pub connect: Vec<SocketAddr>,
@@ -101,6 +160,12 @@ pub struct TauConfig {
     pub tls_identity_path: String,
     /// The address where taud should bind its RPC socket
     pub rpc_listener_url: UrlConfig,
+    /// Accept address for p2p network
+    pub accept_address: Option<UrlConfig>,
+    /// Number of outbound connections for p2p
+    pub outbound_connections: Option<u32>,
+    /// The seeds for receiving ip addresses from the p2p network
+    pub seeds: Option<Vec<UrlConfig>>,
 }
 
 #[cfg(test)]

+ 11 - 0
bin/tau/taud/taud_config.toml

@@ -18,3 +18,14 @@ url="127.0.0.1:8875"
 # Password for the created TLS identity or tor password
 password = "FOOBAR"
 
+[accept]
+url="127.0.0.1:8875"
+password = "FOOBAR"
+
+outbound_connections = 5
+
+[[seeds]]
+url="127.0.0.1:8875"
+password = "FOOBAR"
+# one or more seed
+