add the swap indexes

This commit is contained in:
Tamo 2024-12-26 16:16:56 +01:00
parent 9473a2a6ca
commit e2686c0fce
No known key found for this signature in database
GPG Key ID: 20CD8020AFA88D69
3 changed files with 42 additions and 4 deletions

View File

@ -4,6 +4,7 @@ use crate::extractors::authentication::policies::*;
use crate::extractors::authentication::GuardedData; use crate::extractors::authentication::GuardedData;
use crate::routes::indexes::documents::DocumentEditionByFunction; use crate::routes::indexes::documents::DocumentEditionByFunction;
use crate::routes::multi_search::SearchResults; use crate::routes::multi_search::SearchResults;
use crate::routes::swap_indexes::SwapIndexesPayload;
use crate::search::{ use crate::search::{
FederatedSearch, FederatedSearchResult, Federation, FederationOptions, MergeFacets, FederatedSearch, FederatedSearchResult, Federation, FederationOptions, MergeFacets,
SearchQueryWithIndex, SearchResultWithIndex, SimilarQuery, SimilarResult, SearchQueryWithIndex, SearchResultWithIndex, SimilarQuery, SimilarResult,
@ -70,13 +71,14 @@ pub mod tasks;
(path = "/metrics", api = metrics::MetricApi), (path = "/metrics", api = metrics::MetricApi),
(path = "/logs", api = logs::LogsApi), (path = "/logs", api = logs::LogsApi),
(path = "/multi-search", api = multi_search::MultiSearchApi), (path = "/multi-search", api = multi_search::MultiSearchApi),
(path = "/swap-indexes", api = swap_indexes::SwapIndexesApi),
), ),
paths(get_health, get_version, get_stats), paths(get_health, get_version, get_stats),
tags( tags(
(name = "Stats", description = "Stats gives extended information and metrics about indexes and the Meilisearch database."), (name = "Stats", description = "Stats gives extended information and metrics about indexes and the Meilisearch database."),
), ),
modifiers(&OpenApiAuth), modifiers(&OpenApiAuth),
components(schemas(DocumentEditionByFunction, MergeFacets, FederationOptions, SearchQueryWithIndex, Federation, FederatedSearch, FederatedSearchResult, SearchResults, SearchResultWithIndex, SimilarQuery, SimilarResult, PaginationView<serde_json::Value>, BrowseQuery, UpdateIndexRequest, IndexUid, IndexCreateRequest, KeyView, Action, CreateApiKey, UpdateStderrLogs, LogMode, GetLogs, IndexStats, Stats, HealthStatus, HealthResponse, VersionResponse, Code, ErrorType, AllTasks, TaskView, Status, DetailsView, ResponseError, Settings<Unchecked>, Settings<Checked>, TypoSettings, MinWordSizeTyposSetting, FacetingSettings, PaginationSettings, SummarizedTaskView, Kind)) components(schemas(SwapIndexesPayload, DocumentEditionByFunction, MergeFacets, FederationOptions, SearchQueryWithIndex, Federation, FederatedSearch, FederatedSearchResult, SearchResults, SearchResultWithIndex, SimilarQuery, SimilarResult, PaginationView<serde_json::Value>, BrowseQuery, UpdateIndexRequest, IndexUid, IndexCreateRequest, KeyView, Action, CreateApiKey, UpdateStderrLogs, LogMode, GetLogs, IndexStats, Stats, HealthStatus, HealthResponse, VersionResponse, Code, ErrorType, AllTasks, TaskView, Status, DetailsView, ResponseError, Settings<Unchecked>, Settings<Checked>, TypoSettings, MinWordSizeTyposSetting, FacetingSettings, PaginationSettings, SummarizedTaskView, Kind))
)] )]
pub struct MeilisearchApi; pub struct MeilisearchApi;
@ -96,7 +98,7 @@ pub fn configure(cfg: &mut web::ServiceConfig) {
.service(web::resource("/stats").route(web::get().to(get_stats))) // done .service(web::resource("/stats").route(web::get().to(get_stats))) // done
.service(web::resource("/version").route(web::get().to(get_version))) // done .service(web::resource("/version").route(web::get().to(get_version))) // done
.service(web::scope("/indexes").configure(indexes::configure)) // done .service(web::scope("/indexes").configure(indexes::configure)) // done
.service(web::scope("/multi-search").configure(multi_search::configure)) // TODO .service(web::scope("/multi-search").configure(multi_search::configure)) // done
.service(web::scope("/swap-indexes").configure(swap_indexes::configure)) // TODO .service(web::scope("/swap-indexes").configure(swap_indexes::configure)) // TODO
.service(web::scope("/metrics").configure(metrics::configure)) // done .service(web::scope("/metrics").configure(metrics::configure)) // done
.service(web::scope("/experimental-features").configure(features::configure)); .service(web::scope("/experimental-features").configure(features::configure));

View File

@ -23,7 +23,6 @@ use crate::search::{
}; };
use crate::search_queue::SearchQueue; use crate::search_queue::SearchQueue;
#[derive(OpenApi)] #[derive(OpenApi)]
#[openapi( #[openapi(
paths(multi_search_with_post), paths(multi_search_with_post),

View File

@ -9,6 +9,7 @@ use meilisearch_types::error::ResponseError;
use meilisearch_types::index_uid::IndexUid; use meilisearch_types::index_uid::IndexUid;
use meilisearch_types::tasks::{IndexSwap, KindWithContent}; use meilisearch_types::tasks::{IndexSwap, KindWithContent};
use serde::Serialize; use serde::Serialize;
use utoipa::{OpenApi, ToSchema};
use super::{get_task_id, is_dry_run, SummarizedTaskView}; use super::{get_task_id, is_dry_run, SummarizedTaskView};
use crate::analytics::{Aggregate, Analytics}; use crate::analytics::{Aggregate, Analytics};
@ -18,13 +19,18 @@ use crate::extractors::authentication::{AuthenticationError, GuardedData};
use crate::extractors::sequential_extractor::SeqHandler; use crate::extractors::sequential_extractor::SeqHandler;
use crate::Opt; use crate::Opt;
#[derive(OpenApi)]
#[openapi(paths(swap_indexes))]
pub struct SwapIndexesApi;
pub fn configure(cfg: &mut web::ServiceConfig) { pub fn configure(cfg: &mut web::ServiceConfig) {
cfg.service(web::resource("").route(web::post().to(SeqHandler(swap_indexes)))); cfg.service(web::resource("").route(web::post().to(SeqHandler(swap_indexes))));
} }
#[derive(Deserr, Debug, Clone, PartialEq, Eq)] #[derive(Deserr, Debug, Clone, PartialEq, Eq, ToSchema)]
#[deserr(error = DeserrJsonError, rename_all = camelCase, deny_unknown_fields)] #[deserr(error = DeserrJsonError, rename_all = camelCase, deny_unknown_fields)]
pub struct SwapIndexesPayload { pub struct SwapIndexesPayload {
/// Array of the two indexUids to be swapped
#[deserr(error = DeserrJsonError<InvalidSwapIndexes>, missing_field_error = DeserrJsonError::missing_swap_indexes)] #[deserr(error = DeserrJsonError<InvalidSwapIndexes>, missing_field_error = DeserrJsonError::missing_swap_indexes)]
indexes: Vec<IndexUid>, indexes: Vec<IndexUid>,
} }
@ -50,6 +56,37 @@ impl Aggregate for IndexSwappedAnalytics {
} }
} }
/// Swap indexes
///
/// Swap the documents, settings, and task history of two or more indexes. You can only swap indexes in pairs. However, a single request can swap as many index pairs as you wish.
/// Swapping indexes is an atomic transaction: either all indexes are successfully swapped, or none are.
/// Swapping indexA and indexB will also replace every mention of indexA by indexB and vice-versa in the task history. enqueued tasks are left unmodified.
#[utoipa::path(
post,
path = "/",
tag = "Indexes",
security(("Bearer" = ["search", "*"])),
request_body = Vec<SwapIndexesPayload>,
responses(
(status = OK, description = "Task successfully enqueued", body = SummarizedTaskView, content_type = "application/json", example = json!(
{
"taskUid": 3,
"indexUid": null,
"status": "enqueued",
"type": "indexSwap",
"enqueuedAt": "2021-08-12T10:00:00.000000Z"
}
)),
(status = 401, description = "The authorization header is missing", body = ResponseError, content_type = "application/json", example = json!(
{
"message": "The Authorization header is missing. It must use the bearer authorization method.",
"code": "missing_authorization_header",
"type": "auth",
"link": "https://docs.meilisearch.com/errors#missing_authorization_header"
}
)),
)
)]
pub async fn swap_indexes( pub async fn swap_indexes(
index_scheduler: GuardedData<ActionPolicy<{ actions::INDEXES_SWAP }>, Data<IndexScheduler>>, index_scheduler: GuardedData<ActionPolicy<{ actions::INDEXES_SWAP }>, Data<IndexScheduler>>,
params: AwebJson<Vec<SwapIndexesPayload>, DeserrJsonError>, params: AwebJson<Vec<SwapIndexesPayload>, DeserrJsonError>,