mirror of
https://github.com/meilisearch/meilisearch.git
synced 2024-11-26 12:05:05 +08:00
index_scheduler.features() is no longer fallible
This commit is contained in:
parent
dd619913da
commit
cf8dad1ca0
@ -896,7 +896,7 @@ impl IndexScheduler {
|
|||||||
})?;
|
})?;
|
||||||
|
|
||||||
// 4. Dump experimental feature settings
|
// 4. Dump experimental feature settings
|
||||||
let features = self.features()?.runtime_features();
|
let features = self.features().runtime_features();
|
||||||
dump.create_experimental_features(features)?;
|
dump.create_experimental_features(features)?;
|
||||||
|
|
||||||
let dump_uid = started_at.format(format_description!(
|
let dump_uid = started_at.format(format_description!(
|
||||||
|
@ -113,8 +113,6 @@ pub enum Error {
|
|||||||
Dump(#[from] dump::Error),
|
Dump(#[from] dump::Error),
|
||||||
#[error(transparent)]
|
#[error(transparent)]
|
||||||
Heed(#[from] heed::Error),
|
Heed(#[from] heed::Error),
|
||||||
#[error("Unable to record metrics for request.")]
|
|
||||||
CannotRecordMetrics,
|
|
||||||
#[error(transparent)]
|
#[error(transparent)]
|
||||||
Milli(#[from] milli::Error),
|
Milli(#[from] milli::Error),
|
||||||
#[error("An unexpected crash occurred when processing the task.")]
|
#[error("An unexpected crash occurred when processing the task.")]
|
||||||
@ -127,8 +125,6 @@ pub enum Error {
|
|||||||
Persist(#[from] tempfile::PersistError),
|
Persist(#[from] tempfile::PersistError),
|
||||||
#[error(transparent)]
|
#[error(transparent)]
|
||||||
FeatureNotEnabled(#[from] FeatureNotEnabledError),
|
FeatureNotEnabled(#[from] FeatureNotEnabledError),
|
||||||
#[error("An unexpected error occurred when accessing the runtime features.")]
|
|
||||||
RuntimeFeatureToggleError,
|
|
||||||
|
|
||||||
#[error(transparent)]
|
#[error(transparent)]
|
||||||
Anyhow(#[from] anyhow::Error),
|
Anyhow(#[from] anyhow::Error),
|
||||||
@ -181,14 +177,12 @@ impl Error {
|
|||||||
| Error::TaskCancelationWithEmptyQuery
|
| Error::TaskCancelationWithEmptyQuery
|
||||||
| Error::Dump(_)
|
| Error::Dump(_)
|
||||||
| Error::Heed(_)
|
| Error::Heed(_)
|
||||||
| Error::CannotRecordMetrics
|
|
||||||
| Error::Milli(_)
|
| Error::Milli(_)
|
||||||
| Error::ProcessBatchPanicked
|
| Error::ProcessBatchPanicked
|
||||||
| Error::FileStore(_)
|
| Error::FileStore(_)
|
||||||
| Error::IoError(_)
|
| Error::IoError(_)
|
||||||
| Error::Persist(_)
|
| Error::Persist(_)
|
||||||
| Error::FeatureNotEnabled(_)
|
| Error::FeatureNotEnabled(_)
|
||||||
| Error::RuntimeFeatureToggleError
|
|
||||||
| Error::Anyhow(_) => true,
|
| Error::Anyhow(_) => true,
|
||||||
Error::CreateBatch(_)
|
Error::CreateBatch(_)
|
||||||
| Error::CorruptedTaskQueue
|
| Error::CorruptedTaskQueue
|
||||||
@ -229,13 +223,11 @@ impl ErrorCode for Error {
|
|||||||
Error::Milli(e) => e.error_code(),
|
Error::Milli(e) => e.error_code(),
|
||||||
Error::ProcessBatchPanicked => Code::Internal,
|
Error::ProcessBatchPanicked => Code::Internal,
|
||||||
Error::Heed(e) => e.error_code(),
|
Error::Heed(e) => e.error_code(),
|
||||||
Error::CannotRecordMetrics => Code::Internal,
|
|
||||||
Error::HeedTransaction(e) => e.error_code(),
|
Error::HeedTransaction(e) => e.error_code(),
|
||||||
Error::FileStore(e) => e.error_code(),
|
Error::FileStore(e) => e.error_code(),
|
||||||
Error::IoError(e) => e.error_code(),
|
Error::IoError(e) => e.error_code(),
|
||||||
Error::Persist(e) => e.error_code(),
|
Error::Persist(e) => e.error_code(),
|
||||||
Error::FeatureNotEnabled(_) => Code::FeatureNotEnabled,
|
Error::FeatureNotEnabled(_) => Code::FeatureNotEnabled,
|
||||||
Error::RuntimeFeatureToggleError => Code::Internal,
|
|
||||||
|
|
||||||
// Irrecoverable errors
|
// Irrecoverable errors
|
||||||
Error::Anyhow(_) => Code::Internal,
|
Error::Anyhow(_) => Code::Internal,
|
||||||
|
@ -4,7 +4,6 @@ use meilisearch_types::features::{InstanceTogglableFeatures, RuntimeTogglableFea
|
|||||||
use meilisearch_types::heed::types::{SerdeJson, Str};
|
use meilisearch_types::heed::types::{SerdeJson, Str};
|
||||||
use meilisearch_types::heed::{Database, Env, RwTxn};
|
use meilisearch_types::heed::{Database, Env, RwTxn};
|
||||||
|
|
||||||
use crate::error::Error::RuntimeFeatureToggleError;
|
|
||||||
use crate::error::FeatureNotEnabledError;
|
use crate::error::FeatureNotEnabledError;
|
||||||
use crate::Result;
|
use crate::Result;
|
||||||
|
|
||||||
@ -22,9 +21,9 @@ pub struct RoFeatures {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl RoFeatures {
|
impl RoFeatures {
|
||||||
fn new(data: &FeatureData) -> Result<Self> {
|
fn new(data: &FeatureData) -> Self {
|
||||||
let runtime = data.runtime_features()?;
|
let runtime = data.runtime_features();
|
||||||
Ok(Self { runtime })
|
Self { runtime }
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn runtime_features(&self) -> RuntimeTogglableFeatures {
|
pub fn runtime_features(&self) -> RuntimeTogglableFeatures {
|
||||||
@ -109,16 +108,22 @@ impl FeatureData {
|
|||||||
self.persisted.put(&mut wtxn, EXPERIMENTAL_FEATURES, &features)?;
|
self.persisted.put(&mut wtxn, EXPERIMENTAL_FEATURES, &features)?;
|
||||||
wtxn.commit()?;
|
wtxn.commit()?;
|
||||||
|
|
||||||
let mut toggled_features = self.runtime.write().map_err(|_| RuntimeFeatureToggleError)?;
|
// safe to unwrap, the lock will only fail if:
|
||||||
|
// 1. requested by the same thread concurrently -> it is called and released in methods that don't call each other
|
||||||
|
// 2. there's a panic while the thread is held -> it is only used for an assignment here.
|
||||||
|
let mut toggled_features = self.runtime.write().unwrap();
|
||||||
*toggled_features = features;
|
*toggled_features = features;
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
fn runtime_features(&self) -> Result<RuntimeTogglableFeatures> {
|
fn runtime_features(&self) -> RuntimeTogglableFeatures {
|
||||||
Ok(*self.runtime.read().map_err(|_| RuntimeFeatureToggleError)?)
|
// sound to unwrap, the lock will only fail if:
|
||||||
|
// 1. requested by the same thread concurrently -> it is called and released in methods that don't call each other
|
||||||
|
// 2. there's a panic while the thread is held -> it is only used for copying the data here
|
||||||
|
*self.runtime.read().unwrap()
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn features(&self) -> Result<RoFeatures> {
|
pub fn features(&self) -> RoFeatures {
|
||||||
RoFeatures::new(self)
|
RoFeatures::new(self)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -579,13 +579,7 @@ impl IndexScheduler {
|
|||||||
run.wake_up.wait();
|
run.wake_up.wait();
|
||||||
|
|
||||||
loop {
|
loop {
|
||||||
let puffin_enabled = match run.features() {
|
let puffin_enabled = run.features().check_puffin().is_ok();
|
||||||
Ok(features) => features.check_puffin().is_ok(),
|
|
||||||
Err(e) => {
|
|
||||||
log::error!("{e}");
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
puffin::set_scopes_on(puffin_enabled);
|
puffin::set_scopes_on(puffin_enabled);
|
||||||
puffin::GlobalProfiler::lock().new_frame();
|
puffin::GlobalProfiler::lock().new_frame();
|
||||||
|
|
||||||
@ -1299,7 +1293,7 @@ impl IndexScheduler {
|
|||||||
Ok(IndexStats { is_indexing, inner_stats: index_stats })
|
Ok(IndexStats { is_indexing, inner_stats: index_stats })
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn features(&self) -> Result<RoFeatures> {
|
pub fn features(&self) -> RoFeatures {
|
||||||
self.features.features()
|
self.features.features()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -6,9 +6,7 @@ use actix_web::dev::{self, Service, ServiceRequest, ServiceResponse, Transform};
|
|||||||
use actix_web::web::Data;
|
use actix_web::web::Data;
|
||||||
use actix_web::Error;
|
use actix_web::Error;
|
||||||
use futures_util::future::LocalBoxFuture;
|
use futures_util::future::LocalBoxFuture;
|
||||||
use index_scheduler::Error::CannotRecordMetrics;
|
|
||||||
use index_scheduler::IndexScheduler;
|
use index_scheduler::IndexScheduler;
|
||||||
use meilisearch_types::error::ResponseError;
|
|
||||||
use prometheus::HistogramTimer;
|
use prometheus::HistogramTimer;
|
||||||
|
|
||||||
pub struct RouteMetrics;
|
pub struct RouteMetrics;
|
||||||
@ -55,14 +53,7 @@ where
|
|||||||
// calling unwrap here is safe because index scheduler is added to app data while creating actix app.
|
// calling unwrap here is safe because index scheduler is added to app data while creating actix app.
|
||||||
// also, the tests will fail if this is not present.
|
// also, the tests will fail if this is not present.
|
||||||
let index_scheduler = req.app_data::<Data<IndexScheduler>>().unwrap();
|
let index_scheduler = req.app_data::<Data<IndexScheduler>>().unwrap();
|
||||||
let features = match index_scheduler.features() {
|
let features = index_scheduler.features();
|
||||||
Ok(features) => features,
|
|
||||||
Err(_e) => {
|
|
||||||
return Box::pin(
|
|
||||||
async move { Err(ResponseError::from(CannotRecordMetrics).into()) },
|
|
||||||
);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
if features.check_metrics().is_ok() {
|
if features.check_metrics().is_ok() {
|
||||||
let request_path = req.path();
|
let request_path = req.path();
|
||||||
|
@ -29,12 +29,12 @@ async fn get_features(
|
|||||||
>,
|
>,
|
||||||
req: HttpRequest,
|
req: HttpRequest,
|
||||||
analytics: Data<dyn Analytics>,
|
analytics: Data<dyn Analytics>,
|
||||||
) -> Result<HttpResponse, ResponseError> {
|
) -> HttpResponse {
|
||||||
let features = index_scheduler.features()?;
|
let features = index_scheduler.features();
|
||||||
|
|
||||||
analytics.publish("Experimental features Seen".to_string(), json!(null), Some(&req));
|
analytics.publish("Experimental features Seen".to_string(), json!(null), Some(&req));
|
||||||
debug!("returns: {:?}", features.runtime_features());
|
debug!("returns: {:?}", features.runtime_features());
|
||||||
Ok(HttpResponse::Ok().json(features.runtime_features()))
|
HttpResponse::Ok().json(features.runtime_features())
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, Deserr)]
|
#[derive(Debug, Deserr)]
|
||||||
@ -59,7 +59,7 @@ async fn patch_features(
|
|||||||
req: HttpRequest,
|
req: HttpRequest,
|
||||||
analytics: Data<dyn Analytics>,
|
analytics: Data<dyn Analytics>,
|
||||||
) -> Result<HttpResponse, ResponseError> {
|
) -> Result<HttpResponse, ResponseError> {
|
||||||
let features = index_scheduler.features()?;
|
let features = index_scheduler.features();
|
||||||
|
|
||||||
let old_features = features.runtime_features();
|
let old_features = features.runtime_features();
|
||||||
let new_features = meilisearch_types::features::RuntimeTogglableFeatures {
|
let new_features = meilisearch_types::features::RuntimeTogglableFeatures {
|
||||||
|
@ -68,7 +68,7 @@ pub async fn search(
|
|||||||
}
|
}
|
||||||
|
|
||||||
let index = index_scheduler.index(&index_uid)?;
|
let index = index_scheduler.index(&index_uid)?;
|
||||||
let features = index_scheduler.features()?;
|
let features = index_scheduler.features();
|
||||||
let search_result = tokio::task::spawn_blocking(move || {
|
let search_result = tokio::task::spawn_blocking(move || {
|
||||||
perform_facet_search(&index, search_query, facet_query, facet_name, features)
|
perform_facet_search(&index, search_query, facet_query, facet_name, features)
|
||||||
})
|
})
|
||||||
|
@ -157,7 +157,7 @@ pub async fn search_with_url_query(
|
|||||||
let mut aggregate = SearchAggregator::from_query(&query, &req);
|
let mut aggregate = SearchAggregator::from_query(&query, &req);
|
||||||
|
|
||||||
let index = index_scheduler.index(&index_uid)?;
|
let index = index_scheduler.index(&index_uid)?;
|
||||||
let features = index_scheduler.features()?;
|
let features = index_scheduler.features();
|
||||||
let search_result =
|
let search_result =
|
||||||
tokio::task::spawn_blocking(move || perform_search(&index, query, features)).await?;
|
tokio::task::spawn_blocking(move || perform_search(&index, query, features)).await?;
|
||||||
if let Ok(ref search_result) = search_result {
|
if let Ok(ref search_result) = search_result {
|
||||||
@ -192,7 +192,7 @@ pub async fn search_with_post(
|
|||||||
|
|
||||||
let index = index_scheduler.index(&index_uid)?;
|
let index = index_scheduler.index(&index_uid)?;
|
||||||
|
|
||||||
let features = index_scheduler.features()?;
|
let features = index_scheduler.features();
|
||||||
let search_result =
|
let search_result =
|
||||||
tokio::task::spawn_blocking(move || perform_search(&index, query, features)).await?;
|
tokio::task::spawn_blocking(move || perform_search(&index, query, features)).await?;
|
||||||
if let Ok(ref search_result) = search_result {
|
if let Ok(ref search_result) = search_result {
|
||||||
|
@ -19,7 +19,7 @@ pub async fn get_metrics(
|
|||||||
index_scheduler: GuardedData<ActionPolicy<{ actions::METRICS_GET }>, Data<IndexScheduler>>,
|
index_scheduler: GuardedData<ActionPolicy<{ actions::METRICS_GET }>, Data<IndexScheduler>>,
|
||||||
auth_controller: Data<AuthController>,
|
auth_controller: Data<AuthController>,
|
||||||
) -> Result<HttpResponse, ResponseError> {
|
) -> Result<HttpResponse, ResponseError> {
|
||||||
index_scheduler.features()?.check_metrics()?;
|
index_scheduler.features().check_metrics()?;
|
||||||
let auth_filters = index_scheduler.filters();
|
let auth_filters = index_scheduler.filters();
|
||||||
if !auth_filters.all_indexes_authorized() {
|
if !auth_filters.all_indexes_authorized() {
|
||||||
let mut error = ResponseError::from(AuthenticationError::InvalidToken);
|
let mut error = ResponseError::from(AuthenticationError::InvalidToken);
|
||||||
|
@ -41,7 +41,7 @@ pub async fn multi_search_with_post(
|
|||||||
let queries = params.into_inner().queries;
|
let queries = params.into_inner().queries;
|
||||||
|
|
||||||
let mut multi_aggregate = MultiSearchAggregator::from_queries(&queries, &req);
|
let mut multi_aggregate = MultiSearchAggregator::from_queries(&queries, &req);
|
||||||
let features = index_scheduler.features()?;
|
let features = index_scheduler.features();
|
||||||
|
|
||||||
// Explicitly expect a `(ResponseError, usize)` for the error type rather than `ResponseError` only,
|
// Explicitly expect a `(ResponseError, usize)` for the error type rather than `ResponseError` only,
|
||||||
// so that `?` doesn't work if it doesn't use `with_index`, ensuring that it is not forgotten in case of code
|
// so that `?` doesn't work if it doesn't use `with_index`, ensuring that it is not forgotten in case of code
|
||||||
|
Loading…
Reference in New Issue
Block a user