3967: Bring back changes from `release-v1.3.0` into `main` r=ManyTheFish a=curquiza

Using a temp branch because of git conflict

Co-authored-by: Cong Chen <cong.chen@ocrlabs.com>
Co-authored-by: ManyTheFish <many@meilisearch.com>
Co-authored-by: Louis Dureuil <louis@meilisearch.com>
Co-authored-by: meili-bors[bot] <89034592+meili-bors[bot]@users.noreply.github.com>
Co-authored-by: Tamo <tamo@meilisearch.com>
Co-authored-by: Kerollmops <clement@meilisearch.com>
Co-authored-by: Clément Renault <clement@meilisearch.com>
This commit is contained in:
meili-bors[bot] 2023-08-01 16:22:09 +00:00 committed by GitHub
commit f391039a6f
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
163 changed files with 2239 additions and 1059 deletions

361
Cargo.lock generated
View File

@ -8,7 +8,7 @@ version = "0.5.1"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "617a8268e3537fe1d8c9ead925fca49ef6400927ee7bc26750e90ecee14ce4b8" checksum = "617a8268e3537fe1d8c9ead925fca49ef6400927ee7bc26750e90ecee14ce4b8"
dependencies = [ dependencies = [
"bitflags", "bitflags 1.3.2",
"bytes", "bytes",
"futures-core", "futures-core",
"futures-sink", "futures-sink",
@ -47,7 +47,7 @@ dependencies = [
"actix-utils", "actix-utils",
"ahash 0.8.3", "ahash 0.8.3",
"base64 0.21.2", "base64 0.21.2",
"bitflags", "bitflags 1.3.2",
"brotli", "brotli",
"bytes", "bytes",
"bytestring", "bytestring",
@ -405,7 +405,7 @@ checksum = "16e62a023e7c117e27523144c5d2459f4397fcc3cab0085af8e2224f643a0193"
dependencies = [ dependencies = [
"proc-macro2", "proc-macro2",
"quote", "quote",
"syn 2.0.18", "syn 2.0.28",
] ]
[[package]] [[package]]
@ -416,7 +416,7 @@ checksum = "b9ccdd8f2a161be9bd5c023df56f1b2a0bd1d83872ae53b71a84a12c9bf6e842"
dependencies = [ dependencies = [
"proc-macro2", "proc-macro2",
"quote", "quote",
"syn 2.0.18", "syn 2.0.28",
] ]
[[package]] [[package]]
@ -428,17 +428,6 @@ dependencies = [
"critical-section", "critical-section",
] ]
[[package]]
name = "atty"
version = "0.2.14"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d9b39be18770d11421cdb1b9947a45dd3f37e93092cbf377614828a319d5fee8"
dependencies = [
"hermit-abi 0.1.19",
"libc",
"winapi",
]
[[package]] [[package]]
name = "autocfg" name = "autocfg"
version = "1.1.0" version = "1.1.0"
@ -527,6 +516,12 @@ version = "1.3.2"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a" checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a"
[[package]]
name = "bitflags"
version = "2.3.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "630be753d4e58660abd17930c71b647fe46c27ea6b63cc59e1e3851406972e42"
[[package]] [[package]]
name = "block-buffer" name = "block-buffer"
version = "0.10.4" version = "0.10.4"
@ -608,7 +603,7 @@ checksum = "fdde5c9cd29ebd706ce1b35600920a33550e402fc998a2e53ad3b42c3c47a192"
dependencies = [ dependencies = [
"proc-macro2", "proc-macro2",
"quote", "quote",
"syn 2.0.18", "syn 2.0.28",
] ]
[[package]] [[package]]
@ -705,16 +700,15 @@ dependencies = [
[[package]] [[package]]
name = "charabia" name = "charabia"
version = "0.8.1" version = "0.8.2"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "bb49850f555eb71aa6fc6d4d79420e81f4d89fa56e0e9c0f6d19aace2f56c554" checksum = "57aa1b4a8dda126c03ebf2f7e31d16cfc8781c2fe80dedd1a33459efc3e07578"
dependencies = [ dependencies = [
"aho-corasick", "aho-corasick",
"cow-utils", "cow-utils",
"csv", "csv",
"deunicode", "deunicode",
"either", "either",
"finl_unicode",
"fst", "fst",
"irg-kvariants", "irg-kvariants",
"jieba-rs", "jieba-rs",
@ -767,18 +761,6 @@ dependencies = [
"inout", "inout",
] ]
[[package]]
name = "clap"
version = "3.2.25"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "4ea181bf566f71cb9a5d17a59e1871af638180a18fb0035c92ae62b705207123"
dependencies = [
"bitflags",
"clap_lex 0.2.4",
"indexmap",
"textwrap",
]
[[package]] [[package]]
name = "clap" name = "clap"
version = "4.3.0" version = "4.3.0"
@ -798,8 +780,8 @@ checksum = "4f423e341edefb78c9caba2d9c7f7687d0e72e89df3ce3394554754393ac3990"
dependencies = [ dependencies = [
"anstream", "anstream",
"anstyle", "anstyle",
"bitflags", "bitflags 1.3.2",
"clap_lex 0.5.0", "clap_lex",
"strsim", "strsim",
] ]
@ -812,16 +794,7 @@ dependencies = [
"heck", "heck",
"proc-macro2", "proc-macro2",
"quote", "quote",
"syn 2.0.18", "syn 2.0.28",
]
[[package]]
name = "clap_lex"
version = "0.2.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "2850f2f5a82cbf437dd5af4d49848fbdfc27c157c3d010345776f952765261c5"
dependencies = [
"os_str_bytes",
] ]
[[package]] [[package]]
@ -929,19 +902,19 @@ dependencies = [
[[package]] [[package]]
name = "criterion" name = "criterion"
version = "0.4.0" version = "0.5.1"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e7c76e09c1aae2bc52b3d2f29e13c6572553b30c4aa1b8a49fd70de6412654cb" checksum = "f2b12d017a929603d80db1831cd3a24082f8137ce19c69e6447f54f5fc8d692f"
dependencies = [ dependencies = [
"anes", "anes",
"atty",
"cast", "cast",
"ciborium", "ciborium",
"clap 3.2.25", "clap",
"criterion-plot", "criterion-plot",
"is-terminal",
"itertools", "itertools",
"lazy_static",
"num-traits", "num-traits",
"once_cell",
"oorandom", "oorandom",
"plotters", "plotters",
"rayon", "rayon",
@ -1048,9 +1021,9 @@ dependencies = [
[[package]] [[package]]
name = "csv" name = "csv"
version = "1.2.1" version = "1.2.2"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0b015497079b9a9d69c02ad25de6c0a6edef051ea6360a327d0bd05802ef64ad" checksum = "626ae34994d3d8d668f4269922248239db4ae42d538b14c398b74a52208e8086"
dependencies = [ dependencies = [
"csv-core", "csv-core",
"itoa", "itoa",
@ -1224,12 +1197,6 @@ dependencies = [
"winapi", "winapi",
] ]
[[package]]
name = "doc-comment"
version = "0.3.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "fea41bba32d969b513997752735605054bc0dfa92b4c56bf1189f2e174be7a10"
[[package]] [[package]]
name = "dump" name = "dump"
version = "1.3.0" version = "1.3.0"
@ -1369,7 +1336,7 @@ checksum = "eecf8589574ce9b895052fa12d69af7a233f99e6107f5cb8dd1044f2a17bfdcb"
dependencies = [ dependencies = [
"proc-macro2", "proc-macro2",
"quote", "quote",
"syn 2.0.18", "syn 2.0.28",
] ]
[[package]] [[package]]
@ -1385,6 +1352,12 @@ dependencies = [
"termcolor", "termcolor",
] ]
[[package]]
name = "equivalent"
version = "1.0.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5443807d6dff69373d433ab9ef5378ad8df50ca6298caf15de6e52e24aaf54d5"
[[package]] [[package]]
name = "errno" name = "errno"
version = "0.3.1" version = "0.3.1"
@ -1469,12 +1442,6 @@ dependencies = [
"nom_locate", "nom_locate",
] ]
[[package]]
name = "finl_unicode"
version = "1.2.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8fcfdc7a0362c9f4444381a9e697c79d435fe65b52a37466fc2c1184cee9edc6"
[[package]] [[package]]
name = "flate2" name = "flate2"
version = "1.0.26" version = "1.0.26"
@ -1570,7 +1537,7 @@ checksum = "89ca545a94061b6365f2c7355b4b32bd20df3ff95f02da9329b34ccc3bd6ee72"
dependencies = [ dependencies = [
"proc-macro2", "proc-macro2",
"quote", "quote",
"syn 2.0.18", "syn 2.0.28",
] ]
[[package]] [[package]]
@ -1608,7 +1575,7 @@ name = "fuzzers"
version = "1.3.0" version = "1.3.0"
dependencies = [ dependencies = [
"arbitrary", "arbitrary",
"clap 4.3.0", "clap",
"fastrand", "fastrand",
"milli", "milli",
"serde", "serde",
@ -1676,7 +1643,7 @@ version = "0.16.1"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ccf7f68c2995f392c49fffb4f95ae2c873297830eb25c6bc4c114ce8f4562acc" checksum = "ccf7f68c2995f392c49fffb4f95ae2c873297830eb25c6bc4c114ce8f4562acc"
dependencies = [ dependencies = [
"bitflags", "bitflags 1.3.2",
"libc", "libc",
"libgit2-sys", "libgit2-sys",
"log", "log",
@ -1712,7 +1679,7 @@ dependencies = [
"futures-sink", "futures-sink",
"futures-util", "futures-util",
"http", "http",
"indexmap", "indexmap 1.9.3",
"slab", "slab",
"tokio", "tokio",
"tokio-util", "tokio-util",
@ -1734,15 +1701,6 @@ dependencies = [
"byteorder", "byteorder",
] ]
[[package]]
name = "hashbrown"
version = "0.11.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ab5ef0d4909ef3724cc8cce6ccc8572c5c817592e9285f5464f8e86f8bd3726e"
dependencies = [
"ahash 0.7.6",
]
[[package]] [[package]]
name = "hashbrown" name = "hashbrown"
version = "0.12.3" version = "0.12.3"
@ -1752,6 +1710,12 @@ dependencies = [
"ahash 0.7.6", "ahash 0.7.6",
] ]
[[package]]
name = "hashbrown"
version = "0.14.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "2c6201b9ff9fd90a5a3bac2e56a830d0caa509576f0e503818ee82c181b3437a"
[[package]] [[package]]
name = "heapless" name = "heapless"
version = "0.7.16" version = "0.7.16"
@ -1773,8 +1737,8 @@ checksum = "95505c38b4572b2d910cecb0281560f54b440a19336cbbcb27bf6ce6adc6f5a8"
[[package]] [[package]]
name = "heed" name = "heed"
version = "0.12.5" version = "0.12.7"
source = "git+https://github.com/meilisearch/heed?tag=v0.12.6#8c5b94225fc949c02bb7b900cc50ffaf6b584b1e" source = "git+https://github.com/meilisearch/heed?tag=v0.12.7#061a5276b1f336f5f3302bee291e336041d88632"
dependencies = [ dependencies = [
"byteorder", "byteorder",
"heed-traits", "heed-traits",
@ -1791,12 +1755,12 @@ dependencies = [
[[package]] [[package]]
name = "heed-traits" name = "heed-traits"
version = "0.7.0" version = "0.7.0"
source = "git+https://github.com/meilisearch/heed?tag=v0.12.6#8c5b94225fc949c02bb7b900cc50ffaf6b584b1e" source = "git+https://github.com/meilisearch/heed?tag=v0.12.7#061a5276b1f336f5f3302bee291e336041d88632"
[[package]] [[package]]
name = "heed-types" name = "heed-types"
version = "0.7.2" version = "0.7.2"
source = "git+https://github.com/meilisearch/heed?tag=v0.12.6#8c5b94225fc949c02bb7b900cc50ffaf6b584b1e" source = "git+https://github.com/meilisearch/heed?tag=v0.12.7#061a5276b1f336f5f3302bee291e336041d88632"
dependencies = [ dependencies = [
"bincode", "bincode",
"heed-traits", "heed-traits",
@ -1805,15 +1769,6 @@ dependencies = [
"zerocopy", "zerocopy",
] ]
[[package]]
name = "hermit-abi"
version = "0.1.19"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "62b467343b94ba476dcb2500d242dadbb39557df889310ac77c5d99100aaac33"
dependencies = [
"libc",
]
[[package]] [[package]]
name = "hermit-abi" name = "hermit-abi"
version = "0.2.6" version = "0.2.6"
@ -1844,22 +1799,6 @@ dependencies = [
"digest", "digest",
] ]
[[package]]
name = "hnsw"
version = "0.11.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "2b9740ebf8769ec4ad6762cc951ba18f39bba6dfbc2fbbe46285f7539af79752"
dependencies = [
"ahash 0.7.6",
"hashbrown 0.11.2",
"libm",
"num-traits",
"rand_core",
"serde",
"smallvec",
"space",
]
[[package]] [[package]]
name = "http" name = "http"
version = "0.2.9" version = "0.2.9"
@ -1995,6 +1934,16 @@ dependencies = [
"serde", "serde",
] ]
[[package]]
name = "indexmap"
version = "2.0.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d5477fe2230a79769d8dc68e0eabf5437907c0457a5614a9e8dddb67f65eb65d"
dependencies = [
"equivalent",
"hashbrown 0.14.0",
]
[[package]] [[package]]
name = "inout" name = "inout"
version = "0.1.3" version = "0.1.3"
@ -2029,6 +1978,21 @@ dependencies = [
"cfg-if", "cfg-if",
] ]
[[package]]
name = "instant-distance"
version = "0.6.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8c619cdaa30bb84088963968bee12a45ea5fbbf355f2c021bcd15589f5ca494a"
dependencies = [
"num_cpus",
"ordered-float",
"parking_lot",
"rand",
"rayon",
"serde",
"serde-big-array",
]
[[package]] [[package]]
name = "io-lifetimes" name = "io-lifetimes"
version = "1.0.11" version = "1.0.11"
@ -2059,13 +2023,12 @@ dependencies = [
[[package]] [[package]]
name = "is-terminal" name = "is-terminal"
version = "0.4.7" version = "0.4.9"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "adcf93614601c8129ddf72e2d5633df827ba6551541c6d8c59520a371475be1f" checksum = "cb0889898416213fab133e1d33a0e5858a48177452750691bde3666d0fdbaf8b"
dependencies = [ dependencies = [
"hermit-abi 0.3.1", "hermit-abi 0.3.1",
"io-lifetimes", "rustix 0.38.4",
"rustix 0.37.19",
"windows-sys 0.48.0", "windows-sys 0.48.0",
] ]
@ -2162,9 +2125,9 @@ dependencies = [
[[package]] [[package]]
name = "libc" name = "libc"
version = "0.2.144" version = "0.2.147"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "2b00cc1c228a6782d0f076e7b232802e0c5689d41bb5df366f2a6b6621cfdfe1" checksum = "b4668fb0ea861c1df094127ac5f1da3409a82116a4ba74fca2e58ef927159bb3"
[[package]] [[package]]
name = "libgit2-sys" name = "libgit2-sys"
@ -2208,9 +2171,9 @@ dependencies = [
[[package]] [[package]]
name = "lindera-cc-cedict-builder" name = "lindera-cc-cedict-builder"
version = "0.25.0" version = "0.27.0"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "4c6bf79b29a90bcd22036e494d6cc9ac3abe9ab604b21f3258ba6dc1ce501801" checksum = "2d2e8f2ca97ddf952fe340642511b9c14b373cb2eef711d526bb8ef2ca0969b8"
dependencies = [ dependencies = [
"anyhow", "anyhow",
"bincode", "bincode",
@ -2227,9 +2190,9 @@ dependencies = [
[[package]] [[package]]
name = "lindera-compress" name = "lindera-compress"
version = "0.25.0" version = "0.27.0"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8f2e99e67736352bbb6ed1c273643975822505067ca32194b0981040bc50527a" checksum = "f72b460559bcbe8a9cee85ea4a5056133ed3abf373031191589236e656d65b59"
dependencies = [ dependencies = [
"anyhow", "anyhow",
"flate2", "flate2",
@ -2238,9 +2201,9 @@ dependencies = [
[[package]] [[package]]
name = "lindera-core" name = "lindera-core"
version = "0.25.0" version = "0.27.0"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7c3935e966409156f22cb4b334b21b0dce84b7aa1cad62214b466489d249c8e5" checksum = "f586eb8a9393c32d5525e0e9336a3727bd1329674740097126f3b0bff8a1a1ea"
dependencies = [ dependencies = [
"anyhow", "anyhow",
"bincode", "bincode",
@ -2255,9 +2218,9 @@ dependencies = [
[[package]] [[package]]
name = "lindera-decompress" name = "lindera-decompress"
version = "0.25.0" version = "0.27.0"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7476406abb63c49d7f59c88b9b868ee8d2981495ea7e2c3ad129902f9916b3c6" checksum = "1fb1facd8da698072fcc7338bd757730db53d59f313f44dd583fa03681dcc0e1"
dependencies = [ dependencies = [
"anyhow", "anyhow",
"flate2", "flate2",
@ -2266,9 +2229,9 @@ dependencies = [
[[package]] [[package]]
name = "lindera-dictionary" name = "lindera-dictionary"
version = "0.25.0" version = "0.27.0"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "808b7d2b3cabc25a4022526d484a4cfd1d5924dc76a26e0379707698841acef2" checksum = "ec7be7410b1da7017a8948986b87af67082f605e9a716f0989790d795d677f0c"
dependencies = [ dependencies = [
"anyhow", "anyhow",
"bincode", "bincode",
@ -2286,9 +2249,9 @@ dependencies = [
[[package]] [[package]]
name = "lindera-ipadic-builder" name = "lindera-ipadic-builder"
version = "0.25.0" version = "0.27.0"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "31f373a280958c930e5ee4a1e4db3a0ee0542afaf02d3b5cacb8cab4e298648e" checksum = "705d07f8a45d04fd95149f7ad41a26d1f9e56c9c00402be6f9dd05e3d88b99c6"
dependencies = [ dependencies = [
"anyhow", "anyhow",
"bincode", "bincode",
@ -2307,9 +2270,9 @@ dependencies = [
[[package]] [[package]]
name = "lindera-ipadic-neologd-builder" name = "lindera-ipadic-neologd-builder"
version = "0.25.0" version = "0.27.0"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "92eff98e9ed1a7a412b91709c2343457a04ef02fa0c27c27e3a5892f5591eae9" checksum = "633a93983ba13fba42328311a501091bd4a7aff0c94ae9eaa9d4733dd2b0468a"
dependencies = [ dependencies = [
"anyhow", "anyhow",
"bincode", "bincode",
@ -2328,9 +2291,9 @@ dependencies = [
[[package]] [[package]]
name = "lindera-ko-dic" name = "lindera-ko-dic"
version = "0.25.0" version = "0.27.0"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "74c6d5bf7d8092bd6d10de7a5d74b70ea7cf234586235b0d6cdb903b05a6c9e2" checksum = "a428e0d316b6c86f51bd919479692bc41ad840dba266ebc044663970f431ea18"
dependencies = [ dependencies = [
"bincode", "bincode",
"byteorder", "byteorder",
@ -2345,9 +2308,9 @@ dependencies = [
[[package]] [[package]]
name = "lindera-ko-dic-builder" name = "lindera-ko-dic-builder"
version = "0.25.0" version = "0.27.0"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f0a4add6d3c1e41ec9e2690d33e287d0223fb59a30ccee4980c23f31368cae1e" checksum = "2a5288704c6b8a069c0a1705c38758e836497698b50453373ab3d56c6f9a7ef8"
dependencies = [ dependencies = [
"anyhow", "anyhow",
"bincode", "bincode",
@ -2365,9 +2328,9 @@ dependencies = [
[[package]] [[package]]
name = "lindera-tokenizer" name = "lindera-tokenizer"
version = "0.25.0" version = "0.27.0"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "cb6a8acbd068019d1cdac7316f0dcb87f8e33ede2b13aa237f45114f9750afb8" checksum = "106ba439b2e87529d9bbedbb88d69f635baba1195c26502b308f55a85885fc81"
dependencies = [ dependencies = [
"bincode", "bincode",
"byteorder", "byteorder",
@ -2380,9 +2343,9 @@ dependencies = [
[[package]] [[package]]
name = "lindera-unidic" name = "lindera-unidic"
version = "0.25.0" version = "0.27.0"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "14abf0613d350b30d3b0406a33b1de8fa8d829f26516909421702174785991c8" checksum = "3399b6dcfe1701333451d184ff3c677f433b320153427b146360c9e4bd8cb816"
dependencies = [ dependencies = [
"bincode", "bincode",
"byteorder", "byteorder",
@ -2397,9 +2360,9 @@ dependencies = [
[[package]] [[package]]
name = "lindera-unidic-builder" name = "lindera-unidic-builder"
version = "0.25.0" version = "0.27.0"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e204ed53d9bd63227d1e6a6c1f122ca039e00a8634ac32e7fb0281eeec8615c4" checksum = "b698227fdaeac32289173ab389b990d4eb00a40cbc9912020f69a0c491dabf55"
dependencies = [ dependencies = [
"anyhow", "anyhow",
"bincode", "bincode",
@ -2433,6 +2396,12 @@ version = "0.3.8"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ef53942eb7bf7ff43a617b3e2c1c4a5ecf5944a7c1bc12d7ee39bbb15e5c1519" checksum = "ef53942eb7bf7ff43a617b3e2c1c4a5ecf5944a7c1bc12d7ee39bbb15e5c1519"
[[package]]
name = "linux-raw-sys"
version = "0.4.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "57bcfdad1b858c2db7c38303a6d2ad4dfaf5eb53dfeb0910128b2c26d6158503"
[[package]] [[package]]
name = "lmdb-rkv-sys" name = "lmdb-rkv-sys"
version = "0.15.1" version = "0.15.1"
@ -2473,9 +2442,9 @@ dependencies = [
[[package]] [[package]]
name = "log" name = "log"
version = "0.4.18" version = "0.4.19"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "518ef76f2f87365916b142844c16d8fefd85039bc5699050210a7778ee1cd1de" checksum = "b06a4cde4c0f271a446782e3eff8de789548ce57dbc8eca9292c27f4a42004b4"
[[package]] [[package]]
name = "logging_timer" name = "logging_timer"
@ -2514,7 +2483,7 @@ dependencies = [
"once_cell", "once_cell",
"proc-macro2", "proc-macro2",
"quote", "quote",
"syn 2.0.18", "syn 2.0.28",
] ]
[[package]] [[package]]
@ -2552,13 +2521,12 @@ dependencies = [
"assert-json-diff", "assert-json-diff",
"async-stream", "async-stream",
"async-trait", "async-trait",
"atty",
"brotli", "brotli",
"bstr", "bstr",
"byte-unit", "byte-unit",
"bytes", "bytes",
"cargo_toml", "cargo_toml",
"clap 4.3.0", "clap",
"crossbeam-channel", "crossbeam-channel",
"deserr", "deserr",
"dump", "dump",
@ -2572,8 +2540,9 @@ dependencies = [
"hex", "hex",
"http", "http",
"index-scheduler", "index-scheduler",
"indexmap", "indexmap 1.9.3",
"insta", "insta",
"is-terminal",
"itertools", "itertools",
"jsonwebtoken", "jsonwebtoken",
"lazy_static", "lazy_static",
@ -2725,9 +2694,9 @@ dependencies = [
"geoutils", "geoutils",
"grenad", "grenad",
"heed", "heed",
"hnsw", "indexmap 1.9.3",
"indexmap",
"insta", "insta",
"instant-distance",
"itertools", "itertools",
"json-depth-checker", "json-depth-checker",
"levenshtein_automata", "levenshtein_automata",
@ -2752,7 +2721,6 @@ dependencies = [
"smallstr", "smallstr",
"smallvec", "smallvec",
"smartstring", "smartstring",
"space",
"tempfile", "tempfile",
"thiserror", "thiserror",
"time", "time",
@ -2913,9 +2881,9 @@ checksum = "f69e48cd7c8e5bb52a1da1287fdbfd877c32673176583ce664cd63b201aba385"
[[package]] [[package]]
name = "once_cell" name = "once_cell"
version = "1.17.1" version = "1.18.0"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b7e5500299e16ebb147ae15a00a942af264cf3688f47923b8fc2cd5858f23ad3" checksum = "dd8b5dd2ae5ed71462c540258bedcb51965123ad7e7ccf4b9a8cafaa4a63576d"
[[package]] [[package]]
name = "oorandom" name = "oorandom"
@ -2932,12 +2900,6 @@ dependencies = [
"num-traits", "num-traits",
] ]
[[package]]
name = "os_str_bytes"
version = "6.5.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ceedf44fb00f2d1984b0bc98102627ce622e083e49a5bacdb3e514fa4238e267"
[[package]] [[package]]
name = "page_size" name = "page_size"
version = "0.4.2" version = "0.4.2"
@ -3078,7 +3040,7 @@ dependencies = [
"pest_meta", "pest_meta",
"proc-macro2", "proc-macro2",
"quote", "quote",
"syn 2.0.18", "syn 2.0.28",
] ]
[[package]] [[package]]
@ -3236,7 +3198,7 @@ version = "0.14.2"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b1de8dacb0873f77e6aefc6d71e044761fcc68060290f5b1089fcdf84626bb69" checksum = "b1de8dacb0873f77e6aefc6d71e044761fcc68060290f5b1089fcdf84626bb69"
dependencies = [ dependencies = [
"bitflags", "bitflags 1.3.2",
"byteorder", "byteorder",
"hex", "hex",
"lazy_static", "lazy_static",
@ -3297,9 +3259,9 @@ dependencies = [
[[package]] [[package]]
name = "quote" name = "quote"
version = "1.0.28" version = "1.0.30"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1b9ab9c7eadfd8df19006f1cf1a4aed13540ed5cbc047010ece5826e10825488" checksum = "5907a1b7c277254a8b15170f6e7c97cfa60ee7872a3217663bb81151e48184bb"
dependencies = [ dependencies = [
"proc-macro2", "proc-macro2",
] ]
@ -3372,7 +3334,7 @@ version = "0.2.16"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "fb5a58c1855b4b6819d59012155603f0b22ad30cad752600aadfcb695265519a" checksum = "fb5a58c1855b4b6819d59012155603f0b22ad30cad752600aadfcb695265519a"
dependencies = [ dependencies = [
"bitflags", "bitflags 1.3.2",
] ]
[[package]] [[package]]
@ -3381,7 +3343,7 @@ version = "0.3.5"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "567664f262709473930a4bf9e51bf2ebf3348f2e748ccc50dea20646858f8f29" checksum = "567664f262709473930a4bf9e51bf2ebf3348f2e748ccc50dea20646858f8f29"
dependencies = [ dependencies = [
"bitflags", "bitflags 1.3.2",
] ]
[[package]] [[package]]
@ -3523,7 +3485,7 @@ version = "0.36.14"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "14e4d67015953998ad0eb82887a0eb0129e18a7e2f3b7b0f6c422fddcd503d62" checksum = "14e4d67015953998ad0eb82887a0eb0129e18a7e2f3b7b0f6c422fddcd503d62"
dependencies = [ dependencies = [
"bitflags", "bitflags 1.3.2",
"errno", "errno",
"io-lifetimes", "io-lifetimes",
"libc", "libc",
@ -3537,7 +3499,7 @@ version = "0.37.19"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "acf8729d8542766f1b2cf77eb034d52f40d375bb8b615d0b147089946e16613d" checksum = "acf8729d8542766f1b2cf77eb034d52f40d375bb8b615d0b147089946e16613d"
dependencies = [ dependencies = [
"bitflags", "bitflags 1.3.2",
"errno", "errno",
"io-lifetimes", "io-lifetimes",
"libc", "libc",
@ -3545,6 +3507,19 @@ dependencies = [
"windows-sys 0.48.0", "windows-sys 0.48.0",
] ]
[[package]]
name = "rustix"
version = "0.38.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0a962918ea88d644592894bc6dc55acc6c0956488adcebbfb6e273506b7fd6e5"
dependencies = [
"bitflags 2.3.3",
"errno",
"libc",
"linux-raw-sys 0.4.5",
"windows-sys 0.48.0",
]
[[package]] [[package]]
name = "rustls" name = "rustls"
version = "0.20.8" version = "0.20.8"
@ -3647,13 +3622,22 @@ checksum = "bebd363326d05ec3e2f532ab7660680f3b02130d780c299bca73469d521bc0ed"
[[package]] [[package]]
name = "serde" name = "serde"
version = "1.0.163" version = "1.0.180"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "2113ab51b87a539ae008b5c6c02dc020ffa39afd2d83cffcb3f4eb2722cebec2" checksum = "0ea67f183f058fe88a4e3ec6e2788e003840893b91bac4559cabedd00863b3ed"
dependencies = [ dependencies = [
"serde_derive", "serde_derive",
] ]
[[package]]
name = "serde-big-array"
version = "0.5.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "11fc7cc2c76d73e0f27ee52abbd64eec84d46f370c88371120433196934e4b7f"
dependencies = [
"serde",
]
[[package]] [[package]]
name = "serde-cs" name = "serde-cs"
version = "0.2.4" version = "0.2.4"
@ -3665,22 +3649,22 @@ dependencies = [
[[package]] [[package]]
name = "serde_derive" name = "serde_derive"
version = "1.0.163" version = "1.0.180"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8c805777e3930c8883389c602315a24224bcc738b63905ef87cd1420353ea93e" checksum = "24e744d7782b686ab3b73267ef05697159cc0e5abbed3f47f9933165e5219036"
dependencies = [ dependencies = [
"proc-macro2", "proc-macro2",
"quote", "quote",
"syn 2.0.18", "syn 2.0.28",
] ]
[[package]] [[package]]
name = "serde_json" name = "serde_json"
version = "1.0.96" version = "1.0.104"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "057d394a50403bcac12672b2b18fb387ab6d289d957dab67dd201875391e52f1" checksum = "076066c5f1078eac5b722a31827a8832fe108bed65dfa75e233c89f8206e976c"
dependencies = [ dependencies = [
"indexmap", "indexmap 2.0.0",
"itoa", "itoa",
"ryu", "ryu",
"serde", "serde",
@ -3803,9 +3787,6 @@ name = "smallvec"
version = "1.10.0" version = "1.10.0"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a507befe795404456341dfab10cef66ead4c041f62b8b11bbb92bffe5d0953e0" checksum = "a507befe795404456341dfab10cef66ead4c041f62b8b11bbb92bffe5d0953e0"
dependencies = [
"serde",
]
[[package]] [[package]]
name = "smartstring" name = "smartstring"
@ -3828,16 +3809,6 @@ dependencies = [
"winapi", "winapi",
] ]
[[package]]
name = "space"
version = "0.17.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c5ab9701ae895386d13db622abf411989deff7109b13b46b6173bb4ce5c1d123"
dependencies = [
"doc-comment",
"num-traits",
]
[[package]] [[package]]
name = "spin" name = "spin"
version = "0.5.2" version = "0.5.2"
@ -3901,9 +3872,9 @@ dependencies = [
[[package]] [[package]]
name = "syn" name = "syn"
version = "2.0.18" version = "2.0.28"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "32d41677bcbe24c20c52e7c70b0d8db04134c5d1066bf98662e2871ad200ea3e" checksum = "04361975b3f5e348b2189d8dc55bc942f278b2d482a6a0365de5bdd62d351567"
dependencies = [ dependencies = [
"proc-macro2", "proc-macro2",
"quote", "quote",
@ -3988,30 +3959,24 @@ dependencies = [
"winapi-util", "winapi-util",
] ]
[[package]]
name = "textwrap"
version = "0.16.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "222a222a5bfe1bba4a77b45ec488a741b3cb8872e5e499451fd7d0129c9c7c3d"
[[package]] [[package]]
name = "thiserror" name = "thiserror"
version = "1.0.40" version = "1.0.44"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "978c9a314bd8dc99be594bc3c175faaa9794be04a5a5e153caba6915336cebac" checksum = "611040a08a0439f8248d1990b111c95baa9c704c805fa1f62104b39655fd7f90"
dependencies = [ dependencies = [
"thiserror-impl", "thiserror-impl",
] ]
[[package]] [[package]]
name = "thiserror-impl" name = "thiserror-impl"
version = "1.0.40" version = "1.0.44"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f9456a42c5b0d803c8cd86e73dd7cc9edd429499f37a3550d286d5e86720569f" checksum = "090198534930841fab3a5d1bb637cde49e339654e606195f8d9c76eeb081dc96"
dependencies = [ dependencies = [
"proc-macro2", "proc-macro2",
"quote", "quote",
"syn 2.0.18", "syn 2.0.28",
] ]
[[package]] [[package]]
@ -4093,7 +4058,7 @@ checksum = "630bdcf245f78637c13ec01ffae6187cca34625e8c63150d424b59e55af2675e"
dependencies = [ dependencies = [
"proc-macro2", "proc-macro2",
"quote", "quote",
"syn 2.0.18", "syn 2.0.28",
] ]
[[package]] [[package]]
@ -4169,7 +4134,7 @@ version = "0.19.10"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "2380d56e8670370eee6566b0bfd4265f65b3f432e8c6d85623f728d4fa31f739" checksum = "2380d56e8670370eee6566b0bfd4265f65b3f432e8c6d85623f728d4fa31f739"
dependencies = [ dependencies = [
"indexmap", "indexmap 1.9.3",
"serde", "serde",
"serde_spanned", "serde_spanned",
"toml_datetime", "toml_datetime",
@ -4418,7 +4383,7 @@ dependencies = [
"once_cell", "once_cell",
"proc-macro2", "proc-macro2",
"quote", "quote",
"syn 2.0.18", "syn 2.0.28",
"wasm-bindgen-shared", "wasm-bindgen-shared",
] ]
@ -4452,7 +4417,7 @@ checksum = "e128beba882dd1eb6200e1dc92ae6c5dbaa4311aa7bb211ca035779e5efc39f8"
dependencies = [ dependencies = [
"proc-macro2", "proc-macro2",
"quote", "quote",
"syn 2.0.18", "syn 2.0.28",
"wasm-bindgen-backend", "wasm-bindgen-backend",
"wasm-bindgen-shared", "wasm-bindgen-shared",
] ]

View File

@ -65,7 +65,7 @@ You may also want to check out [Meilisearch 101](https://www.meilisearch.com/doc
## ⚡ Supercharge your Meilisearch experience ## ⚡ Supercharge your Meilisearch experience
Say goodbye to server deployment and manual updates with [Meilisearch Cloud](https://www.meilisearch.com/pricing?utm_campaign=oss&utm_source=engine&utm_medium=meilisearch). Get started with a 14-day free trial! No credit card required. Say goodbye to server deployment and manual updates with [Meilisearch Cloud](https://www.meilisearch.com/cloud?utm_campaign=oss&utm_source=github&utm_medium=meilisearch). No credit card required.
## 🧰 SDKs & integration tools ## 🧰 SDKs & integration tools
@ -87,7 +87,7 @@ Finally, for more in-depth information, refer to our articles explaining fundame
Meilisearch collects **anonymized** data from users to help us improve our product. You can [deactivate this](https://www.meilisearch.com/docs/learn/what_is_meilisearch/telemetry?utm_campaign=oss&utm_source=github&utm_medium=meilisearch&utm_content=telemetry#how-to-disable-data-collection) whenever you want. Meilisearch collects **anonymized** data from users to help us improve our product. You can [deactivate this](https://www.meilisearch.com/docs/learn/what_is_meilisearch/telemetry?utm_campaign=oss&utm_source=github&utm_medium=meilisearch&utm_content=telemetry#how-to-disable-data-collection) whenever you want.
To request deletion of collected data, please write to us at [privacy@meilisearch.com](mailto:privacy@meilisearch.com). Don't forget to include your `Instance UID` in the message, as this helps us quickly find and delete your data. To request deletion of collected data, please write to us at [privacy@meilisearch.com](mailto:privacy@meilisearch.com). Don't forget to include your `Instance UID` in the message, as this helps us quickly find and delete your data.
If you want to know more about the kind of data we collect and what we use it for, check the [telemetry section](https://www.meilisearch.com/docs/learn/what_is_meilisearch/telemetry?utm_campaign=oss&utm_source=github&utm_medium=meilisearch&utm_content=telemetry#how-to-disable-data-collection) of our documentation. If you want to know more about the kind of data we collect and what we use it for, check the [telemetry section](https://www.meilisearch.com/docs/learn/what_is_meilisearch/telemetry?utm_campaign=oss&utm_source=github&utm_medium=meilisearch&utm_content=telemetry#how-to-disable-data-collection) of our documentation.

View File

@ -18,7 +18,7 @@ mimalloc = { version = "0.1.37", default-features = false }
serde_json = { version = "1.0.95", features = ["preserve_order"] } serde_json = { version = "1.0.95", features = ["preserve_order"] }
[dev-dependencies] [dev-dependencies]
criterion = { version = "0.4.0", features = ["html_reports"] } criterion = { version = "0.5.1", features = ["html_reports"] }
rand = "0.8.5" rand = "0.8.5"
rand_chacha = "0.3.1" rand_chacha = "0.3.1"
roaring = "0.10.1" roaring = "0.10.1"

View File

@ -210,6 +210,7 @@ pub(crate) mod test {
use big_s::S; use big_s::S;
use maplit::{btreemap, btreeset}; use maplit::{btreemap, btreeset};
use meilisearch_types::facet_values_sort::FacetValuesSort; use meilisearch_types::facet_values_sort::FacetValuesSort;
use meilisearch_types::features::RuntimeTogglableFeatures;
use meilisearch_types::index_uid_pattern::IndexUidPattern; use meilisearch_types::index_uid_pattern::IndexUidPattern;
use meilisearch_types::keys::{Action, Key}; use meilisearch_types::keys::{Action, Key};
use meilisearch_types::milli; use meilisearch_types::milli;
@ -418,7 +419,10 @@ pub(crate) mod test {
} }
keys.flush().unwrap(); keys.flush().unwrap();
// ========== TODO: create features here // ========== experimental features
let features = create_test_features();
dump.create_experimental_features(features).unwrap();
// create the dump // create the dump
let mut file = tempfile::tempfile().unwrap(); let mut file = tempfile::tempfile().unwrap();
@ -428,6 +432,10 @@ pub(crate) mod test {
file file
} }
fn create_test_features() -> RuntimeTogglableFeatures {
RuntimeTogglableFeatures { vector_store: true, ..Default::default() }
}
#[test] #[test]
fn test_creating_and_read_dump() { fn test_creating_and_read_dump() {
let mut file = create_test_dump(); let mut file = create_test_dump();
@ -472,5 +480,9 @@ pub(crate) mod test {
for (key, expected) in dump.keys().unwrap().zip(create_test_api_keys()) { for (key, expected) in dump.keys().unwrap().zip(create_test_api_keys()) {
assert_eq!(key.unwrap(), expected); assert_eq!(key.unwrap(), expected);
} }
// ==== checking the features
let expected = create_test_features();
assert_eq!(dump.features().unwrap().unwrap(), expected);
} }
} }

View File

@ -195,8 +195,53 @@ pub(crate) mod test {
use meili_snap::insta; use meili_snap::insta;
use super::*; use super::*;
use crate::reader::v6::RuntimeTogglableFeatures;
// TODO: add `features` to tests #[test]
fn import_dump_v6_experimental() {
let dump = File::open("tests/assets/v6-with-experimental.dump").unwrap();
let mut dump = DumpReader::open(dump).unwrap();
// top level infos
insta::assert_display_snapshot!(dump.date().unwrap(), @"2023-07-06 7:10:27.21958 +00:00:00");
insta::assert_debug_snapshot!(dump.instance_uid().unwrap(), @"None");
// tasks
let tasks = dump.tasks().unwrap().collect::<Result<Vec<_>>>().unwrap();
let (tasks, update_files): (Vec<_>, Vec<_>) = tasks.into_iter().unzip();
meili_snap::snapshot_hash!(meili_snap::json_string!(tasks), @"d45cd8571703e58ae53c7bd7ce3f5c22");
assert_eq!(update_files.len(), 2);
assert!(update_files[0].is_none()); // the dump creation
assert!(update_files[1].is_none()); // the processed document addition
// keys
let keys = dump.keys().unwrap().collect::<Result<Vec<_>>>().unwrap();
meili_snap::snapshot_hash!(meili_snap::json_string!(keys), @"13c2da155e9729c2344688cab29af71d");
// indexes
let mut indexes = dump.indexes().unwrap().collect::<Result<Vec<_>>>().unwrap();
// the index are not ordered in any way by default
indexes.sort_by_key(|index| index.metadata().uid.to_string());
let mut test = indexes.pop().unwrap();
assert!(indexes.is_empty());
insta::assert_json_snapshot!(test.metadata(), @r###"
{
"uid": "test",
"primaryKey": "id",
"createdAt": "2023-07-06T07:07:41.364694Z",
"updatedAt": "2023-07-06T07:07:41.396114Z"
}
"###);
assert_eq!(test.documents().unwrap().count(), 1);
assert_eq!(
dump.features().unwrap().unwrap(),
RuntimeTogglableFeatures { vector_store: true, ..Default::default() }
);
}
#[test] #[test]
fn import_dump_v5() { fn import_dump_v5() {
@ -274,6 +319,8 @@ pub(crate) mod test {
let documents = spells.documents().unwrap().collect::<Result<Vec<_>>>().unwrap(); let documents = spells.documents().unwrap().collect::<Result<Vec<_>>>().unwrap();
assert_eq!(documents.len(), 10); assert_eq!(documents.len(), 10);
meili_snap::snapshot_hash!(format!("{:#?}", documents), @"235016433dd04262c7f2da01d1e808ce"); meili_snap::snapshot_hash!(format!("{:#?}", documents), @"235016433dd04262c7f2da01d1e808ce");
assert_eq!(dump.features().unwrap(), None);
} }
#[test] #[test]

View File

@ -292,6 +292,7 @@ pub(crate) mod test {
---- update_files/ ---- update_files/
---- 1.jsonl ---- 1.jsonl
---- queue.jsonl ---- queue.jsonl
---- experimental-features.json
---- instance_uid.uuid ---- instance_uid.uuid
---- keys.jsonl ---- keys.jsonl
---- metadata.json ---- metadata.json

Binary file not shown.

View File

@ -472,6 +472,77 @@ pub fn parse_filter(input: Span) -> IResult<FilterCondition> {
terminated(|input| parse_expression(input, 0), eof)(input) terminated(|input| parse_expression(input, 0), eof)(input)
} }
impl<'a> std::fmt::Display for FilterCondition<'a> {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
match self {
FilterCondition::Not(filter) => {
write!(f, "NOT ({filter})")
}
FilterCondition::Condition { fid, op } => {
write!(f, "{fid} {op}")
}
FilterCondition::In { fid, els } => {
write!(f, "{fid} IN[")?;
for el in els {
write!(f, "{el}, ")?;
}
write!(f, "]")
}
FilterCondition::Or(els) => {
write!(f, "OR[")?;
for el in els {
write!(f, "{el}, ")?;
}
write!(f, "]")
}
FilterCondition::And(els) => {
write!(f, "AND[")?;
for el in els {
write!(f, "{el}, ")?;
}
write!(f, "]")
}
FilterCondition::GeoLowerThan { point, radius } => {
write!(f, "_geoRadius({}, {}, {})", point[0], point[1], radius)
}
FilterCondition::GeoBoundingBox {
top_right_point: top_left_point,
bottom_left_point: bottom_right_point,
} => {
write!(
f,
"_geoBoundingBox([{}, {}], [{}, {}])",
top_left_point[0],
top_left_point[1],
bottom_right_point[0],
bottom_right_point[1]
)
}
}
}
}
impl<'a> std::fmt::Display for Condition<'a> {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
match self {
Condition::GreaterThan(token) => write!(f, "> {token}"),
Condition::GreaterThanOrEqual(token) => write!(f, ">= {token}"),
Condition::Equal(token) => write!(f, "= {token}"),
Condition::NotEqual(token) => write!(f, "!= {token}"),
Condition::Null => write!(f, "IS NULL"),
Condition::Empty => write!(f, "IS EMPTY"),
Condition::Exists => write!(f, "EXISTS"),
Condition::LowerThan(token) => write!(f, "< {token}"),
Condition::LowerThanOrEqual(token) => write!(f, "<= {token}"),
Condition::Between { from, to } => write!(f, "{from} TO {to}"),
}
}
}
impl<'a> std::fmt::Display for Token<'a> {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
write!(f, "{{{}}}", self.value())
}
}
#[cfg(test)] #[cfg(test)]
pub mod tests { pub mod tests {
use super::*; use super::*;
@ -852,74 +923,3 @@ pub mod tests {
assert_eq!(token.value(), s); assert_eq!(token.value(), s);
} }
} }
impl<'a> std::fmt::Display for FilterCondition<'a> {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
match self {
FilterCondition::Not(filter) => {
write!(f, "NOT ({filter})")
}
FilterCondition::Condition { fid, op } => {
write!(f, "{fid} {op}")
}
FilterCondition::In { fid, els } => {
write!(f, "{fid} IN[")?;
for el in els {
write!(f, "{el}, ")?;
}
write!(f, "]")
}
FilterCondition::Or(els) => {
write!(f, "OR[")?;
for el in els {
write!(f, "{el}, ")?;
}
write!(f, "]")
}
FilterCondition::And(els) => {
write!(f, "AND[")?;
for el in els {
write!(f, "{el}, ")?;
}
write!(f, "]")
}
FilterCondition::GeoLowerThan { point, radius } => {
write!(f, "_geoRadius({}, {}, {})", point[0], point[1], radius)
}
FilterCondition::GeoBoundingBox {
top_right_point: top_left_point,
bottom_left_point: bottom_right_point,
} => {
write!(
f,
"_geoBoundingBox([{}, {}], [{}, {}])",
top_left_point[0],
top_left_point[1],
bottom_right_point[0],
bottom_right_point[1]
)
}
}
}
}
impl<'a> std::fmt::Display for Condition<'a> {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
match self {
Condition::GreaterThan(token) => write!(f, "> {token}"),
Condition::GreaterThanOrEqual(token) => write!(f, ">= {token}"),
Condition::Equal(token) => write!(f, "= {token}"),
Condition::NotEqual(token) => write!(f, "!= {token}"),
Condition::Null => write!(f, "IS NULL"),
Condition::Empty => write!(f, "IS EMPTY"),
Condition::Exists => write!(f, "EXISTS"),
Condition::LowerThan(token) => write!(f, "< {token}"),
Condition::LowerThanOrEqual(token) => write!(f, "<= {token}"),
Condition::Between { from, to } => write!(f, "{from} TO {to}"),
}
}
}
impl<'a> std::fmt::Display for Token<'a> {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
write!(f, "{{{}}}", self.value())
}
}

View File

@ -16,7 +16,7 @@ license.workspace = true
serde_json = "1.0" serde_json = "1.0"
[dev-dependencies] [dev-dependencies]
criterion = { version = "0.4.0", features = ["html_reports"] } criterion = { version = "0.5.1", features = ["html_reports"] }
[[bench]] [[bench]]
name = "benchmarks" name = "benchmarks"

View File

@ -138,6 +138,12 @@ impl Query {
index_vec.push(index_uid); index_vec.push(index_uid);
Self { index_uids: Some(index_vec), ..self } Self { index_uids: Some(index_vec), ..self }
} }
// Removes the `from` and `limit` restrictions from the query.
// Useful to get the total number of tasks matching a filter.
pub fn without_limits(self) -> Self {
Query { limit: None, from: None, ..self }
}
} }
#[derive(Debug, Clone)] #[derive(Debug, Clone)]
@ -807,6 +813,11 @@ impl IndexScheduler {
Ok(res) Ok(res)
} }
// Return true if there is at least one task that is processing.
pub fn is_task_processing(&self) -> Result<bool> {
Ok(!self.processing_tasks.read().unwrap().processing.is_empty())
}
/// Return true iff there is at least one task associated with this index /// Return true iff there is at least one task associated with this index
/// that is processing. /// that is processing.
pub fn is_index_processing(&self, index: &str) -> Result<bool> { pub fn is_index_processing(&self, index: &str) -> Result<bool> {
@ -817,7 +828,8 @@ impl IndexScheduler {
Ok(nbr_index_processing_tasks > 0) Ok(nbr_index_processing_tasks > 0)
} }
/// Return the task ids matching the query from the user's point of view. /// Return the task ids matching the query along with the total number of tasks
/// by ignoring the from and limit parameters from the user's point of view.
/// ///
/// There are two differences between an internal query and a query executed by /// There are two differences between an internal query and a query executed by
/// the user. /// the user.
@ -830,7 +842,13 @@ impl IndexScheduler {
rtxn: &RoTxn, rtxn: &RoTxn,
query: &Query, query: &Query,
filters: &meilisearch_auth::AuthFilter, filters: &meilisearch_auth::AuthFilter,
) -> Result<RoaringBitmap> { ) -> Result<(RoaringBitmap, u64)> {
// compute all tasks matching the filter by ignoring the limits, to find the number of tasks matching
// the filter.
// As this causes us to compute the filter twice it is slightly inefficient, but doing it this way spares
// us from modifying the underlying implementation, and the performance remains sufficient.
// Should this change, we would modify `get_task_ids` to directly return the number of matching tasks.
let total_tasks = self.get_task_ids(rtxn, &query.clone().without_limits())?;
let mut tasks = self.get_task_ids(rtxn, query)?; let mut tasks = self.get_task_ids(rtxn, query)?;
// If the query contains a list of index uid or there is a finite list of authorized indexes, // If the query contains a list of index uid or there is a finite list of authorized indexes,
@ -853,10 +871,11 @@ impl IndexScheduler {
} }
} }
Ok(tasks) Ok((tasks, total_tasks.len()))
} }
/// Return the tasks matching the query from the user's point of view. /// Return the tasks matching the query from the user's point of view along
/// with the total number of tasks matching the query, ignoring from and limit.
/// ///
/// There are two differences between an internal query and a query executed by /// There are two differences between an internal query and a query executed by
/// the user. /// the user.
@ -868,11 +887,10 @@ impl IndexScheduler {
&self, &self,
query: Query, query: Query,
filters: &meilisearch_auth::AuthFilter, filters: &meilisearch_auth::AuthFilter,
) -> Result<Vec<Task>> { ) -> Result<(Vec<Task>, u64)> {
let rtxn = self.env.read_txn()?; let rtxn = self.env.read_txn()?;
let tasks = self.get_task_ids_from_authorized_indexes(&rtxn, &query, filters)?; let (tasks, total) = self.get_task_ids_from_authorized_indexes(&rtxn, &query, filters)?;
let tasks = self.get_existing_tasks( let tasks = self.get_existing_tasks(
&rtxn, &rtxn,
tasks.into_iter().rev().take(query.limit.unwrap_or(u32::MAX) as usize), tasks.into_iter().rev().take(query.limit.unwrap_or(u32::MAX) as usize),
@ -883,16 +901,19 @@ impl IndexScheduler {
let ret = tasks.into_iter(); let ret = tasks.into_iter();
if processing.is_empty() { if processing.is_empty() {
Ok(ret.collect()) Ok((ret.collect(), total))
} else { } else {
Ok(ret Ok((
.map(|task| match processing.contains(task.uid) { ret.map(|task| {
true => { if processing.contains(task.uid) {
Task { status: Status::Processing, started_at: Some(started_at), ..task } Task { status: Status::Processing, started_at: Some(started_at), ..task }
} else {
task
} }
false => task,
}) })
.collect()) .collect(),
total,
))
} }
} }
@ -1835,6 +1856,17 @@ mod tests {
snapshot!(snapshot_index_scheduler(&index_scheduler), name: "registered_the_third_task"); snapshot!(snapshot_index_scheduler(&index_scheduler), name: "registered_the_third_task");
} }
#[test]
fn test_task_is_processing() {
let (index_scheduler, mut handle) = IndexScheduler::test(true, vec![]);
index_scheduler.register(index_creation_task("index_a", "id")).unwrap();
snapshot!(snapshot_index_scheduler(&index_scheduler), name: "registered_a_task");
handle.advance_till([Start, BatchCreated]);
assert!(index_scheduler.is_task_processing().unwrap());
}
/// We send a lot of tasks but notify the tasks scheduler only once as /// We send a lot of tasks but notify the tasks scheduler only once as
/// we send them very fast, we must make sure that they are all processed. /// we send them very fast, we must make sure that they are all processed.
#[test] #[test]
@ -2767,43 +2799,43 @@ mod tests {
let rtxn = index_scheduler.env.read_txn().unwrap(); let rtxn = index_scheduler.env.read_txn().unwrap();
let query = Query { limit: Some(0), ..Default::default() }; let query = Query { limit: Some(0), ..Default::default() };
let tasks = index_scheduler let (tasks, _) = index_scheduler
.get_task_ids_from_authorized_indexes(&rtxn, &query, &AuthFilter::default()) .get_task_ids_from_authorized_indexes(&rtxn, &query, &AuthFilter::default())
.unwrap(); .unwrap();
snapshot!(snapshot_bitmap(&tasks), @"[]"); snapshot!(snapshot_bitmap(&tasks), @"[]");
let query = Query { limit: Some(1), ..Default::default() }; let query = Query { limit: Some(1), ..Default::default() };
let tasks = index_scheduler let (tasks, _) = index_scheduler
.get_task_ids_from_authorized_indexes(&rtxn, &query, &AuthFilter::default()) .get_task_ids_from_authorized_indexes(&rtxn, &query, &AuthFilter::default())
.unwrap(); .unwrap();
snapshot!(snapshot_bitmap(&tasks), @"[2,]"); snapshot!(snapshot_bitmap(&tasks), @"[2,]");
let query = Query { limit: Some(2), ..Default::default() }; let query = Query { limit: Some(2), ..Default::default() };
let tasks = index_scheduler let (tasks, _) = index_scheduler
.get_task_ids_from_authorized_indexes(&rtxn, &query, &AuthFilter::default()) .get_task_ids_from_authorized_indexes(&rtxn, &query, &AuthFilter::default())
.unwrap(); .unwrap();
snapshot!(snapshot_bitmap(&tasks), @"[1,2,]"); snapshot!(snapshot_bitmap(&tasks), @"[1,2,]");
let query = Query { from: Some(1), ..Default::default() }; let query = Query { from: Some(1), ..Default::default() };
let tasks = index_scheduler let (tasks, _) = index_scheduler
.get_task_ids_from_authorized_indexes(&rtxn, &query, &AuthFilter::default()) .get_task_ids_from_authorized_indexes(&rtxn, &query, &AuthFilter::default())
.unwrap(); .unwrap();
snapshot!(snapshot_bitmap(&tasks), @"[0,1,]"); snapshot!(snapshot_bitmap(&tasks), @"[0,1,]");
let query = Query { from: Some(2), ..Default::default() }; let query = Query { from: Some(2), ..Default::default() };
let tasks = index_scheduler let (tasks, _) = index_scheduler
.get_task_ids_from_authorized_indexes(&rtxn, &query, &AuthFilter::default()) .get_task_ids_from_authorized_indexes(&rtxn, &query, &AuthFilter::default())
.unwrap(); .unwrap();
snapshot!(snapshot_bitmap(&tasks), @"[0,1,2,]"); snapshot!(snapshot_bitmap(&tasks), @"[0,1,2,]");
let query = Query { from: Some(1), limit: Some(1), ..Default::default() }; let query = Query { from: Some(1), limit: Some(1), ..Default::default() };
let tasks = index_scheduler let (tasks, _) = index_scheduler
.get_task_ids_from_authorized_indexes(&rtxn, &query, &AuthFilter::default()) .get_task_ids_from_authorized_indexes(&rtxn, &query, &AuthFilter::default())
.unwrap(); .unwrap();
snapshot!(snapshot_bitmap(&tasks), @"[1,]"); snapshot!(snapshot_bitmap(&tasks), @"[1,]");
let query = Query { from: Some(1), limit: Some(2), ..Default::default() }; let query = Query { from: Some(1), limit: Some(2), ..Default::default() };
let tasks = index_scheduler let (tasks, _) = index_scheduler
.get_task_ids_from_authorized_indexes(&rtxn, &query, &AuthFilter::default()) .get_task_ids_from_authorized_indexes(&rtxn, &query, &AuthFilter::default())
.unwrap(); .unwrap();
snapshot!(snapshot_bitmap(&tasks), @"[0,1,]"); snapshot!(snapshot_bitmap(&tasks), @"[0,1,]");
@ -2830,13 +2862,13 @@ mod tests {
let rtxn = index_scheduler.env.read_txn().unwrap(); let rtxn = index_scheduler.env.read_txn().unwrap();
let query = Query { statuses: Some(vec![Status::Processing]), ..Default::default() }; let query = Query { statuses: Some(vec![Status::Processing]), ..Default::default() };
let tasks = index_scheduler let (tasks, _) = index_scheduler
.get_task_ids_from_authorized_indexes(&rtxn, &query, &AuthFilter::default()) .get_task_ids_from_authorized_indexes(&rtxn, &query, &AuthFilter::default())
.unwrap(); .unwrap();
snapshot!(snapshot_bitmap(&tasks), @"[0,]"); // only the processing tasks in the first tick snapshot!(snapshot_bitmap(&tasks), @"[0,]"); // only the processing tasks in the first tick
let query = Query { statuses: Some(vec![Status::Enqueued]), ..Default::default() }; let query = Query { statuses: Some(vec![Status::Enqueued]), ..Default::default() };
let tasks = index_scheduler let (tasks, _) = index_scheduler
.get_task_ids_from_authorized_indexes(&rtxn, &query, &AuthFilter::default()) .get_task_ids_from_authorized_indexes(&rtxn, &query, &AuthFilter::default())
.unwrap(); .unwrap();
snapshot!(snapshot_bitmap(&tasks), @"[1,2,]"); // only the enqueued tasks in the first tick snapshot!(snapshot_bitmap(&tasks), @"[1,2,]"); // only the enqueued tasks in the first tick
@ -2845,7 +2877,7 @@ mod tests {
statuses: Some(vec![Status::Enqueued, Status::Processing]), statuses: Some(vec![Status::Enqueued, Status::Processing]),
..Default::default() ..Default::default()
}; };
let tasks = index_scheduler let (tasks, _) = index_scheduler
.get_task_ids_from_authorized_indexes(&rtxn, &query, &AuthFilter::default()) .get_task_ids_from_authorized_indexes(&rtxn, &query, &AuthFilter::default())
.unwrap(); .unwrap();
snapshot!(snapshot_bitmap(&tasks), @"[0,1,2,]"); // both enqueued and processing tasks in the first tick snapshot!(snapshot_bitmap(&tasks), @"[0,1,2,]"); // both enqueued and processing tasks in the first tick
@ -2855,7 +2887,7 @@ mod tests {
after_started_at: Some(start_time), after_started_at: Some(start_time),
..Default::default() ..Default::default()
}; };
let tasks = index_scheduler let (tasks, _) = index_scheduler
.get_task_ids_from_authorized_indexes(&rtxn, &query, &AuthFilter::default()) .get_task_ids_from_authorized_indexes(&rtxn, &query, &AuthFilter::default())
.unwrap(); .unwrap();
// both enqueued and processing tasks in the first tick, but limited to those with a started_at // both enqueued and processing tasks in the first tick, but limited to those with a started_at
@ -2867,7 +2899,7 @@ mod tests {
before_started_at: Some(start_time), before_started_at: Some(start_time),
..Default::default() ..Default::default()
}; };
let tasks = index_scheduler let (tasks, _) = index_scheduler
.get_task_ids_from_authorized_indexes(&rtxn, &query, &AuthFilter::default()) .get_task_ids_from_authorized_indexes(&rtxn, &query, &AuthFilter::default())
.unwrap(); .unwrap();
// both enqueued and processing tasks in the first tick, but limited to those with a started_at // both enqueued and processing tasks in the first tick, but limited to those with a started_at
@ -2880,7 +2912,7 @@ mod tests {
before_started_at: Some(start_time + Duration::minutes(1)), before_started_at: Some(start_time + Duration::minutes(1)),
..Default::default() ..Default::default()
}; };
let tasks = index_scheduler let (tasks, _) = index_scheduler
.get_task_ids_from_authorized_indexes(&rtxn, &query, &AuthFilter::default()) .get_task_ids_from_authorized_indexes(&rtxn, &query, &AuthFilter::default())
.unwrap(); .unwrap();
// both enqueued and processing tasks in the first tick, but limited to those with a started_at // both enqueued and processing tasks in the first tick, but limited to those with a started_at
@ -2907,7 +2939,7 @@ mod tests {
before_started_at: Some(start_time + Duration::minutes(1)), before_started_at: Some(start_time + Duration::minutes(1)),
..Default::default() ..Default::default()
}; };
let tasks = index_scheduler let (tasks, _) = index_scheduler
.get_task_ids_from_authorized_indexes(&rtxn, &query, &AuthFilter::default()) .get_task_ids_from_authorized_indexes(&rtxn, &query, &AuthFilter::default())
.unwrap(); .unwrap();
// both succeeded and processing tasks in the first tick, but limited to those with a started_at // both succeeded and processing tasks in the first tick, but limited to those with a started_at
@ -2920,7 +2952,7 @@ mod tests {
before_started_at: Some(start_time), before_started_at: Some(start_time),
..Default::default() ..Default::default()
}; };
let tasks = index_scheduler let (tasks, _) = index_scheduler
.get_task_ids_from_authorized_indexes(&rtxn, &query, &AuthFilter::default()) .get_task_ids_from_authorized_indexes(&rtxn, &query, &AuthFilter::default())
.unwrap(); .unwrap();
// both succeeded and processing tasks in the first tick, but limited to those with a started_at // both succeeded and processing tasks in the first tick, but limited to those with a started_at
@ -2933,7 +2965,7 @@ mod tests {
before_started_at: Some(second_start_time + Duration::minutes(1)), before_started_at: Some(second_start_time + Duration::minutes(1)),
..Default::default() ..Default::default()
}; };
let tasks = index_scheduler let (tasks, _) = index_scheduler
.get_task_ids_from_authorized_indexes(&rtxn, &query, &AuthFilter::default()) .get_task_ids_from_authorized_indexes(&rtxn, &query, &AuthFilter::default())
.unwrap(); .unwrap();
// both succeeded and processing tasks in the first tick, but limited to those with a started_at // both succeeded and processing tasks in the first tick, but limited to those with a started_at
@ -2953,7 +2985,7 @@ mod tests {
let rtxn = index_scheduler.env.read_txn().unwrap(); let rtxn = index_scheduler.env.read_txn().unwrap();
let tasks = index_scheduler let (tasks, _) = index_scheduler
.get_task_ids_from_authorized_indexes(&rtxn, &query, &AuthFilter::default()) .get_task_ids_from_authorized_indexes(&rtxn, &query, &AuthFilter::default())
.unwrap(); .unwrap();
// we run the same query to verify that, and indeed find that the last task is matched // we run the same query to verify that, and indeed find that the last task is matched
@ -2965,7 +2997,7 @@ mod tests {
before_started_at: Some(second_start_time + Duration::minutes(1)), before_started_at: Some(second_start_time + Duration::minutes(1)),
..Default::default() ..Default::default()
}; };
let tasks = index_scheduler let (tasks, _) = index_scheduler
.get_task_ids_from_authorized_indexes(&rtxn, &query, &AuthFilter::default()) .get_task_ids_from_authorized_indexes(&rtxn, &query, &AuthFilter::default())
.unwrap(); .unwrap();
// enqueued, succeeded, or processing tasks started after the second part of the test, should // enqueued, succeeded, or processing tasks started after the second part of the test, should
@ -2977,7 +3009,7 @@ mod tests {
// now the last task should have failed // now the last task should have failed
snapshot!(snapshot_index_scheduler(&index_scheduler), name: "end"); snapshot!(snapshot_index_scheduler(&index_scheduler), name: "end");
let tasks = index_scheduler let (tasks, _) = index_scheduler
.get_task_ids_from_authorized_indexes(&rtxn, &query, &AuthFilter::default()) .get_task_ids_from_authorized_indexes(&rtxn, &query, &AuthFilter::default())
.unwrap(); .unwrap();
// so running the last query should return nothing // so running the last query should return nothing
@ -2989,7 +3021,7 @@ mod tests {
before_started_at: Some(second_start_time + Duration::minutes(1)), before_started_at: Some(second_start_time + Duration::minutes(1)),
..Default::default() ..Default::default()
}; };
let tasks = index_scheduler let (tasks, _) = index_scheduler
.get_task_ids_from_authorized_indexes(&rtxn, &query, &AuthFilter::default()) .get_task_ids_from_authorized_indexes(&rtxn, &query, &AuthFilter::default())
.unwrap(); .unwrap();
// but the same query on failed tasks should return the last task // but the same query on failed tasks should return the last task
@ -3001,7 +3033,7 @@ mod tests {
before_started_at: Some(second_start_time + Duration::minutes(1)), before_started_at: Some(second_start_time + Duration::minutes(1)),
..Default::default() ..Default::default()
}; };
let tasks = index_scheduler let (tasks, _) = index_scheduler
.get_task_ids_from_authorized_indexes(&rtxn, &query, &AuthFilter::default()) .get_task_ids_from_authorized_indexes(&rtxn, &query, &AuthFilter::default())
.unwrap(); .unwrap();
// but the same query on failed tasks should return the last task // but the same query on failed tasks should return the last task
@ -3014,7 +3046,7 @@ mod tests {
before_started_at: Some(second_start_time + Duration::minutes(1)), before_started_at: Some(second_start_time + Duration::minutes(1)),
..Default::default() ..Default::default()
}; };
let tasks = index_scheduler let (tasks, _) = index_scheduler
.get_task_ids_from_authorized_indexes(&rtxn, &query, &AuthFilter::default()) .get_task_ids_from_authorized_indexes(&rtxn, &query, &AuthFilter::default())
.unwrap(); .unwrap();
// same query but with an invalid uid // same query but with an invalid uid
@ -3027,7 +3059,7 @@ mod tests {
before_started_at: Some(second_start_time + Duration::minutes(1)), before_started_at: Some(second_start_time + Duration::minutes(1)),
..Default::default() ..Default::default()
}; };
let tasks = index_scheduler let (tasks, _) = index_scheduler
.get_task_ids_from_authorized_indexes(&rtxn, &query, &AuthFilter::default()) .get_task_ids_from_authorized_indexes(&rtxn, &query, &AuthFilter::default())
.unwrap(); .unwrap();
// same query but with a valid uid // same query but with a valid uid
@ -3059,14 +3091,14 @@ mod tests {
let rtxn = index_scheduler.env.read_txn().unwrap(); let rtxn = index_scheduler.env.read_txn().unwrap();
let query = Query { index_uids: Some(vec!["catto".to_owned()]), ..Default::default() }; let query = Query { index_uids: Some(vec!["catto".to_owned()]), ..Default::default() };
let tasks = index_scheduler let (tasks, _) = index_scheduler
.get_task_ids_from_authorized_indexes(&rtxn, &query, &AuthFilter::default()) .get_task_ids_from_authorized_indexes(&rtxn, &query, &AuthFilter::default())
.unwrap(); .unwrap();
// only the first task associated with catto is returned, the indexSwap tasks are excluded! // only the first task associated with catto is returned, the indexSwap tasks are excluded!
snapshot!(snapshot_bitmap(&tasks), @"[0,]"); snapshot!(snapshot_bitmap(&tasks), @"[0,]");
let query = Query { index_uids: Some(vec!["catto".to_owned()]), ..Default::default() }; let query = Query { index_uids: Some(vec!["catto".to_owned()]), ..Default::default() };
let tasks = index_scheduler let (tasks, _) = index_scheduler
.get_task_ids_from_authorized_indexes( .get_task_ids_from_authorized_indexes(
&rtxn, &rtxn,
&query, &query,
@ -3080,7 +3112,7 @@ mod tests {
snapshot!(snapshot_bitmap(&tasks), @"[]"); snapshot!(snapshot_bitmap(&tasks), @"[]");
let query = Query::default(); let query = Query::default();
let tasks = index_scheduler let (tasks, _) = index_scheduler
.get_task_ids_from_authorized_indexes( .get_task_ids_from_authorized_indexes(
&rtxn, &rtxn,
&query, &query,
@ -3094,7 +3126,7 @@ mod tests {
snapshot!(snapshot_bitmap(&tasks), @"[1,]"); snapshot!(snapshot_bitmap(&tasks), @"[1,]");
let query = Query::default(); let query = Query::default();
let tasks = index_scheduler let (tasks, _) = index_scheduler
.get_task_ids_from_authorized_indexes( .get_task_ids_from_authorized_indexes(
&rtxn, &rtxn,
&query, &query,
@ -3113,7 +3145,7 @@ mod tests {
snapshot!(snapshot_bitmap(&tasks), @"[0,1,]"); snapshot!(snapshot_bitmap(&tasks), @"[0,1,]");
let query = Query::default(); let query = Query::default();
let tasks = index_scheduler let (tasks, _) = index_scheduler
.get_task_ids_from_authorized_indexes(&rtxn, &query, &AuthFilter::default()) .get_task_ids_from_authorized_indexes(&rtxn, &query, &AuthFilter::default())
.unwrap(); .unwrap();
// we asked for all the tasks with all index authorized -> all tasks returned // we asked for all the tasks with all index authorized -> all tasks returned
@ -3146,7 +3178,7 @@ mod tests {
let rtxn = index_scheduler.read_txn().unwrap(); let rtxn = index_scheduler.read_txn().unwrap();
let query = Query { canceled_by: Some(vec![task_cancelation.uid]), ..Query::default() }; let query = Query { canceled_by: Some(vec![task_cancelation.uid]), ..Query::default() };
let tasks = index_scheduler let (tasks, _) = index_scheduler
.get_task_ids_from_authorized_indexes(&rtxn, &query, &AuthFilter::default()) .get_task_ids_from_authorized_indexes(&rtxn, &query, &AuthFilter::default())
.unwrap(); .unwrap();
// 0 is not returned because it was not canceled, 3 is not returned because it is the uid of the // 0 is not returned because it was not canceled, 3 is not returned because it is the uid of the
@ -3154,7 +3186,7 @@ mod tests {
snapshot!(snapshot_bitmap(&tasks), @"[1,2,]"); snapshot!(snapshot_bitmap(&tasks), @"[1,2,]");
let query = Query { canceled_by: Some(vec![task_cancelation.uid]), ..Query::default() }; let query = Query { canceled_by: Some(vec![task_cancelation.uid]), ..Query::default() };
let tasks = index_scheduler let (tasks, _) = index_scheduler
.get_task_ids_from_authorized_indexes( .get_task_ids_from_authorized_indexes(
&rtxn, &rtxn,
&query, &query,

View File

@ -0,0 +1,36 @@
---
source: index-scheduler/src/lib.rs
---
### Autobatching Enabled = true
### Processing Tasks:
[]
----------------------------------------------------------------------
### All Tasks:
0 {uid: 0, status: enqueued, details: { primary_key: Some("id") }, kind: IndexCreation { index_uid: "index_a", primary_key: Some("id") }}
----------------------------------------------------------------------
### Status:
enqueued [0,]
----------------------------------------------------------------------
### Kind:
"indexCreation" [0,]
----------------------------------------------------------------------
### Index Tasks:
index_a [0,]
----------------------------------------------------------------------
### Index Mapper:
----------------------------------------------------------------------
### Canceled By:
----------------------------------------------------------------------
### Enqueued At:
[timestamp] [0,]
----------------------------------------------------------------------
### Started At:
----------------------------------------------------------------------
### Finished At:
----------------------------------------------------------------------
### File Store:
----------------------------------------------------------------------

View File

@ -15,7 +15,7 @@ license.workspace = true
serde_json = "1.0" serde_json = "1.0"
[dev-dependencies] [dev-dependencies]
criterion = "0.4.0" criterion = "0.5.1"
[[bench]] [[bench]]
name = "depth" name = "depth"

View File

@ -199,6 +199,30 @@ macro_rules! snapshot {
}; };
} }
/// Create a string from the value by serializing it as Json, optionally
/// redacting some parts of it.
///
/// The second argument to the macro can be an object expression for redaction.
/// It's in the form { selector => replacement }. For more information about redactions
/// refer to the redactions feature in the `insta` guide.
#[macro_export]
macro_rules! json_string {
($value:expr, {$($k:expr => $v:expr),*$(,)?}) => {
{
let (_, snap) = meili_snap::insta::_prepare_snapshot_for_redaction!($value, {$($k => $v),*}, Json, File);
snap
}
};
($value:expr) => {{
let value = meili_snap::insta::_macro_support::serialize_value(
&$value,
meili_snap::insta::_macro_support::SerializationFormat::Json,
meili_snap::insta::_macro_support::SnapshotLocation::File
);
value
}};
}
#[cfg(test)] #[cfg(test)]
mod tests { mod tests {
use crate as meili_snap; use crate as meili_snap;
@ -250,27 +274,3 @@ mod tests {
} }
} }
} }
/// Create a string from the value by serializing it as Json, optionally
/// redacting some parts of it.
///
/// The second argument to the macro can be an object expression for redaction.
/// It's in the form { selector => replacement }. For more information about redactions
/// refer to the redactions feature in the `insta` guide.
#[macro_export]
macro_rules! json_string {
($value:expr, {$($k:expr => $v:expr),*$(,)?}) => {
{
let (_, snap) = meili_snap::insta::_prepare_snapshot_for_redaction!($value, {$($k => $v),*}, Json, File);
snap
}
};
($value:expr) => {{
let value = meili_snap::insta::_macro_support::serialize_value(
&$value,
meili_snap::insta::_macro_support::SerializationFormat::Json,
meili_snap::insta::_macro_support::SnapshotLocation::File
);
value
}};
}

View File

@ -1,6 +1,6 @@
use serde::{Deserialize, Serialize}; use serde::{Deserialize, Serialize};
#[derive(Serialize, Deserialize, Debug, Clone, Copy, Default)] #[derive(Serialize, Deserialize, Debug, Clone, Copy, Default, PartialEq, Eq)]
#[serde(rename_all = "camelCase", default)] #[serde(rename_all = "camelCase", default)]
pub struct RuntimeTogglableFeatures { pub struct RuntimeTogglableFeatures {
pub score_details: bool, pub score_details: bool,

View File

@ -19,6 +19,7 @@ actix-http = { version = "3.3.1", default-features = false, features = [
"compress-gzip", "compress-gzip",
"rustls", "rustls",
] } ] }
actix-utils = "3.0.1"
actix-web = { version = "4.3.1", default-features = false, features = [ actix-web = { version = "4.3.1", default-features = false, features = [
"macros", "macros",
"compress-brotli", "compress-brotli",
@ -50,6 +51,7 @@ futures-util = "0.3.28"
http = "0.2.9" http = "0.2.9"
index-scheduler = { path = "../index-scheduler" } index-scheduler = { path = "../index-scheduler" }
indexmap = { version = "1.9.3", features = ["serde-1"] } indexmap = { version = "1.9.3", features = ["serde-1"] }
is-terminal = "0.4.8"
itertools = "0.10.5" itertools = "0.10.5"
jsonwebtoken = "8.3.0" jsonwebtoken = "8.3.0"
lazy_static = "1.4.0" lazy_static = "1.4.0"
@ -102,8 +104,6 @@ uuid = { version = "1.3.1", features = ["serde", "v4"] }
walkdir = "2.3.3" walkdir = "2.3.3"
yaup = "0.2.1" yaup = "0.2.1"
serde_urlencoded = "0.7.1" serde_urlencoded = "0.7.1"
actix-utils = "3.0.1"
atty = "0.2.14"
termcolor = "1.2.0" termcolor = "1.2.0"
[dev-dependencies] [dev-dependencies]
@ -154,5 +154,5 @@ thai = ["meilisearch-types/thai"]
greek = ["meilisearch-types/greek"] greek = ["meilisearch-types/greek"]
[package.metadata.mini-dashboard] [package.metadata.mini-dashboard]
assets-url = "https://github.com/meilisearch/mini-dashboard/releases/download/v0.2.7/build.zip" assets-url = "https://github.com/meilisearch/mini-dashboard/releases/download/v0.2.11/build.zip"
sha1 = "28b45bf772c84f9a6e16bc1689b393bfce8da7d6" sha1 = "83cd44ed1e5f97ecb581dc9f958a63f4ccc982d9"

View File

@ -574,6 +574,10 @@ pub struct SearchAggregator {
filter_total_number_of_criteria: usize, filter_total_number_of_criteria: usize,
used_syntax: HashMap<String, usize>, used_syntax: HashMap<String, usize>,
// attributes_to_search_on
// every time a search is done using attributes_to_search_on
attributes_to_search_on_total_number_of_uses: usize,
// q // q
// The maximum number of terms in a q request // The maximum number of terms in a q request
max_terms_number: usize, max_terms_number: usize,
@ -647,6 +651,11 @@ impl SearchAggregator {
ret.filter_sum_of_criteria_terms = RE.split(&stringified_filters).count(); ret.filter_sum_of_criteria_terms = RE.split(&stringified_filters).count();
} }
// attributes_to_search_on
if let Some(_) = query.attributes_to_search_on {
ret.attributes_to_search_on_total_number_of_uses = 1;
}
if let Some(ref q) = query.q { if let Some(ref q) = query.q {
ret.max_terms_number = q.split_whitespace().count(); ret.max_terms_number = q.split_whitespace().count();
} }
@ -720,9 +729,18 @@ impl SearchAggregator {
let used_syntax = self.used_syntax.entry(key).or_insert(0); let used_syntax = self.used_syntax.entry(key).or_insert(0);
*used_syntax = used_syntax.saturating_add(value); *used_syntax = used_syntax.saturating_add(value);
} }
// attributes_to_search_on
self.attributes_to_search_on_total_number_of_uses = self
.attributes_to_search_on_total_number_of_uses
.saturating_add(other.attributes_to_search_on_total_number_of_uses);
// q // q
self.max_terms_number = self.max_terms_number.max(other.max_terms_number); self.max_terms_number = self.max_terms_number.max(other.max_terms_number);
// vector
self.max_vector_size = self.max_vector_size.max(other.max_vector_size);
// pagination // pagination
self.max_limit = self.max_limit.max(other.max_limit); self.max_limit = self.max_limit.max(other.max_limit);
self.max_offset = self.max_offset.max(other.max_offset); self.max_offset = self.max_offset.max(other.max_offset);
@ -761,17 +779,17 @@ impl SearchAggregator {
if self.total_received == 0 { if self.total_received == 0 {
None None
} else { } else {
// the index of the 99th percentage of value
let percentile_99th = 0.99 * (self.total_succeeded as f64 - 1.) + 1.;
// we get all the values in a sorted manner // we get all the values in a sorted manner
let time_spent = self.time_spent.into_sorted_vec(); let time_spent = self.time_spent.into_sorted_vec();
// the index of the 99th percentage of value
let percentile_99th = time_spent.len() * 99 / 100;
// We are only interested by the slowest value of the 99th fastest results // We are only interested by the slowest value of the 99th fastest results
let time_spent = time_spent.get(percentile_99th as usize); let time_spent = time_spent.get(percentile_99th);
let properties = json!({ let properties = json!({
"user-agent": self.user_agents, "user-agent": self.user_agents,
"requests": { "requests": {
"99th_response_time": time_spent.map(|t| format!("{:.2}", t)), "99th_response_time": time_spent.map(|t| format!("{:.2}", t)),
"total_succeeded": self.total_succeeded, "total_succeeded": self.total_succeeded,
"total_failed": self.total_received.saturating_sub(self.total_succeeded), // just to be sure we never panics "total_failed": self.total_received.saturating_sub(self.total_succeeded), // just to be sure we never panics
"total_received": self.total_received, "total_received": self.total_received,
@ -786,9 +804,15 @@ impl SearchAggregator {
"avg_criteria_number": format!("{:.2}", self.filter_sum_of_criteria_terms as f64 / self.filter_total_number_of_criteria as f64), "avg_criteria_number": format!("{:.2}", self.filter_sum_of_criteria_terms as f64 / self.filter_total_number_of_criteria as f64),
"most_used_syntax": self.used_syntax.iter().max_by_key(|(_, v)| *v).map(|(k, _)| json!(k)).unwrap_or_else(|| json!(null)), "most_used_syntax": self.used_syntax.iter().max_by_key(|(_, v)| *v).map(|(k, _)| json!(k)).unwrap_or_else(|| json!(null)),
}, },
"attributes_to_search_on": {
"total_number_of_uses": self.attributes_to_search_on_total_number_of_uses,
},
"q": { "q": {
"max_terms_number": self.max_terms_number, "max_terms_number": self.max_terms_number,
}, },
"vector": {
"max_vector_size": self.max_vector_size,
},
"pagination": { "pagination": {
"max_limit": self.max_limit, "max_limit": self.max_limit,
"max_offset": self.max_offset, "max_offset": self.max_offset,
@ -843,6 +867,10 @@ pub struct MultiSearchAggregator {
// sum of the number of search queries in the requests, use with total_received to compute an average // sum of the number of search queries in the requests, use with total_received to compute an average
total_search_count: usize, total_search_count: usize,
// scoring
show_ranking_score: bool,
show_ranking_score_details: bool,
// context // context
user_agents: HashSet<String>, user_agents: HashSet<String>,
} }
@ -856,6 +884,9 @@ impl MultiSearchAggregator {
let distinct_indexes: HashSet<_> = let distinct_indexes: HashSet<_> =
query.iter().map(|query| query.index_uid.as_str()).collect(); query.iter().map(|query| query.index_uid.as_str()).collect();
let show_ranking_score = query.iter().any(|query| query.show_ranking_score);
let show_ranking_score_details = query.iter().any(|query| query.show_ranking_score_details);
Self { Self {
timestamp, timestamp,
total_received: 1, total_received: 1,
@ -863,6 +894,8 @@ impl MultiSearchAggregator {
total_distinct_index_count: distinct_indexes.len(), total_distinct_index_count: distinct_indexes.len(),
total_single_index: if distinct_indexes.len() == 1 { 1 } else { 0 }, total_single_index: if distinct_indexes.len() == 1 { 1 } else { 0 },
total_search_count: query.len(), total_search_count: query.len(),
show_ranking_score,
show_ranking_score_details,
user_agents, user_agents,
} }
} }
@ -884,6 +917,9 @@ impl MultiSearchAggregator {
this.total_distinct_index_count.saturating_add(other.total_distinct_index_count); this.total_distinct_index_count.saturating_add(other.total_distinct_index_count);
let total_single_index = this.total_single_index.saturating_add(other.total_single_index); let total_single_index = this.total_single_index.saturating_add(other.total_single_index);
let total_search_count = this.total_search_count.saturating_add(other.total_search_count); let total_search_count = this.total_search_count.saturating_add(other.total_search_count);
let show_ranking_score = this.show_ranking_score || other.show_ranking_score;
let show_ranking_score_details =
this.show_ranking_score_details || other.show_ranking_score_details;
let mut user_agents = this.user_agents; let mut user_agents = this.user_agents;
for user_agent in other.user_agents.into_iter() { for user_agent in other.user_agents.into_iter() {
@ -899,6 +935,8 @@ impl MultiSearchAggregator {
total_single_index, total_single_index,
total_search_count, total_search_count,
user_agents, user_agents,
show_ranking_score,
show_ranking_score_details,
// do not add _ or ..Default::default() here // do not add _ or ..Default::default() here
}; };
@ -925,6 +963,10 @@ impl MultiSearchAggregator {
"searches": { "searches": {
"total_search_count": self.total_search_count, "total_search_count": self.total_search_count,
"avg_search_count": (self.total_search_count as f64) / (self.total_received as f64), "avg_search_count": (self.total_search_count as f64) / (self.total_received as f64),
},
"scoring": {
"show_ranking_score": self.show_ranking_score,
"show_ranking_score_details": self.show_ranking_score_details,
} }
}); });
@ -1145,6 +1187,7 @@ pub struct DocumentsDeletionAggregator {
#[serde(rename = "user-agent")] #[serde(rename = "user-agent")]
user_agents: HashSet<String>, user_agents: HashSet<String>,
#[serde(rename = "requests.total_received")]
total_received: usize, total_received: usize,
per_document_id: bool, per_document_id: bool,
clear_all: bool, clear_all: bool,
@ -1295,6 +1338,7 @@ pub struct HealthAggregator {
#[serde(rename = "user-agent")] #[serde(rename = "user-agent")]
user_agents: HashSet<String>, user_agents: HashSet<String>,
#[serde(rename = "requests.total_received")]
total_received: usize, total_received: usize,
} }
@ -1345,7 +1389,7 @@ pub struct DocumentsFetchAggregator {
#[serde(rename = "user-agent")] #[serde(rename = "user-agent")]
user_agents: HashSet<String>, user_agents: HashSet<String>,
#[serde(rename = "requests.max_limit")] #[serde(rename = "requests.total_received")]
total_received: usize, total_received: usize,
// a call on ../documents/:doc_id // a call on ../documents/:doc_id

View File

@ -1,5 +1,5 @@
use std::env; use std::env;
use std::io::Write; use std::io::{stderr, Write};
use std::path::PathBuf; use std::path::PathBuf;
use std::sync::Arc; use std::sync::Arc;
@ -7,6 +7,7 @@ use actix_web::http::KeepAlive;
use actix_web::web::Data; use actix_web::web::Data;
use actix_web::HttpServer; use actix_web::HttpServer;
use index_scheduler::IndexScheduler; use index_scheduler::IndexScheduler;
use is_terminal::IsTerminal;
use meilisearch::analytics::Analytics; use meilisearch::analytics::Analytics;
use meilisearch::{analytics, create_app, prototype_name, setup_meilisearch, Opt}; use meilisearch::{analytics, create_app, prototype_name, setup_meilisearch, Opt};
use meilisearch_auth::{generate_master_key, AuthController, MASTER_KEY_MIN_SIZE}; use meilisearch_auth::{generate_master_key, AuthController, MASTER_KEY_MIN_SIZE};
@ -190,7 +191,7 @@ Anonymous telemetry:\t\"Enabled\""
} }
eprintln!(); eprintln!();
eprintln!("Check out Meilisearch Cloud!\thttps://cloud.meilisearch.com/login?utm_campaign=oss&utm_source=engine&utm_medium=cli"); eprintln!("Check out Meilisearch Cloud!\thttps://www.meilisearch.com/cloud?utm_campaign=oss&utm_source=engine&utm_medium=cli");
eprintln!("Documentation:\t\t\thttps://www.meilisearch.com/docs"); eprintln!("Documentation:\t\t\thttps://www.meilisearch.com/docs");
eprintln!("Source code:\t\t\thttps://github.com/meilisearch/meilisearch"); eprintln!("Source code:\t\t\thttps://github.com/meilisearch/meilisearch");
eprintln!("Discord:\t\t\thttps://discord.meilisearch.com"); eprintln!("Discord:\t\t\thttps://discord.meilisearch.com");
@ -201,8 +202,7 @@ const WARNING_BG_COLOR: Option<Color> = Some(Color::Ansi256(178));
const WARNING_FG_COLOR: Option<Color> = Some(Color::Ansi256(0)); const WARNING_FG_COLOR: Option<Color> = Some(Color::Ansi256(0));
fn print_master_key_too_short_warning() { fn print_master_key_too_short_warning() {
let choice = let choice = if stderr().is_terminal() { ColorChoice::Auto } else { ColorChoice::Never };
if atty::is(atty::Stream::Stderr) { ColorChoice::Auto } else { ColorChoice::Never };
let mut stderr = StandardStream::stderr(choice); let mut stderr = StandardStream::stderr(choice);
stderr stderr
.set_color( .set_color(
@ -227,8 +227,7 @@ fn print_master_key_too_short_warning() {
} }
fn print_missing_master_key_warning() { fn print_missing_master_key_warning() {
let choice = let choice = if stderr().is_terminal() { ColorChoice::Auto } else { ColorChoice::Never };
if atty::is(atty::Stream::Stderr) { ColorChoice::Auto } else { ColorChoice::Never };
let mut stderr = StandardStream::stderr(choice); let mut stderr = StandardStream::stderr(choice);
stderr stderr
.set_color( .set_color(

View File

@ -50,4 +50,10 @@ lazy_static! {
&["kind", "value"] &["kind", "value"]
) )
.expect("Can't create a metric"); .expect("Can't create a metric");
pub static ref MEILISEARCH_LAST_UPDATE: IntGauge =
register_int_gauge!(opts!("meilisearch_last_update", "Meilisearch Last Update"))
.expect("Can't create a metric");
pub static ref MEILISEARCH_IS_INDEXING: IntGauge =
register_int_gauge!(opts!("meilisearch_is_indexing", "Meilisearch Is Indexing"))
.expect("Can't create a metric");
} }

View File

@ -64,7 +64,20 @@ async fn patch_features(
vector_store: new_features.0.vector_store.unwrap_or(old_features.vector_store), vector_store: new_features.0.vector_store.unwrap_or(old_features.vector_store),
}; };
analytics.publish("Experimental features Updated".to_string(), json!(new_features), Some(&req)); // explicitly destructure for analytics rather than using the `Serialize` implementation, because
// the it renames to camelCase, which we don't want for analytics.
// **Do not** ignore fields with `..` or `_` here, because we want to add them in the future.
let meilisearch_types::features::RuntimeTogglableFeatures { score_details, vector_store } =
new_features;
analytics.publish(
"Experimental features Updated".to_string(),
json!({
"score_details": score_details,
"vector_store": vector_store,
}),
Some(&req),
);
index_scheduler.put_runtime_features(new_features)?; index_scheduler.put_runtime_features(new_features)?;
Ok(HttpResponse::Ok().json(new_features)) Ok(HttpResponse::Ok().json(new_features))
} }

View File

@ -35,7 +35,7 @@ pub struct SearchQueryGet {
#[deserr(default, error = DeserrQueryParamError<InvalidSearchQ>)] #[deserr(default, error = DeserrQueryParamError<InvalidSearchQ>)]
q: Option<String>, q: Option<String>,
#[deserr(default, error = DeserrQueryParamError<InvalidSearchVector>)] #[deserr(default, error = DeserrQueryParamError<InvalidSearchVector>)]
vector: Option<Vec<f32>>, vector: Option<CS<f32>>,
#[deserr(default = Param(DEFAULT_SEARCH_OFFSET()), error = DeserrQueryParamError<InvalidSearchOffset>)] #[deserr(default = Param(DEFAULT_SEARCH_OFFSET()), error = DeserrQueryParamError<InvalidSearchOffset>)]
offset: Param<usize>, offset: Param<usize>,
#[deserr(default = Param(DEFAULT_SEARCH_LIMIT()), error = DeserrQueryParamError<InvalidSearchLimit>)] #[deserr(default = Param(DEFAULT_SEARCH_LIMIT()), error = DeserrQueryParamError<InvalidSearchLimit>)]
@ -88,7 +88,7 @@ impl From<SearchQueryGet> for SearchQuery {
Self { Self {
q: other.q, q: other.q,
vector: other.vector, vector: other.vector.map(CS::into_inner),
offset: other.offset.0, offset: other.offset.0,
limit: other.limit.0, limit: other.limit.0,
page: other.page.as_deref().copied(), page: other.page.as_deref().copied(),

View File

@ -5,6 +5,7 @@ use index_scheduler::IndexScheduler;
use log::debug; use log::debug;
use meilisearch_types::deserr::DeserrJsonError; use meilisearch_types::deserr::DeserrJsonError;
use meilisearch_types::error::ResponseError; use meilisearch_types::error::ResponseError;
use meilisearch_types::facet_values_sort::FacetValuesSort;
use meilisearch_types::index_uid::IndexUid; use meilisearch_types::index_uid::IndexUid;
use meilisearch_types::settings::{settings, RankingRuleView, Settings, Unchecked}; use meilisearch_types::settings::{settings, RankingRuleView, Settings, Unchecked};
use meilisearch_types::tasks::KindWithContent; use meilisearch_types::tasks::KindWithContent;
@ -550,10 +551,16 @@ pub async fn update_all(
.as_ref() .as_ref()
.set() .set()
.and_then(|s| s.max_values_per_facet.as_ref().set()), .and_then(|s| s.max_values_per_facet.as_ref().set()),
"sort_facet_values_by": new_settings.faceting "sort_facet_values_by_star_count": new_settings.faceting
.as_ref() .as_ref()
.set() .set()
.and_then(|s| s.sort_facet_values_by.as_ref().set()), .and_then(|s| {
s.sort_facet_values_by.as_ref().set().map(|s| s.iter().any(|(k, v)| k == "*" && v == &FacetValuesSort::Count))
}),
"sort_facet_values_by_total": new_settings.faceting
.as_ref()
.set()
.and_then(|s| s.sort_facet_values_by.as_ref().set().map(|s| s.len())),
}, },
"pagination": { "pagination": {
"max_total_hits": new_settings.pagination "max_total_hits": new_settings.pagination

View File

@ -49,6 +49,11 @@ pub async fn get_metrics(
} }
} }
if let Some(last_update) = response.last_update {
crate::metrics::MEILISEARCH_LAST_UPDATE.set(last_update.unix_timestamp());
}
crate::metrics::MEILISEARCH_IS_INDEXING.set(index_scheduler.is_task_processing()? as i64);
let encoder = TextEncoder::new(); let encoder = TextEncoder::new();
let mut buffer = vec![]; let mut buffer = vec![];
encoder.encode(&prometheus::gather(), &mut buffer).expect("Failed to encode metrics"); encoder.encode(&prometheus::gather(), &mut buffer).expect("Failed to encode metrics");

View File

@ -284,9 +284,6 @@ pub fn create_all_stats(
used_database_size += index_scheduler.used_size()?; used_database_size += index_scheduler.used_size()?;
database_size += auth_controller.size()?; database_size += auth_controller.size()?;
used_database_size += auth_controller.used_size()?; used_database_size += auth_controller.used_size()?;
let update_file_size = index_scheduler.compute_update_file_size()?;
database_size += update_file_size;
used_database_size += update_file_size;
let stats = Stats { database_size, used_database_size, last_update: last_task, indexes }; let stats = Stats { database_size, used_database_size, last_update: last_task, indexes };
Ok(stats) Ok(stats)

View File

@ -325,7 +325,7 @@ async fn cancel_tasks(
let query = params.into_query(); let query = params.into_query();
let tasks = index_scheduler.get_task_ids_from_authorized_indexes( let (tasks, _) = index_scheduler.get_task_ids_from_authorized_indexes(
&index_scheduler.read_txn()?, &index_scheduler.read_txn()?,
&query, &query,
index_scheduler.filters(), index_scheduler.filters(),
@ -370,7 +370,7 @@ async fn delete_tasks(
); );
let query = params.into_query(); let query = params.into_query();
let tasks = index_scheduler.get_task_ids_from_authorized_indexes( let (tasks, _) = index_scheduler.get_task_ids_from_authorized_indexes(
&index_scheduler.read_txn()?, &index_scheduler.read_txn()?,
&query, &query,
index_scheduler.filters(), index_scheduler.filters(),
@ -387,6 +387,7 @@ async fn delete_tasks(
#[derive(Debug, Serialize)] #[derive(Debug, Serialize)]
pub struct AllTasks { pub struct AllTasks {
results: Vec<TaskView>, results: Vec<TaskView>,
total: u64,
limit: u32, limit: u32,
from: Option<u32>, from: Option<u32>,
next: Option<u32>, next: Option<u32>,
@ -406,23 +407,17 @@ async fn get_tasks(
let limit = params.limit.0; let limit = params.limit.0;
let query = params.into_query(); let query = params.into_query();
let mut tasks_results: Vec<TaskView> = index_scheduler let filters = index_scheduler.filters();
.get_tasks_from_authorized_indexes(query, index_scheduler.filters())? let (tasks, total) = index_scheduler.get_tasks_from_authorized_indexes(query, filters)?;
.into_iter() let mut results: Vec<_> = tasks.iter().map(TaskView::from_task).collect();
.map(|t| TaskView::from_task(&t))
.collect();
// If we were able to fetch the number +1 tasks we asked // If we were able to fetch the number +1 tasks we asked
// it means that there is more to come. // it means that there is more to come.
let next = if tasks_results.len() == limit as usize { let next = if results.len() == limit as usize { results.pop().map(|t| t.uid) } else { None };
tasks_results.pop().map(|t| t.uid)
} else {
None
};
let from = tasks_results.first().map(|t| t.uid); let from = results.first().map(|t| t.uid);
let tasks = AllTasks { results, limit: limit.saturating_sub(1), total, from, next };
let tasks = AllTasks { results: tasks_results, limit: limit.saturating_sub(1), from, next };
Ok(HttpResponse::Ok().json(tasks)) Ok(HttpResponse::Ok().json(tasks))
} }
@ -444,10 +439,10 @@ async fn get_task(
analytics.publish("Tasks Seen".to_string(), json!({ "per_task_uid": true }), Some(&req)); analytics.publish("Tasks Seen".to_string(), json!({ "per_task_uid": true }), Some(&req));
let query = index_scheduler::Query { uids: Some(vec![task_uid]), ..Query::default() }; let query = index_scheduler::Query { uids: Some(vec![task_uid]), ..Query::default() };
let filters = index_scheduler.filters();
let (tasks, _) = index_scheduler.get_tasks_from_authorized_indexes(query, filters)?;
if let Some(task) = if let Some(task) = tasks.first() {
index_scheduler.get_tasks_from_authorized_indexes(query, index_scheduler.filters())?.first()
{
let task_view = TaskView::from_task(task); let task_view = TaskView::from_task(task);
Ok(HttpResponse::Ok().json(task_view)) Ok(HttpResponse::Ok().json(task_view))
} else { } else {

View File

@ -61,6 +61,8 @@ pub static AUTHORIZATIONS: Lazy<HashMap<(&'static str, &'static str), HashSet<&'
("DELETE", "/keys/mykey/") => hashset!{"keys.delete", "*"}, ("DELETE", "/keys/mykey/") => hashset!{"keys.delete", "*"},
("POST", "/keys") => hashset!{"keys.create", "*"}, ("POST", "/keys") => hashset!{"keys.create", "*"},
("GET", "/keys") => hashset!{"keys.get", "*"}, ("GET", "/keys") => hashset!{"keys.get", "*"},
("GET", "/experimental-features") => hashset!{"experimental.get", "*"},
("PATCH", "/experimental-features") => hashset!{"experimental.update", "*"},
}; };
authorizations authorizations

View File

@ -189,6 +189,14 @@ impl Server {
let url = format!("/tasks/{}", update_id); let url = format!("/tasks/{}", update_id);
self.service.get(url).await self.service.get(url).await
} }
pub async fn get_features(&self) -> (Value, StatusCode) {
self.service.get("/experimental-features").await
}
pub async fn set_features(&self, value: Value) -> (Value, StatusCode) {
self.service.patch("/experimental-features", value).await
}
} }
pub fn default_settings(dir: impl AsRef<Path>) -> Opt { pub fn default_settings(dir: impl AsRef<Path>) -> Opt {

View File

@ -43,7 +43,7 @@ async fn import_dump_v1_movie_raw() {
assert_eq!(code, 200); assert_eq!(code, 200);
assert_eq!( assert_eq!(
tasks, tasks,
json!({ "results": [{"uid": 0, "indexUid": "indexUID", "status": "succeeded", "type": "documentAdditionOrUpdate", "canceledBy": null, "details": { "receivedDocuments": 0, "indexedDocuments": 31968 }, "error": null, "duration": "PT9.317060500S", "enqueuedAt": "2021-09-08T09:08:45.153219Z", "startedAt": "2021-09-08T09:08:45.3961665Z", "finishedAt": "2021-09-08T09:08:54.713227Z" }], "limit": 20, "from": 0, "next": null }) json!({ "results": [{"uid": 0, "indexUid": "indexUID", "status": "succeeded", "type": "documentAdditionOrUpdate", "canceledBy": null, "details": { "receivedDocuments": 0, "indexedDocuments": 31968 }, "error": null, "duration": "PT9.317060500S", "enqueuedAt": "2021-09-08T09:08:45.153219Z", "startedAt": "2021-09-08T09:08:45.3961665Z", "finishedAt": "2021-09-08T09:08:54.713227Z" }], "total": 1, "limit": 20, "from": 0, "next": null })
); );
// finally we're just going to check that we can still get a few documents by id // finally we're just going to check that we can still get a few documents by id
@ -135,7 +135,7 @@ async fn import_dump_v1_movie_with_settings() {
assert_eq!(code, 200); assert_eq!(code, 200);
assert_eq!( assert_eq!(
tasks, tasks,
json!({ "results": [{ "uid": 1, "indexUid": "indexUID", "status": "succeeded", "type": "settingsUpdate", "canceledBy": null, "details": { "displayedAttributes": ["genres", "id", "overview", "poster", "release_date", "title"], "searchableAttributes": ["title", "overview"], "filterableAttributes": ["genres"], "sortableAttributes": ["genres"], "stopWords": ["of", "the"] }, "error": null, "duration": "PT7.288826907S", "enqueuedAt": "2021-09-08T09:34:40.882977Z", "startedAt": "2021-09-08T09:34:40.883073093Z", "finishedAt": "2021-09-08T09:34:48.1719Z"}, { "uid": 0, "indexUid": "indexUID", "status": "succeeded", "type": "documentAdditionOrUpdate", "canceledBy": null, "details": { "receivedDocuments": 0, "indexedDocuments": 31968 }, "error": null, "duration": "PT9.090735774S", "enqueuedAt": "2021-09-08T09:34:16.036101Z", "startedAt": "2021-09-08T09:34:16.261191226Z", "finishedAt": "2021-09-08T09:34:25.351927Z" }], "limit": 20, "from": 1, "next": null }) json!({ "results": [{ "uid": 1, "indexUid": "indexUID", "status": "succeeded", "type": "settingsUpdate", "canceledBy": null, "details": { "displayedAttributes": ["genres", "id", "overview", "poster", "release_date", "title"], "searchableAttributes": ["title", "overview"], "filterableAttributes": ["genres"], "sortableAttributes": ["genres"], "stopWords": ["of", "the"] }, "error": null, "duration": "PT7.288826907S", "enqueuedAt": "2021-09-08T09:34:40.882977Z", "startedAt": "2021-09-08T09:34:40.883073093Z", "finishedAt": "2021-09-08T09:34:48.1719Z"}, { "uid": 0, "indexUid": "indexUID", "status": "succeeded", "type": "documentAdditionOrUpdate", "canceledBy": null, "details": { "receivedDocuments": 0, "indexedDocuments": 31968 }, "error": null, "duration": "PT9.090735774S", "enqueuedAt": "2021-09-08T09:34:16.036101Z", "startedAt": "2021-09-08T09:34:16.261191226Z", "finishedAt": "2021-09-08T09:34:25.351927Z" }], "total": 2, "limit": 20, "from": 1, "next": null })
); );
// finally we're just going to check that we can still get a few documents by id // finally we're just going to check that we can still get a few documents by id
@ -317,7 +317,7 @@ async fn import_dump_v2_movie_raw() {
assert_eq!(code, 200); assert_eq!(code, 200);
assert_eq!( assert_eq!(
tasks, tasks,
json!({ "results": [{"uid": 0, "indexUid": "indexUID", "status": "succeeded", "type": "documentAdditionOrUpdate", "canceledBy": null, "details": { "receivedDocuments": 0, "indexedDocuments": 31944 }, "error": null, "duration": "PT41.751156S", "enqueuedAt": "2021-09-08T08:30:30.550282Z", "startedAt": "2021-09-08T08:30:30.553012Z", "finishedAt": "2021-09-08T08:31:12.304168Z" }], "limit": 20, "from": 0, "next": null }) json!({ "results": [{"uid": 0, "indexUid": "indexUID", "status": "succeeded", "type": "documentAdditionOrUpdate", "canceledBy": null, "details": { "receivedDocuments": 0, "indexedDocuments": 31944 }, "error": null, "duration": "PT41.751156S", "enqueuedAt": "2021-09-08T08:30:30.550282Z", "startedAt": "2021-09-08T08:30:30.553012Z", "finishedAt": "2021-09-08T08:31:12.304168Z" }], "total": 1, "limit": 20, "from": 0, "next": null })
); );
// finally we're just going to check that we can still get a few documents by id // finally we're just going to check that we can still get a few documents by id
@ -409,7 +409,7 @@ async fn import_dump_v2_movie_with_settings() {
assert_eq!(code, 200); assert_eq!(code, 200);
assert_eq!( assert_eq!(
tasks, tasks,
json!({ "results": [{ "uid": 1, "indexUid": "indexUID", "status": "succeeded", "type": "settingsUpdate", "canceledBy": null, "details": { "displayedAttributes": ["title", "genres", "overview", "poster", "release_date"], "searchableAttributes": ["title", "overview"], "filterableAttributes": ["genres"], "stopWords": ["of", "the"] }, "error": null, "duration": "PT37.488777S", "enqueuedAt": "2021-09-08T08:24:02.323444Z", "startedAt": "2021-09-08T08:24:02.324145Z", "finishedAt": "2021-09-08T08:24:39.812922Z" }, { "uid": 0, "indexUid": "indexUID", "status": "succeeded", "type": "documentAdditionOrUpdate", "canceledBy": null, "details": { "receivedDocuments": 0, "indexedDocuments": 31944 }, "error": null, "duration": "PT39.941318S", "enqueuedAt": "2021-09-08T08:21:14.742672Z", "startedAt": "2021-09-08T08:21:14.750166Z", "finishedAt": "2021-09-08T08:21:54.691484Z" }], "limit": 20, "from": 1, "next": null }) json!({ "results": [{ "uid": 1, "indexUid": "indexUID", "status": "succeeded", "type": "settingsUpdate", "canceledBy": null, "details": { "displayedAttributes": ["title", "genres", "overview", "poster", "release_date"], "searchableAttributes": ["title", "overview"], "filterableAttributes": ["genres"], "stopWords": ["of", "the"] }, "error": null, "duration": "PT37.488777S", "enqueuedAt": "2021-09-08T08:24:02.323444Z", "startedAt": "2021-09-08T08:24:02.324145Z", "finishedAt": "2021-09-08T08:24:39.812922Z" }, { "uid": 0, "indexUid": "indexUID", "status": "succeeded", "type": "documentAdditionOrUpdate", "canceledBy": null, "details": { "receivedDocuments": 0, "indexedDocuments": 31944 }, "error": null, "duration": "PT39.941318S", "enqueuedAt": "2021-09-08T08:21:14.742672Z", "startedAt": "2021-09-08T08:21:14.750166Z", "finishedAt": "2021-09-08T08:21:54.691484Z" }], "total": 2, "limit": 20, "from": 1, "next": null })
); );
// finally we're just going to check that we can still get a few documents by id // finally we're just going to check that we can still get a few documents by id
@ -591,7 +591,7 @@ async fn import_dump_v3_movie_raw() {
assert_eq!(code, 200); assert_eq!(code, 200);
assert_eq!( assert_eq!(
tasks, tasks,
json!({ "results": [{"uid": 0, "indexUid": "indexUID", "status": "succeeded", "type": "documentAdditionOrUpdate", "canceledBy": null, "details": { "receivedDocuments": 0, "indexedDocuments": 31944 }, "error": null, "duration": "PT41.751156S", "enqueuedAt": "2021-09-08T08:30:30.550282Z", "startedAt": "2021-09-08T08:30:30.553012Z", "finishedAt": "2021-09-08T08:31:12.304168Z" }], "limit": 20, "from": 0, "next": null }) json!({ "results": [{"uid": 0, "indexUid": "indexUID", "status": "succeeded", "type": "documentAdditionOrUpdate", "canceledBy": null, "details": { "receivedDocuments": 0, "indexedDocuments": 31944 }, "error": null, "duration": "PT41.751156S", "enqueuedAt": "2021-09-08T08:30:30.550282Z", "startedAt": "2021-09-08T08:30:30.553012Z", "finishedAt": "2021-09-08T08:31:12.304168Z" }], "total": 1, "limit": 20, "from": 0, "next": null })
); );
// finally we're just going to check that we can still get a few documents by id // finally we're just going to check that we can still get a few documents by id
@ -683,7 +683,7 @@ async fn import_dump_v3_movie_with_settings() {
assert_eq!(code, 200); assert_eq!(code, 200);
assert_eq!( assert_eq!(
tasks, tasks,
json!({ "results": [{ "uid": 1, "indexUid": "indexUID", "status": "succeeded", "type": "settingsUpdate", "canceledBy": null, "details": { "displayedAttributes": ["title", "genres", "overview", "poster", "release_date"], "searchableAttributes": ["title", "overview"], "filterableAttributes": ["genres"], "stopWords": ["of", "the"] }, "error": null, "duration": "PT37.488777S", "enqueuedAt": "2021-09-08T08:24:02.323444Z", "startedAt": "2021-09-08T08:24:02.324145Z", "finishedAt": "2021-09-08T08:24:39.812922Z" }, { "uid": 0, "indexUid": "indexUID", "status": "succeeded", "type": "documentAdditionOrUpdate", "canceledBy": null, "details": { "receivedDocuments": 0, "indexedDocuments": 31944 }, "error": null, "duration": "PT39.941318S", "enqueuedAt": "2021-09-08T08:21:14.742672Z", "startedAt": "2021-09-08T08:21:14.750166Z", "finishedAt": "2021-09-08T08:21:54.691484Z" }], "limit": 20, "from": 1, "next": null }) json!({ "results": [{ "uid": 1, "indexUid": "indexUID", "status": "succeeded", "type": "settingsUpdate", "canceledBy": null, "details": { "displayedAttributes": ["title", "genres", "overview", "poster", "release_date"], "searchableAttributes": ["title", "overview"], "filterableAttributes": ["genres"], "stopWords": ["of", "the"] }, "error": null, "duration": "PT37.488777S", "enqueuedAt": "2021-09-08T08:24:02.323444Z", "startedAt": "2021-09-08T08:24:02.324145Z", "finishedAt": "2021-09-08T08:24:39.812922Z" }, { "uid": 0, "indexUid": "indexUID", "status": "succeeded", "type": "documentAdditionOrUpdate", "canceledBy": null, "details": { "receivedDocuments": 0, "indexedDocuments": 31944 }, "error": null, "duration": "PT39.941318S", "enqueuedAt": "2021-09-08T08:21:14.742672Z", "startedAt": "2021-09-08T08:21:14.750166Z", "finishedAt": "2021-09-08T08:21:54.691484Z" }], "total": 2, "limit": 20, "from": 1, "next": null })
); );
// finally we're just going to check that we can["results"] still get a few documents by id // finally we're just going to check that we can["results"] still get a few documents by id
@ -865,7 +865,7 @@ async fn import_dump_v4_movie_raw() {
assert_eq!(code, 200); assert_eq!(code, 200);
assert_eq!( assert_eq!(
tasks, tasks,
json!({ "results": [{"uid": 0, "indexUid": "indexUID", "status": "succeeded", "type": "documentAdditionOrUpdate", "canceledBy": null, "details": { "receivedDocuments": 0, "indexedDocuments": 31944 }, "error": null, "duration": "PT41.751156S", "enqueuedAt": "2021-09-08T08:30:30.550282Z", "startedAt": "2021-09-08T08:30:30.553012Z", "finishedAt": "2021-09-08T08:31:12.304168Z" }], "limit" : 20, "from": 0, "next": null }) json!({ "results": [{"uid": 0, "indexUid": "indexUID", "status": "succeeded", "type": "documentAdditionOrUpdate", "canceledBy": null, "details": { "receivedDocuments": 0, "indexedDocuments": 31944 }, "error": null, "duration": "PT41.751156S", "enqueuedAt": "2021-09-08T08:30:30.550282Z", "startedAt": "2021-09-08T08:30:30.553012Z", "finishedAt": "2021-09-08T08:31:12.304168Z" }], "total": 1, "limit" : 20, "from": 0, "next": null })
); );
// finally we're just going to check that we can still get a few documents by id // finally we're just going to check that we can still get a few documents by id
@ -957,7 +957,7 @@ async fn import_dump_v4_movie_with_settings() {
assert_eq!(code, 200); assert_eq!(code, 200);
assert_eq!( assert_eq!(
tasks, tasks,
json!({ "results": [{ "uid": 1, "indexUid": "indexUID", "status": "succeeded", "type": "settingsUpdate", "canceledBy": null, "details": { "displayedAttributes": ["title", "genres", "overview", "poster", "release_date"], "searchableAttributes": ["title", "overview"], "filterableAttributes": ["genres"], "stopWords": ["of", "the"] }, "error": null, "duration": "PT37.488777S", "enqueuedAt": "2021-09-08T08:24:02.323444Z", "startedAt": "2021-09-08T08:24:02.324145Z", "finishedAt": "2021-09-08T08:24:39.812922Z" }, { "uid": 0, "indexUid": "indexUID", "status": "succeeded", "type": "documentAdditionOrUpdate", "canceledBy": null, "details": { "receivedDocuments": 0, "indexedDocuments": 31944 }, "error": null, "duration": "PT39.941318S", "enqueuedAt": "2021-09-08T08:21:14.742672Z", "startedAt": "2021-09-08T08:21:14.750166Z", "finishedAt": "2021-09-08T08:21:54.691484Z" }], "limit": 20, "from": 1, "next": null }) json!({ "results": [{ "uid": 1, "indexUid": "indexUID", "status": "succeeded", "type": "settingsUpdate", "canceledBy": null, "details": { "displayedAttributes": ["title", "genres", "overview", "poster", "release_date"], "searchableAttributes": ["title", "overview"], "filterableAttributes": ["genres"], "stopWords": ["of", "the"] }, "error": null, "duration": "PT37.488777S", "enqueuedAt": "2021-09-08T08:24:02.323444Z", "startedAt": "2021-09-08T08:24:02.324145Z", "finishedAt": "2021-09-08T08:24:39.812922Z" }, { "uid": 0, "indexUid": "indexUID", "status": "succeeded", "type": "documentAdditionOrUpdate", "canceledBy": null, "details": { "receivedDocuments": 0, "indexedDocuments": 31944 }, "error": null, "duration": "PT39.941318S", "enqueuedAt": "2021-09-08T08:21:14.742672Z", "startedAt": "2021-09-08T08:21:14.750166Z", "finishedAt": "2021-09-08T08:21:54.691484Z" }], "total": 2, "limit": 20, "from": 1, "next": null })
); );
// finally we're just going to check that we can still get a few documents by id // finally we're just going to check that we can still get a few documents by id

View File

@ -20,6 +20,7 @@ source: meilisearch/tests/dumps/mod.rs
"finishedAt": "2021-09-08T09:08:54.713227Z" "finishedAt": "2021-09-08T09:08:54.713227Z"
} }
], ],
"total": 1,
"limit": 1, "limit": 1,
"from": 0, "from": 0,
"next": null "next": null

View File

@ -20,6 +20,7 @@ source: meilisearch/tests/dumps/mod.rs
"finishedAt": "2021-09-08T09:08:54.713227Z" "finishedAt": "2021-09-08T09:08:54.713227Z"
} }
], ],
"total": 1,
"limit": 1, "limit": 1,
"from": 0, "from": 0,
"next": null "next": null

View File

@ -20,6 +20,7 @@ source: meilisearch/tests/dumps/mod.rs
"finishedAt": "2021-09-08T09:08:54.713227Z" "finishedAt": "2021-09-08T09:08:54.713227Z"
} }
], ],
"total": 1,
"limit": 1, "limit": 1,
"from": 0, "from": 0,
"next": null "next": null

View File

@ -20,6 +20,7 @@ source: meilisearch/tests/dumps/mod.rs
"finishedAt": "2021-09-08T09:08:54.713227Z" "finishedAt": "2021-09-08T09:08:54.713227Z"
} }
], ],
"total": 1,
"limit": 1, "limit": 1,
"from": 0, "from": 0,
"next": null "next": null

View File

@ -20,6 +20,7 @@ source: meilisearch/tests/dumps/mod.rs
"finishedAt": "2021-09-08T09:08:54.713227Z" "finishedAt": "2021-09-08T09:08:54.713227Z"
} }
], ],
"total": 1,
"limit": 1, "limit": 1,
"from": 0, "from": 0,
"next": null "next": null

View File

@ -20,6 +20,7 @@ source: meilisearch/tests/dumps/mod.rs
"finishedAt": "2021-09-08T09:08:54.713227Z" "finishedAt": "2021-09-08T09:08:54.713227Z"
} }
], ],
"total": 1,
"limit": 1, "limit": 1,
"from": 0, "from": 0,
"next": null "next": null

View File

@ -20,6 +20,7 @@ source: meilisearch/tests/dumps/mod.rs
"finishedAt": "2021-09-08T09:08:54.713227Z" "finishedAt": "2021-09-08T09:08:54.713227Z"
} }
], ],
"total": 1,
"limit": 1, "limit": 1,
"from": 0, "from": 0,
"next": null "next": null

View File

@ -20,6 +20,7 @@ source: meilisearch/tests/dumps/mod.rs
"finishedAt": "2021-09-08T09:34:25.351927Z" "finishedAt": "2021-09-08T09:34:25.351927Z"
} }
], ],
"total": 1,
"limit": 1, "limit": 1,
"from": 0, "from": 0,
"next": null "next": null

View File

@ -20,6 +20,7 @@ source: meilisearch/tests/dumps/mod.rs
"finishedAt": "2021-09-08T09:34:25.351927Z" "finishedAt": "2021-09-08T09:34:25.351927Z"
} }
], ],
"total": 1,
"limit": 1, "limit": 1,
"from": 0, "from": 0,
"next": null "next": null

View File

@ -40,6 +40,7 @@ source: meilisearch/tests/dumps/mod.rs
"finishedAt": "2021-09-08T09:34:48.1719Z" "finishedAt": "2021-09-08T09:34:48.1719Z"
} }
], ],
"total": 2,
"limit": 1, "limit": 1,
"from": 1, "from": 1,
"next": 0 "next": 0

View File

@ -40,6 +40,7 @@ source: meilisearch/tests/dumps/mod.rs
"finishedAt": "2021-09-08T09:34:48.1719Z" "finishedAt": "2021-09-08T09:34:48.1719Z"
} }
], ],
"total": 2,
"limit": 1, "limit": 1,
"from": 1, "from": 1,
"next": 0 "next": 0

View File

@ -40,6 +40,7 @@ source: meilisearch/tests/dumps/mod.rs
"finishedAt": "2021-09-08T09:34:48.1719Z" "finishedAt": "2021-09-08T09:34:48.1719Z"
} }
], ],
"total": 2,
"limit": 1, "limit": 1,
"from": 1, "from": 1,
"next": 0 "next": 0

View File

@ -40,6 +40,7 @@ source: meilisearch/tests/dumps/mod.rs
"finishedAt": "2021-09-08T09:34:48.1719Z" "finishedAt": "2021-09-08T09:34:48.1719Z"
} }
], ],
"total": 2,
"limit": 1, "limit": 1,
"from": 1, "from": 1,
"next": 0 "next": 0

View File

@ -40,6 +40,7 @@ source: meilisearch/tests/dumps/mod.rs
"finishedAt": "2021-09-08T09:34:48.1719Z" "finishedAt": "2021-09-08T09:34:48.1719Z"
} }
], ],
"total": 2,
"limit": 1, "limit": 1,
"from": 1, "from": 1,
"next": 0 "next": 0

View File

@ -45,6 +45,7 @@ source: meilisearch/tests/dumps/mod.rs
"finishedAt": "2021-09-08T09:26:57.319083Z" "finishedAt": "2021-09-08T09:26:57.319083Z"
} }
], ],
"total": 1,
"limit": 1, "limit": 1,
"from": 0, "from": 0,
"next": null "next": null

View File

@ -20,6 +20,7 @@ source: meilisearch/tests/dumps/mod.rs
"finishedAt": "2021-09-08T09:28:46.369971Z" "finishedAt": "2021-09-08T09:28:46.369971Z"
} }
], ],
"total": 92,
"limit": 1, "limit": 1,
"from": 92, "from": 92,
"next": 91 "next": 91

View File

@ -20,6 +20,7 @@ source: meilisearch/tests/dumps/mod.rs
"finishedAt": "2021-09-08T09:28:46.369971Z" "finishedAt": "2021-09-08T09:28:46.369971Z"
} }
], ],
"total": 93,
"limit": 1, "limit": 1,
"from": 92, "from": 92,
"next": 91 "next": 91

View File

@ -20,6 +20,7 @@ source: meilisearch/tests/dumps/mod.rs
"finishedAt": "2021-09-08T09:28:46.369971Z" "finishedAt": "2021-09-08T09:28:46.369971Z"
} }
], ],
"total": 93,
"limit": 1, "limit": 1,
"from": 92, "from": 92,
"next": 91 "next": 91

View File

@ -20,6 +20,7 @@ source: meilisearch/tests/dumps/mod.rs
"finishedAt": "2021-09-08T09:28:46.369971Z" "finishedAt": "2021-09-08T09:28:46.369971Z"
} }
], ],
"total": 93,
"limit": 1, "limit": 1,
"from": 92, "from": 92,
"next": 91 "next": 91

View File

@ -20,6 +20,7 @@ source: meilisearch/tests/dumps/mod.rs
"finishedAt": "2021-09-08T09:28:46.369971Z" "finishedAt": "2021-09-08T09:28:46.369971Z"
} }
], ],
"total": 93,
"limit": 1, "limit": 1,
"from": 92, "from": 92,
"next": 91 "next": 91

View File

@ -20,6 +20,7 @@ source: meilisearch/tests/dumps/mod.rs
"finishedAt": "2021-09-08T09:28:46.369971Z" "finishedAt": "2021-09-08T09:28:46.369971Z"
} }
], ],
"total": 93,
"limit": 1, "limit": 1,
"from": 92, "from": 92,
"next": 91 "next": 91

View File

@ -20,6 +20,7 @@ source: meilisearch/tests/dumps/mod.rs
"finishedAt": "2021-09-08T08:31:12.304168Z" "finishedAt": "2021-09-08T08:31:12.304168Z"
} }
], ],
"total": 1,
"limit": 1, "limit": 1,
"from": 0, "from": 0,
"next": null "next": null

View File

@ -20,6 +20,7 @@ source: meilisearch/tests/dumps/mod.rs
"finishedAt": "2021-09-08T08:31:12.304168Z" "finishedAt": "2021-09-08T08:31:12.304168Z"
} }
], ],
"total": 1,
"limit": 1, "limit": 1,
"from": 0, "from": 0,
"next": null "next": null

View File

@ -20,6 +20,7 @@ source: meilisearch/tests/dumps/mod.rs
"finishedAt": "2021-09-08T08:31:12.304168Z" "finishedAt": "2021-09-08T08:31:12.304168Z"
} }
], ],
"total": 1,
"limit": 1, "limit": 1,
"from": 0, "from": 0,
"next": null "next": null

View File

@ -20,6 +20,7 @@ source: meilisearch/tests/dumps/mod.rs
"finishedAt": "2021-09-08T08:31:12.304168Z" "finishedAt": "2021-09-08T08:31:12.304168Z"
} }
], ],
"total": 1,
"limit": 1, "limit": 1,
"from": 0, "from": 0,
"next": null "next": null

View File

@ -20,6 +20,7 @@ source: meilisearch/tests/dumps/mod.rs
"finishedAt": "2021-09-08T08:31:12.304168Z" "finishedAt": "2021-09-08T08:31:12.304168Z"
} }
], ],
"total": 1,
"limit": 1, "limit": 1,
"from": 0, "from": 0,
"next": null "next": null

View File

@ -20,6 +20,7 @@ source: meilisearch/tests/dumps/mod.rs
"finishedAt": "2021-09-08T08:31:12.304168Z" "finishedAt": "2021-09-08T08:31:12.304168Z"
} }
], ],
"total": 1,
"limit": 1, "limit": 1,
"from": 0, "from": 0,
"next": null "next": null

View File

@ -20,6 +20,7 @@ source: meilisearch/tests/dumps/mod.rs
"finishedAt": "2021-09-08T08:31:12.304168Z" "finishedAt": "2021-09-08T08:31:12.304168Z"
} }
], ],
"total": 1,
"limit": 1, "limit": 1,
"from": 0, "from": 0,
"next": null "next": null

View File

@ -20,6 +20,7 @@ source: meilisearch/tests/dumps/mod.rs
"finishedAt": "2021-09-08T08:21:54.691484Z" "finishedAt": "2021-09-08T08:21:54.691484Z"
} }
], ],
"total": 1,
"limit": 1, "limit": 1,
"from": 0, "from": 0,
"next": null "next": null

View File

@ -20,6 +20,7 @@ source: meilisearch/tests/dumps/mod.rs
"finishedAt": "2021-09-08T08:21:54.691484Z" "finishedAt": "2021-09-08T08:21:54.691484Z"
} }
], ],
"total": 1,
"limit": 1, "limit": 1,
"from": 0, "from": 0,
"next": null "next": null

View File

@ -36,6 +36,7 @@ source: meilisearch/tests/dumps/mod.rs
"finishedAt": "2021-09-08T08:24:39.812922Z" "finishedAt": "2021-09-08T08:24:39.812922Z"
} }
], ],
"total": 2,
"limit": 1, "limit": 1,
"from": 1, "from": 1,
"next": 0 "next": 0

View File

@ -36,6 +36,7 @@ source: meilisearch/tests/dumps/mod.rs
"finishedAt": "2021-09-08T08:24:39.812922Z" "finishedAt": "2021-09-08T08:24:39.812922Z"
} }
], ],
"total": 2,
"limit": 1, "limit": 1,
"from": 1, "from": 1,
"next": 0 "next": 0

View File

@ -36,6 +36,7 @@ source: meilisearch/tests/dumps/mod.rs
"finishedAt": "2021-09-08T08:24:39.812922Z" "finishedAt": "2021-09-08T08:24:39.812922Z"
} }
], ],
"total": 2,
"limit": 1, "limit": 1,
"from": 1, "from": 1,
"next": 0 "next": 0

View File

@ -36,6 +36,7 @@ source: meilisearch/tests/dumps/mod.rs
"finishedAt": "2021-09-08T08:24:39.812922Z" "finishedAt": "2021-09-08T08:24:39.812922Z"
} }
], ],
"total": 2,
"limit": 1, "limit": 1,
"from": 1, "from": 1,
"next": 0 "next": 0

View File

@ -36,6 +36,7 @@ source: meilisearch/tests/dumps/mod.rs
"finishedAt": "2021-09-08T08:24:39.812922Z" "finishedAt": "2021-09-08T08:24:39.812922Z"
} }
], ],
"total": 2,
"limit": 1, "limit": 1,
"from": 1, "from": 1,
"next": 0 "next": 0

View File

@ -41,6 +41,7 @@ source: meilisearch/tests/dumps/mod.rs
"finishedAt": "2021-09-08T08:40:28.669652Z" "finishedAt": "2021-09-08T08:40:28.669652Z"
} }
], ],
"total": 1,
"limit": 1, "limit": 1,
"from": 0, "from": 0,
"next": null "next": null

View File

@ -20,6 +20,7 @@ source: meilisearch/tests/dumps/mod.rs
"finishedAt": "2021-09-08T08:51:53.095314Z" "finishedAt": "2021-09-08T08:51:53.095314Z"
} }
], ],
"total": 92,
"limit": 1, "limit": 1,
"from": 92, "from": 92,
"next": 91 "next": 91

View File

@ -20,6 +20,7 @@ source: meilisearch/tests/dumps/mod.rs
"finishedAt": "2021-09-08T08:51:53.095314Z" "finishedAt": "2021-09-08T08:51:53.095314Z"
} }
], ],
"total": 93,
"limit": 1, "limit": 1,
"from": 92, "from": 92,
"next": 91 "next": 91

View File

@ -20,6 +20,7 @@ source: meilisearch/tests/dumps/mod.rs
"finishedAt": "2021-09-08T08:51:53.095314Z" "finishedAt": "2021-09-08T08:51:53.095314Z"
} }
], ],
"total": 93,
"limit": 1, "limit": 1,
"from": 92, "from": 92,
"next": 91 "next": 91

View File

@ -20,6 +20,7 @@ source: meilisearch/tests/dumps/mod.rs
"finishedAt": "2021-09-08T08:51:53.095314Z" "finishedAt": "2021-09-08T08:51:53.095314Z"
} }
], ],
"total": 93,
"limit": 1, "limit": 1,
"from": 92, "from": 92,
"next": 91 "next": 91

View File

@ -20,6 +20,7 @@ source: meilisearch/tests/dumps/mod.rs
"finishedAt": "2021-09-08T08:51:53.095314Z" "finishedAt": "2021-09-08T08:51:53.095314Z"
} }
], ],
"total": 93,
"limit": 1, "limit": 1,
"from": 92, "from": 92,
"next": 91 "next": 91

View File

@ -20,6 +20,7 @@ source: meilisearch/tests/dumps/mod.rs
"finishedAt": "2021-09-08T08:51:53.095314Z" "finishedAt": "2021-09-08T08:51:53.095314Z"
} }
], ],
"total": 93,
"limit": 1, "limit": 1,
"from": 92, "from": 92,
"next": 91 "next": 91

View File

@ -20,6 +20,7 @@ source: meilisearch/tests/dumps/mod.rs
"finishedAt": "2021-09-08T08:31:12.304168Z" "finishedAt": "2021-09-08T08:31:12.304168Z"
} }
], ],
"total": 1,
"limit": 1, "limit": 1,
"from": 0, "from": 0,
"next": null "next": null

View File

@ -20,6 +20,7 @@ source: meilisearch/tests/dumps/mod.rs
"finishedAt": "2021-09-08T08:31:12.304168Z" "finishedAt": "2021-09-08T08:31:12.304168Z"
} }
], ],
"total": 1,
"limit": 1, "limit": 1,
"from": 0, "from": 0,
"next": null "next": null

View File

@ -20,6 +20,7 @@ source: meilisearch/tests/dumps/mod.rs
"finishedAt": "2021-09-08T08:31:12.304168Z" "finishedAt": "2021-09-08T08:31:12.304168Z"
} }
], ],
"total": 1,
"limit": 1, "limit": 1,
"from": 0, "from": 0,
"next": null "next": null

View File

@ -20,6 +20,7 @@ source: meilisearch/tests/dumps/mod.rs
"finishedAt": "2021-09-08T08:31:12.304168Z" "finishedAt": "2021-09-08T08:31:12.304168Z"
} }
], ],
"total": 1,
"limit": 1, "limit": 1,
"from": 0, "from": 0,
"next": null "next": null

View File

@ -20,6 +20,7 @@ source: meilisearch/tests/dumps/mod.rs
"finishedAt": "2021-09-08T08:31:12.304168Z" "finishedAt": "2021-09-08T08:31:12.304168Z"
} }
], ],
"total": 1,
"limit": 1, "limit": 1,
"from": 0, "from": 0,
"next": null "next": null

View File

@ -20,6 +20,7 @@ source: meilisearch/tests/dumps/mod.rs
"finishedAt": "2021-09-08T08:31:12.304168Z" "finishedAt": "2021-09-08T08:31:12.304168Z"
} }
], ],
"total": 1,
"limit": 1, "limit": 1,
"from": 0, "from": 0,
"next": null "next": null

View File

@ -20,6 +20,7 @@ source: meilisearch/tests/dumps/mod.rs
"finishedAt": "2021-09-08T08:31:12.304168Z" "finishedAt": "2021-09-08T08:31:12.304168Z"
} }
], ],
"total": 1,
"limit": 1, "limit": 1,
"from": 0, "from": 0,
"next": null "next": null

View File

@ -20,6 +20,7 @@ source: meilisearch/tests/dumps/mod.rs
"finishedAt": "2021-09-08T08:21:54.691484Z" "finishedAt": "2021-09-08T08:21:54.691484Z"
} }
], ],
"total": 1,
"limit": 1, "limit": 1,
"from": 0, "from": 0,
"next": null "next": null

View File

@ -20,6 +20,7 @@ source: meilisearch/tests/dumps/mod.rs
"finishedAt": "2021-09-08T08:21:54.691484Z" "finishedAt": "2021-09-08T08:21:54.691484Z"
} }
], ],
"total": 1,
"limit": 1, "limit": 1,
"from": 0, "from": 0,
"next": null "next": null

View File

@ -36,6 +36,7 @@ source: meilisearch/tests/dumps/mod.rs
"finishedAt": "2021-09-08T08:24:39.812922Z" "finishedAt": "2021-09-08T08:24:39.812922Z"
} }
], ],
"total": 2,
"limit": 1, "limit": 1,
"from": 1, "from": 1,
"next": 0 "next": 0

View File

@ -36,6 +36,7 @@ source: meilisearch/tests/dumps/mod.rs
"finishedAt": "2021-09-08T08:24:39.812922Z" "finishedAt": "2021-09-08T08:24:39.812922Z"
} }
], ],
"total": 2,
"limit": 1, "limit": 1,
"from": 1, "from": 1,
"next": 0 "next": 0

View File

@ -36,6 +36,7 @@ source: meilisearch/tests/dumps/mod.rs
"finishedAt": "2021-09-08T08:24:39.812922Z" "finishedAt": "2021-09-08T08:24:39.812922Z"
} }
], ],
"total": 2,
"limit": 1, "limit": 1,
"from": 1, "from": 1,
"next": 0 "next": 0

View File

@ -36,6 +36,7 @@ source: meilisearch/tests/dumps/mod.rs
"finishedAt": "2021-09-08T08:24:39.812922Z" "finishedAt": "2021-09-08T08:24:39.812922Z"
} }
], ],
"total": 2,
"limit": 1, "limit": 1,
"from": 1, "from": 1,
"next": 0 "next": 0

View File

@ -36,6 +36,7 @@ source: meilisearch/tests/dumps/mod.rs
"finishedAt": "2021-09-08T08:24:39.812922Z" "finishedAt": "2021-09-08T08:24:39.812922Z"
} }
], ],
"total": 2,
"limit": 1, "limit": 1,
"from": 1, "from": 1,
"next": 0 "next": 0

View File

@ -41,6 +41,7 @@ source: meilisearch/tests/dumps/mod.rs
"finishedAt": "2021-09-08T08:40:28.669652Z" "finishedAt": "2021-09-08T08:40:28.669652Z"
} }
], ],
"total": 1,
"limit": 1, "limit": 1,
"from": 0, "from": 0,
"next": null "next": null

View File

@ -20,6 +20,7 @@ source: meilisearch/tests/dumps/mod.rs
"finishedAt": "2021-09-08T08:51:53.095314Z" "finishedAt": "2021-09-08T08:51:53.095314Z"
} }
], ],
"total": 92,
"limit": 1, "limit": 1,
"from": 92, "from": 92,
"next": 91 "next": 91

View File

@ -20,6 +20,7 @@ source: meilisearch/tests/dumps/mod.rs
"finishedAt": "2021-09-08T08:51:53.095314Z" "finishedAt": "2021-09-08T08:51:53.095314Z"
} }
], ],
"total": 93,
"limit": 1, "limit": 1,
"from": 92, "from": 92,
"next": 91 "next": 91

View File

@ -20,6 +20,7 @@ source: meilisearch/tests/dumps/mod.rs
"finishedAt": "2021-09-08T08:51:53.095314Z" "finishedAt": "2021-09-08T08:51:53.095314Z"
} }
], ],
"total": 93,
"limit": 1, "limit": 1,
"from": 92, "from": 92,
"next": 91 "next": 91

View File

@ -20,6 +20,7 @@ source: meilisearch/tests/dumps/mod.rs
"finishedAt": "2021-09-08T08:51:53.095314Z" "finishedAt": "2021-09-08T08:51:53.095314Z"
} }
], ],
"total": 93,
"limit": 1, "limit": 1,
"from": 92, "from": 92,
"next": 91 "next": 91

View File

@ -20,6 +20,7 @@ source: meilisearch/tests/dumps/mod.rs
"finishedAt": "2021-09-08T08:51:53.095314Z" "finishedAt": "2021-09-08T08:51:53.095314Z"
} }
], ],
"total": 93,
"limit": 1, "limit": 1,
"from": 92, "from": 92,
"next": 91 "next": 91

View File

@ -20,6 +20,7 @@ source: meilisearch/tests/dumps/mod.rs
"finishedAt": "2021-09-08T08:51:53.095314Z" "finishedAt": "2021-09-08T08:51:53.095314Z"
} }
], ],
"total": 93,
"limit": 1, "limit": 1,
"from": 92, "from": 92,
"next": 91 "next": 91

View File

@ -20,6 +20,7 @@ source: meilisearch/tests/dumps/mod.rs
"finishedAt": "2021-09-08T08:31:12.304168Z" "finishedAt": "2021-09-08T08:31:12.304168Z"
} }
], ],
"total": 1,
"limit": 1, "limit": 1,
"from": 0, "from": 0,
"next": null "next": null

View File

@ -20,6 +20,7 @@ source: meilisearch/tests/dumps/mod.rs
"finishedAt": "2021-09-08T08:31:12.304168Z" "finishedAt": "2021-09-08T08:31:12.304168Z"
} }
], ],
"total": 1,
"limit": 1, "limit": 1,
"from": 0, "from": 0,
"next": null "next": null

View File

@ -20,6 +20,7 @@ source: meilisearch/tests/dumps/mod.rs
"finishedAt": "2021-09-08T08:31:12.304168Z" "finishedAt": "2021-09-08T08:31:12.304168Z"
} }
], ],
"total": 1,
"limit": 1, "limit": 1,
"from": 0, "from": 0,
"next": null "next": null

View File

@ -20,6 +20,7 @@ source: meilisearch/tests/dumps/mod.rs
"finishedAt": "2021-09-08T08:31:12.304168Z" "finishedAt": "2021-09-08T08:31:12.304168Z"
} }
], ],
"total": 1,
"limit": 1, "limit": 1,
"from": 0, "from": 0,
"next": null "next": null

View File

@ -20,6 +20,7 @@ source: meilisearch/tests/dumps/mod.rs
"finishedAt": "2021-09-08T08:31:12.304168Z" "finishedAt": "2021-09-08T08:31:12.304168Z"
} }
], ],
"total": 1,
"limit": 1, "limit": 1,
"from": 0, "from": 0,
"next": null "next": null

View File

@ -20,6 +20,7 @@ source: meilisearch/tests/dumps/mod.rs
"finishedAt": "2021-09-08T08:31:12.304168Z" "finishedAt": "2021-09-08T08:31:12.304168Z"
} }
], ],
"total": 1,
"limit": 1, "limit": 1,
"from": 0, "from": 0,
"next": null "next": null

View File

@ -20,6 +20,7 @@ source: meilisearch/tests/dumps/mod.rs
"finishedAt": "2021-09-08T08:31:12.304168Z" "finishedAt": "2021-09-08T08:31:12.304168Z"
} }
], ],
"total": 1,
"limit": 1, "limit": 1,
"from": 0, "from": 0,
"next": null "next": null

View File

@ -20,6 +20,7 @@ source: meilisearch/tests/dumps/mod.rs
"finishedAt": "2021-09-08T08:21:54.691484Z" "finishedAt": "2021-09-08T08:21:54.691484Z"
} }
], ],
"total": 1,
"limit": 1, "limit": 1,
"from": 0, "from": 0,
"next": null "next": null

View File

@ -20,6 +20,7 @@ source: meilisearch/tests/dumps/mod.rs
"finishedAt": "2021-09-08T08:21:54.691484Z" "finishedAt": "2021-09-08T08:21:54.691484Z"
} }
], ],
"total": 1,
"limit": 1, "limit": 1,
"from": 0, "from": 0,
"next": null "next": null

View File

@ -36,6 +36,7 @@ source: meilisearch/tests/dumps/mod.rs
"finishedAt": "2021-09-08T08:24:39.812922Z" "finishedAt": "2021-09-08T08:24:39.812922Z"
} }
], ],
"total": 2,
"limit": 1, "limit": 1,
"from": 1, "from": 1,
"next": 0 "next": 0

Some files were not shown because too many files have changed in this diff Show More