diff --git a/bin/darkirc/darkirc_config.toml b/bin/darkirc/darkirc_config.toml
index 775b6c791..c5a779c4c 100644
--- a/bin/darkirc/darkirc_config.toml
+++ b/bin/darkirc/darkirc_config.toml
@@ -13,8 +13,18 @@
## TLS secret key path if IRC acceptor uses TLS (optional)
#irc_tls_secret = "/etc/letsencrypt/ircd/privkey.pem"
+## Sets Datastore Path
+#datastore = "~/.darkirc"
+
## List of channels to autojoin for new client connections
-autojoin = ["#dev", "#memes", "#philosophy", "#markets", "#math", "#random"]
+autojoin = [
+ "#dev",
+ "#memes",
+ "#philosophy",
+ "#markets",
+ "#math",
+ "#random",
+]
## Daemon specific password (optional, but once you configure it,
## it is required from the client side)
@@ -26,7 +36,7 @@ autojoin = ["#dev", "#memes", "#philosophy", "#markets", "#math", "#random"]
#inbound = ["tcp+tls://0.0.0.0:26661", "tcp+tls://[::]:26661"]
## Connection slots
-outbound_connections=8
+outbound_connections = 8
## Addresses we want to advertise to peers (optional)
## These should be reachable externally
diff --git a/bin/darkirc/src/main.rs b/bin/darkirc/src/main.rs
index 2e745aa7e..d01b4ff31 100644
--- a/bin/darkirc/src/main.rs
+++ b/bin/darkirc/src/main.rs
@@ -16,13 +16,14 @@
* along with this program. If not, see .
*/
-use std::collections::HashMap;
+use std::{collections::HashMap, fs::create_dir_all};
use async_std::{
stream::StreamExt,
sync::{Arc, Mutex},
task,
};
+
use chrono::{Duration, Utc};
use irc::ClientSubMsg;
use log::{debug, info};
@@ -72,7 +73,8 @@ async fn parse_signals(
}
}
-async fn reset_root(model: ModelPtr) {
+// Removes events older than one week ,then sleeps untill next midnight
+async fn remove_old_events(model: ModelPtr) -> Result<()> {
loop {
let now = Utc::now();
@@ -81,21 +83,24 @@ async fn reset_root(model: ModelPtr) {
let duration = next_midnight.signed_duration_since(now.naive_utc()).to_std().unwrap();
- // make sure the root is the same as everyone else's at
- // startup by passing today's date 00:00 AM UTC as
- // timestamp to root_event
- let now_datetime = now.date_naive().and_hms_opt(0, 0, 0).unwrap();
- let timestamp = now_datetime.timestamp() as u64;
+ let week_old_datetime =
+ (now - Duration::weeks(1)).date_naive().and_hms_opt(0, 0, 0).unwrap();
+ let timestamp = week_old_datetime.timestamp() as u64;
- model.lock().await.reset_root(Timestamp(timestamp));
+ model.lock().await.remove_old_events(Timestamp(timestamp))?;
+ info!("Removing old events");
- sleep(duration.as_secs()).await;
- info!("Resetting root");
+ sleep(duration.as_secs() + 1).await;
}
}
async_daemonize!(realmain);
async fn realmain(settings: Args, executor: Arc>) -> Result<()> {
+ let datastore_path = expand_path(&settings.datastore)?;
+
+ // mkdir datastore_path if not exists
+ create_dir_all(datastore_path.clone())?;
+
// Signal handling for config reload and graceful termination.
let (signals_handler, signals_task) = SignalHandler::new()?;
let client_sub = Subscriber::new();
@@ -155,10 +160,29 @@ async fn realmain(settings: Args, executor: Arc>) -> Result<(
////////////////////
let events_queue = EventsQueue::::new();
let model = Arc::new(Mutex::new(Model::new(events_queue.clone())));
- let view = Arc::new(Mutex::new(View::new(events_queue)));
+ let view = Arc::new(Mutex::new(View::new(events_queue.clone())));
let model_clone = model.clone();
let model_clone2 = model.clone();
+ {
+ // Temporarly load model and check if the loaded head is not
+ // older than one week (already removed from other node's tree)
+ let now = Utc::now();
+
+ let now_datetime = (now - Duration::weeks(1)).date_naive().and_hms_opt(0, 0, 0).unwrap();
+ let timestamp = Timestamp(now_datetime.timestamp() as u64);
+
+ let mut loaded_model = Model::new(events_queue.clone());
+ loaded_model.load_tree(&datastore_path)?;
+
+ if loaded_model
+ .get_event(&loaded_model.get_head_hash())
+ .is_some_and(|event| event.timestamp >= timestamp)
+ {
+ model.lock().await.load_tree(&datastore_path)?;
+ }
+ }
+
////////////////////
// P2p setup
////////////////////
@@ -207,21 +231,28 @@ async fn realmain(settings: Args, executor: Arc>) -> Result<(
////////////////////
// New irc server
- let irc_server =
- IrcServer::new(settings.clone(), p2p.clone(), model_clone, view.clone(), client_sub)
- .await?;
+ let irc_server = IrcServer::new(
+ settings.clone(),
+ p2p.clone(),
+ model_clone.clone(),
+ view.clone(),
+ client_sub,
+ )
+ .await?;
// Start the irc server and detach it
let executor_cloned = executor.clone();
executor.spawn(async move { irc_server.start(executor_cloned).await }).detach();
// Reset root task
- executor.spawn(async move { reset_root(model_clone2).await }).detach();
+ executor.spawn(async move { remove_old_events(model_clone2).await }).detach();
// Wait for termination signal
signals_handler.wait_termination(signals_task).await?;
info!("Caught termination signal, cleaning up and exiting...");
+ model_clone.lock().await.save_tree(&datastore_path)?;
+
// stop p2p
p2p2.stop().await;
Ok(())
diff --git a/bin/darkirc/src/settings.rs b/bin/darkirc/src/settings.rs
index 3baeb59ca..dfb6525e0 100644
--- a/bin/darkirc/src/settings.rs
+++ b/bin/darkirc/src/settings.rs
@@ -53,6 +53,10 @@ pub struct Args {
#[structopt(long)]
pub config: Option,
+ /// Sets Datastore Path
+ #[structopt(long, default_value = "~/.darkirc")]
+ pub datastore: String,
+
/// JSON-RPC listen URL
#[structopt(long = "rpc", default_value = "tcp://127.0.0.1:26660")]
pub rpc_listen: Url,