2024-08-05 09:30:26 +00:00
|
|
|
use std::sync::{
|
|
|
|
atomic::{AtomicBool, Ordering},
|
|
|
|
Arc,
|
|
|
|
};
|
|
|
|
|
|
|
|
use anyhow::Result;
|
|
|
|
use log_entry_sync::LogSyncEvent;
|
|
|
|
use storage_async::Store;
|
|
|
|
use task_executor::TaskExecutor;
|
|
|
|
use tokio::sync::{
|
|
|
|
broadcast,
|
2024-10-28 06:56:08 +00:00
|
|
|
mpsc::{unbounded_channel, UnboundedReceiver, UnboundedSender},
|
2024-08-05 09:30:26 +00:00
|
|
|
oneshot,
|
|
|
|
};
|
|
|
|
|
|
|
|
use crate::{Config, SyncSender};
|
|
|
|
|
2024-10-28 06:56:08 +00:00
|
|
|
use super::{
|
|
|
|
batcher_random::RandomBatcher,
|
|
|
|
batcher_serial::SerialBatcher,
|
|
|
|
sync_store::{Queue, SyncStore},
|
|
|
|
};
|
2024-08-05 09:30:26 +00:00
|
|
|
|
|
|
|
pub struct AutoSyncManager {
|
2024-10-28 06:56:08 +00:00
|
|
|
pub serial: Option<SerialBatcher>,
|
2024-08-05 09:30:26 +00:00
|
|
|
pub random: RandomBatcher,
|
|
|
|
pub file_announcement_send: UnboundedSender<u64>,
|
2024-10-28 06:56:08 +00:00
|
|
|
pub new_file_send: UnboundedSender<u64>,
|
2024-08-19 01:54:52 +00:00
|
|
|
pub catched_up: Arc<AtomicBool>,
|
2024-08-05 09:30:26 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
impl AutoSyncManager {
|
|
|
|
pub async fn spawn(
|
|
|
|
config: Config,
|
|
|
|
executor: &TaskExecutor,
|
|
|
|
store: Store,
|
|
|
|
sync_send: SyncSender,
|
|
|
|
log_sync_recv: broadcast::Receiver<LogSyncEvent>,
|
|
|
|
catch_up_end_recv: oneshot::Receiver<()>,
|
|
|
|
) -> Result<Self> {
|
2024-10-28 06:56:08 +00:00
|
|
|
let (file_announcement_send, file_announcement_recv) = unbounded_channel();
|
|
|
|
let (new_file_send, new_file_recv) = unbounded_channel();
|
|
|
|
let sync_store = if config.neighbors_only {
|
|
|
|
// use v2 db to avoid reading v1 files that announced from the whole network instead of neighbors
|
|
|
|
Arc::new(SyncStore::new_with_name(
|
|
|
|
store.clone(),
|
|
|
|
"pendingv2",
|
|
|
|
"readyv2",
|
|
|
|
))
|
|
|
|
} else {
|
|
|
|
Arc::new(SyncStore::new(store.clone()))
|
|
|
|
};
|
2024-08-05 09:30:26 +00:00
|
|
|
let catched_up = Arc::new(AtomicBool::new(false));
|
|
|
|
|
2024-10-28 06:56:08 +00:00
|
|
|
// handle new file
|
2024-08-05 09:30:26 +00:00
|
|
|
executor.spawn(
|
2024-10-28 06:56:08 +00:00
|
|
|
Self::handle_new_file(new_file_recv, sync_store.clone()),
|
|
|
|
"auto_sync_handle_new_file",
|
2024-08-05 09:30:26 +00:00
|
|
|
);
|
|
|
|
|
2024-10-28 06:56:08 +00:00
|
|
|
// sync in sequence
|
|
|
|
let serial = if config.neighbors_only {
|
|
|
|
None
|
|
|
|
} else {
|
|
|
|
let serial =
|
|
|
|
SerialBatcher::new(config, store.clone(), sync_send.clone(), sync_store.clone())
|
|
|
|
.await?;
|
|
|
|
executor.spawn(
|
|
|
|
serial
|
|
|
|
.clone()
|
|
|
|
.start(file_announcement_recv, log_sync_recv, catched_up.clone()),
|
|
|
|
"auto_sync_serial",
|
|
|
|
);
|
|
|
|
|
|
|
|
Some(serial)
|
|
|
|
};
|
|
|
|
|
2024-08-05 09:30:26 +00:00
|
|
|
// sync randomly
|
|
|
|
let random = RandomBatcher::new(config, store, sync_send, sync_store);
|
|
|
|
executor.spawn(random.clone().start(catched_up.clone()), "auto_sync_random");
|
|
|
|
|
|
|
|
// handle on catched up notification
|
|
|
|
executor.spawn(
|
2024-10-28 06:56:08 +00:00
|
|
|
Self::listen_catch_up(catch_up_end_recv, catched_up.clone()),
|
2024-08-05 09:30:26 +00:00
|
|
|
"auto_sync_wait_for_catchup",
|
|
|
|
);
|
|
|
|
|
|
|
|
Ok(Self {
|
|
|
|
serial,
|
|
|
|
random,
|
2024-10-28 06:56:08 +00:00
|
|
|
file_announcement_send,
|
|
|
|
new_file_send,
|
2024-08-19 01:54:52 +00:00
|
|
|
catched_up,
|
2024-08-05 09:30:26 +00:00
|
|
|
})
|
|
|
|
}
|
2024-10-28 06:56:08 +00:00
|
|
|
|
|
|
|
async fn handle_new_file(
|
|
|
|
mut new_file_recv: UnboundedReceiver<u64>,
|
|
|
|
sync_store: Arc<SyncStore>,
|
|
|
|
) {
|
|
|
|
while let Some(tx_seq) = new_file_recv.recv().await {
|
|
|
|
if let Err(err) = sync_store.insert(tx_seq, Queue::Ready).await {
|
|
|
|
warn!(?err, %tx_seq, "Failed to insert new file to ready queue");
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
async fn listen_catch_up(
|
|
|
|
catch_up_end_recv: oneshot::Receiver<()>,
|
|
|
|
catched_up: Arc<AtomicBool>,
|
|
|
|
) {
|
|
|
|
if catch_up_end_recv.await.is_ok() {
|
|
|
|
info!("log entry catched up");
|
|
|
|
catched_up.store(true, Ordering::Relaxed);
|
|
|
|
}
|
|
|
|
}
|
2024-08-05 09:30:26 +00:00
|
|
|
}
|