mirror of
https://github.com/meilisearch/meilisearch.git
synced 2025-11-29 09:15:38 +00:00
WIP
This commit is contained in:
@@ -38,6 +38,10 @@ impl RoFeatures {
|
||||
Self { runtime }
|
||||
}
|
||||
|
||||
pub fn from_runtime_features(features: RuntimeTogglableFeatures) -> Self {
|
||||
Self { runtime: features }
|
||||
}
|
||||
|
||||
pub fn runtime_features(&self) -> RuntimeTogglableFeatures {
|
||||
self.runtime
|
||||
}
|
||||
|
||||
@@ -398,6 +398,7 @@ TooManyOpenFiles , System , UNPROCES
|
||||
TooManyVectors , InvalidRequest , BAD_REQUEST ;
|
||||
UnexpectedNetworkPreviousRemotes , InvalidRequest , BAD_REQUEST ;
|
||||
NetworkVersionTooOld , InvalidRequest , BAD_REQUEST ;
|
||||
UnprocessedNetworkTask , InvalidRequest , BAD_REQUEST ;
|
||||
UnretrievableDocument , Internal , BAD_REQUEST ;
|
||||
UnretrievableErrorCode , InvalidRequest , BAD_REQUEST ;
|
||||
UnsupportedMediaType , InvalidRequest , UNSUPPORTED_MEDIA_TYPE ;
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
use actix_web as aweb;
|
||||
use aweb::error::{JsonPayloadError, QueryPayloadError};
|
||||
use byte_unit::{Byte, UnitType};
|
||||
use index_scheduler::error::FeatureNotEnabledError;
|
||||
use meilisearch_types::document_formats::{DocumentFormatError, PayloadType};
|
||||
use meilisearch_types::error::{Code, ErrorCode, ResponseError};
|
||||
use meilisearch_types::index_uid::{IndexUid, IndexUidFormatError};
|
||||
@@ -143,6 +144,13 @@ pub enum MeilisearchHttpError {
|
||||
UnexpectedNetworkPreviousRemotes,
|
||||
#[error("The network version in request is too old.\n - Received: {received}\n - Expected at least: {expected_at_least}")]
|
||||
NetworkVersionTooOld { received: Uuid, expected_at_least: Uuid },
|
||||
#[error("Remote `{remote}` encountered an error: {error}")]
|
||||
RemoteIndexScheduler { remote: String, error: index_scheduler::Error },
|
||||
#[error("{if_remote}Already has a pending network task with uid {task_uid}.\n - Note: No network task can be registered while any previous network task is not done processing.\n - Hint: Wait for task {task_uid} to complete or cancel it.",
|
||||
if_remote=if let Some(remote) = remote {
|
||||
format!("Remote `{remote}` encountered an error: ")
|
||||
} else {"".into()} )]
|
||||
UnprocessedNetworkTask { remote: Option<String>, task_uid: meilisearch_types::tasks::TaskId },
|
||||
}
|
||||
|
||||
impl MeilisearchHttpError {
|
||||
@@ -170,6 +178,7 @@ impl ErrorCode for MeilisearchHttpError {
|
||||
MeilisearchHttpError::SerdeJson(_) => Code::Internal,
|
||||
MeilisearchHttpError::HeedError(_) => Code::Internal,
|
||||
MeilisearchHttpError::IndexScheduler(e) => e.error_code(),
|
||||
MeilisearchHttpError::RemoteIndexScheduler { error, .. } => error.error_code(),
|
||||
MeilisearchHttpError::Milli { error, .. } => error.error_code(),
|
||||
MeilisearchHttpError::Payload(e) => e.error_code(),
|
||||
MeilisearchHttpError::FileStore(_) => Code::Internal,
|
||||
@@ -202,6 +211,7 @@ impl ErrorCode for MeilisearchHttpError {
|
||||
Code::UnexpectedNetworkPreviousRemotes
|
||||
}
|
||||
MeilisearchHttpError::NetworkVersionTooOld { .. } => Code::NetworkVersionTooOld,
|
||||
MeilisearchHttpError::UnprocessedNetworkTask { .. } => Code::UnprocessedNetworkTask,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -4,8 +4,9 @@ use actix_web::web::{self, Data};
|
||||
use actix_web::{HttpRequest, HttpResponse};
|
||||
use deserr::actix_web::AwebJson;
|
||||
use deserr::Deserr;
|
||||
use index_scheduler::IndexScheduler;
|
||||
use index_scheduler::{IndexScheduler, Query, RoFeatures};
|
||||
use itertools::{EitherOrBoth, Itertools};
|
||||
use meilisearch_auth::AuthFilter;
|
||||
use meilisearch_types::deserr::DeserrJsonError;
|
||||
use meilisearch_types::enterprise_edition::network::{Network as DbNetwork, Remote as DbRemote};
|
||||
use meilisearch_types::error::deserr_codes::{
|
||||
@@ -288,7 +289,33 @@ async fn patch_network_without_origin(
|
||||
|
||||
let merged_network = merge_networks(old_network.clone(), new_network)?;
|
||||
|
||||
// When a network task must be created, perform some sanity checks against common errors:
|
||||
// - missing experimental feature on an host from the network
|
||||
// - a network task is already enqueued
|
||||
//
|
||||
// These checks are by no mean perfect (they are not atomic since the network is involved), but they should
|
||||
// help preventing a bad situation.
|
||||
if merged_network.leader.is_some() {
|
||||
let query = Query {
|
||||
statuses: Some(vec![
|
||||
meilisearch_types::tasks::Status::Enqueued,
|
||||
meilisearch_types::tasks::Status::Processing,
|
||||
]),
|
||||
types: Some(vec![meilisearch_types::tasks::Kind::NetworkTopologyChange]),
|
||||
..Default::default()
|
||||
};
|
||||
|
||||
let filters = AuthFilter::default();
|
||||
let (tasks, _) = index_scheduler.get_task_ids_from_authorized_indexes(&query, &filters)?;
|
||||
|
||||
if let Some(first) = tasks.min() {
|
||||
return Err(MeilisearchHttpError::UnprocessedNetworkTask {
|
||||
remote: None,
|
||||
task_uid: first,
|
||||
}
|
||||
.into());
|
||||
}
|
||||
|
||||
for eob in old_network
|
||||
.remotes
|
||||
.iter()
|
||||
@@ -308,10 +335,14 @@ async fn patch_network_without_origin(
|
||||
remote,
|
||||
)
|
||||
.await?;
|
||||
if !remote_features.network {
|
||||
/// TODO: clean error!
|
||||
panic!("boom")
|
||||
}
|
||||
let remote_features = RoFeatures::from_runtime_features(remote_features);
|
||||
remote_features.check_network("receiving a proxied network task").map_err(
|
||||
|error| MeilisearchHttpError::RemoteIndexScheduler {
|
||||
remote: remote_name.to_owned(),
|
||||
error,
|
||||
},
|
||||
)?;
|
||||
|
||||
// 2. check whether there are any unfinished network task
|
||||
let network_tasks: AllTasks = proxy::send_request(
|
||||
"/tasks?types=networkTopologyChanges&statuses=enqueued,processing&limit=1",
|
||||
@@ -323,9 +354,12 @@ async fn patch_network_without_origin(
|
||||
)
|
||||
.await?;
|
||||
|
||||
if network_tasks.total != 0 {
|
||||
/// TODO: clean error!
|
||||
panic!("boom")
|
||||
if let [first, ..] = network_tasks.results.as_slice() {
|
||||
return Err(MeilisearchHttpError::UnprocessedNetworkTask {
|
||||
remote: Some(remote_name.to_owned()),
|
||||
task_uid: first.uid,
|
||||
}
|
||||
.into());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user