use crate::NetworkState;
use ckb_logger::debug;
use futures::Future;
use std::{
pin::Pin,
sync::Arc,
task::{Context, Poll},
time::Duration,
};
const DEFAULT_DUMP_INTERVAL: Duration = Duration::from_secs(3600);
pub struct DumpPeerStoreService {
network_state: Arc<NetworkState>,
interval: Option<p2p::runtime::Interval>,
}
impl DumpPeerStoreService {
pub fn new(network_state: Arc<NetworkState>) -> Self {
DumpPeerStoreService {
network_state,
interval: None,
}
}
#[cfg(not(target_family = "wasm"))]
fn dump_peer_store(&self) {
let path = self.network_state.config.peer_store_path();
self.network_state.with_peer_store_mut(|peer_store| {
if let Err(err) = peer_store.dump_to_dir(&path) {
ckb_logger::warn!("Dump peer store error, path: {:?} error: {}", path, err);
} else {
debug!("Dump peer store to {:?}", path);
}
});
}
#[cfg(target_family = "wasm")]
fn dump_peer_store(&self) {
let path = self.network_state.config.peer_store_path();
self.network_state.with_peer_store_mut(|peer_store| {
let task = peer_store.dump_to_idb(path);
p2p::runtime::spawn(task)
});
}
}
impl Drop for DumpPeerStoreService {
fn drop(&mut self) {
debug!("Dump peer store before exiting");
self.dump_peer_store();
#[cfg(target_family = "wasm")]
{
use crate::peer_store::browser::get_db;
let path = self.network_state.config.peer_store_path();
p2p::runtime::spawn(async {
let _ignore = get_db(path).await.shutdown().await;
});
}
}
}
impl Future for DumpPeerStoreService {
type Output = ();
fn poll(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Self::Output> {
use futures::StreamExt;
if self.interval.is_none() {
self.interval = {
let mut interval =
p2p::runtime::Interval::new_at(DEFAULT_DUMP_INTERVAL, DEFAULT_DUMP_INTERVAL);
interval.set_missed_tick_behavior(p2p::runtime::MissedTickBehavior::Skip);
Some(interval)
}
}
while self
.interval
.as_mut()
.unwrap()
.poll_next_unpin(cx)
.is_ready()
{
self.dump_peer_store()
}
Poll::Pending
}
}