mirror of
https://github.com/pseXperiments/freedit.git
synced 2026-01-09 15:48:05 -05:00
snapshot pruning (#2)
* feat: snapshot pruning logic, use unix timestamps instead of whatever jiff nonsense * chore: cleanup
This commit is contained in:
61
src/main.rs
61
src/main.rs
@@ -3,11 +3,13 @@
|
||||
#![warn(clippy::pedantic)]
|
||||
// #![warn(clippy::unwrap_used)]
|
||||
|
||||
use std::time::SystemTime;
|
||||
use std::time::UNIX_EPOCH;
|
||||
use std::{fs, net::SocketAddr, path::PathBuf};
|
||||
|
||||
use freedit::{
|
||||
router, AppError, CONFIG, DB, VERSION, {clear_invalid, cron_feed, Tan},
|
||||
};
|
||||
use jiff::Timestamp;
|
||||
use std::{fs, net::SocketAddr, path::PathBuf};
|
||||
use tokio::net::TcpListener;
|
||||
use tracing::{error, info, warn};
|
||||
use tracing_subscriber::{layer::SubscriberExt, util::SubscriberInitExt};
|
||||
@@ -27,9 +29,19 @@ async fn main() -> Result<(), AppError> {
|
||||
#[cfg(not(debug_assertions))]
|
||||
tokio::spawn(async move {
|
||||
loop {
|
||||
create_snapshot(&DB);
|
||||
let snapshot_path = PathBuf::from("snapshots");
|
||||
// create snapshot dir if needed
|
||||
if !snapshot_path.exists() {
|
||||
fs::create_dir_all(&snapshot_path).unwrap();
|
||||
}
|
||||
// create a snapshot
|
||||
create_snapshot(&snapshot_path, &DB);
|
||||
// remove snapshots older than 48 hours
|
||||
if let Err(e) = prune_snapshots(&snapshot_path) {
|
||||
error!(%e, "error pruning snapshots");
|
||||
}
|
||||
// snapshot every 30 mins
|
||||
sleep_seconds(1800).await;
|
||||
sleep_seconds(60 * 30).await;
|
||||
}
|
||||
});
|
||||
|
||||
@@ -91,16 +103,17 @@ async fn main() -> Result<(), AppError> {
|
||||
|
||||
// TODO: TEST with https://github.com/hatoo/oha
|
||||
#[allow(dead_code)]
|
||||
fn create_snapshot(db: &sled::Db) {
|
||||
fn create_snapshot(snapshot_path: &PathBuf, db: &sled::Db) {
|
||||
let checksum = db.checksum().unwrap();
|
||||
info!(%checksum);
|
||||
|
||||
let ts = Timestamp::now().strftime("%Y-%m-%d-%H-%M-%S");
|
||||
let mut snapshot_path = PathBuf::from("snapshots");
|
||||
if !snapshot_path.exists() {
|
||||
fs::create_dir_all(&snapshot_path).unwrap();
|
||||
}
|
||||
snapshot_path.push(format!("{VERSION}-{ts}-{checksum}"));
|
||||
let timestamp = SystemTime::now()
|
||||
.duration_since(UNIX_EPOCH)
|
||||
.unwrap()
|
||||
.as_secs();
|
||||
|
||||
let mut snapshot_path = snapshot_path.clone();
|
||||
snapshot_path.push(format!("{VERSION}_{timestamp}_{checksum}"));
|
||||
let snapshot_cfg = sled::Config::default().path(&snapshot_path);
|
||||
let snapshot = snapshot_cfg.open().unwrap();
|
||||
snapshot.import(db.export());
|
||||
@@ -108,6 +121,32 @@ fn create_snapshot(db: &sled::Db) {
|
||||
drop(snapshot);
|
||||
}
|
||||
|
||||
#[allow(dead_code)]
|
||||
fn prune_snapshots(snapshot_path: &PathBuf) -> Result<(), AppError> {
|
||||
let contents = fs::read_dir(snapshot_path)?;
|
||||
let now = SystemTime::now()
|
||||
.duration_since(UNIX_EPOCH)
|
||||
.unwrap()
|
||||
.as_secs();
|
||||
|
||||
for name in contents {
|
||||
let name = name?;
|
||||
let file_name = name.file_name();
|
||||
let file_name = file_name.to_string_lossy();
|
||||
let split_contents: Vec<&str> = file_name.split('_').collect();
|
||||
// timestamp is the second element
|
||||
let ts = split_contents[1];
|
||||
let snapshot_ts = ts.parse::<u64>().unwrap();
|
||||
let diff = now - snapshot_ts;
|
||||
// 48 hours
|
||||
let max_age: u64 = 60 * 60 * 48;
|
||||
if diff > max_age {
|
||||
fs::remove_dir_all(name.path())?;
|
||||
}
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
|
||||
async fn sleep_seconds(seconds: u64) {
|
||||
tokio::time::sleep(std::time::Duration::from_secs(seconds)).await;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user