mirror of
https://github.com/meilisearch/MeiliSearch
synced 2025-07-04 20:37:15 +02:00
restore snapshots
This commit is contained in:
parent
b9d189bf12
commit
90018755c5
15 changed files with 397 additions and 317 deletions
|
@ -4,6 +4,8 @@ use std::path::PathBuf;
|
|||
use tokio::sync::{mpsc, oneshot};
|
||||
use uuid::Uuid;
|
||||
|
||||
use crate::index::Index;
|
||||
|
||||
use super::error::Result;
|
||||
use super::{Update, UpdateStatus, UpdateStoreInfo};
|
||||
|
||||
|
@ -28,7 +30,7 @@ pub enum UpdateMsg {
|
|||
ret: oneshot::Sender<Result<()>>,
|
||||
},
|
||||
Snapshot {
|
||||
uuids: HashSet<Uuid>,
|
||||
indexes: Vec<Index>,
|
||||
path: PathBuf,
|
||||
ret: oneshot::Sender<Result<()>>,
|
||||
},
|
||||
|
@ -43,17 +45,20 @@ pub enum UpdateMsg {
|
|||
}
|
||||
|
||||
impl UpdateMsg {
|
||||
pub async fn snapshot(sender: &mpsc::Sender<Self>, path: PathBuf, indexes: Vec<Index>) -> Result<()> {
|
||||
let (ret, rcv) = oneshot::channel();
|
||||
let msg = Self::Snapshot { path, indexes, ret };
|
||||
sender.send(msg).await?;
|
||||
rcv.await?
|
||||
}
|
||||
|
||||
pub async fn dump(
|
||||
sender: &mpsc::Sender<Self>,
|
||||
uuids: HashSet<Uuid>,
|
||||
path: PathBuf,
|
||||
) -> Result<()> {
|
||||
let (ret, rcv) = oneshot::channel();
|
||||
let msg = Self::Dump {
|
||||
path,
|
||||
uuids,
|
||||
ret,
|
||||
};
|
||||
let msg = Self::Dump { path, uuids, ret };
|
||||
sender.send(msg).await?;
|
||||
rcv.await?
|
||||
}
|
||||
|
@ -63,11 +68,7 @@ impl UpdateMsg {
|
|||
update: Update,
|
||||
) -> Result<UpdateStatus> {
|
||||
let (ret, rcv) = oneshot::channel();
|
||||
let msg = Self::Update {
|
||||
uuid,
|
||||
update,
|
||||
ret,
|
||||
};
|
||||
let msg = Self::Update { uuid, update, ret };
|
||||
sender.send(msg).await?;
|
||||
rcv.await?
|
||||
}
|
||||
|
@ -78,11 +79,7 @@ impl UpdateMsg {
|
|||
id: u64,
|
||||
) -> Result<UpdateStatus> {
|
||||
let (ret, rcv) = oneshot::channel();
|
||||
let msg = Self::GetUpdate {
|
||||
uuid,
|
||||
id,
|
||||
ret,
|
||||
};
|
||||
let msg = Self::GetUpdate { uuid, id, ret };
|
||||
sender.send(msg).await?;
|
||||
rcv.await?
|
||||
}
|
||||
|
@ -92,21 +89,14 @@ impl UpdateMsg {
|
|||
uuid: Uuid,
|
||||
) -> Result<Vec<UpdateStatus>> {
|
||||
let (ret, rcv) = oneshot::channel();
|
||||
let msg = Self::ListUpdates {
|
||||
uuid,
|
||||
ret,
|
||||
};
|
||||
let msg = Self::ListUpdates { uuid, ret };
|
||||
sender.send(msg).await?;
|
||||
rcv.await?
|
||||
}
|
||||
|
||||
pub async fn get_info(
|
||||
sender: &mpsc::Sender<Self>,
|
||||
) -> Result<UpdateStoreInfo> {
|
||||
pub async fn get_info(sender: &mpsc::Sender<Self>) -> Result<UpdateStoreInfo> {
|
||||
let (ret, rcv) = oneshot::channel();
|
||||
let msg = Self::GetInfo {
|
||||
ret,
|
||||
};
|
||||
let msg = Self::GetInfo { ret };
|
||||
sender.send(msg).await?;
|
||||
rcv.await?
|
||||
}
|
||||
|
|
|
@ -24,7 +24,7 @@ use uuid::Uuid;
|
|||
use self::error::{Result, UpdateLoopError};
|
||||
pub use self::message::UpdateMsg;
|
||||
use self::store::{UpdateStore, UpdateStoreInfo};
|
||||
use crate::index::{Settings, Unchecked};
|
||||
use crate::index::{Index, Settings, Unchecked};
|
||||
use crate::index_controller::update_file_store::UpdateFileStore;
|
||||
use status::UpdateStatus;
|
||||
|
||||
|
@ -123,12 +123,11 @@ impl UpdateLoop {
|
|||
|
||||
let must_exit = Arc::new(AtomicBool::new(false));
|
||||
|
||||
let store = UpdateStore::open(options, &path, index_resolver.clone(), must_exit.clone())?;
|
||||
let update_file_store = UpdateFileStore::new(&path).unwrap();
|
||||
let store = UpdateStore::open(options, &path, index_resolver.clone(), must_exit.clone(), update_file_store.clone())?;
|
||||
|
||||
let inbox = Some(inbox);
|
||||
|
||||
let update_file_store = UpdateFileStore::new(&path).unwrap();
|
||||
|
||||
Ok(Self {
|
||||
store,
|
||||
inbox,
|
||||
|
@ -179,8 +178,8 @@ impl UpdateLoop {
|
|||
Delete { uuid, ret } => {
|
||||
let _ = ret.send(self.handle_delete(uuid).await);
|
||||
}
|
||||
Snapshot { uuids, path, ret } => {
|
||||
let _ = ret.send(self.handle_snapshot(uuids, path).await);
|
||||
Snapshot { indexes, path, ret } => {
|
||||
let _ = ret.send(self.handle_snapshot(indexes, path).await);
|
||||
}
|
||||
GetInfo { ret } => {
|
||||
let _ = ret.send(self.handle_get_info().await);
|
||||
|
@ -270,15 +269,13 @@ impl UpdateLoop {
|
|||
Ok(())
|
||||
}
|
||||
|
||||
async fn handle_snapshot(&self, _uuids: HashSet<Uuid>,_pathh: PathBuf) -> Result<()> {
|
||||
todo!()
|
||||
//let index_handle = self.index_resolver.clone();
|
||||
//let update_store = self.store.clone();
|
||||
async fn handle_snapshot(&self, indexes: Vec<Index>, path: PathBuf) -> Result<()> {
|
||||
let update_store = self.store.clone();
|
||||
|
||||
//tokio::task::spawn_blocking(move || update_store.snapshot(&uuids, &path, index_handle))
|
||||
//.await??;
|
||||
tokio::task::spawn_blocking(move || update_store.snapshot(indexes, path))
|
||||
.await??;
|
||||
|
||||
//Ok(())
|
||||
Ok(())
|
||||
}
|
||||
|
||||
async fn handle_dump(&self, uuids: HashSet<Uuid>, path: PathBuf) -> Result<()> {
|
||||
|
|
|
@ -45,16 +45,17 @@ impl UpdateStore {
|
|||
uuids: &HashSet<Uuid>,
|
||||
path: impl AsRef<Path>,
|
||||
) -> Result<()> {
|
||||
let dump_data_path = path.as_ref().join("data.jsonl");
|
||||
let mut dump_data_file = File::create(dump_data_path)?;
|
||||
//let dump_data_path = path.as_ref().join("data.jsonl");
|
||||
//let mut dump_data_file = File::create(dump_data_path)?;
|
||||
|
||||
let update_files_path = path.as_ref().join(super::UPDATE_DIR);
|
||||
create_dir_all(&update_files_path)?;
|
||||
//let update_files_path = path.as_ref().join(super::UPDATE_DIR);
|
||||
//create_dir_all(&update_files_path)?;
|
||||
|
||||
self.dump_pending(txn, uuids, &mut dump_data_file, &path)?;
|
||||
self.dump_completed(txn, uuids, &mut dump_data_file)?;
|
||||
//self.dump_pending(txn, uuids, &mut dump_data_file, &path)?;
|
||||
//self.dump_completed(txn, uuids, &mut dump_data_file)?;
|
||||
|
||||
Ok(())
|
||||
//Ok(())
|
||||
todo!()
|
||||
}
|
||||
|
||||
fn dump_pending(
|
||||
|
|
|
@ -22,6 +22,7 @@ use tokio::sync::mpsc;
|
|||
use tokio::sync::mpsc::error::TrySendError;
|
||||
use tokio::time::timeout;
|
||||
use uuid::Uuid;
|
||||
use rayon::prelude::*;
|
||||
|
||||
use codec::*;
|
||||
|
||||
|
@ -31,12 +32,11 @@ use super::status::{Enqueued, Processing};
|
|||
use crate::EnvSizer;
|
||||
use crate::index_controller::update_files_path;
|
||||
use crate::index_controller::updates::*;
|
||||
use crate::index::Index;
|
||||
|
||||
#[allow(clippy::upper_case_acronyms)]
|
||||
type BEU64 = U64<heed::byteorder::BE>;
|
||||
|
||||
const UPDATE_DIR: &str = "update_files";
|
||||
|
||||
#[derive(Debug)]
|
||||
pub struct UpdateStoreInfo {
|
||||
/// Size of the update store in bytes.
|
||||
|
@ -108,6 +108,7 @@ pub struct UpdateStore {
|
|||
state: Arc<StateLock>,
|
||||
/// Wake up the loop when a new event occurs.
|
||||
notification_sender: mpsc::Sender<()>,
|
||||
update_file_store: UpdateFileStore,
|
||||
path: PathBuf,
|
||||
}
|
||||
|
||||
|
@ -115,6 +116,7 @@ impl UpdateStore {
|
|||
fn new(
|
||||
mut options: EnvOpenOptions,
|
||||
path: impl AsRef<Path>,
|
||||
update_file_store: UpdateFileStore,
|
||||
) -> anyhow::Result<(Self, mpsc::Receiver<()>)> {
|
||||
options.max_dbs(5);
|
||||
|
||||
|
@ -138,6 +140,7 @@ impl UpdateStore {
|
|||
state,
|
||||
notification_sender,
|
||||
path: path.as_ref().to_owned(),
|
||||
update_file_store,
|
||||
},
|
||||
notification_receiver,
|
||||
))
|
||||
|
@ -148,8 +151,9 @@ impl UpdateStore {
|
|||
path: impl AsRef<Path>,
|
||||
index_resolver: Arc<HardStateIndexResolver>,
|
||||
must_exit: Arc<AtomicBool>,
|
||||
update_file_store: UpdateFileStore,
|
||||
) -> anyhow::Result<Arc<Self>> {
|
||||
let (update_store, mut notification_receiver) = Self::new(options, path)?;
|
||||
let (update_store, mut notification_receiver) = Self::new(options, path, update_file_store)?;
|
||||
let update_store = Arc::new(update_store);
|
||||
|
||||
// Send a first notification to trigger the process.
|
||||
|
@ -482,13 +486,13 @@ impl UpdateStore {
|
|||
|
||||
pub fn snapshot(
|
||||
&self,
|
||||
_uuids: &HashSet<Uuid>,
|
||||
indexes: Vec<Index>,
|
||||
path: impl AsRef<Path>,
|
||||
handle: Arc<HardStateIndexResolver>,
|
||||
) -> Result<()> {
|
||||
let state_lock = self.state.write();
|
||||
state_lock.swap(State::Snapshoting);
|
||||
|
||||
|
||||
let txn = self.env.write_txn()?;
|
||||
|
||||
let update_path = path.as_ref().join("updates");
|
||||
|
@ -501,42 +505,28 @@ impl UpdateStore {
|
|||
// create db snapshot
|
||||
self.env.copy_to_path(&db_path, CompactionOption::Enabled)?;
|
||||
|
||||
let update_files_path = update_path.join(UPDATE_DIR);
|
||||
create_dir_all(&update_files_path)?;
|
||||
|
||||
let pendings = self.pending_queue.iter(&txn)?.lazily_decode_data();
|
||||
|
||||
let uuids: HashSet<_> = indexes.iter().map(|i| i.uuid).collect();
|
||||
for entry in pendings {
|
||||
let ((_, _uuid, _), _pending) = entry?;
|
||||
//if uuids.contains(&uuid) {
|
||||
//if let Enqueued {
|
||||
//content: Some(uuid),
|
||||
//..
|
||||
//} = pending.decode()?
|
||||
//{
|
||||
//let path = update_uuid_to_file_path(&self.path, uuid);
|
||||
//copy(path, &update_files_path)?;
|
||||
//}
|
||||
//}
|
||||
let ((_, uuid, _), pending) = entry?;
|
||||
if uuids.contains(&uuid) {
|
||||
if let Enqueued {
|
||||
meta: RegisterUpdate::DocumentAddition {
|
||||
content_uuid, ..
|
||||
},
|
||||
..
|
||||
} = pending.decode()?
|
||||
{
|
||||
self.update_file_store.snapshot(content_uuid, &path).unwrap();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
let _path = &path.as_ref().to_path_buf();
|
||||
let _handle = &handle;
|
||||
// Perform the snapshot of each index concurently. Only a third of the capabilities of
|
||||
// the index actor at a time not to put too much pressure on the index actor
|
||||
todo!()
|
||||
//let mut stream = futures::stream::iter(uuids.iter())
|
||||
//.map(move |uuid| IndexMsg::snapshot(handle,*uuid, path.clone()))
|
||||
//.buffer_unordered(CONCURRENT_INDEX_MSG / 3);
|
||||
let path = path.as_ref().to_owned();
|
||||
indexes.par_iter().try_for_each(|index| index.snapshot(&path)).unwrap();
|
||||
|
||||
//Handle::current().block_on(async {
|
||||
//while let Some(res) = stream.next().await {
|
||||
//res?;
|
||||
//}
|
||||
//Ok(()) as Result<()>
|
||||
//})?;
|
||||
|
||||
//Ok(())
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub fn get_info(&self) -> Result<UpdateStoreInfo> {
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue