MeiliSearch/meilisearch-lib/src/index_controller/index_resolver/mod.rs

186 lines
5.8 KiB
Rust
Raw Normal View History

2021-09-24 11:53:11 +02:00
pub mod error;
2021-10-04 18:31:05 +02:00
pub mod index_store;
2021-09-28 22:22:59 +02:00
pub mod uuid_store;
2021-09-24 11:53:11 +02:00
use std::path::Path;
2021-09-28 22:22:59 +02:00
use error::{IndexResolverError, Result};
2021-09-24 11:53:11 +02:00
use index_store::{IndexStore, MapIndexStore};
use log::error;
2021-09-28 22:22:59 +02:00
use uuid::Uuid;
use uuid_store::{HeedUuidStore, UuidStore};
2021-09-24 11:53:11 +02:00
2021-09-28 22:22:59 +02:00
use crate::{
index::{update_handler::UpdateHandler, Index},
options::IndexerOpts,
};
2021-09-24 11:53:11 +02:00
pub type HardStateIndexResolver = IndexResolver<HeedUuidStore, MapIndexStore>;
2021-09-28 22:22:59 +02:00
pub fn create_index_resolver(
path: impl AsRef<Path>,
index_size: usize,
indexer_opts: &IndexerOpts,
) -> anyhow::Result<HardStateIndexResolver> {
2021-09-24 11:53:11 +02:00
let uuid_store = HeedUuidStore::new(&path)?;
let index_store = MapIndexStore::new(&path, index_size, indexer_opts)?;
Ok(IndexResolver::new(uuid_store, index_store))
}
pub struct IndexResolver<U, I> {
index_uuid_store: U,
index_store: I,
}
2021-09-28 11:59:55 +02:00
impl IndexResolver<HeedUuidStore, MapIndexStore> {
pub fn load_dump(
src: impl AsRef<Path>,
dst: impl AsRef<Path>,
index_db_size: usize,
indexer_opts: &IndexerOpts,
2021-09-28 22:22:59 +02:00
) -> anyhow::Result<()> {
2021-09-28 11:59:55 +02:00
HeedUuidStore::load_dump(&src, &dst)?;
let indexes_path = src.as_ref().join("indexes");
let indexes = indexes_path.read_dir()?;
2021-09-28 20:20:13 +02:00
let update_handler = UpdateHandler::new(indexer_opts)?;
2021-09-28 11:59:55 +02:00
for index in indexes {
let index = index?;
Index::load_dump(&index.path(), &dst, index_db_size, &update_handler)?;
}
Ok(())
}
}
2021-09-28 22:22:59 +02:00
impl<U, I> IndexResolver<U, I>
where
U: UuidStore,
I: IndexStore,
2021-09-24 11:53:11 +02:00
{
2021-09-28 22:22:59 +02:00
pub fn new(index_uuid_store: U, index_store: I) -> Self {
2021-09-24 11:53:11 +02:00
Self {
index_uuid_store,
index_store,
}
}
2021-09-28 11:59:55 +02:00
pub async fn dump(&self, path: impl AsRef<Path>) -> Result<Vec<Index>> {
let uuids = self.index_uuid_store.dump(path.as_ref().to_owned()).await?;
let mut indexes = Vec::new();
for uuid in uuids {
indexes.push(self.get_index_by_uuid(uuid).await?);
}
Ok(indexes)
2021-09-24 11:53:11 +02:00
}
2021-09-28 12:05:22 +02:00
pub async fn get_uuids_size(&self) -> Result<u64> {
Ok(self.index_uuid_store.get_size().await?)
2021-09-24 11:53:11 +02:00
}
2021-09-27 16:48:03 +02:00
pub async fn snapshot(&self, path: impl AsRef<Path>) -> Result<Vec<Index>> {
2021-09-28 22:22:59 +02:00
let uuids = self
.index_uuid_store
.snapshot(path.as_ref().to_owned())
.await?;
2021-09-27 16:48:03 +02:00
let mut indexes = Vec::new();
for uuid in uuids {
indexes.push(self.get_index_by_uuid(uuid).await?);
}
Ok(indexes)
2021-09-24 11:53:11 +02:00
}
2021-09-28 18:10:09 +02:00
pub async fn create_index(&self, uid: String, primary_key: Option<String>) -> Result<Index> {
if !is_index_uid_valid(&uid) {
return Err(IndexResolverError::BadlyFormatted(uid));
}
2021-09-24 11:53:11 +02:00
let uuid = Uuid::new_v4();
let index = self.index_store.create(uuid, primary_key).await?;
match self.index_uuid_store.insert(uid, uuid).await {
Err(e) => {
match self.index_store.delete(uuid).await {
Ok(Some(index)) => {
index.inner().clone().prepare_for_closing();
}
Ok(None) => (),
Err(e) => error!("Error while deleting index: {:?}", e),
}
Err(e)
}
Ok(()) => Ok(index),
}
2021-09-24 11:53:11 +02:00
}
pub async fn list(&self) -> Result<Vec<(String, Index)>> {
let uuids = self.index_uuid_store.list().await?;
let mut indexes = Vec::new();
for (name, uuid) in uuids {
match self.index_store.get(uuid).await? {
2021-09-28 22:22:59 +02:00
Some(index) => indexes.push((name, index)),
2021-09-24 11:53:11 +02:00
None => {
// we found an unexisting index, we remove it from the uuid store
let _ = self.index_uuid_store.delete(name).await;
2021-09-28 22:22:59 +02:00
}
2021-09-24 11:53:11 +02:00
}
}
Ok(indexes)
}
2021-09-28 18:10:09 +02:00
pub async fn delete_index(&self, uid: String) -> Result<Uuid> {
2021-09-24 11:53:11 +02:00
match self.index_uuid_store.delete(uid.clone()).await? {
Some(uuid) => {
match self.index_store.delete(uuid).await {
Ok(Some(index)) => {
index.inner().clone().prepare_for_closing();
}
Ok(None) => (),
Err(e) => error!("Error while deleting index: {:?}", e),
}
2021-09-28 18:10:09 +02:00
Ok(uuid)
2021-09-24 11:53:11 +02:00
}
None => Err(IndexResolverError::UnexistingIndex(uid)),
}
}
pub async fn get_index_by_uuid(&self, uuid: Uuid) -> Result<Index> {
// TODO: Handle this error better.
2021-09-28 22:22:59 +02:00
self.index_store
.get(uuid)
.await?
.ok_or_else(|| IndexResolverError::UnexistingIndex(String::new()))
2021-09-24 11:53:11 +02:00
}
pub async fn get_index(&self, uid: String) -> Result<Index> {
match self.index_uuid_store.get_uuid(uid).await? {
(name, Some(uuid)) => {
match self.index_store.get(uuid).await? {
Some(index) => Ok(index),
None => {
// For some reason we got a uuid to an unexisting index, we return an error,
2021-09-29 12:02:27 +02:00
// and remove the uuid from the uuid store.
2021-09-24 11:53:11 +02:00
let _ = self.index_uuid_store.delete(name.clone()).await;
Err(IndexResolverError::UnexistingIndex(name))
2021-09-28 22:22:59 +02:00
}
2021-09-24 11:53:11 +02:00
}
}
2021-09-28 22:22:59 +02:00
(name, _) => Err(IndexResolverError::UnexistingIndex(name)),
2021-09-24 11:53:11 +02:00
}
}
pub async fn get_uuid(&self, uid: String) -> Result<Uuid> {
match self.index_uuid_store.get_uuid(uid).await? {
(_, Some(uuid)) => Ok(uuid),
2021-09-28 22:22:59 +02:00
(name, _) => Err(IndexResolverError::UnexistingIndex(name)),
2021-09-24 11:53:11 +02:00
}
}
}
2021-09-28 18:10:09 +02:00
fn is_index_uid_valid(uid: &str) -> bool {
uid.chars()
.all(|x| x.is_ascii_alphanumeric() || x == '-' || x == '_')
}