bin/darkirc: implement removing events older than one week, and save/load tree state

This commit is contained in:
Dastan-glitch
2023-08-21 05:05:17 +03:00
parent 4060ad6821
commit fc8740fe91
3 changed files with 62 additions and 17 deletions

View File

@@ -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

View File

@@ -16,13 +16,14 @@
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
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<PrivMsgEvent>) {
// Removes events older than one week ,then sleeps untill next midnight
async fn remove_old_events(model: ModelPtr<PrivMsgEvent>) -> Result<()> {
loop {
let now = Utc::now();
@@ -81,21 +83,24 @@ async fn reset_root(model: ModelPtr<PrivMsgEvent>) {
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<smol::Executor<'_>>) -> 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<smol::Executor<'_>>) -> Result<(
////////////////////
let events_queue = EventsQueue::<PrivMsgEvent>::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<smol::Executor<'_>>) -> 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(())

View File

@@ -53,6 +53,10 @@ pub struct Args {
#[structopt(long)]
pub config: Option<String>,
/// 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,