From 387874ea269c81299a86d9e263f9b800dda0a540 Mon Sep 17 00:00:00 2001 From: Tamo Date: Wed, 11 Jan 2023 18:50:46 +0100 Subject: [PATCH 1/5] test the error codes on the task routes --- meilisearch/src/routes/tasks.rs | 1 + meilisearch/tests/tasks/errors.rs | 498 ++++++++++++++++++++++++++++++ meilisearch/tests/tasks/mod.rs | 2 + 3 files changed, 501 insertions(+) create mode 100644 meilisearch/tests/tasks/errors.rs diff --git a/meilisearch/src/routes/tasks.rs b/meilisearch/src/routes/tasks.rs index d25707530..4be88c88c 100644 --- a/meilisearch/src/routes/tasks.rs +++ b/meilisearch/src/routes/tasks.rs @@ -270,6 +270,7 @@ pub struct TaskDateQueryRaw { pub after_finished_at: Option, pub before_finished_at: Option, } + impl TaskDateQueryRaw { fn validate(self) -> Result { let Self { diff --git a/meilisearch/tests/tasks/errors.rs b/meilisearch/tests/tasks/errors.rs new file mode 100644 index 000000000..667532f17 --- /dev/null +++ b/meilisearch/tests/tasks/errors.rs @@ -0,0 +1,498 @@ +use meili_snap::*; +use serde_json::json; + +use crate::common::Server; + +#[actix_rt::test] +async fn task_bad_uids() { + let server = Server::new().await; + + let (response, code) = server.tasks_filter(json!({"uids": "doggo"})).await; + snapshot!(code, @"400 Bad Request"); + snapshot!(json_string!(response), @r###" + { + "message": "Task uid `doggo` is invalid. It should only contain numeric characters.", + "code": "invalid_task_uids", + "type": "invalid_request", + "link": "https://docs.meilisearch.com/errors#invalid-task-uids" + } + "###); + + let (response, code) = server.cancel_tasks(json!({"uids": "doggo"})).await; + snapshot!(code, @"400 Bad Request"); + snapshot!(json_string!(response), @r###" + { + "message": "Task uid `doggo` is invalid. It should only contain numeric characters.", + "code": "invalid_task_uids", + "type": "invalid_request", + "link": "https://docs.meilisearch.com/errors#invalid-task-uids" + } + "###); + + let (response, code) = server.delete_tasks(json!({"uids": "doggo"})).await; + snapshot!(code, @"400 Bad Request"); + snapshot!(json_string!(response), @r###" + { + "message": "Task uid `doggo` is invalid. It should only contain numeric characters.", + "code": "invalid_task_uids", + "type": "invalid_request", + "link": "https://docs.meilisearch.com/errors#invalid-task-uids" + } + "###); +} + +#[actix_rt::test] +async fn task_bad_canceled_by() { + let server = Server::new().await; + + let (response, code) = server.tasks_filter(json!({"canceledBy": "doggo"})).await; + snapshot!(code, @"400 Bad Request"); + snapshot!(json_string!(response), @r###" + { + "message": "Task canceledBy `doggo` is invalid. It should only contains numeric characters separated by `,` character.", + "code": "invalid_task_canceled_by", + "type": "invalid_request", + "link": "https://docs.meilisearch.com/errors#invalid-task-canceled-by" + } + "###); + + let (response, code) = server.cancel_tasks(json!({"canceledBy": "doggo"})).await; + snapshot!(code, @"400 Bad Request"); + snapshot!(json_string!(response), @r###" + { + "message": "Task canceledBy `doggo` is invalid. It should only contains numeric characters separated by `,` character.", + "code": "invalid_task_canceled_by", + "type": "invalid_request", + "link": "https://docs.meilisearch.com/errors#invalid-task-canceled-by" + } + "###); + + let (response, code) = server.delete_tasks(json!({"canceledBy": "doggo"})).await; + snapshot!(code, @"400 Bad Request"); + snapshot!(json_string!(response), @r###" + { + "message": "Task canceledBy `doggo` is invalid. It should only contains numeric characters separated by `,` character.", + "code": "invalid_task_canceled_by", + "type": "invalid_request", + "link": "https://docs.meilisearch.com/errors#invalid-task-canceled-by" + } + "###); +} + +#[actix_rt::test] +async fn task_bad_types() { + let server = Server::new().await; + + let (response, code) = server.tasks_filter(json!({"types": "doggo"})).await; + snapshot!(code, @"400 Bad Request"); + snapshot!(json_string!(response), @r###" + { + "message": "Task type `doggo` is invalid. Available task types are `documentAdditionOrUpdate`, `documentDeletion`, `settingsUpdate`, `indexCreation`, `indexDeletion`, `indexUpdate`, `indexSwap`, `taskCancelation`, `taskDeletion`, `dumpCreation`, `snapshotCreation`", + "code": "invalid_task_types", + "type": "invalid_request", + "link": "https://docs.meilisearch.com/errors#invalid-task-types" + } + "###); + + let (response, code) = server.cancel_tasks(json!({"types": "doggo"})).await; + snapshot!(code, @"400 Bad Request"); + snapshot!(json_string!(response), @r###" + { + "message": "Task type `doggo` is invalid. Available task types are `documentAdditionOrUpdate`, `documentDeletion`, `settingsUpdate`, `indexCreation`, `indexDeletion`, `indexUpdate`, `indexSwap`, `taskCancelation`, `taskDeletion`, `dumpCreation`, `snapshotCreation`", + "code": "invalid_task_types", + "type": "invalid_request", + "link": "https://docs.meilisearch.com/errors#invalid-task-types" + } + "###); + + let (response, code) = server.delete_tasks(json!({"types": "doggo"})).await; + snapshot!(code, @"400 Bad Request"); + snapshot!(json_string!(response), @r###" + { + "message": "Task type `doggo` is invalid. Available task types are `documentAdditionOrUpdate`, `documentDeletion`, `settingsUpdate`, `indexCreation`, `indexDeletion`, `indexUpdate`, `indexSwap`, `taskCancelation`, `taskDeletion`, `dumpCreation`, `snapshotCreation`", + "code": "invalid_task_types", + "type": "invalid_request", + "link": "https://docs.meilisearch.com/errors#invalid-task-types" + } + "###); +} + +#[actix_rt::test] +async fn task_bad_statuses() { + let server = Server::new().await; + + let (response, code) = server.tasks_filter(json!({"statuses": "doggo"})).await; + snapshot!(code, @"400 Bad Request"); + snapshot!(json_string!(response), @r###" + { + "message": "Task status `doggo` is invalid. Available task statuses are `enqueued`, `processing`, `succeeded`, `failed`, `canceled`.", + "code": "invalid_task_statuses", + "type": "invalid_request", + "link": "https://docs.meilisearch.com/errors#invalid-task-statuses" + } + "###); + + let (response, code) = server.cancel_tasks(json!({"statuses": "doggo"})).await; + snapshot!(code, @"400 Bad Request"); + snapshot!(json_string!(response), @r###" + { + "message": "Task status `doggo` is invalid. Available task statuses are `enqueued`, `processing`, `succeeded`, `failed`, `canceled`.", + "code": "invalid_task_statuses", + "type": "invalid_request", + "link": "https://docs.meilisearch.com/errors#invalid-task-statuses" + } + "###); + + let (response, code) = server.delete_tasks(json!({"statuses": "doggo"})).await; + snapshot!(code, @"400 Bad Request"); + snapshot!(json_string!(response), @r###" + { + "message": "Task status `doggo` is invalid. Available task statuses are `enqueued`, `processing`, `succeeded`, `failed`, `canceled`.", + "code": "invalid_task_statuses", + "type": "invalid_request", + "link": "https://docs.meilisearch.com/errors#invalid-task-statuses" + } + "###); +} + +#[actix_rt::test] +async fn task_bad_index_uids() { + let server = Server::new().await; + + let (response, code) = server.tasks_filter(json!({"indexUids": "the good doggo"})).await; + snapshot!(code, @"400 Bad Request"); + snapshot!(json_string!(response), @r###" + { + "message": "the good doggo is not a valid index uid. Index uid can be an integer or a string containing only alphanumeric characters, hyphens (-) and underscores (_).", + "code": "invalid_index_uid", + "type": "invalid_request", + "link": "https://docs.meilisearch.com/errors#invalid-index-uid" + } + "###); + + let (response, code) = server.cancel_tasks(json!({"indexUids": "the good doggo"})).await; + snapshot!(code, @"400 Bad Request"); + snapshot!(json_string!(response), @r###" + { + "message": "the good doggo is not a valid index uid. Index uid can be an integer or a string containing only alphanumeric characters, hyphens (-) and underscores (_).", + "code": "invalid_index_uid", + "type": "invalid_request", + "link": "https://docs.meilisearch.com/errors#invalid-index-uid" + } + "###); + + let (response, code) = server.delete_tasks(json!({"indexUids": "the good doggo"})).await; + snapshot!(code, @"400 Bad Request"); + snapshot!(json_string!(response), @r###" + { + "message": "the good doggo is not a valid index uid. Index uid can be an integer or a string containing only alphanumeric characters, hyphens (-) and underscores (_).", + "code": "invalid_index_uid", + "type": "invalid_request", + "link": "https://docs.meilisearch.com/errors#invalid-index-uid" + } + "###); +} + +#[actix_rt::test] +async fn task_bad_limit() { + let server = Server::new().await; + + let (response, code) = server.tasks_filter(json!({"limit": "doggo"})).await; + snapshot!(code, @"400 Bad Request"); + snapshot!(json_string!(response), @r###" + { + "message": "Query deserialize error: invalid digit found in string", + "code": "bad_request", + "type": "invalid_request", + "link": "https://docs.meilisearch.com/errors#bad-request" + } + "###); + + let (response, code) = server.cancel_tasks(json!({"limit": "doggo"})).await; + snapshot!(code, @"400 Bad Request"); + snapshot!(json_string!(response), @r###" + { + "message": "Query deserialize error: unknown field `limit`", + "code": "bad_request", + "type": "invalid_request", + "link": "https://docs.meilisearch.com/errors#bad-request" + } + "###); + + let (response, code) = server.delete_tasks(json!({"limit": "doggo"})).await; + snapshot!(code, @"400 Bad Request"); + snapshot!(json_string!(response), @r###" + { + "message": "Query deserialize error: unknown field `limit`", + "code": "bad_request", + "type": "invalid_request", + "link": "https://docs.meilisearch.com/errors#bad-request" + } + "###); +} + +#[actix_rt::test] +async fn task_bad_from() { + let server = Server::new().await; + + let (response, code) = server.tasks_filter(json!({"from": "doggo"})).await; + snapshot!(code, @"400 Bad Request"); + snapshot!(json_string!(response), @r###" + { + "message": "Query deserialize error: invalid digit found in string", + "code": "bad_request", + "type": "invalid_request", + "link": "https://docs.meilisearch.com/errors#bad-request" + } + "###); + + let (response, code) = server.cancel_tasks(json!({"from": "doggo"})).await; + snapshot!(code, @"400 Bad Request"); + snapshot!(json_string!(response), @r###" + { + "message": "Query deserialize error: unknown field `from`", + "code": "bad_request", + "type": "invalid_request", + "link": "https://docs.meilisearch.com/errors#bad-request" + } + "###); + + let (response, code) = server.delete_tasks(json!({"from": "doggo"})).await; + snapshot!(code, @"400 Bad Request"); + snapshot!(json_string!(response), @r###" + { + "message": "Query deserialize error: unknown field `from`", + "code": "bad_request", + "type": "invalid_request", + "link": "https://docs.meilisearch.com/errors#bad-request" + } + "###); +} + +#[actix_rt::test] +async fn task_bad_after_enqueued_at() { + let server = Server::new().await; + + let (response, code) = server.tasks_filter(json!({"afterEnqueuedAt": "doggo"})).await; + snapshot!(code, @"400 Bad Request"); + snapshot!(json_string!(response), @r###" + { + "message": "Task `afterEnqueuedAt` `doggo` is invalid. It should follow the YYYY-MM-DD or RFC 3339 date-time format.", + "code": "invalid_task_after_enqueued_at", + "type": "invalid_request", + "link": "https://docs.meilisearch.com/errors#invalid-task-after-enqueued-at" + } + "###); + + let (response, code) = server.cancel_tasks(json!({"afterEnqueuedAt": "doggo"})).await; + snapshot!(code, @"400 Bad Request"); + snapshot!(json_string!(response), @r###" + { + "message": "Task `afterEnqueuedAt` `doggo` is invalid. It should follow the YYYY-MM-DD or RFC 3339 date-time format.", + "code": "invalid_task_after_enqueued_at", + "type": "invalid_request", + "link": "https://docs.meilisearch.com/errors#invalid-task-after-enqueued-at" + } + "###); + + let (response, code) = server.delete_tasks(json!({"afterEnqueuedAt": "doggo"})).await; + snapshot!(code, @"400 Bad Request"); + snapshot!(json_string!(response), @r###" + { + "message": "Task `afterEnqueuedAt` `doggo` is invalid. It should follow the YYYY-MM-DD or RFC 3339 date-time format.", + "code": "invalid_task_after_enqueued_at", + "type": "invalid_request", + "link": "https://docs.meilisearch.com/errors#invalid-task-after-enqueued-at" + } + "###); +} + +#[actix_rt::test] +async fn task_bad_before_enqueued_at() { + let server = Server::new().await; + + let (response, code) = server.tasks_filter(json!({"beforeEnqueuedAt": "doggo"})).await; + snapshot!(code, @"400 Bad Request"); + snapshot!(json_string!(response), @r###" + { + "message": "Task `beforeEnqueuedAt` `doggo` is invalid. It should follow the YYYY-MM-DD or RFC 3339 date-time format.", + "code": "invalid_task_before_enqueued_at", + "type": "invalid_request", + "link": "https://docs.meilisearch.com/errors#invalid-task-before-enqueued-at" + } + "###); + + let (response, code) = server.cancel_tasks(json!({"beforeEnqueuedAt": "doggo"})).await; + snapshot!(code, @"400 Bad Request"); + snapshot!(json_string!(response), @r###" + { + "message": "Task `beforeEnqueuedAt` `doggo` is invalid. It should follow the YYYY-MM-DD or RFC 3339 date-time format.", + "code": "invalid_task_before_enqueued_at", + "type": "invalid_request", + "link": "https://docs.meilisearch.com/errors#invalid-task-before-enqueued-at" + } + "###); + + let (response, code) = server.delete_tasks(json!({"beforeEnqueuedAt": "doggo"})).await; + snapshot!(code, @"400 Bad Request"); + snapshot!(json_string!(response), @r###" + { + "message": "Task `beforeEnqueuedAt` `doggo` is invalid. It should follow the YYYY-MM-DD or RFC 3339 date-time format.", + "code": "invalid_task_before_enqueued_at", + "type": "invalid_request", + "link": "https://docs.meilisearch.com/errors#invalid-task-before-enqueued-at" + } + "###); +} + +#[actix_rt::test] +async fn task_bad_after_started_at() { + let server = Server::new().await; + + let (response, code) = server.tasks_filter(json!({"afterStartedAt": "doggo"})).await; + snapshot!(code, @"400 Bad Request"); + snapshot!(json_string!(response), @r###" + { + "message": "Task `afterStartedAt` `doggo` is invalid. It should follow the YYYY-MM-DD or RFC 3339 date-time format.", + "code": "invalid_task_after_started_at", + "type": "invalid_request", + "link": "https://docs.meilisearch.com/errors#invalid-task-after-started-at" + } + "###); + + let (response, code) = server.cancel_tasks(json!({"afterStartedAt": "doggo"})).await; + snapshot!(code, @"400 Bad Request"); + snapshot!(json_string!(response), @r###" + { + "message": "Task `afterStartedAt` `doggo` is invalid. It should follow the YYYY-MM-DD or RFC 3339 date-time format.", + "code": "invalid_task_after_started_at", + "type": "invalid_request", + "link": "https://docs.meilisearch.com/errors#invalid-task-after-started-at" + } + "###); + + let (response, code) = server.delete_tasks(json!({"afterStartedAt": "doggo"})).await; + snapshot!(code, @"400 Bad Request"); + snapshot!(json_string!(response), @r###" + { + "message": "Task `afterStartedAt` `doggo` is invalid. It should follow the YYYY-MM-DD or RFC 3339 date-time format.", + "code": "invalid_task_after_started_at", + "type": "invalid_request", + "link": "https://docs.meilisearch.com/errors#invalid-task-after-started-at" + } + "###); +} + +#[actix_rt::test] +async fn task_bad_before_started_at() { + let server = Server::new().await; + + let (response, code) = server.tasks_filter(json!({"beforeStartedAt": "doggo"})).await; + snapshot!(code, @"400 Bad Request"); + snapshot!(json_string!(response), @r###" + { + "message": "Task `beforeStartedAt` `doggo` is invalid. It should follow the YYYY-MM-DD or RFC 3339 date-time format.", + "code": "invalid_task_before_started_at", + "type": "invalid_request", + "link": "https://docs.meilisearch.com/errors#invalid-task-before-started-at" + } + "###); + + let (response, code) = server.cancel_tasks(json!({"beforeStartedAt": "doggo"})).await; + snapshot!(code, @"400 Bad Request"); + snapshot!(json_string!(response), @r###" + { + "message": "Task `beforeStartedAt` `doggo` is invalid. It should follow the YYYY-MM-DD or RFC 3339 date-time format.", + "code": "invalid_task_before_started_at", + "type": "invalid_request", + "link": "https://docs.meilisearch.com/errors#invalid-task-before-started-at" + } + "###); + + let (response, code) = server.delete_tasks(json!({"beforeStartedAt": "doggo"})).await; + snapshot!(code, @"400 Bad Request"); + snapshot!(json_string!(response), @r###" + { + "message": "Task `beforeStartedAt` `doggo` is invalid. It should follow the YYYY-MM-DD or RFC 3339 date-time format.", + "code": "invalid_task_before_started_at", + "type": "invalid_request", + "link": "https://docs.meilisearch.com/errors#invalid-task-before-started-at" + } + "###); +} + +#[actix_rt::test] +async fn task_bad_after_finished_at() { + let server = Server::new().await; + + let (response, code) = server.tasks_filter(json!({"afterFinishedAt": "doggo"})).await; + snapshot!(code, @"400 Bad Request"); + snapshot!(json_string!(response), @r###" + { + "message": "Task `afterFinishedAt` `doggo` is invalid. It should follow the YYYY-MM-DD or RFC 3339 date-time format.", + "code": "invalid_task_after_finished_at", + "type": "invalid_request", + "link": "https://docs.meilisearch.com/errors#invalid-task-after-finished-at" + } + "###); + + let (response, code) = server.cancel_tasks(json!({"afterFinishedAt": "doggo"})).await; + snapshot!(code, @"400 Bad Request"); + snapshot!(json_string!(response), @r###" + { + "message": "Task `afterFinishedAt` `doggo` is invalid. It should follow the YYYY-MM-DD or RFC 3339 date-time format.", + "code": "invalid_task_after_finished_at", + "type": "invalid_request", + "link": "https://docs.meilisearch.com/errors#invalid-task-after-finished-at" + } + "###); + + let (response, code) = server.delete_tasks(json!({"afterFinishedAt": "doggo"})).await; + snapshot!(code, @"400 Bad Request"); + snapshot!(json_string!(response), @r###" + { + "message": "Task `afterFinishedAt` `doggo` is invalid. It should follow the YYYY-MM-DD or RFC 3339 date-time format.", + "code": "invalid_task_after_finished_at", + "type": "invalid_request", + "link": "https://docs.meilisearch.com/errors#invalid-task-after-finished-at" + } + "###); +} + +#[actix_rt::test] +async fn task_bad_before_finished_at() { + let server = Server::new().await; + + let (response, code) = server.tasks_filter(json!({"beforeFinishedAt": "doggo"})).await; + snapshot!(code, @"400 Bad Request"); + snapshot!(json_string!(response), @r###" + { + "message": "Task `beforeFinishedAt` `doggo` is invalid. It should follow the YYYY-MM-DD or RFC 3339 date-time format.", + "code": "invalid_task_before_finished_at", + "type": "invalid_request", + "link": "https://docs.meilisearch.com/errors#invalid-task-before-finished-at" + } + "###); + + let (response, code) = server.cancel_tasks(json!({"beforeFinishedAt": "doggo"})).await; + snapshot!(code, @"400 Bad Request"); + snapshot!(json_string!(response), @r###" + { + "message": "Task `beforeFinishedAt` `doggo` is invalid. It should follow the YYYY-MM-DD or RFC 3339 date-time format.", + "code": "invalid_task_before_finished_at", + "type": "invalid_request", + "link": "https://docs.meilisearch.com/errors#invalid-task-before-finished-at" + } + "###); + + let (response, code) = server.delete_tasks(json!({"beforeFinishedAt": "doggo"})).await; + snapshot!(code, @"400 Bad Request"); + snapshot!(json_string!(response), @r###" + { + "message": "Task `beforeFinishedAt` `doggo` is invalid. It should follow the YYYY-MM-DD or RFC 3339 date-time format.", + "code": "invalid_task_before_finished_at", + "type": "invalid_request", + "link": "https://docs.meilisearch.com/errors#invalid-task-before-finished-at" + } + "###); +} diff --git a/meilisearch/tests/tasks/mod.rs b/meilisearch/tests/tasks/mod.rs index a47c1ad9a..2e18d6237 100644 --- a/meilisearch/tests/tasks/mod.rs +++ b/meilisearch/tests/tasks/mod.rs @@ -1,3 +1,5 @@ +mod errors; + use meili_snap::insta::assert_json_snapshot; use serde_json::json; use time::format_description::well_known::Rfc3339; From a09b6a341d4bed8c03d4ce339ddefeb0a21c3f3b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Lo=C3=AFc=20Lecrenier?= Date: Wed, 11 Jan 2023 20:33:07 +0100 Subject: [PATCH 2/5] Move tasks route to deserr --- meilisearch-types/Cargo.toml | 2 +- meilisearch/Cargo.toml | 2 +- meilisearch/src/analytics/mock_analytics.rs | 4 +- meilisearch/src/analytics/mod.rs | 4 +- meilisearch/src/routes/tasks.rs | 858 +++++++------------- meilisearch/tests/tasks/errors.rs | 86 +- meilisearch/tests/tasks/mod.rs | 20 +- 7 files changed, 372 insertions(+), 604 deletions(-) diff --git a/meilisearch-types/Cargo.toml b/meilisearch-types/Cargo.toml index 379ac26aa..bd596ba2d 100644 --- a/meilisearch-types/Cargo.toml +++ b/meilisearch-types/Cargo.toml @@ -9,7 +9,7 @@ actix-web = { version = "4.2.1", default-features = false } anyhow = "1.0.65" convert_case = "0.6.0" csv = "1.1.6" -deserr = { version = "0.1.4", features = ["serde-json"] } +deserr = "0.1.4" either = { version = "1.6.1", features = ["serde"] } enum-iterator = "1.1.3" file-store = { path = "../file-store" } diff --git a/meilisearch/Cargo.toml b/meilisearch/Cargo.toml index 4ed1843db..a42e5cc7b 100644 --- a/meilisearch/Cargo.toml +++ b/meilisearch/Cargo.toml @@ -19,7 +19,7 @@ byte-unit = { version = "4.0.14", default-features = false, features = ["std", " bytes = "1.2.1" clap = { version = "4.0.9", features = ["derive", "env"] } crossbeam-channel = "0.5.6" -deserr = { version = "0.1.4", features = ["serde-json"] } +deserr = "0.1.4" dump = { path = "../dump" } either = "1.8.0" env_logger = "0.9.1" diff --git a/meilisearch/src/analytics/mock_analytics.rs b/meilisearch/src/analytics/mock_analytics.rs index ad45a1ac8..504c3baad 100644 --- a/meilisearch/src/analytics/mock_analytics.rs +++ b/meilisearch/src/analytics/mock_analytics.rs @@ -7,8 +7,8 @@ use serde_json::Value; use super::{find_user_id, Analytics, DocumentDeletionKind}; use crate::routes::indexes::documents::UpdateDocumentsQuery; -use crate::routes::tasks::TasksFilterQueryRaw; use crate::Opt; +use crate::routes::tasks::TasksFilterQuery; pub struct MockAnalytics { instance_uid: Option, @@ -58,6 +58,6 @@ impl Analytics for MockAnalytics { _request: &HttpRequest, ) { } - fn get_tasks(&self, _query: &TasksFilterQueryRaw, _request: &HttpRequest) {} + fn get_tasks(&self, _query: &TasksFilterQuery, _request: &HttpRequest) {} fn health_seen(&self, _request: &HttpRequest) {} } diff --git a/meilisearch/src/analytics/mod.rs b/meilisearch/src/analytics/mod.rs index 1effe6692..ec15707bf 100644 --- a/meilisearch/src/analytics/mod.rs +++ b/meilisearch/src/analytics/mod.rs @@ -15,7 +15,7 @@ use platform_dirs::AppDirs; use serde_json::Value; use crate::routes::indexes::documents::UpdateDocumentsQuery; -use crate::routes::tasks::TasksFilterQueryRaw; +use crate::routes::tasks::TasksFilterQuery; // if we are in debug mode OR the analytics feature is disabled // the `SegmentAnalytics` point to the mock instead of the real analytics @@ -94,7 +94,7 @@ pub trait Analytics: Sync + Send { ); // this method should be called to aggregate the get tasks requests. - fn get_tasks(&self, query: &TasksFilterQueryRaw, request: &HttpRequest); + fn get_tasks(&self, query: &TasksFilterQuery, request: &HttpRequest); // this method should be called to aggregate a add documents request fn health_seen(&self, request: &HttpRequest); diff --git a/meilisearch/src/routes/tasks.rs b/meilisearch/src/routes/tasks.rs index 4be88c88c..68eb1963f 100644 --- a/meilisearch/src/routes/tasks.rs +++ b/meilisearch/src/routes/tasks.rs @@ -1,10 +1,12 @@ +use std::num::ParseIntError; use std::str::FromStr; use actix_web::web::Data; use actix_web::{web, HttpRequest, HttpResponse}; -use index_scheduler::error::DateField; +use deserr::DeserializeFromValue; use index_scheduler::{IndexScheduler, Query, TaskId}; -use meilisearch_types::error::ResponseError; +use meilisearch_types::error::{deserr_codes::*, TakeErrorMessage}; +use meilisearch_types::error::{DeserrError, ResponseError}; use meilisearch_types::index_uid::IndexUid; use meilisearch_types::settings::{Settings, Unchecked}; use meilisearch_types::star_or::StarOr; @@ -14,14 +16,16 @@ use meilisearch_types::tasks::{ use serde::{Deserialize, Serialize}; use serde_cs::vec::CS; use serde_json::json; -use time::{Duration, OffsetDateTime}; +use time::format_description::well_known::Rfc3339; +use time::macros::format_description; +use time::{Date, Duration, OffsetDateTime, Time}; use tokio::task; -use self::date_deserializer::{deserialize_date, DeserializeDateOption}; use super::{fold_star_or, SummarizedTaskView}; use crate::analytics::Analytics; use crate::extractors::authentication::policies::*; use crate::extractors::authentication::GuardedData; +use crate::extractors::query_parameters::QueryParameter; use crate::extractors::sequential_extractor::SeqHandler; const DEFAULT_LIMIT: fn() -> u32 = || 20; @@ -160,308 +164,124 @@ impl From
for DetailsView { } } -#[derive(Deserialize, Debug)] -#[serde(rename_all = "camelCase", deny_unknown_fields)] -pub struct TaskCommonQueryRaw { - pub uids: Option>, - pub canceled_by: Option>, - pub types: Option>>, - pub statuses: Option>>, - pub index_uids: Option>>, +fn parse_option_cs( + s: Option>, +) -> Result>, TakeErrorMessage> { + if let Some(s) = s { + s.into_iter() + .map(|s| T::from_str(&s)) + .collect::, T::Err>>() + .map_err(TakeErrorMessage) + .map(Some) + } else { + Ok(None) + } } - -impl TaskCommonQueryRaw { - fn validate(self) -> Result { - let Self { uids, canceled_by, types, statuses, index_uids } = self; - let uids = if let Some(uids) = uids { - Some( - uids.into_iter() - .map(|uid_string| { - uid_string.parse::().map_err(|_e| { - index_scheduler::Error::InvalidTaskUids { task_uid: uid_string }.into() - }) - }) - .collect::, ResponseError>>()?, - ) - } else { - None - }; - let canceled_by = if let Some(canceled_by) = canceled_by { - Some( - canceled_by - .into_iter() - .map(|canceled_by_string| { - canceled_by_string.parse::().map_err(|_e| { - index_scheduler::Error::InvalidTaskCanceledBy { - canceled_by: canceled_by_string, - } - .into() - }) - }) - .collect::, ResponseError>>()?, - ) - } else { - None - }; - - let types = if let Some(types) = types.and_then(fold_star_or) as Option> { - Some( - types - .into_iter() - .map(|type_string| { - Kind::from_str(&type_string).map_err(|_e| { - index_scheduler::Error::InvalidTaskTypes { type_: type_string }.into() - }) - }) - .collect::, ResponseError>>()?, - ) - } else { - None - }; - let statuses = if let Some(statuses) = - statuses.and_then(fold_star_or) as Option> - { - Some( - statuses - .into_iter() - .map(|status_string| { - Status::from_str(&status_string).map_err(|_e| { - index_scheduler::Error::InvalidTaskStatuses { status: status_string } - .into() - }) - }) - .collect::, ResponseError>>()?, - ) - } else { - None - }; - - let index_uids = - if let Some(index_uids) = index_uids.and_then(fold_star_or) as Option> { - Some( - index_uids - .into_iter() - .map(|index_uid_string| { - IndexUid::from_str(&index_uid_string) - .map(|index_uid| index_uid.to_string()) - .map_err(|_e| { - index_scheduler::Error::InvalidIndexUid { - index_uid: index_uid_string, - } - .into() - }) - }) - .collect::, ResponseError>>()?, - ) - } else { - None - }; - Ok(TaskCommonQuery { types, uids, canceled_by, statuses, index_uids }) +fn parse_option_cs_star_or( + s: Option>>, +) -> Result>, TakeErrorMessage> { + if let Some(s) = s.and_then(fold_star_or) as Option> { + s.into_iter() + .map(|s| T::from_str(&s)) + .collect::, T::Err>>() + .map_err(TakeErrorMessage) + .map(Some) + } else { + Ok(None) + } +} +fn parse_option_str(s: Option) -> Result, TakeErrorMessage> { + if let Some(s) = s { + T::from_str(&s).map_err(TakeErrorMessage).map(Some) + } else { + Ok(None) } } -#[derive(Deserialize, Debug)] -#[serde(rename_all = "camelCase", deny_unknown_fields)] -pub struct TaskDateQueryRaw { - pub after_enqueued_at: Option, - pub before_enqueued_at: Option, - pub after_started_at: Option, - pub before_started_at: Option, - pub after_finished_at: Option, - pub before_finished_at: Option, +fn parse_str(s: String) -> Result> { + T::from_str(&s).map_err(TakeErrorMessage) } -impl TaskDateQueryRaw { - fn validate(self) -> Result { - let Self { - after_enqueued_at, - before_enqueued_at, - after_started_at, - before_started_at, - after_finished_at, - before_finished_at, - } = self; - - let mut query = TaskDateQuery { - after_enqueued_at: None, - before_enqueued_at: None, - after_started_at: None, - before_started_at: None, - after_finished_at: None, - before_finished_at: None, - }; - - for (field_name, string_value, before_or_after, dest) in [ - ( - DateField::AfterEnqueuedAt, - after_enqueued_at, - DeserializeDateOption::After, - &mut query.after_enqueued_at, - ), - ( - DateField::BeforeEnqueuedAt, - before_enqueued_at, - DeserializeDateOption::Before, - &mut query.before_enqueued_at, - ), - ( - DateField::AfterStartedAt, - after_started_at, - DeserializeDateOption::After, - &mut query.after_started_at, - ), - ( - DateField::BeforeStartedAt, - before_started_at, - DeserializeDateOption::Before, - &mut query.before_started_at, - ), - ( - DateField::AfterFinishedAt, - after_finished_at, - DeserializeDateOption::After, - &mut query.after_finished_at, - ), - ( - DateField::BeforeFinishedAt, - before_finished_at, - DeserializeDateOption::Before, - &mut query.before_finished_at, - ), - ] { - if let Some(string_value) = string_value { - *dest = Some(deserialize_date(field_name, &string_value, before_or_after)?); - } - } - - Ok(query) - } -} - -#[derive(Deserialize, Debug)] -#[serde(rename_all = "camelCase", deny_unknown_fields)] -pub struct TasksFilterQueryRaw { - #[serde(flatten)] - pub common: TaskCommonQueryRaw, - #[serde(default = "DEFAULT_LIMIT")] - pub limit: u32, - pub from: Option, - #[serde(flatten)] - pub dates: TaskDateQueryRaw, -} - -#[derive(Deserialize, Debug)] -#[serde(rename_all = "camelCase", deny_unknown_fields)] -pub struct TaskDeletionOrCancelationQueryRaw { - #[serde(flatten)] - pub common: TaskCommonQueryRaw, - #[serde(flatten)] - pub dates: TaskDateQueryRaw, -} - -impl TasksFilterQueryRaw { - fn validate(self) -> Result { - let Self { common, limit, from, dates } = self; - let common = common.validate()?; - let dates = dates.validate()?; - - Ok(TasksFilterQuery { common, limit, from, dates }) - } -} - -impl TaskDeletionOrCancelationQueryRaw { - fn validate(self) -> Result { - let Self { common, dates } = self; - let common = common.validate()?; - let dates = dates.validate()?; - - Ok(TaskDeletionOrCancelationQuery { common, dates }) - } -} - -#[derive(Serialize, Debug)] -#[serde(rename_all = "camelCase", deny_unknown_fields)] -pub struct TaskDateQuery { - #[serde( - default, - skip_serializing_if = "Option::is_none", - serialize_with = "time::serde::rfc3339::option::serialize" - )] - after_enqueued_at: Option, - #[serde( - default, - skip_serializing_if = "Option::is_none", - serialize_with = "time::serde::rfc3339::option::serialize" - )] - before_enqueued_at: Option, - #[serde( - default, - skip_serializing_if = "Option::is_none", - serialize_with = "time::serde::rfc3339::option::serialize" - )] - after_started_at: Option, - #[serde( - default, - skip_serializing_if = "Option::is_none", - serialize_with = "time::serde::rfc3339::option::serialize" - )] - before_started_at: Option, - #[serde( - default, - skip_serializing_if = "Option::is_none", - serialize_with = "time::serde::rfc3339::option::serialize" - )] - after_finished_at: Option, - #[serde( - default, - skip_serializing_if = "Option::is_none", - serialize_with = "time::serde::rfc3339::option::serialize" - )] - before_finished_at: Option, -} - -#[derive(Debug)] -pub struct TaskCommonQuery { - types: Option>, - uids: Option>, - canceled_by: Option>, - statuses: Option>, - index_uids: Option>, -} - -#[derive(Debug)] +#[derive(Debug, DeserializeFromValue)] +#[deserr(error = DeserrError, rename_all = camelCase, deny_unknown_fields)] pub struct TasksFilterQuery { - limit: u32, - from: Option, - common: TaskCommonQuery, - dates: TaskDateQuery, + #[deserr(error = DeserrError, default = DEFAULT_LIMIT(), from(String) = parse_str:: -> TakeErrorMessage)] + pub limit: u32, + #[deserr(error = DeserrError, from(Option) = parse_option_str:: -> TakeErrorMessage)] + pub from: Option, + + #[deserr(error = DeserrError, from(Option>) = parse_option_cs:: -> TakeErrorMessage)] + pub uids: Option>, + #[deserr(error = DeserrError, from(Option>) = parse_option_cs:: -> TakeErrorMessage)] + pub canceled_by: Option>, + #[deserr(error = DeserrError, default = None, from(Option>>) = parse_option_cs_star_or:: -> TakeErrorMessage)] + pub types: Option>, + #[deserr(error = DeserrError, default = None, from(Option>>) = parse_option_cs_star_or:: -> TakeErrorMessage)] + pub statuses: Option>, + #[deserr(error = DeserrError, default = None, from(Option>>) = parse_option_cs_star_or:: -> TakeErrorMessage)] + pub index_uids: Option>, + + #[deserr(error = DeserrError, default = None, from(Option) = deserialize_date_after -> TakeErrorMessage)] + pub after_enqueued_at: Option, + #[deserr(error = DeserrError, default = None, from(Option) = deserialize_date_before -> TakeErrorMessage)] + pub before_enqueued_at: Option, + #[deserr(error = DeserrError, default = None, from(Option) = deserialize_date_after -> TakeErrorMessage)] + pub after_started_at: Option, + #[deserr(error = DeserrError, default = None, from(Option) = deserialize_date_before -> TakeErrorMessage)] + pub before_started_at: Option, + #[deserr(error = DeserrError, default = None, from(Option) = deserialize_date_after -> TakeErrorMessage)] + pub after_finished_at: Option, + #[deserr(error = DeserrError, default = None, from(Option) = deserialize_date_before -> TakeErrorMessage)] + pub before_finished_at: Option, } -#[derive(Debug)] +#[derive(Deserialize, Debug, DeserializeFromValue)] +#[deserr(error = DeserrError, rename_all = camelCase, deny_unknown_fields)] pub struct TaskDeletionOrCancelationQuery { - common: TaskCommonQuery, - dates: TaskDateQuery, + #[deserr(error = DeserrError, from(Option>) = parse_option_cs:: -> TakeErrorMessage)] + pub uids: Option>, + #[deserr(error = DeserrError, from(Option>) = parse_option_cs:: -> TakeErrorMessage)] + pub canceled_by: Option>, + #[deserr(error = DeserrError, default = None, from(Option>>) = parse_option_cs_star_or:: -> TakeErrorMessage)] + pub types: Option>, + #[deserr(error = DeserrError, default = None, from(Option>>) = parse_option_cs_star_or:: -> TakeErrorMessage)] + pub statuses: Option>, + #[deserr(error = DeserrError, default = None, from(Option>>) = parse_option_cs_star_or:: -> TakeErrorMessage)] + pub index_uids: Option>, + + #[deserr(error = DeserrError, default = None, from(Option) = deserialize_date_after -> TakeErrorMessage)] + pub after_enqueued_at: Option, + #[deserr(error = DeserrError, default = None, from(Option) = deserialize_date_before -> TakeErrorMessage)] + pub before_enqueued_at: Option, + #[deserr(error = DeserrError, default = None, from(Option) = deserialize_date_after -> TakeErrorMessage)] + pub after_started_at: Option, + #[deserr(error = DeserrError, default = None, from(Option) = deserialize_date_before -> TakeErrorMessage)] + pub before_started_at: Option, + #[deserr(error = DeserrError, default = None, from(Option) = deserialize_date_after -> TakeErrorMessage)] + pub after_finished_at: Option, + #[deserr(error = DeserrError, default = None, from(Option) = deserialize_date_before -> TakeErrorMessage)] + pub before_finished_at: Option, } async fn cancel_tasks( index_scheduler: GuardedData, Data>, - params: web::Query, + params: QueryParameter, req: HttpRequest, analytics: web::Data, ) -> Result { - let query = params.into_inner().validate()?; let TaskDeletionOrCancelationQuery { - common: TaskCommonQuery { types, uids, canceled_by, statuses, index_uids }, - dates: - TaskDateQuery { - after_enqueued_at, - before_enqueued_at, - after_started_at, - before_started_at, - after_finished_at, - before_finished_at, - }, - } = query; + types, + uids, + canceled_by, + statuses, + index_uids, + after_enqueued_at, + before_enqueued_at, + after_started_at, + before_started_at, + after_finished_at, + before_finished_at, + } = params.into_inner(); analytics.publish( "Tasks Canceled".to_string(), @@ -486,7 +306,7 @@ async fn cancel_tasks( from: None, statuses, types, - index_uids, + index_uids: index_uids.map(|xs| xs.into_iter().map(|s| s.to_string()).collect()), uids, canceled_by, before_enqueued_at, @@ -517,22 +337,24 @@ async fn cancel_tasks( async fn delete_tasks( index_scheduler: GuardedData, Data>, - params: web::Query, + params: QueryParameter, req: HttpRequest, analytics: web::Data, ) -> Result { let TaskDeletionOrCancelationQuery { - common: TaskCommonQuery { types, uids, canceled_by, statuses, index_uids }, - dates: - TaskDateQuery { - after_enqueued_at, - before_enqueued_at, - after_started_at, - before_started_at, - after_finished_at, - before_finished_at, - }, - } = params.into_inner().validate()?; + types, + uids, + canceled_by, + statuses, + index_uids, + + after_enqueued_at, + before_enqueued_at, + after_started_at, + before_started_at, + after_finished_at, + before_finished_at, + } = params.into_inner(); analytics.publish( "Tasks Deleted".to_string(), @@ -557,7 +379,7 @@ async fn delete_tasks( from: None, statuses, types, - index_uids, + index_uids: index_uids.map(|xs| xs.into_iter().map(|s| s.to_string()).collect()), uids, canceled_by, after_enqueued_at, @@ -596,26 +418,28 @@ pub struct AllTasks { async fn get_tasks( index_scheduler: GuardedData, Data>, - params: web::Query, + params: QueryParameter, req: HttpRequest, analytics: web::Data, ) -> Result { + let params = params.into_inner(); analytics.get_tasks(¶ms, &req); let TasksFilterQuery { - common: TaskCommonQuery { types, uids, canceled_by, statuses, index_uids }, + types, + uids, + canceled_by, + statuses, + index_uids, limit, from, - dates: - TaskDateQuery { - after_enqueued_at, - before_enqueued_at, - after_started_at, - before_started_at, - after_finished_at, - before_finished_at, - }, - } = params.into_inner().validate()?; + after_enqueued_at, + before_enqueued_at, + after_started_at, + before_started_at, + after_finished_at, + before_finished_at, + } = params; // We +1 just to know if there is more after this "page" or not. let limit = limit.saturating_add(1); @@ -625,7 +449,7 @@ async fn get_tasks( from, statuses, types, - index_uids, + index_uids: index_uids.map(|xs| xs.into_iter().map(|s| s.to_string()).collect()), uids, canceled_by, before_enqueued_at, @@ -692,333 +516,277 @@ async fn get_task( } } -pub(crate) mod date_deserializer { - use index_scheduler::error::DateField; - use meilisearch_types::error::ResponseError; - use time::format_description::well_known::Rfc3339; - use time::macros::format_description; - use time::{Date, Duration, OffsetDateTime, Time}; +pub enum DeserializeDateOption { + Before, + After, +} - pub enum DeserializeDateOption { - Before, - After, - } - - pub fn deserialize_date( - field_name: DateField, - value: &str, - option: DeserializeDateOption, - ) -> std::result::Result { - // We can't parse using time's rfc3339 format, since then we won't know what part of the - // datetime was not explicitly specified, and thus we won't be able to increment it to the - // next step. - if let Ok(datetime) = OffsetDateTime::parse(value, &Rfc3339) { - // fully specified up to the second - // we assume that the subseconds are 0 if not specified, and we don't increment to the next second - Ok(datetime) - } else if let Ok(datetime) = Date::parse( - value, - format_description!("[year repr:full base:calendar]-[month repr:numerical]-[day]"), - ) { - let datetime = datetime.with_time(Time::MIDNIGHT).assume_utc(); - // add one day since the time was not specified - match option { - DeserializeDateOption::Before => Ok(datetime), - DeserializeDateOption::After => { - let datetime = datetime.checked_add(Duration::days(1)).unwrap_or(datetime); - Ok(datetime) - } +pub fn deserialize_date( + value: &str, + option: DeserializeDateOption, +) -> std::result::Result> { + // We can't parse using time's rfc3339 format, since then we won't know what part of the + // datetime was not explicitly specified, and thus we won't be able to increment it to the + // next step. + if let Ok(datetime) = OffsetDateTime::parse(value, &Rfc3339) { + // fully specified up to the second + // we assume that the subseconds are 0 if not specified, and we don't increment to the next second + Ok(datetime) + } else if let Ok(datetime) = Date::parse( + value, + format_description!("[year repr:full base:calendar]-[month repr:numerical]-[day]"), + ) { + let datetime = datetime.with_time(Time::MIDNIGHT).assume_utc(); + // add one day since the time was not specified + match option { + DeserializeDateOption::Before => Ok(datetime), + DeserializeDateOption::After => { + let datetime = datetime.checked_add(Duration::days(1)).unwrap_or(datetime); + Ok(datetime) } - } else { - Err(index_scheduler::Error::InvalidTaskDate { - field: field_name, - date: value.to_string(), - } - .into()) } + } else { + Err(TakeErrorMessage(InvalidTaskDateError(value.to_owned()))) } } +pub fn deserialize_date_before( + value: Option, +) -> std::result::Result, TakeErrorMessage> { + if let Some(value) = value { + let date = deserialize_date(&value, DeserializeDateOption::Before)?; + Ok(Some(date)) + } else { + Ok(None) + } +} +pub fn deserialize_date_after( + value: Option, +) -> std::result::Result, TakeErrorMessage> { + if let Some(value) = value { + let date = deserialize_date(&value, DeserializeDateOption::After)?; + Ok(Some(date)) + } else { + Ok(None) + } +} + +#[derive(Debug)] +pub struct InvalidTaskDateError(String); +impl std::fmt::Display for InvalidTaskDateError { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + write!(f, "`{}` is an invalid date-time. It should follow the YYYY-MM-DD or RFC 3339 date-time format.", self.0) + } +} +impl std::error::Error for InvalidTaskDateError {} + #[cfg(test)] mod tests { + use deserr::DeserializeFromValue; use meili_snap::snapshot; + use meilisearch_types::error::DeserrError; - use crate::routes::tasks::{TaskDeletionOrCancelationQueryRaw, TasksFilterQueryRaw}; + use crate::{ + extractors::query_parameters::QueryParameter, + routes::tasks::{TaskDeletionOrCancelationQuery, TasksFilterQuery}, + }; + + fn deserr_query_params(j: &str) -> Result + where + T: DeserializeFromValue, + { + QueryParameter::::from_query(j).map(|p| p.0) + } #[test] fn deserialize_task_filter_dates() { { - let json = r#" { - "afterEnqueuedAt": "2021-12-03", - "beforeEnqueuedAt": "2021-12-03", - "afterStartedAt": "2021-12-03", - "beforeStartedAt": "2021-12-03", - "afterFinishedAt": "2021-12-03", - "beforeFinishedAt": "2021-12-03" - } "#; - let query = serde_json::from_str::(json) - .unwrap() - .validate() - .unwrap(); - snapshot!(format!("{:?}", query.dates.after_enqueued_at.unwrap()), @"2021-12-04 0:00:00.0 +00:00:00"); - snapshot!(format!("{:?}", query.dates.before_enqueued_at.unwrap()), @"2021-12-03 0:00:00.0 +00:00:00"); - snapshot!(format!("{:?}", query.dates.after_started_at.unwrap()), @"2021-12-04 0:00:00.0 +00:00:00"); - snapshot!(format!("{:?}", query.dates.before_started_at.unwrap()), @"2021-12-03 0:00:00.0 +00:00:00"); - snapshot!(format!("{:?}", query.dates.after_finished_at.unwrap()), @"2021-12-04 0:00:00.0 +00:00:00"); - snapshot!(format!("{:?}", query.dates.before_finished_at.unwrap()), @"2021-12-03 0:00:00.0 +00:00:00"); + let params = "afterEnqueuedAt=2021-12-03&beforeEnqueuedAt=2021-12-03&afterStartedAt=2021-12-03&beforeStartedAt=2021-12-03&afterFinishedAt=2021-12-03&beforeFinishedAt=2021-12-03"; + let query = deserr_query_params::(params).unwrap(); + + snapshot!(format!("{:?}", query.after_enqueued_at.unwrap()), @"2021-12-04 0:00:00.0 +00:00:00"); + snapshot!(format!("{:?}", query.before_enqueued_at.unwrap()), @"2021-12-03 0:00:00.0 +00:00:00"); + snapshot!(format!("{:?}", query.after_started_at.unwrap()), @"2021-12-04 0:00:00.0 +00:00:00"); + snapshot!(format!("{:?}", query.before_started_at.unwrap()), @"2021-12-03 0:00:00.0 +00:00:00"); + snapshot!(format!("{:?}", query.after_finished_at.unwrap()), @"2021-12-04 0:00:00.0 +00:00:00"); + snapshot!(format!("{:?}", query.before_finished_at.unwrap()), @"2021-12-03 0:00:00.0 +00:00:00"); } { - let json = r#" { "afterEnqueuedAt": "2021-12-03T23:45:23Z", "beforeEnqueuedAt": "2021-12-03T23:45:23Z" } "#; - let query = serde_json::from_str::(json) - .unwrap() - .validate() - .unwrap(); - snapshot!(format!("{:?}", query.dates.after_enqueued_at.unwrap()), @"2021-12-03 23:45:23.0 +00:00:00"); - snapshot!(format!("{:?}", query.dates.before_enqueued_at.unwrap()), @"2021-12-03 23:45:23.0 +00:00:00"); + let params = + "afterEnqueuedAt=2021-12-03T23:45:23Z&beforeEnqueuedAt=2021-12-03T23:45:23Z"; + let query = deserr_query_params::(params).unwrap(); + snapshot!(format!("{:?}", query.after_enqueued_at.unwrap()), @"2021-12-03 23:45:23.0 +00:00:00"); + snapshot!(format!("{:?}", query.before_enqueued_at.unwrap()), @"2021-12-03 23:45:23.0 +00:00:00"); } { - let json = r#" { "afterEnqueuedAt": "1997-11-12T09:55:06-06:20" } "#; - let query = serde_json::from_str::(json) - .unwrap() - .validate() - .unwrap(); - snapshot!(format!("{:?}", query.dates.after_enqueued_at.unwrap()), @"1997-11-12 9:55:06.0 -06:20:00"); + let params = "afterEnqueuedAt=1997-11-12T09:55:06-06:20"; + let query = deserr_query_params::(params).unwrap(); + snapshot!(format!("{:?}", query.after_enqueued_at.unwrap()), @"1997-11-12 9:55:06.0 -06:20:00"); } { - let json = r#" { "afterEnqueuedAt": "1997-11-12T09:55:06+00:00" } "#; - let query = serde_json::from_str::(json) - .unwrap() - .validate() - .unwrap(); - snapshot!(format!("{:?}", query.dates.after_enqueued_at.unwrap()), @"1997-11-12 9:55:06.0 +00:00:00"); + let params = "afterEnqueuedAt=1997-11-12T09:55:06%2B00:00"; + let query = deserr_query_params::(params).unwrap(); + snapshot!(format!("{:?}", query.after_enqueued_at.unwrap()), @"1997-11-12 9:55:06.0 +00:00:00"); } { - let json = r#" { "afterEnqueuedAt": "1997-11-12T09:55:06.200000300Z" } "#; - let query = serde_json::from_str::(json) - .unwrap() - .validate() - .unwrap(); - snapshot!(format!("{:?}", query.dates.after_enqueued_at.unwrap()), @"1997-11-12 9:55:06.2000003 +00:00:00"); + let params = "afterEnqueuedAt=1997-11-12T09:55:06.200000300Z"; + let query = deserr_query_params::(params).unwrap(); + snapshot!(format!("{:?}", query.after_enqueued_at.unwrap()), @"1997-11-12 9:55:06.2000003 +00:00:00"); } { - let json = r#" { "afterFinishedAt": "2021" } "#; - let err = serde_json::from_str::(json) - .unwrap() - .validate() - .unwrap_err(); - snapshot!(format!("{err}"), @"Task `afterFinishedAt` `2021` is invalid. It should follow the YYYY-MM-DD or RFC 3339 date-time format."); + let params = "afterFinishedAt=2021"; + let err = deserr_query_params::(params).unwrap_err(); + snapshot!(format!("{err}"), @"`2021` is an invalid date-time. It should follow the YYYY-MM-DD or RFC 3339 date-time format. at `.afterFinishedAt`."); } { - let json = r#" { "beforeFinishedAt": "2021" } "#; - let err = serde_json::from_str::(json) - .unwrap() - .validate() - .unwrap_err(); - snapshot!(format!("{err}"), @"Task `beforeFinishedAt` `2021` is invalid. It should follow the YYYY-MM-DD or RFC 3339 date-time format."); + let params = "beforeFinishedAt=2021"; + let err = deserr_query_params::(params).unwrap_err(); + snapshot!(format!("{err}"), @"`2021` is an invalid date-time. It should follow the YYYY-MM-DD or RFC 3339 date-time format. at `.beforeFinishedAt`."); } { - let json = r#" { "afterEnqueuedAt": "2021-12" } "#; - let err = serde_json::from_str::(json) - .unwrap() - .validate() - .unwrap_err(); - snapshot!(format!("{err}"), @"Task `afterEnqueuedAt` `2021-12` is invalid. It should follow the YYYY-MM-DD or RFC 3339 date-time format."); + let params = "afterEnqueuedAt=2021-12"; + let err = deserr_query_params::(params).unwrap_err(); + snapshot!(format!("{err}"), @"`2021-12` is an invalid date-time. It should follow the YYYY-MM-DD or RFC 3339 date-time format. at `.afterEnqueuedAt`."); } { - let json = r#" { "beforeEnqueuedAt": "2021-12-03T23" } "#; - let err = serde_json::from_str::(json) - .unwrap() - .validate() - .unwrap_err(); - snapshot!(format!("{err}"), @"Task `beforeEnqueuedAt` `2021-12-03T23` is invalid. It should follow the YYYY-MM-DD or RFC 3339 date-time format."); + let params = "beforeEnqueuedAt=2021-12-03T23"; + let err = deserr_query_params::(params).unwrap_err(); + snapshot!(format!("{err}"), @"`2021-12-03T23` is an invalid date-time. It should follow the YYYY-MM-DD or RFC 3339 date-time format. at `.beforeEnqueuedAt`."); } { - let json = r#" { "afterStartedAt": "2021-12-03T23:45" } "#; - let err = serde_json::from_str::(json) - .unwrap() - .validate() - .unwrap_err(); - snapshot!(format!("{err}"), @"Task `afterStartedAt` `2021-12-03T23:45` is invalid. It should follow the YYYY-MM-DD or RFC 3339 date-time format."); - - let json = r#" { "beforeStartedAt": "2021-12-03T23:45" } "#; - let err = serde_json::from_str::(json) - .unwrap() - .validate() - .unwrap_err(); - snapshot!(format!("{err}"), @"Task `beforeStartedAt` `2021-12-03T23:45` is invalid. It should follow the YYYY-MM-DD or RFC 3339 date-time format."); + let params = "afterStartedAt=2021-12-03T23:45"; + let err = deserr_query_params::(params).unwrap_err(); + snapshot!(format!("{err}"), @"`2021-12-03T23:45` is an invalid date-time. It should follow the YYYY-MM-DD or RFC 3339 date-time format. at `.afterStartedAt`."); + } + { + let params = "beforeStartedAt=2021-12-03T23:45"; + let err = deserr_query_params::(params).unwrap_err(); + snapshot!(format!("{err}"), @"`2021-12-03T23:45` is an invalid date-time. It should follow the YYYY-MM-DD or RFC 3339 date-time format. at `.beforeStartedAt`."); } } #[test] fn deserialize_task_filter_uids() { { - let json = r#" { "uids": "78,1,12,73" } "#; - let query = serde_json::from_str::(json) - .unwrap() - .validate() - .unwrap(); - snapshot!(format!("{:?}", query.common.uids.unwrap()), @"[78, 1, 12, 73]"); + let params = "uids=78,1,12,73"; + let query = deserr_query_params::(params).unwrap(); + snapshot!(format!("{:?}", query.uids.unwrap()), @"[78, 1, 12, 73]"); } { - let json = r#" { "uids": "1" } "#; - let query = serde_json::from_str::(json) - .unwrap() - .validate() - .unwrap(); - snapshot!(format!("{:?}", query.common.uids.unwrap()), @"[1]"); + let params = "uids=1"; + let query = deserr_query_params::(params).unwrap(); + snapshot!(format!("{:?}", query.uids.unwrap()), @"[1]"); } { - let json = r#" { "uids": "78,hello,world" } "#; - let err = serde_json::from_str::(json) - .unwrap() - .validate() - .unwrap_err(); - snapshot!(format!("{err}"), @"Task uid `hello` is invalid. It should only contain numeric characters."); + let params = "uids=78,hello,world"; + let err = deserr_query_params::(params).unwrap_err(); + snapshot!(format!("{err}"), @"invalid digit found in string at `.uids`."); } { - let json = r#" { "uids": "cat" } "#; - let err = serde_json::from_str::(json) - .unwrap() - .validate() - .unwrap_err(); - snapshot!(format!("{err}"), @"Task uid `cat` is invalid. It should only contain numeric characters."); + let params = "uids=cat"; + let err = deserr_query_params::(params).unwrap_err(); + snapshot!(format!("{err}"), @"invalid digit found in string at `.uids`."); } } #[test] fn deserialize_task_filter_status() { { - let json = r#" { "statuses": "succeeded,failed,enqueued,processing,canceled" } "#; - let query = serde_json::from_str::(json) - .unwrap() - .validate() - .unwrap(); - snapshot!(format!("{:?}", query.common.statuses.unwrap()), @"[Succeeded, Failed, Enqueued, Processing, Canceled]"); + let params = "statuses=succeeded,failed,enqueued,processing,canceled"; + let query = deserr_query_params::(params).unwrap(); + snapshot!(format!("{:?}", query.statuses.unwrap()), @"[Succeeded, Failed, Enqueued, Processing, Canceled]"); } { - let json = r#" { "statuses": "enqueued" } "#; - let query = serde_json::from_str::(json) - .unwrap() - .validate() - .unwrap(); - snapshot!(format!("{:?}", query.common.statuses.unwrap()), @"[Enqueued]"); + let params = "statuses=enqueued"; + let query = deserr_query_params::(params).unwrap(); + snapshot!(format!("{:?}", query.statuses.unwrap()), @"[Enqueued]"); } { - let json = r#" { "statuses": "finished" } "#; - let err = serde_json::from_str::(json) - .unwrap() - .validate() - .unwrap_err(); - snapshot!(format!("{err}"), @"Task status `finished` is invalid. Available task statuses are `enqueued`, `processing`, `succeeded`, `failed`, `canceled`."); + let params = "statuses=finished"; + let err = deserr_query_params::(params).unwrap_err(); + snapshot!(format!("{err}"), @"`finished` is not a status. Available status are `enqueued`, `processing`, `succeeded`, `failed`, `canceled`. at `.statuses`."); } } #[test] fn deserialize_task_filter_types() { { - let json = r#" { "types": "documentAdditionOrUpdate,documentDeletion,settingsUpdate,indexCreation,indexDeletion,indexUpdate,indexSwap,taskCancelation,taskDeletion,dumpCreation,snapshotCreation" }"#; - let query = serde_json::from_str::(json) - .unwrap() - .validate() - .unwrap(); - snapshot!(format!("{:?}", query.common.types.unwrap()), @"[DocumentAdditionOrUpdate, DocumentDeletion, SettingsUpdate, IndexCreation, IndexDeletion, IndexUpdate, IndexSwap, TaskCancelation, TaskDeletion, DumpCreation, SnapshotCreation]"); + let params = "types=documentAdditionOrUpdate,documentDeletion,settingsUpdate,indexCreation,indexDeletion,indexUpdate,indexSwap,taskCancelation,taskDeletion,dumpCreation,snapshotCreation"; + let query = deserr_query_params::(params).unwrap(); + snapshot!(format!("{:?}", query.types.unwrap()), @"[DocumentAdditionOrUpdate, DocumentDeletion, SettingsUpdate, IndexCreation, IndexDeletion, IndexUpdate, IndexSwap, TaskCancelation, TaskDeletion, DumpCreation, SnapshotCreation]"); } { - let json = r#" { "types": "settingsUpdate" } "#; - let query = serde_json::from_str::(json) - .unwrap() - .validate() - .unwrap(); - snapshot!(format!("{:?}", query.common.types.unwrap()), @"[SettingsUpdate]"); + let params = "types=settingsUpdate"; + let query = deserr_query_params::(params).unwrap(); + snapshot!(format!("{:?}", query.types.unwrap()), @"[SettingsUpdate]"); } { - let json = r#" { "types": "createIndex" } "#; - let err = serde_json::from_str::(json) - .unwrap() - .validate() - .unwrap_err(); - snapshot!(format!("{err}"), @"Task type `createIndex` is invalid. Available task types are `documentAdditionOrUpdate`, `documentDeletion`, `settingsUpdate`, `indexCreation`, `indexDeletion`, `indexUpdate`, `indexSwap`, `taskCancelation`, `taskDeletion`, `dumpCreation`, `snapshotCreation`"); + let params = "types=createIndex"; + let err = deserr_query_params::(params).unwrap_err(); + snapshot!(format!("{err}"), @"`createIndex` is not a type. Available types are `documentAdditionOrUpdate`, `documentDeletion`, `settingsUpdate`, `indexCreation`, `indexDeletion`, `indexUpdate`, `indexSwap`, `taskCancelation`, `taskDeletion`, `dumpCreation`, `snapshotCreation`. at `.types`."); } } #[test] fn deserialize_task_filter_index_uids() { { - let json = r#" { "indexUids": "toto,tata-78" }"#; - let query = serde_json::from_str::(json) - .unwrap() - .validate() - .unwrap(); - snapshot!(format!("{:?}", query.common.index_uids.unwrap()), @r###"["toto", "tata-78"]"###); + let params = "indexUids=toto,tata-78"; + let query = deserr_query_params::(params).unwrap(); + snapshot!(format!("{:?}", query.index_uids.unwrap()), @r###"[IndexUid("toto"), IndexUid("tata-78")]"###); } { - let json = r#" { "indexUids": "index_a" } "#; - let query = serde_json::from_str::(json) - .unwrap() - .validate() - .unwrap(); - snapshot!(format!("{:?}", query.common.index_uids.unwrap()), @r###"["index_a"]"###); + let params = "indexUids=index_a"; + let query = deserr_query_params::(params).unwrap(); + snapshot!(format!("{:?}", query.index_uids.unwrap()), @r###"[IndexUid("index_a")]"###); } { - let json = r#" { "indexUids": "1,hé" } "#; - let err = serde_json::from_str::(json) - .unwrap() - .validate() - .unwrap_err(); - snapshot!(format!("{err}"), @"hé is not a valid index uid. Index uid can be an integer or a string containing only alphanumeric characters, hyphens (-) and underscores (_)."); + let params = "indexUids=1,hé"; + let err = deserr_query_params::(params).unwrap_err(); + snapshot!(format!("{err}"), @"`hé` is not a valid index uid. Index uid can be an integer or a string containing only alphanumeric characters, hyphens (-) and underscores (_). at `.indexUids`."); } { - let json = r#" { "indexUids": "hé" } "#; - let err = serde_json::from_str::(json) - .unwrap() - .validate() - .unwrap_err(); - snapshot!(format!("{err}"), @"hé is not a valid index uid. Index uid can be an integer or a string containing only alphanumeric characters, hyphens (-) and underscores (_)."); + let params = "indexUids=hé"; + let err = deserr_query_params::(params).unwrap_err(); + snapshot!(format!("{err}"), @"`hé` is not a valid index uid. Index uid can be an integer or a string containing only alphanumeric characters, hyphens (-) and underscores (_). at `.indexUids`."); } } #[test] fn deserialize_task_filter_general() { { - let json = r#" { "from": 12, "limit": 15, "indexUids": "toto,tata-78", "statuses": "succeeded,enqueued", "afterEnqueuedAt": "2012-04-23", "uids": "1,2,3" }"#; - let query = - serde_json::from_str::(json).unwrap().validate().unwrap(); - snapshot!(format!("{:?}", query), @r###"TasksFilterQuery { limit: 15, from: Some(12), common: TaskCommonQuery { types: None, uids: Some([1, 2, 3]), canceled_by: None, statuses: Some([Succeeded, Enqueued]), index_uids: Some(["toto", "tata-78"]) }, dates: TaskDateQuery { after_enqueued_at: Some(2012-04-24 0:00:00.0 +00:00:00), before_enqueued_at: None, after_started_at: None, before_started_at: None, after_finished_at: None, before_finished_at: None } }"###); + let params = "from=12&limit=15&indexUids=toto,tata-78&statuses=succeeded,enqueued&afterEnqueuedAt=2012-04-23&uids=1,2,3"; + let query = deserr_query_params::(params).unwrap(); + snapshot!(format!("{:?}", query), @r###"TasksFilterQuery { limit: 15, from: Some(12), uids: Some([1, 2, 3]), canceled_by: None, types: None, statuses: Some([Succeeded, Enqueued]), index_uids: Some([IndexUid("toto"), IndexUid("tata-78")]), after_enqueued_at: Some(2012-04-24 0:00:00.0 +00:00:00), before_enqueued_at: None, after_started_at: None, before_started_at: None, after_finished_at: None, before_finished_at: None }"###); } { // Stars should translate to `None` in the query // Verify value of the default limit - let json = r#" { "indexUids": "*", "statuses": "succeeded,*", "afterEnqueuedAt": "2012-04-23", "uids": "1,2,3" }"#; - let query = - serde_json::from_str::(json).unwrap().validate().unwrap(); - snapshot!(format!("{:?}", query), @"TasksFilterQuery { limit: 20, from: None, common: TaskCommonQuery { types: None, uids: Some([1, 2, 3]), canceled_by: None, statuses: None, index_uids: None }, dates: TaskDateQuery { after_enqueued_at: Some(2012-04-24 0:00:00.0 +00:00:00), before_enqueued_at: None, after_started_at: None, before_started_at: None, after_finished_at: None, before_finished_at: None } }"); + let params = "indexUids=*&statuses=succeeded,*&afterEnqueuedAt=2012-04-23&uids=1,2,3"; + let query = deserr_query_params::(params).unwrap(); + snapshot!(format!("{:?}", query), @"TasksFilterQuery { limit: 20, from: None, uids: Some([1, 2, 3]), canceled_by: None, types: None, statuses: None, index_uids: None, after_enqueued_at: Some(2012-04-24 0:00:00.0 +00:00:00), before_enqueued_at: None, after_started_at: None, before_started_at: None, after_finished_at: None, before_finished_at: None }"); } { // Stars should also translate to `None` in task deletion/cancelation queries - let json = r#" { "indexUids": "*", "statuses": "succeeded,*", "afterEnqueuedAt": "2012-04-23", "uids": "1,2,3" }"#; - let query = serde_json::from_str::(json) - .unwrap() - .validate() - .unwrap(); - snapshot!(format!("{:?}", query), @"TaskDeletionOrCancelationQuery { common: TaskCommonQuery { types: None, uids: Some([1, 2, 3]), canceled_by: None, statuses: None, index_uids: None }, dates: TaskDateQuery { after_enqueued_at: Some(2012-04-24 0:00:00.0 +00:00:00), before_enqueued_at: None, after_started_at: None, before_started_at: None, after_finished_at: None, before_finished_at: None } }"); + let params = "indexUids=*&statuses=succeeded,*&afterEnqueuedAt=2012-04-23&uids=1,2,3"; + let query = deserr_query_params::(params).unwrap(); + snapshot!(format!("{:?}", query), @"TaskDeletionOrCancelationQuery { uids: Some([1, 2, 3]), canceled_by: None, types: None, statuses: None, index_uids: None, after_enqueued_at: Some(2012-04-24 0:00:00.0 +00:00:00), before_enqueued_at: None, after_started_at: None, before_started_at: None, after_finished_at: None, before_finished_at: None }"); } { // Stars in uids not allowed - let json = r#" { "uids": "*" }"#; - let err = - serde_json::from_str::(json).unwrap().validate().unwrap_err(); - snapshot!(format!("{err}"), @"Task uid `*` is invalid. It should only contain numeric characters."); + let params = "uids=*"; + let err = deserr_query_params::(params).unwrap_err(); + snapshot!(format!("{err}"), @"invalid digit found in string at `.uids`."); } { // From not allowed in task deletion/cancelation queries - let json = r#" { "from": 12 }"#; - let err = serde_json::from_str::(json).unwrap_err(); - snapshot!(format!("{err}"), @"unknown field `from` at line 1 column 15"); + let params = "from=12"; + let err = deserr_query_params::(params).unwrap_err(); + snapshot!(format!("{err}"), @"Json deserialize error: unknown field `from`, expected one of `uids`, `canceledBy`, `types`, `statuses`, `indexUids`, `afterEnqueuedAt`, `beforeEnqueuedAt`, `afterStartedAt`, `beforeStartedAt`, `afterFinishedAt`, `beforeFinishedAt` at ``."); } { // Limit not allowed in task deletion/cancelation queries - let json = r#" { "limit": 12 }"#; - let err = serde_json::from_str::(json).unwrap_err(); - snapshot!(format!("{err}"), @"unknown field `limit` at line 1 column 16"); + let params = "limit=12"; + let err = deserr_query_params::(params).unwrap_err(); + snapshot!(format!("{err}"), @"Json deserialize error: unknown field `limit`, expected one of `uids`, `canceledBy`, `types`, `statuses`, `indexUids`, `afterEnqueuedAt`, `beforeEnqueuedAt`, `afterStartedAt`, `beforeStartedAt`, `afterFinishedAt`, `beforeFinishedAt` at ``."); } } } diff --git a/meilisearch/tests/tasks/errors.rs b/meilisearch/tests/tasks/errors.rs index 667532f17..305ab8b9c 100644 --- a/meilisearch/tests/tasks/errors.rs +++ b/meilisearch/tests/tasks/errors.rs @@ -11,7 +11,7 @@ async fn task_bad_uids() { snapshot!(code, @"400 Bad Request"); snapshot!(json_string!(response), @r###" { - "message": "Task uid `doggo` is invalid. It should only contain numeric characters.", + "message": "invalid digit found in string at `.uids`.", "code": "invalid_task_uids", "type": "invalid_request", "link": "https://docs.meilisearch.com/errors#invalid-task-uids" @@ -22,7 +22,7 @@ async fn task_bad_uids() { snapshot!(code, @"400 Bad Request"); snapshot!(json_string!(response), @r###" { - "message": "Task uid `doggo` is invalid. It should only contain numeric characters.", + "message": "invalid digit found in string at `.uids`.", "code": "invalid_task_uids", "type": "invalid_request", "link": "https://docs.meilisearch.com/errors#invalid-task-uids" @@ -33,7 +33,7 @@ async fn task_bad_uids() { snapshot!(code, @"400 Bad Request"); snapshot!(json_string!(response), @r###" { - "message": "Task uid `doggo` is invalid. It should only contain numeric characters.", + "message": "invalid digit found in string at `.uids`.", "code": "invalid_task_uids", "type": "invalid_request", "link": "https://docs.meilisearch.com/errors#invalid-task-uids" @@ -49,7 +49,7 @@ async fn task_bad_canceled_by() { snapshot!(code, @"400 Bad Request"); snapshot!(json_string!(response), @r###" { - "message": "Task canceledBy `doggo` is invalid. It should only contains numeric characters separated by `,` character.", + "message": "invalid digit found in string at `.canceledBy`.", "code": "invalid_task_canceled_by", "type": "invalid_request", "link": "https://docs.meilisearch.com/errors#invalid-task-canceled-by" @@ -60,7 +60,7 @@ async fn task_bad_canceled_by() { snapshot!(code, @"400 Bad Request"); snapshot!(json_string!(response), @r###" { - "message": "Task canceledBy `doggo` is invalid. It should only contains numeric characters separated by `,` character.", + "message": "invalid digit found in string at `.canceledBy`.", "code": "invalid_task_canceled_by", "type": "invalid_request", "link": "https://docs.meilisearch.com/errors#invalid-task-canceled-by" @@ -71,7 +71,7 @@ async fn task_bad_canceled_by() { snapshot!(code, @"400 Bad Request"); snapshot!(json_string!(response), @r###" { - "message": "Task canceledBy `doggo` is invalid. It should only contains numeric characters separated by `,` character.", + "message": "invalid digit found in string at `.canceledBy`.", "code": "invalid_task_canceled_by", "type": "invalid_request", "link": "https://docs.meilisearch.com/errors#invalid-task-canceled-by" @@ -87,7 +87,7 @@ async fn task_bad_types() { snapshot!(code, @"400 Bad Request"); snapshot!(json_string!(response), @r###" { - "message": "Task type `doggo` is invalid. Available task types are `documentAdditionOrUpdate`, `documentDeletion`, `settingsUpdate`, `indexCreation`, `indexDeletion`, `indexUpdate`, `indexSwap`, `taskCancelation`, `taskDeletion`, `dumpCreation`, `snapshotCreation`", + "message": "`doggo` is not a type. Available types are `documentAdditionOrUpdate`, `documentDeletion`, `settingsUpdate`, `indexCreation`, `indexDeletion`, `indexUpdate`, `indexSwap`, `taskCancelation`, `taskDeletion`, `dumpCreation`, `snapshotCreation`. at `.types`.", "code": "invalid_task_types", "type": "invalid_request", "link": "https://docs.meilisearch.com/errors#invalid-task-types" @@ -98,7 +98,7 @@ async fn task_bad_types() { snapshot!(code, @"400 Bad Request"); snapshot!(json_string!(response), @r###" { - "message": "Task type `doggo` is invalid. Available task types are `documentAdditionOrUpdate`, `documentDeletion`, `settingsUpdate`, `indexCreation`, `indexDeletion`, `indexUpdate`, `indexSwap`, `taskCancelation`, `taskDeletion`, `dumpCreation`, `snapshotCreation`", + "message": "`doggo` is not a type. Available types are `documentAdditionOrUpdate`, `documentDeletion`, `settingsUpdate`, `indexCreation`, `indexDeletion`, `indexUpdate`, `indexSwap`, `taskCancelation`, `taskDeletion`, `dumpCreation`, `snapshotCreation`. at `.types`.", "code": "invalid_task_types", "type": "invalid_request", "link": "https://docs.meilisearch.com/errors#invalid-task-types" @@ -109,7 +109,7 @@ async fn task_bad_types() { snapshot!(code, @"400 Bad Request"); snapshot!(json_string!(response), @r###" { - "message": "Task type `doggo` is invalid. Available task types are `documentAdditionOrUpdate`, `documentDeletion`, `settingsUpdate`, `indexCreation`, `indexDeletion`, `indexUpdate`, `indexSwap`, `taskCancelation`, `taskDeletion`, `dumpCreation`, `snapshotCreation`", + "message": "`doggo` is not a type. Available types are `documentAdditionOrUpdate`, `documentDeletion`, `settingsUpdate`, `indexCreation`, `indexDeletion`, `indexUpdate`, `indexSwap`, `taskCancelation`, `taskDeletion`, `dumpCreation`, `snapshotCreation`. at `.types`.", "code": "invalid_task_types", "type": "invalid_request", "link": "https://docs.meilisearch.com/errors#invalid-task-types" @@ -125,7 +125,7 @@ async fn task_bad_statuses() { snapshot!(code, @"400 Bad Request"); snapshot!(json_string!(response), @r###" { - "message": "Task status `doggo` is invalid. Available task statuses are `enqueued`, `processing`, `succeeded`, `failed`, `canceled`.", + "message": "`doggo` is not a status. Available status are `enqueued`, `processing`, `succeeded`, `failed`, `canceled`. at `.statuses`.", "code": "invalid_task_statuses", "type": "invalid_request", "link": "https://docs.meilisearch.com/errors#invalid-task-statuses" @@ -136,7 +136,7 @@ async fn task_bad_statuses() { snapshot!(code, @"400 Bad Request"); snapshot!(json_string!(response), @r###" { - "message": "Task status `doggo` is invalid. Available task statuses are `enqueued`, `processing`, `succeeded`, `failed`, `canceled`.", + "message": "`doggo` is not a status. Available status are `enqueued`, `processing`, `succeeded`, `failed`, `canceled`. at `.statuses`.", "code": "invalid_task_statuses", "type": "invalid_request", "link": "https://docs.meilisearch.com/errors#invalid-task-statuses" @@ -147,7 +147,7 @@ async fn task_bad_statuses() { snapshot!(code, @"400 Bad Request"); snapshot!(json_string!(response), @r###" { - "message": "Task status `doggo` is invalid. Available task statuses are `enqueued`, `processing`, `succeeded`, `failed`, `canceled`.", + "message": "`doggo` is not a status. Available status are `enqueued`, `processing`, `succeeded`, `failed`, `canceled`. at `.statuses`.", "code": "invalid_task_statuses", "type": "invalid_request", "link": "https://docs.meilisearch.com/errors#invalid-task-statuses" @@ -163,7 +163,7 @@ async fn task_bad_index_uids() { snapshot!(code, @"400 Bad Request"); snapshot!(json_string!(response), @r###" { - "message": "the good doggo is not a valid index uid. Index uid can be an integer or a string containing only alphanumeric characters, hyphens (-) and underscores (_).", + "message": "`the good doggo` is not a valid index uid. Index uid can be an integer or a string containing only alphanumeric characters, hyphens (-) and underscores (_). at `.indexUids`.", "code": "invalid_index_uid", "type": "invalid_request", "link": "https://docs.meilisearch.com/errors#invalid-index-uid" @@ -174,7 +174,7 @@ async fn task_bad_index_uids() { snapshot!(code, @"400 Bad Request"); snapshot!(json_string!(response), @r###" { - "message": "the good doggo is not a valid index uid. Index uid can be an integer or a string containing only alphanumeric characters, hyphens (-) and underscores (_).", + "message": "`the good doggo` is not a valid index uid. Index uid can be an integer or a string containing only alphanumeric characters, hyphens (-) and underscores (_). at `.indexUids`.", "code": "invalid_index_uid", "type": "invalid_request", "link": "https://docs.meilisearch.com/errors#invalid-index-uid" @@ -185,7 +185,7 @@ async fn task_bad_index_uids() { snapshot!(code, @"400 Bad Request"); snapshot!(json_string!(response), @r###" { - "message": "the good doggo is not a valid index uid. Index uid can be an integer or a string containing only alphanumeric characters, hyphens (-) and underscores (_).", + "message": "`the good doggo` is not a valid index uid. Index uid can be an integer or a string containing only alphanumeric characters, hyphens (-) and underscores (_). at `.indexUids`.", "code": "invalid_index_uid", "type": "invalid_request", "link": "https://docs.meilisearch.com/errors#invalid-index-uid" @@ -201,10 +201,10 @@ async fn task_bad_limit() { snapshot!(code, @"400 Bad Request"); snapshot!(json_string!(response), @r###" { - "message": "Query deserialize error: invalid digit found in string", - "code": "bad_request", + "message": "invalid digit found in string at `.limit`.", + "code": "invalid_task_limit", "type": "invalid_request", - "link": "https://docs.meilisearch.com/errors#bad-request" + "link": "https://docs.meilisearch.com/errors#invalid-task-limit" } "###); @@ -212,7 +212,7 @@ async fn task_bad_limit() { snapshot!(code, @"400 Bad Request"); snapshot!(json_string!(response), @r###" { - "message": "Query deserialize error: unknown field `limit`", + "message": "Json deserialize error: unknown field `limit`, expected one of `uids`, `canceledBy`, `types`, `statuses`, `indexUids`, `afterEnqueuedAt`, `beforeEnqueuedAt`, `afterStartedAt`, `beforeStartedAt`, `afterFinishedAt`, `beforeFinishedAt` at ``.", "code": "bad_request", "type": "invalid_request", "link": "https://docs.meilisearch.com/errors#bad-request" @@ -223,7 +223,7 @@ async fn task_bad_limit() { snapshot!(code, @"400 Bad Request"); snapshot!(json_string!(response), @r###" { - "message": "Query deserialize error: unknown field `limit`", + "message": "Json deserialize error: unknown field `limit`, expected one of `uids`, `canceledBy`, `types`, `statuses`, `indexUids`, `afterEnqueuedAt`, `beforeEnqueuedAt`, `afterStartedAt`, `beforeStartedAt`, `afterFinishedAt`, `beforeFinishedAt` at ``.", "code": "bad_request", "type": "invalid_request", "link": "https://docs.meilisearch.com/errors#bad-request" @@ -239,10 +239,10 @@ async fn task_bad_from() { snapshot!(code, @"400 Bad Request"); snapshot!(json_string!(response), @r###" { - "message": "Query deserialize error: invalid digit found in string", - "code": "bad_request", + "message": "invalid digit found in string at `.from`.", + "code": "invalid_task_from", "type": "invalid_request", - "link": "https://docs.meilisearch.com/errors#bad-request" + "link": "https://docs.meilisearch.com/errors#invalid-task-from" } "###); @@ -250,7 +250,7 @@ async fn task_bad_from() { snapshot!(code, @"400 Bad Request"); snapshot!(json_string!(response), @r###" { - "message": "Query deserialize error: unknown field `from`", + "message": "Json deserialize error: unknown field `from`, expected one of `uids`, `canceledBy`, `types`, `statuses`, `indexUids`, `afterEnqueuedAt`, `beforeEnqueuedAt`, `afterStartedAt`, `beforeStartedAt`, `afterFinishedAt`, `beforeFinishedAt` at ``.", "code": "bad_request", "type": "invalid_request", "link": "https://docs.meilisearch.com/errors#bad-request" @@ -261,7 +261,7 @@ async fn task_bad_from() { snapshot!(code, @"400 Bad Request"); snapshot!(json_string!(response), @r###" { - "message": "Query deserialize error: unknown field `from`", + "message": "Json deserialize error: unknown field `from`, expected one of `uids`, `canceledBy`, `types`, `statuses`, `indexUids`, `afterEnqueuedAt`, `beforeEnqueuedAt`, `afterStartedAt`, `beforeStartedAt`, `afterFinishedAt`, `beforeFinishedAt` at ``.", "code": "bad_request", "type": "invalid_request", "link": "https://docs.meilisearch.com/errors#bad-request" @@ -277,7 +277,7 @@ async fn task_bad_after_enqueued_at() { snapshot!(code, @"400 Bad Request"); snapshot!(json_string!(response), @r###" { - "message": "Task `afterEnqueuedAt` `doggo` is invalid. It should follow the YYYY-MM-DD or RFC 3339 date-time format.", + "message": "`doggo` is an invalid date-time. It should follow the YYYY-MM-DD or RFC 3339 date-time format. at `.afterEnqueuedAt`.", "code": "invalid_task_after_enqueued_at", "type": "invalid_request", "link": "https://docs.meilisearch.com/errors#invalid-task-after-enqueued-at" @@ -288,7 +288,7 @@ async fn task_bad_after_enqueued_at() { snapshot!(code, @"400 Bad Request"); snapshot!(json_string!(response), @r###" { - "message": "Task `afterEnqueuedAt` `doggo` is invalid. It should follow the YYYY-MM-DD or RFC 3339 date-time format.", + "message": "`doggo` is an invalid date-time. It should follow the YYYY-MM-DD or RFC 3339 date-time format. at `.afterEnqueuedAt`.", "code": "invalid_task_after_enqueued_at", "type": "invalid_request", "link": "https://docs.meilisearch.com/errors#invalid-task-after-enqueued-at" @@ -299,7 +299,7 @@ async fn task_bad_after_enqueued_at() { snapshot!(code, @"400 Bad Request"); snapshot!(json_string!(response), @r###" { - "message": "Task `afterEnqueuedAt` `doggo` is invalid. It should follow the YYYY-MM-DD or RFC 3339 date-time format.", + "message": "`doggo` is an invalid date-time. It should follow the YYYY-MM-DD or RFC 3339 date-time format. at `.afterEnqueuedAt`.", "code": "invalid_task_after_enqueued_at", "type": "invalid_request", "link": "https://docs.meilisearch.com/errors#invalid-task-after-enqueued-at" @@ -315,7 +315,7 @@ async fn task_bad_before_enqueued_at() { snapshot!(code, @"400 Bad Request"); snapshot!(json_string!(response), @r###" { - "message": "Task `beforeEnqueuedAt` `doggo` is invalid. It should follow the YYYY-MM-DD or RFC 3339 date-time format.", + "message": "`doggo` is an invalid date-time. It should follow the YYYY-MM-DD or RFC 3339 date-time format. at `.beforeEnqueuedAt`.", "code": "invalid_task_before_enqueued_at", "type": "invalid_request", "link": "https://docs.meilisearch.com/errors#invalid-task-before-enqueued-at" @@ -326,7 +326,7 @@ async fn task_bad_before_enqueued_at() { snapshot!(code, @"400 Bad Request"); snapshot!(json_string!(response), @r###" { - "message": "Task `beforeEnqueuedAt` `doggo` is invalid. It should follow the YYYY-MM-DD or RFC 3339 date-time format.", + "message": "`doggo` is an invalid date-time. It should follow the YYYY-MM-DD or RFC 3339 date-time format. at `.beforeEnqueuedAt`.", "code": "invalid_task_before_enqueued_at", "type": "invalid_request", "link": "https://docs.meilisearch.com/errors#invalid-task-before-enqueued-at" @@ -337,7 +337,7 @@ async fn task_bad_before_enqueued_at() { snapshot!(code, @"400 Bad Request"); snapshot!(json_string!(response), @r###" { - "message": "Task `beforeEnqueuedAt` `doggo` is invalid. It should follow the YYYY-MM-DD or RFC 3339 date-time format.", + "message": "`doggo` is an invalid date-time. It should follow the YYYY-MM-DD or RFC 3339 date-time format. at `.beforeEnqueuedAt`.", "code": "invalid_task_before_enqueued_at", "type": "invalid_request", "link": "https://docs.meilisearch.com/errors#invalid-task-before-enqueued-at" @@ -353,7 +353,7 @@ async fn task_bad_after_started_at() { snapshot!(code, @"400 Bad Request"); snapshot!(json_string!(response), @r###" { - "message": "Task `afterStartedAt` `doggo` is invalid. It should follow the YYYY-MM-DD or RFC 3339 date-time format.", + "message": "`doggo` is an invalid date-time. It should follow the YYYY-MM-DD or RFC 3339 date-time format. at `.afterStartedAt`.", "code": "invalid_task_after_started_at", "type": "invalid_request", "link": "https://docs.meilisearch.com/errors#invalid-task-after-started-at" @@ -364,7 +364,7 @@ async fn task_bad_after_started_at() { snapshot!(code, @"400 Bad Request"); snapshot!(json_string!(response), @r###" { - "message": "Task `afterStartedAt` `doggo` is invalid. It should follow the YYYY-MM-DD or RFC 3339 date-time format.", + "message": "`doggo` is an invalid date-time. It should follow the YYYY-MM-DD or RFC 3339 date-time format. at `.afterStartedAt`.", "code": "invalid_task_after_started_at", "type": "invalid_request", "link": "https://docs.meilisearch.com/errors#invalid-task-after-started-at" @@ -375,7 +375,7 @@ async fn task_bad_after_started_at() { snapshot!(code, @"400 Bad Request"); snapshot!(json_string!(response), @r###" { - "message": "Task `afterStartedAt` `doggo` is invalid. It should follow the YYYY-MM-DD or RFC 3339 date-time format.", + "message": "`doggo` is an invalid date-time. It should follow the YYYY-MM-DD or RFC 3339 date-time format. at `.afterStartedAt`.", "code": "invalid_task_after_started_at", "type": "invalid_request", "link": "https://docs.meilisearch.com/errors#invalid-task-after-started-at" @@ -391,7 +391,7 @@ async fn task_bad_before_started_at() { snapshot!(code, @"400 Bad Request"); snapshot!(json_string!(response), @r###" { - "message": "Task `beforeStartedAt` `doggo` is invalid. It should follow the YYYY-MM-DD or RFC 3339 date-time format.", + "message": "`doggo` is an invalid date-time. It should follow the YYYY-MM-DD or RFC 3339 date-time format. at `.beforeStartedAt`.", "code": "invalid_task_before_started_at", "type": "invalid_request", "link": "https://docs.meilisearch.com/errors#invalid-task-before-started-at" @@ -402,7 +402,7 @@ async fn task_bad_before_started_at() { snapshot!(code, @"400 Bad Request"); snapshot!(json_string!(response), @r###" { - "message": "Task `beforeStartedAt` `doggo` is invalid. It should follow the YYYY-MM-DD or RFC 3339 date-time format.", + "message": "`doggo` is an invalid date-time. It should follow the YYYY-MM-DD or RFC 3339 date-time format. at `.beforeStartedAt`.", "code": "invalid_task_before_started_at", "type": "invalid_request", "link": "https://docs.meilisearch.com/errors#invalid-task-before-started-at" @@ -413,7 +413,7 @@ async fn task_bad_before_started_at() { snapshot!(code, @"400 Bad Request"); snapshot!(json_string!(response), @r###" { - "message": "Task `beforeStartedAt` `doggo` is invalid. It should follow the YYYY-MM-DD or RFC 3339 date-time format.", + "message": "`doggo` is an invalid date-time. It should follow the YYYY-MM-DD or RFC 3339 date-time format. at `.beforeStartedAt`.", "code": "invalid_task_before_started_at", "type": "invalid_request", "link": "https://docs.meilisearch.com/errors#invalid-task-before-started-at" @@ -429,7 +429,7 @@ async fn task_bad_after_finished_at() { snapshot!(code, @"400 Bad Request"); snapshot!(json_string!(response), @r###" { - "message": "Task `afterFinishedAt` `doggo` is invalid. It should follow the YYYY-MM-DD or RFC 3339 date-time format.", + "message": "`doggo` is an invalid date-time. It should follow the YYYY-MM-DD or RFC 3339 date-time format. at `.afterFinishedAt`.", "code": "invalid_task_after_finished_at", "type": "invalid_request", "link": "https://docs.meilisearch.com/errors#invalid-task-after-finished-at" @@ -440,7 +440,7 @@ async fn task_bad_after_finished_at() { snapshot!(code, @"400 Bad Request"); snapshot!(json_string!(response), @r###" { - "message": "Task `afterFinishedAt` `doggo` is invalid. It should follow the YYYY-MM-DD or RFC 3339 date-time format.", + "message": "`doggo` is an invalid date-time. It should follow the YYYY-MM-DD or RFC 3339 date-time format. at `.afterFinishedAt`.", "code": "invalid_task_after_finished_at", "type": "invalid_request", "link": "https://docs.meilisearch.com/errors#invalid-task-after-finished-at" @@ -451,7 +451,7 @@ async fn task_bad_after_finished_at() { snapshot!(code, @"400 Bad Request"); snapshot!(json_string!(response), @r###" { - "message": "Task `afterFinishedAt` `doggo` is invalid. It should follow the YYYY-MM-DD or RFC 3339 date-time format.", + "message": "`doggo` is an invalid date-time. It should follow the YYYY-MM-DD or RFC 3339 date-time format. at `.afterFinishedAt`.", "code": "invalid_task_after_finished_at", "type": "invalid_request", "link": "https://docs.meilisearch.com/errors#invalid-task-after-finished-at" @@ -467,7 +467,7 @@ async fn task_bad_before_finished_at() { snapshot!(code, @"400 Bad Request"); snapshot!(json_string!(response), @r###" { - "message": "Task `beforeFinishedAt` `doggo` is invalid. It should follow the YYYY-MM-DD or RFC 3339 date-time format.", + "message": "`doggo` is an invalid date-time. It should follow the YYYY-MM-DD or RFC 3339 date-time format. at `.beforeFinishedAt`.", "code": "invalid_task_before_finished_at", "type": "invalid_request", "link": "https://docs.meilisearch.com/errors#invalid-task-before-finished-at" @@ -478,7 +478,7 @@ async fn task_bad_before_finished_at() { snapshot!(code, @"400 Bad Request"); snapshot!(json_string!(response), @r###" { - "message": "Task `beforeFinishedAt` `doggo` is invalid. It should follow the YYYY-MM-DD or RFC 3339 date-time format.", + "message": "`doggo` is an invalid date-time. It should follow the YYYY-MM-DD or RFC 3339 date-time format. at `.beforeFinishedAt`.", "code": "invalid_task_before_finished_at", "type": "invalid_request", "link": "https://docs.meilisearch.com/errors#invalid-task-before-finished-at" @@ -489,7 +489,7 @@ async fn task_bad_before_finished_at() { snapshot!(code, @"400 Bad Request"); snapshot!(json_string!(response), @r###" { - "message": "Task `beforeFinishedAt` `doggo` is invalid. It should follow the YYYY-MM-DD or RFC 3339 date-time format.", + "message": "`doggo` is an invalid date-time. It should follow the YYYY-MM-DD or RFC 3339 date-time format. at `.beforeFinishedAt`.", "code": "invalid_task_before_finished_at", "type": "invalid_request", "link": "https://docs.meilisearch.com/errors#invalid-task-before-finished-at" diff --git a/meilisearch/tests/tasks/mod.rs b/meilisearch/tests/tasks/mod.rs index 2e18d6237..46775e05f 100644 --- a/meilisearch/tests/tasks/mod.rs +++ b/meilisearch/tests/tasks/mod.rs @@ -183,7 +183,7 @@ async fn get_task_filter_error() { assert_eq!(code, 400, "{}", response); meili_snap::snapshot!(meili_snap::json_string!(response), @r###" { - "message": "Query deserialize error: unknown field `lol`", + "message": "Json deserialize error: unknown field `lol`, expected one of `limit`, `from`, `uids`, `canceledBy`, `types`, `statuses`, `indexUids`, `afterEnqueuedAt`, `beforeEnqueuedAt`, `afterStartedAt`, `beforeStartedAt`, `afterFinishedAt`, `beforeFinishedAt` at ``.", "code": "bad_request", "type": "invalid_request", "link": "https://docs.meilisearch.com/errors#bad-request" @@ -194,7 +194,7 @@ async fn get_task_filter_error() { assert_eq!(code, 400, "{}", response); meili_snap::snapshot!(meili_snap::json_string!(response), @r###" { - "message": "Task uid `pied` is invalid. It should only contain numeric characters.", + "message": "invalid digit found in string at `.uids`.", "code": "invalid_task_uids", "type": "invalid_request", "link": "https://docs.meilisearch.com/errors#invalid-task-uids" @@ -205,10 +205,10 @@ async fn get_task_filter_error() { assert_eq!(code, 400, "{}", response); meili_snap::snapshot!(meili_snap::json_string!(response), @r###" { - "message": "Query deserialize error: invalid digit found in string", - "code": "bad_request", + "message": "invalid digit found in string at `.from`.", + "code": "invalid_task_from", "type": "invalid_request", - "link": "https://docs.meilisearch.com/errors#bad-request" + "link": "https://docs.meilisearch.com/errors#invalid-task-from" } "###); @@ -216,7 +216,7 @@ async fn get_task_filter_error() { assert_eq!(code, 400, "{}", response); meili_snap::snapshot!(meili_snap::json_string!(response), @r###" { - "message": "Task `beforeStartedAt` `pied` is invalid. It should follow the YYYY-MM-DD or RFC 3339 date-time format.", + "message": "`pied` is an invalid date-time. It should follow the YYYY-MM-DD or RFC 3339 date-time format. at `.beforeStartedAt`.", "code": "invalid_task_before_started_at", "type": "invalid_request", "link": "https://docs.meilisearch.com/errors#invalid-task-before-started-at" @@ -243,7 +243,7 @@ async fn delete_task_filter_error() { assert_eq!(code, 400, "{}", response); meili_snap::snapshot!(meili_snap::json_string!(response), @r###" { - "message": "Query deserialize error: unknown field `lol`", + "message": "Json deserialize error: unknown field `lol`, expected one of `uids`, `canceledBy`, `types`, `statuses`, `indexUids`, `afterEnqueuedAt`, `beforeEnqueuedAt`, `afterStartedAt`, `beforeStartedAt`, `afterFinishedAt`, `beforeFinishedAt` at ``.", "code": "bad_request", "type": "invalid_request", "link": "https://docs.meilisearch.com/errors#bad-request" @@ -254,7 +254,7 @@ async fn delete_task_filter_error() { assert_eq!(code, 400, "{}", response); meili_snap::snapshot!(meili_snap::json_string!(response), @r###" { - "message": "Task uid `pied` is invalid. It should only contain numeric characters.", + "message": "invalid digit found in string at `.uids`.", "code": "invalid_task_uids", "type": "invalid_request", "link": "https://docs.meilisearch.com/errors#invalid-task-uids" @@ -281,7 +281,7 @@ async fn cancel_task_filter_error() { assert_eq!(code, 400, "{}", response); meili_snap::snapshot!(meili_snap::json_string!(response), @r###" { - "message": "Query deserialize error: unknown field `lol`", + "message": "Json deserialize error: unknown field `lol`, expected one of `uids`, `canceledBy`, `types`, `statuses`, `indexUids`, `afterEnqueuedAt`, `beforeEnqueuedAt`, `afterStartedAt`, `beforeStartedAt`, `afterFinishedAt`, `beforeFinishedAt` at ``.", "code": "bad_request", "type": "invalid_request", "link": "https://docs.meilisearch.com/errors#bad-request" @@ -292,7 +292,7 @@ async fn cancel_task_filter_error() { assert_eq!(code, 400, "{}", response); meili_snap::snapshot!(meili_snap::json_string!(response), @r###" { - "message": "Task uid `pied` is invalid. It should only contain numeric characters.", + "message": "invalid digit found in string at `.uids`.", "code": "invalid_task_uids", "type": "invalid_request", "link": "https://docs.meilisearch.com/errors#invalid-task-uids" From 705fcaa3b8ebcfeb525db285adf71ff6d8f42523 Mon Sep 17 00:00:00 2001 From: Tamo Date: Thu, 12 Jan 2023 14:09:15 +0100 Subject: [PATCH 3/5] reformat the imports --- meilisearch/src/analytics/mock_analytics.rs | 2 +- meilisearch/src/routes/tasks.rs | 10 ++++------ 2 files changed, 5 insertions(+), 7 deletions(-) diff --git a/meilisearch/src/analytics/mock_analytics.rs b/meilisearch/src/analytics/mock_analytics.rs index 504c3baad..092e35424 100644 --- a/meilisearch/src/analytics/mock_analytics.rs +++ b/meilisearch/src/analytics/mock_analytics.rs @@ -7,8 +7,8 @@ use serde_json::Value; use super::{find_user_id, Analytics, DocumentDeletionKind}; use crate::routes::indexes::documents::UpdateDocumentsQuery; -use crate::Opt; use crate::routes::tasks::TasksFilterQuery; +use crate::Opt; pub struct MockAnalytics { instance_uid: Option, diff --git a/meilisearch/src/routes/tasks.rs b/meilisearch/src/routes/tasks.rs index 68eb1963f..09723623f 100644 --- a/meilisearch/src/routes/tasks.rs +++ b/meilisearch/src/routes/tasks.rs @@ -5,8 +5,8 @@ use actix_web::web::Data; use actix_web::{web, HttpRequest, HttpResponse}; use deserr::DeserializeFromValue; use index_scheduler::{IndexScheduler, Query, TaskId}; -use meilisearch_types::error::{deserr_codes::*, TakeErrorMessage}; -use meilisearch_types::error::{DeserrError, ResponseError}; +use meilisearch_types::error::deserr_codes::*; +use meilisearch_types::error::{DeserrError, ResponseError, TakeErrorMessage}; use meilisearch_types::index_uid::IndexUid; use meilisearch_types::settings::{Settings, Unchecked}; use meilisearch_types::star_or::StarOr; @@ -586,10 +586,8 @@ mod tests { use meili_snap::snapshot; use meilisearch_types::error::DeserrError; - use crate::{ - extractors::query_parameters::QueryParameter, - routes::tasks::{TaskDeletionOrCancelationQuery, TasksFilterQuery}, - }; + use crate::extractors::query_parameters::QueryParameter; + use crate::routes::tasks::{TaskDeletionOrCancelationQuery, TasksFilterQuery}; fn deserr_query_params(j: &str) -> Result where From a524dfb713bf25b7dcda5876b51e7dcc9315dcc7 Mon Sep 17 00:00:00 2001 From: Tamo Date: Thu, 12 Jan 2023 14:49:50 +0100 Subject: [PATCH 4/5] fix the analytics --- .../src/analytics/segment_analytics.rs | 28 +++++++++---------- 1 file changed, 14 insertions(+), 14 deletions(-) diff --git a/meilisearch/src/analytics/segment_analytics.rs b/meilisearch/src/analytics/segment_analytics.rs index 8af927811..1b5a1d73f 100644 --- a/meilisearch/src/analytics/segment_analytics.rs +++ b/meilisearch/src/analytics/segment_analytics.rs @@ -27,7 +27,7 @@ use super::{config_user_id_path, DocumentDeletionKind, MEILISEARCH_CONFIG_PATH}; use crate::analytics::Analytics; use crate::option::{default_http_addr, IndexerOpts, MaxMemory, MaxThreads, ScheduleSnapshot}; use crate::routes::indexes::documents::UpdateDocumentsQuery; -use crate::routes::tasks::TasksFilterQueryRaw; +use crate::routes::tasks::TasksFilterQuery; use crate::routes::{create_all_stats, Stats}; use crate::search::{ SearchQuery, SearchResult, DEFAULT_CROP_LENGTH, DEFAULT_CROP_MARKER, @@ -195,7 +195,7 @@ impl super::Analytics for SegmentAnalytics { let _ = self.sender.try_send(AnalyticsMsg::AggregateUpdateDocuments(aggregate)); } - fn get_tasks(&self, query: &TasksFilterQueryRaw, request: &HttpRequest) { + fn get_tasks(&self, query: &TasksFilterQuery, request: &HttpRequest) { let aggregate = TasksAggregator::from_query(query, request); let _ = self.sender.try_send(AnalyticsMsg::AggregateTasks(aggregate)); } @@ -868,21 +868,21 @@ pub struct TasksAggregator { } impl TasksAggregator { - pub fn from_query(query: &TasksFilterQueryRaw, request: &HttpRequest) -> Self { + pub fn from_query(query: &TasksFilterQuery, request: &HttpRequest) -> Self { Self { timestamp: Some(OffsetDateTime::now_utc()), user_agents: extract_user_agents(request).into_iter().collect(), - filtered_by_uid: query.common.uids.is_some(), - filtered_by_index_uid: query.common.index_uids.is_some(), - filtered_by_type: query.common.types.is_some(), - filtered_by_status: query.common.statuses.is_some(), - filtered_by_canceled_by: query.common.canceled_by.is_some(), - filtered_by_before_enqueued_at: query.dates.before_enqueued_at.is_some(), - filtered_by_after_enqueued_at: query.dates.after_enqueued_at.is_some(), - filtered_by_before_started_at: query.dates.before_started_at.is_some(), - filtered_by_after_started_at: query.dates.after_started_at.is_some(), - filtered_by_before_finished_at: query.dates.before_finished_at.is_some(), - filtered_by_after_finished_at: query.dates.after_finished_at.is_some(), + filtered_by_uid: query.uids.is_some(), + filtered_by_index_uid: query.index_uids.is_some(), + filtered_by_type: query.types.is_some(), + filtered_by_status: query.statuses.is_some(), + filtered_by_canceled_by: query.canceled_by.is_some(), + filtered_by_before_enqueued_at: query.before_enqueued_at.is_some(), + filtered_by_after_enqueued_at: query.after_enqueued_at.is_some(), + filtered_by_before_started_at: query.before_started_at.is_some(), + filtered_by_after_started_at: query.after_started_at.is_some(), + filtered_by_before_finished_at: query.before_finished_at.is_some(), + filtered_by_after_finished_at: query.after_finished_at.is_some(), total_received: 1, } } From 79c7f65c304d89afb45adf052ec7bac4b3579a69 Mon Sep 17 00:00:00 2001 From: Tamo Date: Thu, 12 Jan 2023 15:39:28 +0100 Subject: [PATCH 5/5] make a test more reliable --- meilisearch/tests/search/mod.rs | 19 +++++++++++++------ 1 file changed, 13 insertions(+), 6 deletions(-) diff --git a/meilisearch/tests/search/mod.rs b/meilisearch/tests/search/mod.rs index 44a4702d0..60ffa6cee 100644 --- a/meilisearch/tests/search/mod.rs +++ b/meilisearch/tests/search/mod.rs @@ -200,11 +200,14 @@ async fn search_with_filter_string_notation() { let server = Server::new().await; let index = server.index("test"); - index.update_settings(json!({"filterableAttributes": ["title"]})).await; + let (_, code) = index.update_settings(json!({"filterableAttributes": ["title"]})).await; + meili_snap::snapshot!(code, @"202 Accepted"); let documents = DOCUMENTS.clone(); - index.add_documents(documents, None).await; - index.wait_task(1).await; + let (_, code) = index.add_documents(documents, None).await; + meili_snap::snapshot!(code, @"202 Accepted"); + let res = index.wait_task(1).await; + meili_snap::snapshot!(res["status"], @r###""succeeded""###); index .search( @@ -220,11 +223,15 @@ async fn search_with_filter_string_notation() { let index = server.index("nested"); - index.update_settings(json!({"filterableAttributes": ["cattos", "doggos.age"]})).await; + let (_, code) = + index.update_settings(json!({"filterableAttributes": ["cattos", "doggos.age"]})).await; + meili_snap::snapshot!(code, @"202 Accepted"); let documents = NESTED_DOCUMENTS.clone(); - index.add_documents(documents, None).await; - index.wait_task(3).await; + let (_, code) = index.add_documents(documents, None).await; + meili_snap::snapshot!(code, @"202 Accepted"); + let res = index.wait_task(3).await; + meili_snap::snapshot!(res["status"], @r###""succeeded""###); index .search(