mirror of
https://github.com/deuxfleurs-org/garage.git
synced 2026-08-21 02:16:37 +00:00
Background task manager (#332)
- [x] New background worker trait - [x] Adapt all current workers to use new API - [x] Command to list currently running workers, and whether they are active, idle, or dead - [x] Error reporting - Optimizations - [x] Merkle updater: several items per iteration - [ ] Use `tokio::task::spawn_blocking` where appropriate so that CPU-intensive tasks don't block other things going on - scrub: - [x] have only one worker with a channel to start/pause/cancel - [x] automatic scrub - [x] ability to view and change tranquility from CLI - [x] persistence of a few info - [ ] Testing Co-authored-by: Alex Auvolat <alex@adnab.me> Reviewed-on: https://git.deuxfleurs.fr/Deuxfleurs/garage/pulls/332 Co-authored-by: Alex <alex@adnab.me> Co-committed-by: Alex <alex@adnab.me>
This commit is contained in:
+62
-27
@@ -8,12 +8,11 @@ use serde::{Deserialize, Serialize};
|
||||
use serde_bytes::ByteBuf;
|
||||
|
||||
use futures::future::join_all;
|
||||
use futures::select;
|
||||
use futures_util::future::*;
|
||||
use tokio::sync::watch;
|
||||
|
||||
use garage_db::counted_tree_hack::CountedTree;
|
||||
|
||||
use garage_util::background::*;
|
||||
use garage_util::data::*;
|
||||
use garage_util::error::*;
|
||||
use garage_util::time::*;
|
||||
@@ -69,35 +68,11 @@ where
|
||||
|
||||
gc.endpoint.set_handler(gc.clone());
|
||||
|
||||
let gc1 = gc.clone();
|
||||
system.background.spawn_worker(
|
||||
format!("GC loop for {}", F::TABLE_NAME),
|
||||
move |must_exit: watch::Receiver<bool>| gc1.gc_loop(must_exit),
|
||||
);
|
||||
system.background.spawn_worker(GcWorker::new(gc.clone()));
|
||||
|
||||
gc
|
||||
}
|
||||
|
||||
async fn gc_loop(self: Arc<Self>, mut must_exit: watch::Receiver<bool>) {
|
||||
while !*must_exit.borrow() {
|
||||
match self.gc_loop_iter().await {
|
||||
Ok(None) => {
|
||||
// Stuff was done, loop immediately
|
||||
}
|
||||
Ok(Some(wait_delay)) => {
|
||||
// Nothing was done, wait specified delay.
|
||||
select! {
|
||||
_ = tokio::time::sleep(wait_delay).fuse() => {},
|
||||
_ = must_exit.changed().fuse() => {},
|
||||
}
|
||||
}
|
||||
Err(e) => {
|
||||
warn!("({}) Error doing GC: {}", F::TABLE_NAME, e);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
async fn gc_loop_iter(&self) -> Result<Option<Duration>, Error> {
|
||||
let now = now_msec();
|
||||
|
||||
@@ -328,6 +303,66 @@ where
|
||||
}
|
||||
}
|
||||
|
||||
struct GcWorker<F, R>
|
||||
where
|
||||
F: TableSchema + 'static,
|
||||
R: TableReplication + 'static,
|
||||
{
|
||||
gc: Arc<TableGc<F, R>>,
|
||||
wait_delay: Duration,
|
||||
}
|
||||
|
||||
impl<F, R> GcWorker<F, R>
|
||||
where
|
||||
F: TableSchema + 'static,
|
||||
R: TableReplication + 'static,
|
||||
{
|
||||
fn new(gc: Arc<TableGc<F, R>>) -> Self {
|
||||
Self {
|
||||
gc,
|
||||
wait_delay: Duration::from_secs(0),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[async_trait]
|
||||
impl<F, R> Worker for GcWorker<F, R>
|
||||
where
|
||||
F: TableSchema + 'static,
|
||||
R: TableReplication + 'static,
|
||||
{
|
||||
fn name(&self) -> String {
|
||||
format!("{} GC", F::TABLE_NAME)
|
||||
}
|
||||
|
||||
fn info(&self) -> Option<String> {
|
||||
let l = self.gc.data.gc_todo_len().unwrap_or(0);
|
||||
if l > 0 {
|
||||
Some(format!("{} items in queue", l))
|
||||
} else {
|
||||
None
|
||||
}
|
||||
}
|
||||
|
||||
async fn work(&mut self, _must_exit: &mut watch::Receiver<bool>) -> Result<WorkerState, Error> {
|
||||
match self.gc.gc_loop_iter().await? {
|
||||
None => Ok(WorkerState::Busy),
|
||||
Some(delay) => {
|
||||
self.wait_delay = delay;
|
||||
Ok(WorkerState::Idle)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
async fn wait_for_work(&mut self, must_exit: &watch::Receiver<bool>) -> WorkerState {
|
||||
if *must_exit.borrow() {
|
||||
return WorkerState::Done;
|
||||
}
|
||||
tokio::time::sleep(self.wait_delay).await;
|
||||
WorkerState::Busy
|
||||
}
|
||||
}
|
||||
|
||||
/// An entry stored in the gc_todo Sled tree associated with the table
|
||||
/// Contains helper function for parsing, saving, and removing
|
||||
/// such entry in Sled
|
||||
|
||||
Reference in New Issue
Block a user