mirror of
https://github.com/meilisearch/MeiliSearch
synced 2024-11-27 07:14:26 +01:00
error on meili database version mismatch
This commit is contained in:
parent
308630c094
commit
f5a936614a
@ -3,6 +3,7 @@ use std::fs::File;
|
|||||||
use std::path::Path;
|
use std::path::Path;
|
||||||
use std::sync::{Arc, RwLock};
|
use std::sync::{Arc, RwLock};
|
||||||
use std::{fs, thread};
|
use std::{fs, thread};
|
||||||
|
use std::io::{Read, Write, ErrorKind};
|
||||||
|
|
||||||
use chrono::{DateTime, Utc};
|
use chrono::{DateTime, Utc};
|
||||||
use crossbeam_channel::{Receiver, Sender};
|
use crossbeam_channel::{Receiver, Sender};
|
||||||
@ -161,11 +162,62 @@ fn update_awaiter(
|
|||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Ensures Meilisearch version is compatible with the database, returns an error versions mismatch.
|
||||||
|
/// If create is set to true, a VERSION file is created with the current version.
|
||||||
|
fn version_guard(path: &Path, create: bool) -> MResult<()> {
|
||||||
|
let current_version_major = env!("CARGO_PKG_VERSION_MAJOR");
|
||||||
|
let current_version_minor = env!("CARGO_PKG_VERSION_MINOR");
|
||||||
|
let current_version_patch = env!("CARGO_PKG_VERSION_PATCH");
|
||||||
|
let version_path = path.join("VERSION");
|
||||||
|
|
||||||
|
match File::open(&version_path) {
|
||||||
|
Ok(mut file) => {
|
||||||
|
let mut version = String::new();
|
||||||
|
file.read_to_string(&mut version)?;
|
||||||
|
let mut version = version.split(".");
|
||||||
|
|
||||||
|
let version_major = version.next().ok_or(Error::VersionMismatch("bad VERSION file".to_string()))?;
|
||||||
|
let version_minor = version.next().ok_or(Error::VersionMismatch("bad VERSION file".to_string()))?;
|
||||||
|
|
||||||
|
if version_major != current_version_major || version_minor != current_version_minor {
|
||||||
|
return Err(Error::VersionMismatch(format!("{}.{}.XX", version_major, version_major)));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Err(error) => {
|
||||||
|
match error.kind() {
|
||||||
|
ErrorKind::NotFound => {
|
||||||
|
if create {
|
||||||
|
// when no version file is found, and we've beem told to create one,
|
||||||
|
// create a new file wioth the current version in it.
|
||||||
|
let mut version_file = File::create(&version_path)?;
|
||||||
|
version_file.write_all(format!("{}.{}.{}",
|
||||||
|
current_version_major,
|
||||||
|
current_version_minor,
|
||||||
|
current_version_patch).as_bytes())?;
|
||||||
|
} else {
|
||||||
|
// when no version file is found and we were not told to create one, this
|
||||||
|
// means that the version is inferior to the one this feature was added.
|
||||||
|
return Err(Error::VersionMismatch(format!("<0.12.0")));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
_ => return Err(error.into())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
impl Database {
|
impl Database {
|
||||||
pub fn open_or_create(path: impl AsRef<Path>, options: DatabaseOptions) -> MResult<Database> {
|
pub fn open_or_create(path: impl AsRef<Path>, options: DatabaseOptions) -> MResult<Database> {
|
||||||
let main_path = path.as_ref().join("main");
|
let main_path = path.as_ref().join("main");
|
||||||
let update_path = path.as_ref().join("update");
|
let update_path = path.as_ref().join("update");
|
||||||
|
|
||||||
|
//create db directory
|
||||||
|
fs::create_dir_all(&path)?;
|
||||||
|
|
||||||
|
// create file only if main db wasn't created before (first run)
|
||||||
|
version_guard(path.as_ref(), !main_path.exists() && !update_path.exists())?;
|
||||||
|
|
||||||
fs::create_dir_all(&main_path)?;
|
fs::create_dir_all(&main_path)?;
|
||||||
let env = heed::EnvOpenOptions::new()
|
let env = heed::EnvOpenOptions::new()
|
||||||
.map_size(options.main_map_size)
|
.map_size(options.main_map_size)
|
||||||
|
@ -15,22 +15,23 @@ pub type MResult<T> = Result<T, Error>;
|
|||||||
|
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
pub enum Error {
|
pub enum Error {
|
||||||
Io(io::Error),
|
|
||||||
IndexAlreadyExists,
|
|
||||||
MissingPrimaryKey,
|
|
||||||
SchemaMissing,
|
|
||||||
WordIndexMissing,
|
|
||||||
MissingDocumentId,
|
|
||||||
MaxFieldsLimitExceeded,
|
|
||||||
Schema(meilisearch_schema::Error),
|
|
||||||
Heed(heed::Error),
|
|
||||||
Fst(fst::Error),
|
|
||||||
SerdeJson(SerdeJsonError),
|
|
||||||
Bincode(bincode::Error),
|
Bincode(bincode::Error),
|
||||||
Serializer(SerializerError),
|
|
||||||
Deserializer(DeserializerError),
|
Deserializer(DeserializerError),
|
||||||
FilterParseError(PestError<Rule>),
|
|
||||||
FacetError(FacetError),
|
FacetError(FacetError),
|
||||||
|
FilterParseError(PestError<Rule>),
|
||||||
|
Fst(fst::Error),
|
||||||
|
Heed(heed::Error),
|
||||||
|
IndexAlreadyExists,
|
||||||
|
Io(io::Error),
|
||||||
|
MaxFieldsLimitExceeded,
|
||||||
|
MissingDocumentId,
|
||||||
|
MissingPrimaryKey,
|
||||||
|
Schema(meilisearch_schema::Error),
|
||||||
|
SchemaMissing,
|
||||||
|
SerdeJson(SerdeJsonError),
|
||||||
|
Serializer(SerializerError),
|
||||||
|
VersionMismatch(String),
|
||||||
|
WordIndexMissing,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl ErrorCode for Error {
|
impl ErrorCode for Error {
|
||||||
@ -53,6 +54,7 @@ impl ErrorCode for Error {
|
|||||||
| Bincode(_)
|
| Bincode(_)
|
||||||
| Serializer(_)
|
| Serializer(_)
|
||||||
| Deserializer(_)
|
| Deserializer(_)
|
||||||
|
| VersionMismatch(_)
|
||||||
| Io(_) => Code::Internal,
|
| Io(_) => Code::Internal,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -141,22 +143,23 @@ impl fmt::Display for Error {
|
|||||||
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||||
use self::Error::*;
|
use self::Error::*;
|
||||||
match self {
|
match self {
|
||||||
Io(e) => write!(f, "{}", e),
|
|
||||||
IndexAlreadyExists => write!(f, "index already exists"),
|
|
||||||
MissingPrimaryKey => write!(f, "schema cannot be built without a primary key"),
|
|
||||||
SchemaMissing => write!(f, "this index does not have a schema"),
|
|
||||||
WordIndexMissing => write!(f, "this index does not have a word index"),
|
|
||||||
MissingDocumentId => write!(f, "document id is missing"),
|
|
||||||
MaxFieldsLimitExceeded => write!(f, "maximum number of fields in a document exceeded"),
|
|
||||||
Schema(e) => write!(f, "schema error; {}", e),
|
|
||||||
Heed(e) => write!(f, "heed error; {}", e),
|
|
||||||
Fst(e) => write!(f, "fst error; {}", e),
|
|
||||||
SerdeJson(e) => write!(f, "serde json error; {}", e),
|
|
||||||
Bincode(e) => write!(f, "bincode error; {}", e),
|
Bincode(e) => write!(f, "bincode error; {}", e),
|
||||||
Serializer(e) => write!(f, "serializer error; {}", e),
|
|
||||||
Deserializer(e) => write!(f, "deserializer error; {}", e),
|
Deserializer(e) => write!(f, "deserializer error; {}", e),
|
||||||
FilterParseError(e) => write!(f, "error parsing filter; {}", e),
|
|
||||||
FacetError(e) => write!(f, "error processing facet filter: {}", e),
|
FacetError(e) => write!(f, "error processing facet filter: {}", e),
|
||||||
|
FilterParseError(e) => write!(f, "error parsing filter; {}", e),
|
||||||
|
Fst(e) => write!(f, "fst error; {}", e),
|
||||||
|
Heed(e) => write!(f, "heed error; {}", e),
|
||||||
|
IndexAlreadyExists => write!(f, "index already exists"),
|
||||||
|
Io(e) => write!(f, "{}", e),
|
||||||
|
MaxFieldsLimitExceeded => write!(f, "maximum number of fields in a document exceeded"),
|
||||||
|
MissingDocumentId => write!(f, "document id is missing"),
|
||||||
|
MissingPrimaryKey => write!(f, "schema cannot be built without a primary key"),
|
||||||
|
Schema(e) => write!(f, "schema error; {}", e),
|
||||||
|
SchemaMissing => write!(f, "this index does not have a schema"),
|
||||||
|
SerdeJson(e) => write!(f, "serde json error; {}", e),
|
||||||
|
Serializer(e) => write!(f, "serializer error; {}", e),
|
||||||
|
VersionMismatch(version) => write!(f, "Cannot open database, expected Meilisearch version: {}", version),
|
||||||
|
WordIndexMissing => write!(f, "this index does not have a word index"),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -4,6 +4,7 @@ use std::sync::Arc;
|
|||||||
use meilisearch_core::{Database, DatabaseOptions};
|
use meilisearch_core::{Database, DatabaseOptions};
|
||||||
use sha2::Digest;
|
use sha2::Digest;
|
||||||
use sysinfo::Pid;
|
use sysinfo::Pid;
|
||||||
|
use log::error;
|
||||||
|
|
||||||
use crate::index_update_callback;
|
use crate::index_update_callback;
|
||||||
use crate::option::Opt;
|
use crate::option::Opt;
|
||||||
@ -66,7 +67,13 @@ impl Data {
|
|||||||
|
|
||||||
let http_payload_size_limit = opt.http_payload_size_limit;
|
let http_payload_size_limit = opt.http_payload_size_limit;
|
||||||
|
|
||||||
let db = Arc::new(Database::open_or_create(opt.db_path, db_opt).unwrap());
|
let db = match Database::open_or_create(opt.db_path, db_opt) {
|
||||||
|
Ok(db) => Arc::new(db),
|
||||||
|
Err(e) => {
|
||||||
|
error!("{}", e);
|
||||||
|
std::process::exit(1);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
let mut api_keys = ApiKeys {
|
let mut api_keys = ApiKeys {
|
||||||
master: opt.master_key,
|
master: opt.master_key,
|
||||||
|
Loading…
Reference in New Issue
Block a user