diff --git a/.github/workflows/publish-binaries.yml b/.github/workflows/publish-binaries.yml index 64af0e2c0..304798d75 100644 --- a/.github/workflows/publish-binaries.yml +++ b/.github/workflows/publish-binaries.yml @@ -6,7 +6,7 @@ name: Publish binaries to release jobs: publish: - name: Publish for ${{ matrix.os }} + name: Publish binary for ${{ matrix.os }} runs-on: ${{ matrix.os }} strategy: fail-fast: false @@ -39,7 +39,7 @@ jobs: tag: ${{ github.ref }} publish-aarch64: - name: Publish to GitHub + name: Publish binary for aarch64 runs-on: ${{ matrix.os }} continue-on-error: false strategy: diff --git a/.github/workflows/rust.yml b/.github/workflows/rust.yml index a98e29f44..ff28f82ca 100644 --- a/.github/workflows/rust.yml +++ b/.github/workflows/rust.yml @@ -36,6 +36,25 @@ jobs: command: test args: --locked --release + # We run tests in debug also, to make sure that the debug_assertions are hit + test-debug: + name: Run tests in debug + runs-on: ubuntu-18.04 + steps: + - uses: actions/checkout@v2 + - uses: actions-rs/toolchain@v1 + with: + profile: minimal + toolchain: stable + override: true + - name: Cache dependencies + uses: Swatinem/rust-cache@v1.3.0 + - name: Run tests in debug + uses: actions-rs/cargo@v1 + with: + command: test + args: --locked + clippy: name: Run Clippy runs-on: ubuntu-18.04 diff --git a/Cargo.lock b/Cargo.lock index 3a5f8cb7a..250cb37f1 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -21,11 +21,10 @@ dependencies = [ [[package]] name = "actix-cors" -version = "0.6.0" +version = "0.6.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "30dbd116ef7532f56e2f6d7c511736ea0b124d914ee8820a5271247bf89f06aa" +checksum = "414360eed71ba2d5435b185ba43ecbe281dfab5df3898286d6b7be8074372c92" dependencies = [ - "actix-service", "actix-utils", "actix-web", "derive_more", @@ -37,9 +36,9 @@ dependencies = [ [[package]] name = "actix-http" -version = "3.0.0" +version = "3.0.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0f3fdd63b9cfeaf92eeeece719dabbddddb420a57d3fd171ce1490ecfb7086b1" +checksum = "a5885cb81a0d4d0d322864bea1bb6c2a8144626b4fdc625d4c51eba197e7797a" dependencies = [ "actix-codec", "actix-rt", @@ -47,7 +46,7 @@ dependencies = [ "actix-tls", "actix-utils", "ahash 0.7.6", - "base64 0.13.0", + "base64", "bitflags", "brotli", "bytes", @@ -68,9 +67,8 @@ dependencies = [ "percent-encoding", "pin-project-lite", "rand", - "sha-1 0.10.0", + "sha-1", "smallvec", - "zstd", ] [[package]] @@ -79,8 +77,8 @@ version = "0.2.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "465a6172cf69b960917811022d8f29bc0b7fa1398bc4f78b3c466673db1213b6" dependencies = [ - "quote 1.0.15", - "syn 1.0.86", + "quote 1.0.16", + "syn 1.0.89", ] [[package]] @@ -99,9 +97,9 @@ dependencies = [ [[package]] name = "actix-rt" -version = "2.6.0" +version = "2.7.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cdf3f2183be1241ed4dd22611850b85d38de0b08a09f1f7bcccbd0809084b359" +checksum = "7ea16c295198e958ef31930a6ef37d0fb64e9ca3b6116e6b93a8bdae96ee1000" dependencies = [ "actix-macros", "futures-core", @@ -110,20 +108,20 @@ dependencies = [ [[package]] name = "actix-server" -version = "2.0.0" +version = "2.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d9e7472ac180abb0a8e592b653744345983a7a14f44691c8394a799d0df4dbbf" +checksum = "0da34f8e659ea1b077bb4637948b815cd3768ad5a188fdcd74ff4d84240cd824" dependencies = [ "actix-rt", "actix-service", "actix-utils", "futures-core", "futures-util", - "log", "mio", "num_cpus", "socket2", "tokio", + "tracing", ] [[package]] @@ -202,7 +200,7 @@ dependencies = [ "serde_urlencoded", "smallvec", "socket2", - "time 0.3.7", + "time 0.3.9", "url", ] @@ -214,8 +212,8 @@ checksum = "7525bedf54704abb1d469e88d7e7e9226df73778798a69cea5022d53b2ae91bc" dependencies = [ "actix-router", "proc-macro2 1.0.36", - "quote 1.0.15", - "syn 1.0.86", + "quote 1.0.16", + "syn 1.0.89", ] [[package]] @@ -287,19 +285,13 @@ dependencies = [ [[package]] name = "anyhow" -version = "1.0.55" +version = "1.0.56" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "159bb86af3a200e19a068f4224eae4c8bb2d0fa054c7e5d1cacd5cef95e684cd" +checksum = "4361135be9122e0870de935d7c439aef945b9f9ddd4199a553b5270b49c82a27" dependencies = [ "backtrace", ] -[[package]] -name = "arc-swap" -version = "1.5.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c5d78ce20460b82d3fa150275ed9d55e21064fc7951177baacf86a145c4a4b1f" - [[package]] name = "as-slice" version = "0.1.5" @@ -324,9 +316,9 @@ dependencies = [ [[package]] name = "async-stream" -version = "0.3.2" +version = "0.3.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "171374e7e3b2504e0e5236e3b59260560f9fe94bfe9ac39ba5e4e929c5590625" +checksum = "dad5c83079eae9969be7fadefe640a1c566901f05ff91ab221de4b6f68d9507e" dependencies = [ "async-stream-impl", "futures-core", @@ -334,13 +326,13 @@ dependencies = [ [[package]] name = "async-stream-impl" -version = "0.3.2" +version = "0.3.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "648ed8c8d2ce5409ccd57453d9d1b214b342a0d69376a6feda1fd6cae3299308" +checksum = "10f203db73a71dfa2fb6dd22763990fa26f3d2625a6da2da900d23b87d26be27" dependencies = [ "proc-macro2 1.0.36", - "quote 1.0.15", - "syn 1.0.86", + "quote 1.0.16", + "syn 1.0.89", ] [[package]] @@ -350,8 +342,8 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "061a7acccaa286c011ddc30970520b98fa40e00c9d644633fb26b5fc63a265e3" dependencies = [ "proc-macro2 1.0.36", - "quote 1.0.15", - "syn 1.0.86", + "quote 1.0.16", + "syn 1.0.89", ] [[package]] @@ -392,12 +384,6 @@ dependencies = [ "rustc-demangle", ] -[[package]] -name = "base64" -version = "0.12.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3441f0f7b02788e948e47f457ca01f1d7e6d92c693bc132c22b087d3141c03ff" - [[package]] name = "base64" version = "0.13.0" @@ -443,15 +429,6 @@ version = "1.3.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a" -[[package]] -name = "block-buffer" -version = "0.9.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4152116fd6e9dadb291ae18fc1ec3575ed6d84c29642d97890f4b4a3417297e4" -dependencies = [ - "generic-array 0.14.5", -] - [[package]] name = "block-buffer" version = "0.10.2" @@ -494,6 +471,12 @@ dependencies = [ "serde", ] +[[package]] +name = "build_const" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b4ae4235e6dac0694637c763029ecea1a2ec9e4e06ec2729bd21ba4d9c863eb7" + [[package]] name = "bumpalo" version = "3.9.1" @@ -502,9 +485,9 @@ checksum = "a4a45a46ab1f2412e53d3a0ade76ffad2025804294569aae387231a0cd6e0899" [[package]] name = "byte-unit" -version = "4.0.13" +version = "4.0.14" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "956ffc5b0ec7d7a6949e3f21fd63ba5af4cffdc2ba1e0b7bf62b481458c4ae7f" +checksum = "95ebf10dda65f19ff0f42ea15572a359ed60d7fc74fdc984d90310937be0014b" dependencies = [ "serde", "utf8-width", @@ -518,9 +501,9 @@ checksum = "72feb31ffc86498dacdbd0fcebb56138e7177a8cc5cea4516031d15ae85a742e" [[package]] name = "bytemuck" -version = "1.7.3" +version = "1.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "439989e6b8c38d1b6570a384ef1e49c8848128f5a97f3914baef02920842712f" +checksum = "0e851ca7c24871e7336801608a4797d7376545b6928a10d32d75685687141ead" dependencies = [ "bytemuck_derive", ] @@ -532,8 +515,8 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8e215f8c2f9f79cb53c8335e687ffd07d5bfcb6fe5fc80723762d0be46e7cc54" dependencies = [ "proc-macro2 1.0.36", - "quote 1.0.15", - "syn 1.0.86", + "quote 1.0.16", + "syn 1.0.89", ] [[package]] @@ -580,9 +563,9 @@ dependencies = [ [[package]] name = "cargo_toml" -version = "0.9.2" +version = "0.11.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9c3596addfb02dcdc06f5252ddda9f3785f9230f5827fb4284645240fa05ad92" +checksum = "5809dd3e6444651fd1cdd3dbec71eca438c439a0fcc8081674a14da0afe50185" dependencies = [ "serde", "serde_derive", @@ -638,25 +621,11 @@ dependencies = [ "bincode", ] -[[package]] -name = "chrono" -version = "0.4.19" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "670ad68c9088c2a963aaa298cb369688cf3f9465ce5e2d4ca10e6e0098a1ce73" -dependencies = [ - "libc", - "num-integer", - "num-traits", - "serde", - "time 0.1.44", - "winapi", -] - [[package]] name = "clap" -version = "3.1.2" +version = "3.1.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5177fac1ab67102d8989464efd043c6ff44191b1557ec1ddd489b4f7e1447e77" +checksum = "d8c93436c21e4698bacadf42917db28b23017027a4deccb35dbe47a7e7840123" dependencies = [ "atty", "bitflags", @@ -671,15 +640,15 @@ dependencies = [ [[package]] name = "clap_derive" -version = "3.1.2" +version = "3.1.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "01d42c94ce7c2252681b5fed4d3627cc807b13dfc033246bd05d5b252399000e" +checksum = "da95d038ede1a964ce99f49cbe27a7fb538d1da595e4b4f70b8c8f338d17bf16" dependencies = [ "heck", "proc-macro-error", "proc-macro2 1.0.36", - "quote 1.0.15", - "syn 1.0.86", + "quote 1.0.16", + "syn 1.0.89", ] [[package]] @@ -689,8 +658,8 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1df715824eb382e34b7afb7463b0247bf41538aeba731fba05241ecdb5dc3747" dependencies = [ "proc-macro2 1.0.36", - "quote 1.0.15", - "syn 1.0.86", + "quote 1.0.16", + "syn 1.0.89", ] [[package]] @@ -706,10 +675,20 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "94d4706de1b0fa5b132270cddffa8585166037822e260a944fe161acd137ca05" dependencies = [ "percent-encoding", - "time 0.3.7", + "time 0.3.9", "version_check", ] +[[package]] +name = "core-foundation" +version = "0.9.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "194a7a9e6de53fa55116934067c844d9d749312f75c6f6d0980e8c252f8c2146" +dependencies = [ + "core-foundation-sys", + "libc", +] + [[package]] name = "core-foundation-sys" version = "0.8.3" @@ -724,13 +703,22 @@ checksum = "79bb3adfaf5f75d24b01aee375f7555907840fa2800e5ec8fa3b9e2031830173" [[package]] name = "cpufeatures" -version = "0.2.1" +version = "0.2.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "95059428f66df56b63431fdb4e1947ed2190586af5c5a8a8b71122bdf5a7f469" +checksum = "59a6001667ab124aebae2a495118e11d30984c3a653e99d86d58971708cf5e4b" dependencies = [ "libc", ] +[[package]] +name = "crc" +version = "1.8.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d663548de7f5cca343f1e0a48d14dcfb0e9eb4e079ec58883b7251539fa10aeb" +dependencies = [ + "build_const", +] + [[package]] name = "crc32fast" version = "1.3.2" @@ -742,12 +730,12 @@ dependencies = [ [[package]] name = "crossbeam-channel" -version = "0.5.2" +version = "0.5.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e54ea8bc3fb1ee042f5aace6e3c6e025d3874866da222930f70ce62aceba0bfa" +checksum = "5aaa7bd5fb665c6864b5f963dd9097905c54125909c7aa94c9e18507cdbe6c53" dependencies = [ "cfg-if 1.0.0", - "crossbeam-utils 0.8.7", + "crossbeam-utils 0.8.8", ] [[package]] @@ -758,17 +746,18 @@ checksum = "6455c0ca19f0d2fbf751b908d5c55c1f5cbc65e03c4225427254b46890bdde1e" dependencies = [ "cfg-if 1.0.0", "crossbeam-epoch", - "crossbeam-utils 0.8.7", + "crossbeam-utils 0.8.8", ] [[package]] name = "crossbeam-epoch" -version = "0.9.7" +version = "0.9.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c00d6d2ea26e8b151d99093005cb442fb9a37aeaca582a03ec70946f49ab5ed9" +checksum = "1145cf131a2c6ba0615079ab6a638f7e1973ac9c2634fcbeaaad6114246efe8c" dependencies = [ + "autocfg", "cfg-if 1.0.0", - "crossbeam-utils 0.8.7", + "crossbeam-utils 0.8.8", "lazy_static", "memoffset", "scopeguard", @@ -795,9 +784,9 @@ dependencies = [ [[package]] name = "crossbeam-utils" -version = "0.8.7" +version = "0.8.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b5e5bed1f1c269533fa816a0a5492b3545209a205ca1a54842be180eb63a16a6" +checksum = "0bf124c720b7686e3c2663cf54062ab0f68a88af2fb6a030e87e30bf721fcb38" dependencies = [ "cfg-if 1.0.0", "lazy_static", @@ -842,8 +831,8 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "fcc3dd5e9e9c0b295d6e1e4d811fb6f157d5ffd784b8d202fc62eac8035a770b" dependencies = [ "proc-macro2 1.0.36", - "quote 1.0.15", - "syn 1.0.86", + "quote 1.0.16", + "syn 1.0.89", ] [[package]] @@ -854,9 +843,9 @@ checksum = "4fb810d30a7c1953f91334de7244731fc3f3c10d7fe163338a35b9f640960321" dependencies = [ "convert_case", "proc-macro2 1.0.36", - "quote 1.0.15", + "quote 1.0.16", "rustc_version", - "syn 1.0.86", + "syn 1.0.89", ] [[package]] @@ -866,19 +855,10 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f2c9736e15e7df1638a7f6eee92a6511615c738246a052af5ba86f039b65aede" [[package]] -name = "difference" -version = "2.0.0" +name = "difflib" +version = "0.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "524cbf6897b527295dff137cec09ecf3a05f4fddffd7dfcd1585403449e74198" - -[[package]] -name = "digest" -version = "0.9.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d3dd60d1080a57a05ab032377049e0591415d2b31afd7028356dbf3cc6dcb066" -dependencies = [ - "generic-array 0.14.5", -] +checksum = "6184e33543162437515c2e2b48714794e37845ec9851711914eec9d308f6ebe8" [[package]] name = "digest" @@ -886,7 +866,7 @@ version = "0.10.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f2fb860ca6fafa5552fb6d0e816a69c8e49f0908bf524e30a90d97c85892d506" dependencies = [ - "block-buffer 0.10.2", + "block-buffer", "crypto-common", ] @@ -913,9 +893,9 @@ dependencies = [ [[package]] name = "downcast" -version = "0.10.0" +version = "0.11.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4bb454f0228b18c7f4c3b0ebbee346ed9c52e7443b0999cd543ff3571205701d" +checksum = "1435fa1053d8b2fbbe9be7e97eca7f33d37b28409959813daefc1446a14247f1" [[package]] name = "either" @@ -923,6 +903,70 @@ version = "1.6.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e78d4f1cc4ae33bbfc157ed5d5a5ef3bc29227303d595861deb238fcec4e9457" +[[package]] +name = "encoding" +version = "0.2.33" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6b0d943856b990d12d3b55b359144ff341533e516d94098b1d3fc1ac666d36ec" +dependencies = [ + "encoding-index-japanese", + "encoding-index-korean", + "encoding-index-simpchinese", + "encoding-index-singlebyte", + "encoding-index-tradchinese", +] + +[[package]] +name = "encoding-index-japanese" +version = "1.20141219.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "04e8b2ff42e9a05335dbf8b5c6f7567e5591d0d916ccef4e0b1710d32a0d0c91" +dependencies = [ + "encoding_index_tests", +] + +[[package]] +name = "encoding-index-korean" +version = "1.20141219.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4dc33fb8e6bcba213fe2f14275f0963fd16f0a02c878e3095ecfdf5bee529d81" +dependencies = [ + "encoding_index_tests", +] + +[[package]] +name = "encoding-index-simpchinese" +version = "1.20141219.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d87a7194909b9118fc707194baa434a4e3b0fb6a5a757c73c3adb07aa25031f7" +dependencies = [ + "encoding_index_tests", +] + +[[package]] +name = "encoding-index-singlebyte" +version = "1.20141219.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3351d5acffb224af9ca265f435b859c7c01537c0849754d3db3fdf2bfe2ae84a" +dependencies = [ + "encoding_index_tests", +] + +[[package]] +name = "encoding-index-tradchinese" +version = "1.20141219.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fd0e20d5688ce3cab59eb3ef3a2083a5c77bf496cb798dc6fcdb75f323890c18" +dependencies = [ + "encoding_index_tests", +] + +[[package]] +name = "encoding_index_tests" +version = "0.1.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a246d82be1c9d791c5dfde9a2bd045fc3cbba3fa2b11ad558f27d01712f00569" + [[package]] name = "encoding_rs" version = "0.8.30" @@ -948,8 +992,8 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c134c37760b27a871ba422106eedbb8247da973a09e82558bf26d619c882b159" dependencies = [ "proc-macro2 1.0.36", - "quote 1.0.15", - "syn 1.0.86", + "quote 1.0.16", + "syn 1.0.89", ] [[package]] @@ -989,7 +1033,7 @@ dependencies = [ [[package]] name = "filter-parser" version = "0.1.0" -source = "git+https://github.com/meilisearch/milli.git?tag=v0.22.1#ea15ad6c34492b32eb7ac06e69de02b6dc70a707" +source = "git+https://github.com/meilisearch/milli.git?tag=v0.24.0#5863afa1a568950de2928ba2d78b95aee243dad1" dependencies = [ "nom", "nom_locate", @@ -1015,9 +1059,9 @@ dependencies = [ [[package]] name = "float-cmp" -version = "0.8.0" +version = "0.9.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e1267f4ac4f343772758f7b1bdcbe767c218bbab93bb432acbf5162bbf85a6c4" +checksum = "98de4bbd547a563b716d8dfa9aad1cb19bfab00f4fa09a6a4ed21dbcf44ce9c4" dependencies = [ "num-traits", ] @@ -1028,6 +1072,21 @@ version = "1.0.7" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3f9eec918d3f24069decb9af1554cad7c880e2da24a9afd88aca000531ab82c1" +[[package]] +name = "foreign-types" +version = "0.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f6f339eb8adc052cd2ca78910fda869aefa38d22d5cb648e6485e4d3fc06f3b1" +dependencies = [ + "foreign-types-shared", +] + +[[package]] +name = "foreign-types-shared" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "00b0228411908ca8685dba7fc2cdd70ec9990a6e753e89b6ac91a84c40fbaf4b" + [[package]] name = "form_urlencoded" version = "1.0.1" @@ -1111,8 +1170,8 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "33c1e13800337f4d4d7a316bf45a567dbcb6ffe087f16424852d97e97a91f512" dependencies = [ "proc-macro2 1.0.36", - "quote 1.0.15", - "syn 1.0.86", + "quote 1.0.16", + "syn 1.0.89", ] [[package]] @@ -1196,7 +1255,7 @@ checksum = "d39cd93900197114fa1fcb7ae84ca742095eed9442088988ae74fa744e930e77" dependencies = [ "cfg-if 1.0.0", "libc", - "wasi", + "wasi 0.10.2+wasi-snapshot-preview1", ] [[package]] @@ -1207,8 +1266,8 @@ checksum = "e45727250e75cc04ff2846a66397da8ef2b3db8e40e0cef4df67950a07621eb9" dependencies = [ "proc-macro-error", "proc-macro2 1.0.36", - "quote 1.0.15", - "syn 1.0.86", + "quote 1.0.16", + "syn 1.0.89", ] [[package]] @@ -1219,9 +1278,9 @@ checksum = "78cc372d058dcf6d5ecd98510e7fbc9e5aec4d21de70f65fea8fecebcd881bd4" [[package]] name = "git2" -version = "0.14.0" +version = "0.14.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "94781080dd1a6b55dea7c46540d5bac87742a22f6dc2d84e54a5071ad6f0e387" +checksum = "3826a6e0e2215d7a41c2bfc7c9244123969273f3476b939a226aac0ab56e9e3c" dependencies = [ "bitflags", "libc", @@ -1238,9 +1297,9 @@ checksum = "9b919933a397b79c37e33b77bb2aa3dc8eb6e165ad809e58ff75bc7db2e34574" [[package]] name = "grenad" -version = "0.3.1" +version = "0.4.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1a7a9cc43b28a20f791b17863f34a36654fdfa50be6d0a67bb18c1e34d145f18" +checksum = "1d69e46e7b225459e2e0272707d167d7dcaaac89307a848326df6b30ec432151" dependencies = [ "bytemuck", "byteorder", @@ -1249,9 +1308,9 @@ dependencies = [ [[package]] name = "h2" -version = "0.3.11" +version = "0.3.12" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d9f1f717ddc7b2ba36df7e871fd88db79326551d3d6f1fc406fbfd28b582ff8e" +checksum = "62eeb471aa3e3c9197aa4bfeabfe02982f6dc96f750486c0bb0009ac58b26d2b" dependencies = [ "bytes", "fnv", @@ -1312,7 +1371,7 @@ checksum = "2540771e65fc8cb83cd6e8a237f70c319bd5c29f78ed1084ba5d50eeac86f7f9" [[package]] name = "heed" version = "0.12.1" -source = "git+https://github.com/Kerollmops/heed?tag=v0.12.1#fc017cf3394af737f92fd71e16f0499a78b79d65" +source = "git+https://github.com/meilisearch/heed?tag=v0.12.1#fc017cf3394af737f92fd71e16f0499a78b79d65" dependencies = [ "byteorder", "heed-traits", @@ -1321,7 +1380,6 @@ dependencies = [ "lmdb-rkv-sys", "once_cell", "page_size", - "serde", "synchronoise", "url", "zerocopy", @@ -1330,12 +1388,12 @@ dependencies = [ [[package]] name = "heed-traits" version = "0.7.0" -source = "git+https://github.com/Kerollmops/heed?tag=v0.12.1#fc017cf3394af737f92fd71e16f0499a78b79d65" +source = "git+https://github.com/meilisearch/heed?tag=v0.12.1#fc017cf3394af737f92fd71e16f0499a78b79d65" [[package]] name = "heed-types" version = "0.7.2" -source = "git+https://github.com/Kerollmops/heed?tag=v0.12.1#fc017cf3394af737f92fd71e16f0499a78b79d65" +source = "git+https://github.com/meilisearch/heed?tag=v0.12.1#fc017cf3394af737f92fd71e16f0499a78b79d65" dependencies = [ "bincode", "heed-traits", @@ -1393,12 +1451,6 @@ version = "1.0.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c4a1e36c821dbe04574f602848a19f742f4fb3c98d40449f11bcad18d6b17421" -[[package]] -name = "human_format" -version = "1.0.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "86cce260d758a9aa3d7c4b99d55c815a540f8a37514ba6046ab6be402a157cb0" - [[package]] name = "humantime" version = "2.1.0" @@ -1407,9 +1459,9 @@ checksum = "9a3a5bfb195931eeb336b2a7b4d761daec841b97f947d34394601737a7bba5e4" [[package]] name = "hyper" -version = "0.14.17" +version = "0.14.18" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "043f0e083e9901b6cc658a77d1eb86f4fc650bbb977a4337dd63192826aa85dd" +checksum = "b26ae0a80afebe130861d90abf98e3814a4f28a4c6ffeb5ab8ebb2be311e0ef2" dependencies = [ "bytes", "futures-channel", @@ -1437,11 +1489,24 @@ checksum = "d87c48c02e0dc5e3b849a2041db3029fd066650f8f717c07bf8ed78ccb895cac" dependencies = [ "http", "hyper", - "rustls 0.20.4", + "rustls", "tokio", "tokio-rustls", ] +[[package]] +name = "hyper-tls" +version = "0.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d6183ddfa99b85da61a140bea0efc93fdf56ceaa041b37d553518030827f9905" +dependencies = [ + "bytes", + "hyper", + "native-tls", + "tokio", + "tokio-native-tls", +] + [[package]] name = "idna" version = "0.2.3" @@ -1475,9 +1540,9 @@ dependencies = [ [[package]] name = "ipnet" -version = "2.3.1" +version = "2.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "68f2d64f2edebec4ce84ad108148e67e1064789bee435edc5b60ad398714a3a9" +checksum = "35e70ee094dc02fd9c13fdad4940090f22dbd6ac7c9e7094a46cf0232a50bc7c" [[package]] name = "itertools" @@ -1535,11 +1600,11 @@ dependencies = [ [[package]] name = "jsonwebtoken" -version = "7.2.0" +version = "8.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "afabcc15e437a6484fc4f12d0fd63068fe457bf93f1c148d3d9649c60b103f32" +checksum = "012bb02250fdd38faa5feee63235f7a459974440b9b57593822414c31f92839e" dependencies = [ - "base64 0.12.3", + "base64", "pem", "ring", "serde", @@ -1570,15 +1635,15 @@ dependencies = [ [[package]] name = "libc" -version = "0.2.119" +version = "0.2.121" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1bf2e165bb3457c8e098ea76f3e3bc9db55f87aa90d52d0e6be741470916aaa4" +checksum = "efaa7b300f3b5fe8eb6bf21ce3895e1751d9665086af2d64b42f19701015ff4f" [[package]] name = "libgit2-sys" -version = "0.13.0+1.4.1" +version = "0.13.2+1.4.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "864e22fc06cae62860398cd854c93d5867f11c02ec916aa1417b440f170df23a" +checksum = "3a42de9a51a5c12e00fc0e4ca6bc2ea43582fc6418488e8f615e905d886f258b" dependencies = [ "cc", "libc", @@ -1588,9 +1653,9 @@ dependencies = [ [[package]] name = "libz-sys" -version = "1.1.3" +version = "1.1.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "de5435b8549c16d423ed0c03dbaafe57cf6c3344744f1242520d59c9d8ecec66" +checksum = "6f35facd4a5673cb5a48822be2be1d4236c1c99cb4113cab7061ac720d5bf859" dependencies = [ "cc", "libc", @@ -1599,10 +1664,100 @@ dependencies = [ ] [[package]] -name = "linked-hash-map" -version = "0.5.4" +name = "lindera" +version = "0.10.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7fb9b38af92608140b86b693604b9ffcc5824240a484d1ecd4795bacb2fe88f3" +checksum = "29719eff479c5d34182dd16c708a413790106b790aa25f5e2f57ae6730715e69" +dependencies = [ + "anyhow", + "bincode", + "byteorder", + "encoding", + "lindera-core", + "lindera-dictionary", + "lindera-ipadic", + "lindera-ipadic-builder", + "serde", + "serde_json", +] + +[[package]] +name = "lindera-core" +version = "0.10.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5bc4dc99a35081246649b978d212c2c8d6b9adf8171c14bed844ad9c6475af45" +dependencies = [ + "anyhow", + "bincode", + "byteorder", + "encoding", + "log", + "serde", + "thiserror", + "yada", +] + +[[package]] +name = "lindera-decompress" +version = "0.10.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fc8e3d628f7d94c84fa864741b35172ea6b87d2a6efb37f7bca41532b952c24d" +dependencies = [ + "anyhow", + "bincode", + "lzma-rs", + "serde", +] + +[[package]] +name = "lindera-dictionary" +version = "0.10.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "632f75733b3b366a0079ee5fb70215b706c1986dcebddfd5db95849b32e6e694" +dependencies = [ + "anyhow", + "bincode", + "byteorder", + "lindera-core", +] + +[[package]] +name = "lindera-ipadic" +version = "0.10.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b71878006e14474ae3aa7265c4dc5bb9db861e42ba8df9a254e0b5c746cccbd4" +dependencies = [ + "bincode", + "byteorder", + "encoding", + "flate2", + "lindera-core", + "lindera-ipadic-builder", + "once_cell", + "reqwest", + "tar", + "tokio", +] + +[[package]] +name = "lindera-ipadic-builder" +version = "0.10.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bd441a227cbf9b9a9708b01e45e47fe9fde0f7cf8d10639baf59b1696cf2971f" +dependencies = [ + "anyhow", + "bincode", + "byteorder", + "clap", + "encoding", + "env_logger", + "glob", + "lindera-core", + "lindera-decompress", + "log", + "serde", + "yada", +] [[package]] name = "lmdb-rkv-sys" @@ -1643,9 +1798,9 @@ dependencies = [ [[package]] name = "log" -version = "0.4.14" +version = "0.4.16" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "51b9bbe6c47d51fc3e1a9b945965946b4c44142ab8792c50835a980d362c2710" +checksum = "6389c490849ff5bc16be905ae24bc913a9c8892e19b2341dbc175e14c341c2b8" dependencies = [ "cfg-if 1.0.0", ] @@ -1668,8 +1823,18 @@ checksum = "10a9062912d7952c5588cc474795e0b9ee008e7e6781127945b85413d4b99d81" dependencies = [ "log", "proc-macro2 1.0.36", - "quote 1.0.15", - "syn 1.0.86", + "quote 1.0.16", + "syn 1.0.89", +] + +[[package]] +name = "lzma-rs" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "aba8ecb0450dfabce4ad72085eed0a75dffe8f21f7ada05638564ea9db2d7fb1" +dependencies = [ + "byteorder", + "crc", ] [[package]] @@ -1688,15 +1853,15 @@ checksum = "a3e378b66a060d48947b590737b30a1be76706c8dd7b8ba0f2fe3989c68a853f" name = "meilisearch-auth" version = "0.26.0" dependencies = [ - "chrono", "enum-iterator", - "heed", "meilisearch-error", + "milli", "rand", "serde", "serde_json", "sha2", "thiserror", + "time 0.3.9", ] [[package]] @@ -1719,7 +1884,6 @@ dependencies = [ "actix-web", "actix-web-static-files", "anyhow", - "arc-swap", "assert-json-diff", "async-stream", "async-trait", @@ -1727,7 +1891,6 @@ dependencies = [ "byte-unit", "bytes", "cargo_toml", - "chrono", "clap", "crossbeam-channel", "either", @@ -1736,7 +1899,6 @@ dependencies = [ "fst", "futures", "futures-util", - "heed", "hex", "http", "indexmap", @@ -1751,21 +1913,21 @@ dependencies = [ "num_cpus", "obkv", "once_cell", - "parking_lot 0.11.2", + "parking_lot", "paste", - "pin-project", + "pin-project-lite", "platform-dirs", "rand", "rayon", "regex", "reqwest", - "rustls 0.20.4", + "rustls", "rustls-pemfile", "segment", "serde", "serde_json", "serde_url_params", - "sha-1 0.9.8", + "sha-1", "sha2", "siphasher", "slice-group-by", @@ -1775,6 +1937,7 @@ dependencies = [ "tempfile", "thiserror", "tikv-jemallocator", + "time 0.3.9", "tokio", "tokio-stream", "urlencoding", @@ -1796,7 +1959,6 @@ dependencies = [ "atomic_refcell", "byte-unit", "bytes", - "chrono", "clap", "crossbeam-channel", "csv", @@ -1807,7 +1969,6 @@ dependencies = [ "fst", "futures", "futures-util", - "heed", "http", "indexmap", "itertools", @@ -1822,16 +1983,15 @@ dependencies = [ "num_cpus", "obkv", "once_cell", - "parking_lot 0.11.2", + "parking_lot", "paste", - "pin-project", "proptest", "proptest-derive", "rand", "rayon", "regex", "reqwest", - "rustls 0.19.1", + "rustls", "serde", "serde_json", "siphasher", @@ -1840,6 +2000,7 @@ dependencies = [ "tar", "tempfile", "thiserror", + "time 0.3.9", "tokio", "uuid", "walkdir", @@ -1848,14 +2009,16 @@ dependencies = [ [[package]] name = "meilisearch-tokenizer" -version = "0.2.7" -source = "git+https://github.com/meilisearch/tokenizer.git?tag=v0.2.7#e14f64f2482d8f57e9aae8dc37dcb1469099f6f3" +version = "0.2.8" +source = "git+https://github.com/meilisearch/tokenizer.git?tag=v0.2.8#afd1097bdb389d0528fee7cd5167d0b68ca922a0" dependencies = [ "character_converter", "cow-utils", "deunicode", "fst", "jieba-rs", + "lindera", + "lindera-core", "once_cell", "slice-group-by", "unicode-segmentation", @@ -1888,29 +2051,25 @@ dependencies = [ [[package]] name = "milli" -version = "0.22.1" -source = "git+https://github.com/meilisearch/milli.git?tag=v0.22.1#ea15ad6c34492b32eb7ac06e69de02b6dc70a707" +version = "0.23.1" +source = "git+https://github.com/meilisearch/milli.git?tag=v0.24.0#5863afa1a568950de2928ba2d78b95aee243dad1" dependencies = [ "bimap", "bincode", "bstr", "byteorder", - "chrono", "concat-arrays", "crossbeam-channel", "csv", "either", "filter-parser", - "flate2", "fst", "fxhash", "geoutils", "grenad", "heed", - "human_format", "itertools", "levenshtein_automata", - "linked-hash-map", "log", "logging_timer", "meilisearch-tokenizer", @@ -1927,6 +2086,7 @@ dependencies = [ "smallstr", "smallvec", "tempfile", + "time 0.3.9", "uuid", ] @@ -1964,14 +2124,15 @@ dependencies = [ [[package]] name = "mio" -version = "0.8.0" +version = "0.8.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ba272f85fa0b41fc91872be579b3bbe0f56b792aa361a380eb669469f68dafb2" +checksum = "52da4364ffb0e4fe33a9841a98a3f3014fb964045ce4f7a45a398243c8d6b0c9" dependencies = [ "libc", "log", "miow", "ntapi", + "wasi 0.11.0+wasi-snapshot-preview1", "winapi", ] @@ -1986,9 +2147,9 @@ dependencies = [ [[package]] name = "mockall" -version = "0.10.2" +version = "0.11.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6ab571328afa78ae322493cacca3efac6a0f2e0a67305b4df31fd439ef129ac0" +checksum = "3d4d70639a72f972725db16350db56da68266ca368b2a1fe26724a903ad3d6b8" dependencies = [ "cfg-if 1.0.0", "downcast", @@ -2001,14 +2162,32 @@ dependencies = [ [[package]] name = "mockall_derive" -version = "0.10.2" +version = "0.11.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e7e25b214433f669161f414959594216d8e6ba83b6679d3db96899c0b4639033" +checksum = "79ef208208a0dea3f72221e26e904cdc6db2e481d9ade89081ddd494f1dbaa6b" dependencies = [ "cfg-if 1.0.0", "proc-macro2 1.0.36", - "quote 1.0.15", - "syn 1.0.86", + "quote 1.0.16", + "syn 1.0.89", +] + +[[package]] +name = "native-tls" +version = "0.2.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "48ba9f7719b5a0f42f338907614285fb5fd70e53858141f69898a1fb7203b24d" +dependencies = [ + "lazy_static", + "libc", + "log", + "openssl", + "openssl-probe", + "openssl-sys", + "schannel", + "security-framework", + "security-framework-sys", + "tempfile", ] [[package]] @@ -2018,13 +2197,12 @@ source = "git+https://github.com/MarinPostma/nelson.git?rev=675f13885548fb415ead [[package]] name = "nom" -version = "7.1.0" +version = "7.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1b1d11e1ef389c76fe5b81bcaf2ea32cf88b62bc494e19f493d0b30e7a930109" +checksum = "a8903e5a29a317527874d0402f867152a3d21c908bb0b933e416c65e301d4c36" dependencies = [ "memchr", "minimal-lexical", - "version_check", ] [[package]] @@ -2055,9 +2233,9 @@ dependencies = [ [[package]] name = "num-bigint" -version = "0.2.6" +version = "0.4.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "090c7f9998ee0ff65aa5b723e4009f7b217707f1fb5ea551329cc4d6231fb304" +checksum = "f93ab6289c7b344a8a9f60f88d80aa20032336fe78da341afc91c8a2341fc75f" dependencies = [ "autocfg", "num-integer", @@ -2095,9 +2273,9 @@ dependencies = [ [[package]] name = "num_threads" -version = "0.1.3" +version = "0.1.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "97ba99ba6393e2c3734791401b66902d981cb03bf190af674ca69949b6d5fb15" +checksum = "aba1801fb138d8e85e11d0fc70baf4fe1cdfffda7c6cd34a854905df588e5ed0" dependencies = [ "libc", ] @@ -2119,15 +2297,42 @@ checksum = "f69e48cd7c8e5bb52a1da1287fdbfd877c32673176583ce664cd63b201aba385" [[package]] name = "once_cell" -version = "1.9.0" +version = "1.10.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "da32515d9f6e6e489d7bc9d84c71b060db7247dc035bbe44eac88cf87486d8d5" +checksum = "87f3e037eac156d1775da914196f0f37741a274155e34a0b7e427c35d2a2ecb9" [[package]] -name = "opaque-debug" -version = "0.3.0" +name = "openssl" +version = "0.10.38" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "624a8340c38c1b80fd549087862da4ba43e08858af025b236e509b6649fc13d5" +checksum = "0c7ae222234c30df141154f159066c5093ff73b63204dcda7121eb082fc56a95" +dependencies = [ + "bitflags", + "cfg-if 1.0.0", + "foreign-types", + "libc", + "once_cell", + "openssl-sys", +] + +[[package]] +name = "openssl-probe" +version = "0.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ff011a302c396a5197692431fc1948019154afc178baf7d8e37367442a4601cf" + +[[package]] +name = "openssl-sys" +version = "0.9.72" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7e46109c383602735fa0a2e48dd2b7c892b048e1bf69e5c3b1d804b7d9c203cb" +dependencies = [ + "autocfg", + "cc", + "libc", + "pkg-config", + "vcpkg", +] [[package]] name = "ordered-float" @@ -2157,17 +2362,6 @@ dependencies = [ "winapi", ] -[[package]] -name = "parking_lot" -version = "0.11.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7d17b78036a60663b797adeaee46f5c9dfebb86948d1255007a1d6be0271ff99" -dependencies = [ - "instant", - "lock_api", - "parking_lot_core 0.8.5", -] - [[package]] name = "parking_lot" version = "0.12.0" @@ -2175,21 +2369,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "87f5ec2493a61ac0506c0f4199f99070cbe83857b0337006a30f3e6719b8ef58" dependencies = [ "lock_api", - "parking_lot_core 0.9.1", -] - -[[package]] -name = "parking_lot_core" -version = "0.8.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d76e8e1493bcac0d2766c42737f34458f1c8c50c0d23bcb24ea953affb273216" -dependencies = [ - "cfg-if 1.0.0", - "instant", - "libc", - "redox_syscall", - "smallvec", - "winapi", + "parking_lot_core", ] [[package]] @@ -2234,13 +2414,11 @@ checksum = "4ec91767ecc0a0bbe558ce8c9da33c068066c57ecc8bb8477ef8c1ad3ef77c27" [[package]] name = "pem" -version = "0.8.3" +version = "1.0.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fd56cbd21fea48d0c440b41cd69c589faacade08c992d9a54e471b79d0fd13eb" +checksum = "e9a3b09a20e374558580a4914d3b7d89bd61b954a5a5e1dcbea98753addb1947" dependencies = [ - "base64 0.13.0", - "once_cell", - "regex", + "base64", ] [[package]] @@ -2287,26 +2465,6 @@ dependencies = [ "siphasher", ] -[[package]] -name = "pin-project" -version = "1.0.10" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "58ad3879ad3baf4e44784bc6a718a8698867bb991f8ce24d1bcbe2cfb4c3a75e" -dependencies = [ - "pin-project-internal", -] - -[[package]] -name = "pin-project-internal" -version = "1.0.10" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "744b6f092ba29c3650faf274db506afd39944f48420f6c86b17cfe0ee1cb36bb" -dependencies = [ - "proc-macro2 1.0.36", - "quote 1.0.15", - "syn 1.0.86", -] - [[package]] name = "pin-project-lite" version = "0.2.8" @@ -2342,12 +2500,13 @@ checksum = "eb9f9e6e233e5c4a35559a617bf40a4ec447db2e84c20b55a6f83167b7e57872" [[package]] name = "predicates" -version = "1.0.8" +version = "2.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f49cfaf7fdaa3bfacc6fa3e7054e65148878354a5cfddcf661df4c851f8021df" +checksum = "a5aab5be6e4732b473071984b3164dbbfb7a3674d30ea5ff44410b6bcd960c3c" dependencies = [ - "difference", + "difflib", "float-cmp", + "itertools", "normalize-line-endings", "predicates-core", "regex", @@ -2377,8 +2536,8 @@ checksum = "da25490ff9892aab3fcf7c36f08cfb902dd3e71ca0f9f9517bea02a73a5ce38c" dependencies = [ "proc-macro-error-attr", "proc-macro2 1.0.36", - "quote 1.0.15", - "syn 1.0.86", + "quote 1.0.16", + "syn 1.0.89", "version_check", ] @@ -2389,7 +2548,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a1be40180e52ecc98ad80b184934baf3d0d29f979574e439af5a55274b35f869" dependencies = [ "proc-macro2 1.0.36", - "quote 1.0.15", + "quote 1.0.16", "version_check", ] @@ -2454,6 +2613,15 @@ version = "2.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a993555f31e5a609f617c12db6250dedcac1b0a85076912c436e6fc9b2c8e6a3" +[[package]] +name = "quickcheck" +version = "1.0.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "588f6378e4dd99458b60ec275b4477add41ce4fa9f64dcba6f15adccb19b50d6" +dependencies = [ + "rand", +] + [[package]] name = "quote" version = "0.6.13" @@ -2465,9 +2633,9 @@ dependencies = [ [[package]] name = "quote" -version = "1.0.15" +version = "1.0.16" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "864d3e96a899863136fc6e99f3d7cae289dafe43bf2c5ac19b70df7210c0a145" +checksum = "b4af2ec4714533fcdf07e886f17025ace8b997b9ce51204ee69b6da831c3da57" dependencies = [ "proc-macro2 1.0.36", ] @@ -2531,35 +2699,36 @@ checksum = "d78120e2c850279833f1dd3582f730c4ab53ed95aeaaaa862a2a5c71b1656d8e" dependencies = [ "crossbeam-channel", "crossbeam-deque", - "crossbeam-utils 0.8.7", + "crossbeam-utils 0.8.8", "lazy_static", "num_cpus", ] [[package]] name = "redox_syscall" -version = "0.2.10" +version = "0.2.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8383f39639269cde97d255a32bdb68c047337295414940c68bdd30c2e13203ff" +checksum = "8380fe0152551244f0747b1bf41737e0f8a74f97a14ccefd1148187271634f3c" dependencies = [ "bitflags", ] [[package]] name = "redox_users" -version = "0.4.0" +version = "0.4.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "528532f3d801c87aec9def2add9ca802fe569e44a544afe633765267840abe64" +checksum = "7776223e2696f1aa4c6b0170e83212f47296a00424305117d013dfe86fb0fe55" dependencies = [ "getrandom", "redox_syscall", + "thiserror", ] [[package]] name = "regex" -version = "1.5.4" +version = "1.5.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d07a8629359eb56f1e2fb1652bb04212c072a87ba68546a04065d525673ac461" +checksum = "1a11647b6b25ff05a515cb92c365cec08801e83423a235b51e231e1808747286" dependencies = [ "aho-corasick", "memchr", @@ -2589,11 +2758,11 @@ dependencies = [ [[package]] name = "reqwest" -version = "0.11.9" +version = "0.11.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "87f242f1488a539a79bac6dbe7c8609ae43b7914b7736210f239a37cccb32525" +checksum = "46a1f7aa4f35e5e8b4160449f51afc758f0ce6454315a9fa7d0d113e958c41eb" dependencies = [ - "base64 0.13.0", + "base64", "bytes", "encoding_rs", "futures-core", @@ -2603,19 +2772,22 @@ dependencies = [ "http-body", "hyper", "hyper-rustls", + "hyper-tls", "ipnet", "js-sys", "lazy_static", "log", "mime", + "native-tls", "percent-encoding", "pin-project-lite", - "rustls 0.20.4", + "rustls", "rustls-pemfile", "serde", "serde_json", "serde_urlencoded", "tokio", + "tokio-native-tls", "tokio-rustls", "url", "wasm-bindgen", @@ -2648,9 +2820,9 @@ dependencies = [ [[package]] name = "roaring" -version = "0.6.7" +version = "0.9.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "536cfa885fc388b8ae69edf96d7970849b7d9c1395da1b8330f17715babf8a09" +checksum = "dd539cab4e32019956fe7e0cf160bb6d4802f4be2b52c4253d76d3bb0f85a5f7" dependencies = [ "bytemuck", "byteorder", @@ -2685,19 +2857,6 @@ dependencies = [ "semver", ] -[[package]] -name = "rustls" -version = "0.19.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "35edb675feee39aec9c99fa5ff985081995a06d594114ae14cbe797ad7b7a6d7" -dependencies = [ - "base64 0.13.0", - "log", - "ring", - "sct 0.6.1", - "webpki 0.21.4", -] - [[package]] name = "rustls" version = "0.20.4" @@ -2706,17 +2865,17 @@ checksum = "4fbfeb8d0ddb84706bc597a5574ab8912817c52a397f819e5b614e2265206921" dependencies = [ "log", "ring", - "sct 0.7.0", - "webpki 0.22.0", + "sct", + "webpki", ] [[package]] name = "rustls-pemfile" -version = "0.2.1" +version = "0.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5eebeaeb360c87bfb72e84abdb3447159c0eaececf1bef2aecd65a8be949d1c9" +checksum = "1ee86d63972a7c661d1536fefe8c3c8407321c3df668891286de28abcd087360" dependencies = [ - "base64 0.13.0", + "base64", ] [[package]] @@ -2752,22 +2911,22 @@ dependencies = [ "winapi-util", ] +[[package]] +name = "schannel" +version = "0.1.19" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8f05ba609c234e60bee0d547fe94a4c7e9da733d1c962cf6e59efa4cd9c8bc75" +dependencies = [ + "lazy_static", + "winapi", +] + [[package]] name = "scopeguard" version = "1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d29ab0c6d3fc0ee92fe66e2d99f700eab17a8d57d1c1d3b748380fb20baa78cd" -[[package]] -name = "sct" -version = "0.6.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b362b83898e0e69f38515b82ee15aa80636befe47c3b6d3d89a911e78fc228ce" -dependencies = [ - "ring", - "untrusted", -] - [[package]] name = "sct" version = "0.7.0" @@ -2779,17 +2938,40 @@ dependencies = [ ] [[package]] -name = "segment" -version = "0.1.2" +name = "security-framework" +version = "2.6.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9bdcc286fff0e7c5ccd46c06a301c7a8a848b06acedc6983707bd311eb358002" +checksum = "2dc14f172faf8a0194a3aded622712b0de276821addc574fa54fc0a1167e10dc" +dependencies = [ + "bitflags", + "core-foundation", + "core-foundation-sys", + "libc", + "security-framework-sys", +] + +[[package]] +name = "security-framework-sys" +version = "2.6.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0160a13a177a45bfb43ce71c01580998474f556ad854dcbca936dd2841a5c556" +dependencies = [ + "core-foundation-sys", + "libc", +] + +[[package]] +name = "segment" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5c14967a911a216177366bac6dfa1209b597e311a32360431c63526e27b814fb" dependencies = [ "async-trait", - "chrono", "reqwest", "serde", "serde_json", "thiserror", + "time 0.3.9", ] [[package]] @@ -2814,8 +2996,8 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "08597e7152fcd306f41838ed3e37be9eaeed2b61c42e2117266a554fab4662f9" dependencies = [ "proc-macro2 1.0.36", - "quote 1.0.15", - "syn 1.0.86", + "quote 1.0.16", + "syn 1.0.89", ] [[package]] @@ -2852,19 +3034,6 @@ dependencies = [ "serde", ] -[[package]] -name = "sha-1" -version = "0.9.8" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "99cd6713db3cf16b6c84e06321e049a9b9f699826e16096d23bbcc44d15d51a6" -dependencies = [ - "block-buffer 0.9.0", - "cfg-if 1.0.0", - "cpufeatures", - "digest 0.9.0", - "opaque-debug", -] - [[package]] name = "sha-1" version = "0.10.0" @@ -2873,20 +3042,18 @@ checksum = "028f48d513f9678cda28f6e4064755b3fbb2af6acd672f2c209b62323f7aea0f" dependencies = [ "cfg-if 1.0.0", "cpufeatures", - "digest 0.10.3", + "digest", ] [[package]] name = "sha2" -version = "0.9.9" +version = "0.10.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4d58a1e1bf39749807d89cf2d98ac2dfa0ff1cb3faa38fbb64dd88ac8013d800" +checksum = "55deaec60f81eefe3cce0dc50bda92d6d8e88f2a27df7c5033b42afeb1ed2676" dependencies = [ - "block-buffer 0.9.0", "cfg-if 1.0.0", "cpufeatures", - "digest 0.9.0", - "opaque-debug", + "digest", ] [[package]] @@ -2900,20 +3067,21 @@ dependencies = [ [[package]] name = "simple_asn1" -version = "0.4.1" +version = "0.6.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "692ca13de57ce0613a363c8c2f1de925adebc81b04c923ac60c5488bb44abe4b" +checksum = "4a762b1c38b9b990c694b9c2f8abe3372ce6a9ceaae6bca39cfc46e054f45745" dependencies = [ - "chrono", "num-bigint", "num-traits", + "thiserror", + "time 0.3.9", ] [[package]] name = "siphasher" -version = "0.3.9" +version = "0.3.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a86232ab60fa71287d7f2ddae4a7073f6b7aac33631c3015abb556f08c6d0a3e" +checksum = "7bd3e3206899af3f8b12af284fafc038cc1dc2b41d1b89dd17297221c5d225de" [[package]] name = "slab" @@ -2923,15 +3091,15 @@ checksum = "9def91fd1e018fe007022791f865d0ccc9b3a0d5001e01aabb8b40e46000afb5" [[package]] name = "slice-group-by" -version = "0.2.6" +version = "0.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1f7474f0b646d228360ab62ed974744617bc869d959eac8403bfa3665931a7fb" +checksum = "03b634d87b960ab1a38c4fe143b508576f075e7c978bfad18217645ebfdfa2ec" [[package]] name = "smallstr" -version = "0.2.0" +version = "0.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1e922794d168678729ffc7e07182721a14219c65814e66e91b839a272fe5ae4f" +checksum = "63b1aefdf380735ff8ded0b15f31aab05daf1f70216c01c02a12926badd1df9d" dependencies = [ "serde", "smallvec", @@ -2995,12 +3163,12 @@ dependencies = [ [[package]] name = "syn" -version = "1.0.86" +version = "1.0.89" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8a65b3f4ffa0092e9887669db0eae07941f023991ab58ea44da8fe8e2d511c6b" +checksum = "ea297be220d52398dcc07ce15a209fce436d361735ac1db700cab3b6cdfb9f54" dependencies = [ "proc-macro2 1.0.36", - "quote 1.0.15", + "quote 1.0.16", "unicode-xid 0.2.2", ] @@ -3020,16 +3188,16 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f36bdaa60a83aca3921b5259d5400cbf5e90fc51931376a9bd4a0eb79aa7210f" dependencies = [ "proc-macro2 1.0.36", - "quote 1.0.15", - "syn 1.0.86", + "quote 1.0.16", + "syn 1.0.89", "unicode-xid 0.2.2", ] [[package]] name = "sysinfo" -version = "0.20.5" +version = "0.23.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e223c65cd36b485a34c2ce6e38efa40777d31c4166d9076030c74cdcf971679f" +checksum = "07fa4c84a5305909b0eedfcc8d1f2fafdbede645bb700a45ecaafe681a0ac5d6" dependencies = [ "cfg-if 1.0.0", "core-foundation-sys", @@ -3067,9 +3235,9 @@ dependencies = [ [[package]] name = "termcolor" -version = "1.1.2" +version = "1.1.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2dfed899f0eb03f32ee8c6a0aabdb8a7949659e3466561fc0adf54e26d88c5f4" +checksum = "bab24d30b911b2376f3a13cc2cd443142f0c81dda04c118693e35b3835757755" dependencies = [ "winapi-util", ] @@ -3082,9 +3250,9 @@ checksum = "507e9898683b6c43a9aa55b64259b721b52ba226e0f3779137e50ad114a4c90b" [[package]] name = "textwrap" -version = "0.14.2" +version = "0.15.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0066c8d12af8b5acd21e00547c3797fde4e8677254a7ee429176ccebbe93dd80" +checksum = "b1141d4d61095b28419e22cb0bbf02755f5e54e0526f97f1e3d1d160e60885fb" [[package]] name = "thiserror" @@ -3102,8 +3270,8 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "aa32fd3f627f367fe16f893e2597ae3c05020f8bba2666a4e6ea73d377e5714b" dependencies = [ "proc-macro2 1.0.36", - "quote 1.0.15", - "syn 1.0.86", + "quote 1.0.16", + "syn 1.0.89", ] [[package]] @@ -3129,32 +3297,33 @@ dependencies = [ [[package]] name = "time" -version = "0.1.44" +version = "0.1.43" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6db9e6914ab8b1ae1c260a4ae7a49b6c5611b40328a735b21862567685e73255" +checksum = "ca8a50ef2360fbd1eeb0ecd46795a87a19024eb4b53c5dc916ca1fd95fe62438" dependencies = [ "libc", - "wasi", "winapi", ] [[package]] name = "time" -version = "0.3.7" +version = "0.3.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "004cbc98f30fa233c61a38bc77e96a9106e65c88f2d3bef182ae952027e5753d" +checksum = "c2702e08a7a860f005826c6815dcac101b19b5eb330c27fe4a5928fec1d20ddd" dependencies = [ "itoa 1.0.1", "libc", "num_threads", + "quickcheck", + "serde", "time-macros", ] [[package]] name = "time-macros" -version = "0.2.3" +version = "0.2.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "25eb0ca3468fc0acc11828786797f6ef9aa1555e4a211a60d64cc8e4d1be47d6" +checksum = "42657b1a6f4d817cda8e7a0ace261fe0cc946cf3a80314390b22cc61ae080792" [[package]] name = "tinyvec" @@ -3183,7 +3352,7 @@ dependencies = [ "mio", "num_cpus", "once_cell", - "parking_lot 0.12.0", + "parking_lot", "pin-project-lite", "signal-hook-registry", "socket2", @@ -3198,19 +3367,29 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b557f72f448c511a979e2564e55d74e6c4432fc96ff4f6241bc6bded342643b7" dependencies = [ "proc-macro2 1.0.36", - "quote 1.0.15", - "syn 1.0.86", + "quote 1.0.16", + "syn 1.0.89", +] + +[[package]] +name = "tokio-native-tls" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f7d995660bd2b7f8c1568414c1126076c13fbb725c40112dc0120b78eb9b717b" +dependencies = [ + "native-tls", + "tokio", ] [[package]] name = "tokio-rustls" -version = "0.23.2" +version = "0.23.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a27d5f2b839802bd8267fa19b0530f5a08b9c08cd417976be2a65d130fe1c11b" +checksum = "4151fda0cf2798550ad0b34bcfc9b9dcc2a9d2471c895c68f3a8818e54f2389e" dependencies = [ - "rustls 0.20.4", + "rustls", "tokio", - "webpki 0.22.0", + "webpki", ] [[package]] @@ -3269,20 +3448,21 @@ checksum = "360dfd1d6d30e05fda32ace2c8c70e9c0a9da713275777f5a4dbb8a1893930c6" [[package]] name = "tracing" -version = "0.1.31" +version = "0.1.32" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f6c650a8ef0cd2dd93736f033d21cbd1224c5a967aa0c258d00fcf7dafef9b9f" +checksum = "4a1bdf54a7c28a2bbf701e1d2233f6c77f473486b94bee4f9678da5a148dca7f" dependencies = [ "cfg-if 1.0.0", + "log", "pin-project-lite", "tracing-core", ] [[package]] name = "tracing-core" -version = "0.1.22" +version = "0.1.23" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "03cfcb51380632a72d3111cb8d3447a8d908e577d31beeac006f836383d29a23" +checksum = "aa31669fa42c09c34d94d8165dd2012e8ff3c66aca50f3bb226b68f216f2706c" dependencies = [ "lazy_static", ] @@ -3367,9 +3547,9 @@ checksum = "68b90931029ab9b034b300b797048cf23723400aa757e8a2bfb9d748102f9821" [[package]] name = "utf8-width" -version = "0.1.5" +version = "0.1.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7cf7d77f457ef8dfa11e4cd5933c5ddb5dc52a94664071951219a97710f0a32b" +checksum = "5190c9442dcdaf0ddd50f37420417d219ae5261bbf5db120d0f9bab996c9cba1" [[package]] name = "uuid" @@ -3389,18 +3569,18 @@ checksum = "accd4ea62f7bb7a82fe23066fb0957d48ef677f6eeb8215f372f52e48bb32426" [[package]] name = "vergen" -version = "5.1.17" +version = "7.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6cf88d94e969e7956d924ba70741316796177fa0c79a2c9f4ab04998d96e966e" +checksum = "4db743914c971db162f35bf46601c5a63ec4452e61461937b4c1ab817a60c12e" dependencies = [ "anyhow", "cfg-if 1.0.0", - "chrono", "enum-iterator", "getset", "git2", "rustversion", "thiserror", + "time 0.3.9", ] [[package]] @@ -3441,9 +3621,15 @@ dependencies = [ [[package]] name = "wasi" -version = "0.10.0+wasi-snapshot-preview1" +version = "0.10.2+wasi-snapshot-preview1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1a143597ca7c7793eff794def352d41792a93c481eb1042423ff7ff72ba2c31f" +checksum = "fd6fbd9a79829dd1ad0cc20627bf1ed606756a7f77edff7b66b7064f9cb327c6" + +[[package]] +name = "wasi" +version = "0.11.0+wasi-snapshot-preview1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9c8d87e72b64a3b4db28d11ce29237c246188f4f51057d65a7eab63b7987e423" [[package]] name = "wasm-bindgen" @@ -3465,8 +3651,8 @@ dependencies = [ "lazy_static", "log", "proc-macro2 1.0.36", - "quote 1.0.15", - "syn 1.0.86", + "quote 1.0.16", + "syn 1.0.89", "wasm-bindgen-shared", ] @@ -3488,7 +3674,7 @@ version = "0.2.79" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "2f4203d69e40a52ee523b2529a773d5ffc1dc0071801c87b3d270b471b80ed01" dependencies = [ - "quote 1.0.15", + "quote 1.0.16", "wasm-bindgen-macro-support", ] @@ -3499,8 +3685,8 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "bfa8a30d46208db204854cadbb5d4baf5fcf8071ba5bf48190c3e59937962ebc" dependencies = [ "proc-macro2 1.0.36", - "quote 1.0.15", - "syn 1.0.86", + "quote 1.0.16", + "syn 1.0.89", "wasm-bindgen-backend", "wasm-bindgen-shared", ] @@ -3521,16 +3707,6 @@ dependencies = [ "wasm-bindgen", ] -[[package]] -name = "webpki" -version = "0.21.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b8e38c0608262c46d4a56202ebabdeb094cef7e560ca7a226c6bf055188aa4ea" -dependencies = [ - "ring", - "untrusted", -] - [[package]] name = "webpki" version = "0.22.0" @@ -3547,14 +3723,14 @@ version = "0.22.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "552ceb903e957524388c4d3475725ff2c8b7960922063af6ce53c9a43da07449" dependencies = [ - "webpki 0.22.0", + "webpki", ] [[package]] name = "whatlang" -version = "0.12.0" +version = "0.13.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7a346d2eb29c03618693ed24a29d1acd0c3f2cb08ae58b9669d7461e033cf703" +checksum = "349357fdf0f049dcb402da4a4c5a5aae80a7f6b3e5976b38475ce4ac18e5cd2f" dependencies = [ "hashbrown 0.7.2", ] @@ -3645,9 +3821,9 @@ checksum = "504a2476202769977a040c6364301a3f65d0cc9e3fb08600b2bda150a0488316" [[package]] name = "winreg" -version = "0.7.0" +version = "0.10.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0120db82e8a1e0b9fb3345a539c478767c0048d842860994d96113d5b667bd69" +checksum = "80d0f4e272c85def139476380b12f9ac60926689dd2e01d4923222f40580869d" dependencies = [ "winapi", ] @@ -3661,6 +3837,12 @@ dependencies = [ "libc", ] +[[package]] +name = "yada" +version = "0.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b6d12cb7a57bbf2ab670ed9545bae3648048547f9039279a89ce000208e585c1" + [[package]] name = "zerocopy" version = "0.3.0" @@ -3678,7 +3860,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d498dbd1fd7beb83c86709ae1c33ca50942889473473d287d56ce4770a18edfb" dependencies = [ "proc-macro2 1.0.36", - "syn 1.0.86", + "syn 1.0.89", "synstructure", ] @@ -3693,34 +3875,5 @@ dependencies = [ "crc32fast", "flate2", "thiserror", - "time 0.1.44", -] - -[[package]] -name = "zstd" -version = "0.10.0+zstd.1.5.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3b1365becbe415f3f0fcd024e2f7b45bacfb5bdd055f0dc113571394114e7bdd" -dependencies = [ - "zstd-safe", -] - -[[package]] -name = "zstd-safe" -version = "4.1.4+zstd.1.5.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2f7cd17c9af1a4d6c24beb1cc54b17e2ef7b593dc92f19e9d9acad8b182bbaee" -dependencies = [ - "libc", - "zstd-sys", -] - -[[package]] -name = "zstd-sys" -version = "1.6.3+zstd.1.5.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fc49afa5c8d634e75761feda8c592051e7eeb4683ba827211eb0d731d3402ea8" -dependencies = [ - "cc", - "libc", + "time 0.1.43", ] diff --git a/Cargo.toml b/Cargo.toml index 65fa6fe13..a27a29634 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,4 +1,5 @@ [workspace] +resolver = "2" members = [ "meilisearch-http", "meilisearch-error", diff --git a/bors.toml b/bors.toml index ba97aaf43..b357e8d61 100644 --- a/bors.toml +++ b/bors.toml @@ -3,7 +3,8 @@ status = [ 'Tests on macos-latest', 'Tests on windows-latest', 'Run Clippy', - 'Run Rustfmt' + 'Run Rustfmt', + 'Run tests in debug', ] pr_status = ['Milestone Check'] # 3 hours timeout diff --git a/meilisearch-auth/Cargo.toml b/meilisearch-auth/Cargo.toml index d6ef39095..74e4e2db9 100644 --- a/meilisearch-auth/Cargo.toml +++ b/meilisearch-auth/Cargo.toml @@ -5,11 +5,11 @@ edition = "2021" [dependencies] enum-iterator = "0.7.0" -heed = { git = "https://github.com/Kerollmops/heed", tag = "v0.12.1" } -sha2 = "0.9.6" -chrono = { version = "0.4.19", features = ["serde"] } meilisearch-error = { path = "../meilisearch-error" } -serde_json = { version = "1.0.67", features = ["preserve_order"] } +milli = { git = "https://github.com/meilisearch/milli.git", tag = "v0.24.0" } rand = "0.8.4" -serde = { version = "1.0.130", features = ["derive"] } -thiserror = "1.0.28" +serde = { version = "1.0.136", features = ["derive"] } +serde_json = { version = "1.0.79", features = ["preserve_order"] } +sha2 = "0.10.2" +thiserror = "1.0.30" +time = { version = "0.3.7", features = ["serde-well-known", "formatting", "parsing", "macros"] } diff --git a/meilisearch-auth/src/error.rs b/meilisearch-auth/src/error.rs index 8fa6b8430..8a87eda27 100644 --- a/meilisearch-auth/src/error.rs +++ b/meilisearch-auth/src/error.rs @@ -10,13 +10,13 @@ pub type Result = std::result::Result; pub enum AuthControllerError { #[error("`{0}` field is mandatory.")] MissingParameter(&'static str), - #[error("actions field value `{0}` is invalid. It should be an array of string representing action names.")] + #[error("`actions` field value `{0}` is invalid. It should be an array of string representing action names.")] InvalidApiKeyActions(Value), - #[error("indexes field value `{0}` is invalid. It should be an array of string representing index names.")] + #[error("`indexes` field value `{0}` is invalid. It should be an array of string representing index names.")] InvalidApiKeyIndexes(Value), - #[error("expiresAt field value `{0}` is invalid. It should be in ISO-8601 format to represents a date or datetime in the future or specified as a null value. e.g. 'YYYY-MM-DD' or 'YYYY-MM-DDTHH:MM:SS'.")] + #[error("`expiresAt` field value `{0}` is invalid. It should follow the RFC 3339 format to represents a date or datetime in the future or specified as a null value. e.g. 'YYYY-MM-DD' or 'YYYY-MM-DD HH:MM:SS'.")] InvalidApiKeyExpiresAt(Value), - #[error("description field value `{0}` is invalid. It should be a string or specified as a null value.")] + #[error("`description` field value `{0}` is invalid. It should be a string or specified as a null value.")] InvalidApiKeyDescription(Value), #[error("API key `{0}` not found.")] ApiKeyNotFound(String), @@ -25,7 +25,7 @@ pub enum AuthControllerError { } internal_error!( - AuthControllerError: heed::Error, + AuthControllerError: milli::heed::Error, std::io::Error, serde_json::Error, std::str::Utf8Error diff --git a/meilisearch-auth/src/key.rs b/meilisearch-auth/src/key.rs index ffa56fa88..1b06f34be 100644 --- a/meilisearch-auth/src/key.rs +++ b/meilisearch-auth/src/key.rs @@ -1,10 +1,12 @@ use crate::action::Action; use crate::error::{AuthControllerError, Result}; use crate::store::{KeyId, KEY_ID_LENGTH}; -use chrono::{DateTime, NaiveDate, NaiveDateTime, Utc}; use rand::Rng; use serde::{Deserialize, Serialize}; use serde_json::{from_value, Value}; +use time::format_description::well_known::Rfc3339; +use time::macros::{format_description, time}; +use time::{Date, OffsetDateTime, PrimitiveDateTime}; #[derive(Debug, Deserialize, Serialize)] pub struct Key { @@ -13,9 +15,12 @@ pub struct Key { pub id: KeyId, pub actions: Vec, pub indexes: Vec, - pub expires_at: Option>, - pub created_at: DateTime, - pub updated_at: DateTime, + #[serde(with = "time::serde::rfc3339::option")] + pub expires_at: Option, + #[serde(with = "time::serde::rfc3339")] + pub created_at: OffsetDateTime, + #[serde(with = "time::serde::rfc3339")] + pub updated_at: OffsetDateTime, } impl Key { @@ -52,8 +57,8 @@ impl Key { .map(parse_expiration_date) .ok_or(AuthControllerError::MissingParameter("expiresAt"))??; - let created_at = Utc::now(); - let updated_at = Utc::now(); + let created_at = OffsetDateTime::now_utc(); + let updated_at = created_at; Ok(Self { description, @@ -89,24 +94,26 @@ impl Key { self.expires_at = parse_expiration_date(exp)?; } - self.updated_at = Utc::now(); + self.updated_at = OffsetDateTime::now_utc(); Ok(()) } pub(crate) fn default_admin() -> Self { + let now = OffsetDateTime::now_utc(); Self { description: Some("Default Admin API Key (Use it for all other operations. Caution! Do not use it on a public frontend)".to_string()), id: generate_id(), actions: vec![Action::All], indexes: vec!["*".to_string()], expires_at: None, - created_at: Utc::now(), - updated_at: Utc::now(), + created_at: now, + updated_at: now, } } pub(crate) fn default_search() -> Self { + let now = OffsetDateTime::now_utc(); Self { description: Some( "Default Search API Key (Use it to search from the frontend)".to_string(), @@ -115,8 +122,8 @@ impl Key { actions: vec![Action::Search], indexes: vec!["*".to_string()], expires_at: None, - created_at: Utc::now(), - updated_at: Utc::now(), + created_at: now, + updated_at: now, } } } @@ -134,22 +141,34 @@ fn generate_id() -> [u8; KEY_ID_LENGTH] { bytes } -fn parse_expiration_date(value: &Value) -> Result>> { +fn parse_expiration_date(value: &Value) -> Result> { match value { - Value::String(string) => DateTime::parse_from_rfc3339(string) - .map(|d| d.into()) + Value::String(string) => OffsetDateTime::parse(string, &Rfc3339) .or_else(|_| { - NaiveDateTime::parse_from_str(string, "%Y-%m-%dT%H:%M:%S") - .map(|naive| DateTime::from_utc(naive, Utc)) + PrimitiveDateTime::parse( + string, + format_description!( + "[year repr:full base:calendar]-[month repr:numerical]-[day]T[hour]:[minute]:[second]" + ), + ).map(|datetime| datetime.assume_utc()) }) .or_else(|_| { - NaiveDate::parse_from_str(string, "%Y-%m-%d") - .map(|naive| DateTime::from_utc(naive.and_hms(0, 0, 0), Utc)) + PrimitiveDateTime::parse( + string, + format_description!( + "[year repr:full base:calendar]-[month repr:numerical]-[day] [hour]:[minute]:[second]" + ), + ).map(|datetime| datetime.assume_utc()) + }) + .or_else(|_| { + Date::parse(string, format_description!( + "[year repr:full base:calendar]-[month repr:numerical]-[day]" + )).map(|date| PrimitiveDateTime::new(date, time!(00:00)).assume_utc()) }) .map_err(|_| AuthControllerError::InvalidApiKeyExpiresAt(value.clone())) // check if the key is already expired. .and_then(|d| { - if d > Utc::now() { + if d > OffsetDateTime::now_utc() { Ok(d) } else { Err(AuthControllerError::InvalidApiKeyExpiresAt(value.clone())) diff --git a/meilisearch-auth/src/lib.rs b/meilisearch-auth/src/lib.rs index 4edd73b1a..22263735e 100644 --- a/meilisearch-auth/src/lib.rs +++ b/meilisearch-auth/src/lib.rs @@ -9,10 +9,10 @@ use std::path::Path; use std::str::from_utf8; use std::sync::Arc; -use chrono::Utc; use serde::{Deserialize, Serialize}; use serde_json::Value; use sha2::{Digest, Sha256}; +use time::OffsetDateTime; pub use action::{actions, Action}; use error::{AuthControllerError, Result}; @@ -40,18 +40,18 @@ impl AuthController { }) } - pub async fn create_key(&self, value: Value) -> Result { + pub fn create_key(&self, value: Value) -> Result { let key = Key::create_from_value(value)?; self.store.put_api_key(key) } - pub async fn update_key(&self, key: impl AsRef, value: Value) -> Result { - let mut key = self.get_key(key).await?; + pub fn update_key(&self, key: impl AsRef, value: Value) -> Result { + let mut key = self.get_key(key)?; key.update_from_value(value)?; self.store.put_api_key(key) } - pub async fn get_key(&self, key: impl AsRef) -> Result { + pub fn get_key(&self, key: impl AsRef) -> Result { self.store .get_api_key(&key)? .ok_or_else(|| AuthControllerError::ApiKeyNotFound(key.as_ref().to_string())) @@ -101,11 +101,11 @@ impl AuthController { Ok(filters) } - pub async fn list_keys(&self) -> Result> { + pub fn list_keys(&self) -> Result> { self.store.list_api_keys() } - pub async fn delete_key(&self, key: impl AsRef) -> Result<()> { + pub fn delete_key(&self, key: impl AsRef) -> Result<()> { if self.store.delete_api_key(&key)? { Ok(()) } else { @@ -149,7 +149,7 @@ impl AuthController { None => self.store.prefix_first_expiration_date(key, action)?, }) { // check expiration date. - Some(Some(exp)) => Ok(Utc::now() < exp), + Some(Some(exp)) => Ok(OffsetDateTime::now_utc() < exp), // no expiration date. Some(None) => Ok(true), // action or index forbidden. diff --git a/meilisearch-auth/src/store.rs b/meilisearch-auth/src/store.rs index 19ff50990..4bd3cdded 100644 --- a/meilisearch-auth/src/store.rs +++ b/meilisearch-auth/src/store.rs @@ -8,9 +8,9 @@ use std::path::Path; use std::str; use std::sync::Arc; -use chrono::{DateTime, Utc}; -use heed::types::{ByteSlice, DecodeIgnore, SerdeJson}; -use heed::{Database, Env, EnvOpenOptions, RwTxn}; +use milli::heed::types::{ByteSlice, DecodeIgnore, SerdeJson}; +use milli::heed::{Database, Env, EnvOpenOptions, RwTxn}; +use time::OffsetDateTime; use super::error::Result; use super::{Action, Key}; @@ -27,7 +27,7 @@ pub type KeyId = [u8; KEY_ID_LENGTH]; pub struct HeedAuthStore { env: Arc, keys: Database>, - action_keyid_index_expiration: Database>>>, + action_keyid_index_expiration: Database>>, should_close_on_drop: bool, } @@ -39,7 +39,7 @@ impl Drop for HeedAuthStore { } } -pub fn open_auth_store_env(path: &Path) -> heed::Result { +pub fn open_auth_store_env(path: &Path) -> milli::heed::Result { let mut options = EnvOpenOptions::new(); options.map_size(AUTH_STORE_SIZE); // 1GB options.max_dbs(2); @@ -150,7 +150,7 @@ impl HeedAuthStore { key: &[u8], action: Action, index: Option<&[u8]>, - ) -> Result>>> { + ) -> Result>> { let rtxn = self.env.read_txn()?; match self.get_key_id(key) { Some(id) => { @@ -165,7 +165,7 @@ impl HeedAuthStore { &self, key: &[u8], action: Action, - ) -> Result>>> { + ) -> Result>> { let rtxn = self.env.read_txn()?; match self.get_key_id(key) { Some(id) => { @@ -203,7 +203,7 @@ impl HeedAuthStore { /// optionnally on a spcific index, for a given key. pub struct KeyIdActionCodec; -impl<'a> heed::BytesDecode<'a> for KeyIdActionCodec { +impl<'a> milli::heed::BytesDecode<'a> for KeyIdActionCodec { type DItem = (KeyId, Action, Option<&'a [u8]>); fn bytes_decode(bytes: &'a [u8]) -> Option { @@ -218,7 +218,7 @@ impl<'a> heed::BytesDecode<'a> for KeyIdActionCodec { } } -impl<'a> heed::BytesEncode<'a> for KeyIdActionCodec { +impl<'a> milli::heed::BytesEncode<'a> for KeyIdActionCodec { type EItem = (&'a KeyId, &'a Action, Option<&'a [u8]>); fn bytes_encode((key_id, action, index): &Self::EItem) -> Option> { diff --git a/meilisearch-error/Cargo.toml b/meilisearch-error/Cargo.toml index 0b75e4151..ac1a4bddd 100644 --- a/meilisearch-error/Cargo.toml +++ b/meilisearch-error/Cargo.toml @@ -5,11 +5,11 @@ authors = ["marin "] edition = "2021" [dependencies] -actix-web = { version = "4", default-features = false } +actix-web = { version = "4.0.1", default-features = false } proptest = { version = "1.0.0", optional = true } proptest-derive = { version = "0.3.0", optional = true } -serde = { version = "1.0.130", features = ["derive"] } -serde_json = "1.0.69" +serde = { version = "1.0.136", features = ["derive"] } +serde_json = "1.0.79" [features] test-traits = ["proptest", "proptest-derive"] diff --git a/meilisearch-http/Cargo.toml b/meilisearch-http/Cargo.toml index 122da85e6..546e414ce 100644 --- a/meilisearch-http/Cargo.toml +++ b/meilisearch-http/Cargo.toml @@ -11,82 +11,82 @@ name = "meilisearch" path = "src/main.rs" [build-dependencies] -static-files = { version = "0.2.1", optional = true } -anyhow = { version = "1.0.43", optional = true } -cargo_toml = { version = "0.9", optional = true } +anyhow = { version = "1.0.56", optional = true } +cargo_toml = { version = "0.11.4", optional = true } hex = { version = "0.4.3", optional = true } -reqwest = { version = "0.11.4", features = ["blocking", "rustls-tls"], default-features = false, optional = true } -sha-1 = { version = "0.9.8", optional = true } -tempfile = { version = "3.2.0", optional = true } -vergen = { version = "5.1.15", default-features = false, features = ["git"] } +reqwest = { version = "0.11.9", features = ["blocking", "rustls-tls"], default-features = false, optional = true } +sha-1 = { version = "0.10.0", optional = true } +static-files = { version = "0.2.3", optional = true } +tempfile = { version = "3.3.0", optional = true } +vergen = { version = "7.0.0", default-features = false, features = ["git"] } zip = { version = "0.5.13", optional = true } [dependencies] -actix-cors = "0.6" -actix-web = { version = "4", features = ["rustls"] } +actix-cors = "0.6.1" +actix-web = { version = "4.0.1", default-features = false, features = ["macros", "compress-brotli", "compress-gzip", "cookies", "rustls"] } actix-web-static-files = { git = "https://github.com/kilork/actix-web-static-files.git", rev = "2d3b6160", optional = true } -anyhow = { version = "1.0.43", features = ["backtrace"] } -arc-swap = "1.3.2" -async-stream = "0.3.2" -async-trait = "0.1.51" +anyhow = { version = "1.0.56", features = ["backtrace"] } +async-stream = "0.3.3" +async-trait = "0.1.52" bstr = "0.2.17" -byte-unit = { version = "4.0.12", default-features = false, features = ["std", "serde"] } +byte-unit = { version = "4.0.14", default-features = false, features = ["std", "serde"] } bytes = "1.1.0" -chrono = { version = "0.4.19", features = ["serde"] } -crossbeam-channel = "0.5.1" +clap = { version = "3.1.6", features = ["derive", "env"] } +crossbeam-channel = "0.5.2" either = "1.6.1" env_logger = "0.9.0" -flate2 = "1.0.21" +flate2 = "1.0.22" fst = "0.4.7" -futures = "0.3.17" -futures-util = "0.3.17" -heed = { git = "https://github.com/Kerollmops/heed", tag = "v0.12.1" } -http = "0.2.4" -indexmap = { version = "1.7.0", features = ["serde-1"] } -itertools = "0.10.1" -jsonwebtoken = "7" +futures = "0.3.21" +futures-util = "0.3.21" +http = "0.2.6" +indexmap = { version = "1.8.0", features = ["serde-1"] } +itertools = "0.10.3" +jsonwebtoken = "8.0.1" log = "0.4.14" meilisearch-auth = { path = "../meilisearch-auth" } meilisearch-error = { path = "../meilisearch-error" } meilisearch-lib = { path = "../meilisearch-lib" } mime = "0.3.16" -num_cpus = "1.13.0" +num_cpus = "1.13.1" obkv = "0.2.0" -once_cell = "1.8.0" -parking_lot = "0.11.2" -pin-project = "1.0.8" +once_cell = "1.10.0" +parking_lot = "0.12.0" +pin-project-lite = "0.2.8" platform-dirs = "0.3.0" -rand = "0.8.4" +rand = "0.8.5" rayon = "1.5.1" -regex = "1.5.4" -rustls = "0.20.2" -rustls-pemfile = "0.2" -segment = { version = "0.1.2", optional = true } -serde = { version = "1.0.130", features = ["derive"] } -serde_json = { version = "1.0.67", features = ["preserve_order"] } -sha2 = "0.9.6" -siphasher = "0.3.7" -slice-group-by = "0.2.6" -static-files = { version = "0.2.1", optional = true } -clap = { version = "3.0", features = ["derive", "env"] } -sysinfo = "0.20.2" -tar = "0.4.37" -tempfile = "3.2.0" -thiserror = "1.0.28" -tokio = { version = "1.11.0", features = ["full"] } -tokio-stream = "0.1.7" +regex = "1.5.5" +rustls = "0.20.4" +rustls-pemfile = "0.3.0" +segment = { version = "0.2.0", optional = true } +serde = { version = "1.0.136", features = ["derive"] } +serde_json = { version = "1.0.79", features = ["preserve_order"] } +sha2 = "0.10.2" +siphasher = "0.3.10" +slice-group-by = "0.3.0" +static-files = { version = "0.2.3", optional = true } +sysinfo = "0.23.5" +tar = "0.4.38" +tempfile = "3.3.0" +thiserror = "1.0.30" +time = { version = "0.3.7", features = ["serde-well-known", "formatting", "parsing", "macros"] } +tokio = { version = "1.17.0", features = ["full"] } +tokio-stream = "0.1.8" uuid = { version = "0.8.2", features = ["serde"] } walkdir = "2.3.2" [dev-dependencies] -actix-rt = "2.2.0" +actix-rt = "2.7.0" assert-json-diff = "2.0.1" maplit = "1.0.2" -paste = "1.0.5" +paste = "1.0.6" serde_url_params = "0.2.1" urlencoding = "2.1.0" [features] +default = ["analytics", "mini-dashboard"] +analytics = ["segment"] mini-dashboard = [ "actix-web-static-files", "static-files", @@ -98,12 +98,10 @@ mini-dashboard = [ "tempfile", "zip", ] -analytics = ["segment"] -default = ["analytics", "mini-dashboard"] [target.'cfg(target_os = "linux")'.dependencies] -tikv-jemallocator = "0.4.1" +tikv-jemallocator = "0.4.3" [package.metadata.mini-dashboard] -assets-url = "https://github.com/meilisearch/mini-dashboard/releases/download/v0.1.7/build.zip" -sha1 = "e2feedf271917c4b7b88998eff5aaaea1d3925b9" +assets-url = "https://github.com/meilisearch/mini-dashboard/releases/download/v0.1.9/build.zip" +sha1 = "b1833c3e5dc6b5d9d519ae4834935ae6c8a47024" diff --git a/meilisearch-http/src/analytics/segment_analytics.rs b/meilisearch-http/src/analytics/segment_analytics.rs index 2936c4d5d..905d55281 100644 --- a/meilisearch-http/src/analytics/segment_analytics.rs +++ b/meilisearch-http/src/analytics/segment_analytics.rs @@ -6,7 +6,6 @@ use std::time::{Duration, Instant}; use actix_web::http::header::USER_AGENT; use actix_web::HttpRequest; -use chrono::{DateTime, Utc}; use http::header::CONTENT_TYPE; use meilisearch_auth::SearchRules; use meilisearch_lib::index::{SearchQuery, SearchResult}; @@ -18,6 +17,7 @@ use segment::message::{Identify, Track, User}; use segment::{AutoBatcher, Batcher, HttpClient}; use serde_json::{json, Value}; use sysinfo::{DiskExt, System, SystemExt}; +use time::OffsetDateTime; use tokio::select; use tokio::sync::mpsc::{self, Receiver, Sender}; use uuid::Uuid; @@ -323,7 +323,7 @@ impl Segment { #[derive(Default)] pub struct SearchAggregator { - timestamp: Option>, + timestamp: Option, // context user_agents: HashSet, @@ -360,7 +360,7 @@ pub struct SearchAggregator { impl SearchAggregator { pub fn from_query(query: &SearchQuery, request: &HttpRequest) -> Self { let mut ret = Self::default(); - ret.timestamp = Some(chrono::offset::Utc::now()); + ret.timestamp = Some(OffsetDateTime::now_utc()); ret.total_received = 1; ret.user_agents = extract_user_agents(request).into_iter().collect(); @@ -504,7 +504,7 @@ impl SearchAggregator { #[derive(Default)] pub struct DocumentsAggregator { - timestamp: Option>, + timestamp: Option, // set to true when at least one request was received updated: bool, @@ -524,7 +524,7 @@ impl DocumentsAggregator { request: &HttpRequest, ) -> Self { let mut ret = Self::default(); - ret.timestamp = Some(chrono::offset::Utc::now()); + ret.timestamp = Some(OffsetDateTime::now_utc()); ret.updated = true; ret.user_agents = extract_user_agents(request).into_iter().collect(); diff --git a/meilisearch-http/src/extractors/authentication/error.rs b/meilisearch-http/src/extractors/authentication/error.rs index c1af9a3ce..6d362dcbf 100644 --- a/meilisearch-http/src/extractors/authentication/error.rs +++ b/meilisearch-http/src/extractors/authentication/error.rs @@ -5,7 +5,7 @@ pub enum AuthenticationError { #[error("The Authorization header is missing. It must use the bearer authorization method.")] MissingAuthorizationHeader, #[error("The provided API key is invalid.")] - InvalidToken(String), + InvalidToken, // Triggered on configuration error. #[error("An internal error has occurred. `Irretrievable state`.")] IrretrievableState, @@ -15,7 +15,7 @@ impl ErrorCode for AuthenticationError { fn error_code(&self) -> Code { match self { AuthenticationError::MissingAuthorizationHeader => Code::MissingAuthorizationHeader, - AuthenticationError::InvalidToken(_) => Code::InvalidToken, + AuthenticationError::InvalidToken => Code::InvalidToken, AuthenticationError::IrretrievableState => Code::Internal, } } diff --git a/meilisearch-http/src/extractors/authentication/mod.rs b/meilisearch-http/src/extractors/authentication/mod.rs index d4c8d5534..c9c35b748 100644 --- a/meilisearch-http/src/extractors/authentication/mod.rs +++ b/meilisearch-http/src/extractors/authentication/mod.rs @@ -2,28 +2,83 @@ mod error; use std::marker::PhantomData; use std::ops::Deref; +use std::pin::Pin; use actix_web::FromRequest; use futures::future::err; -use futures::future::{ok, Ready}; -use meilisearch_error::ResponseError; +use futures::Future; +use meilisearch_error::{Code, ResponseError}; use error::AuthenticationError; use meilisearch_auth::{AuthController, AuthFilter}; -pub struct GuardedData { +pub struct GuardedData { data: D, filters: AuthFilter, - _marker: PhantomData, + _marker: PhantomData

, } -impl GuardedData { +impl GuardedData { pub fn filters(&self) -> &AuthFilter { &self.filters } + + async fn auth_bearer( + auth: AuthController, + token: String, + index: Option, + data: Option, + ) -> Result + where + P: Policy + 'static, + { + match Self::authenticate(auth, token, index).await? { + Some(filters) => match data { + Some(data) => Ok(Self { + data, + filters, + _marker: PhantomData, + }), + None => Err(AuthenticationError::IrretrievableState.into()), + }, + None => Err(AuthenticationError::InvalidToken.into()), + } + } + + async fn auth_token(auth: AuthController, data: Option) -> Result + where + P: Policy + 'static, + { + match Self::authenticate(auth, String::new(), None).await? { + Some(filters) => match data { + Some(data) => Ok(Self { + data, + filters, + _marker: PhantomData, + }), + None => Err(AuthenticationError::IrretrievableState.into()), + }, + None => Err(AuthenticationError::MissingAuthorizationHeader.into()), + } + } + + async fn authenticate( + auth: AuthController, + token: String, + index: Option, + ) -> Result, ResponseError> + where + P: Policy + 'static, + { + Ok(tokio::task::spawn_blocking(move || { + P::authenticate(auth, token.as_ref(), index.as_deref()) + }) + .await + .map_err(|e| ResponseError::from_msg(e.to_string(), Code::Internal))?) + } } -impl Deref for GuardedData { +impl Deref for GuardedData { type Target = D; fn deref(&self) -> &Self::Target { @@ -34,7 +89,7 @@ impl Deref for GuardedData { impl FromRequest for GuardedData { type Error = ResponseError; - type Future = Ready>; + type Future = Pin>>>; fn from_request( req: &actix_web::HttpRequest, @@ -51,40 +106,22 @@ impl FromRequest for GuardedData // TODO: find a less hardcoded way? let index = req.match_info().get("index_uid"); match type_token.next() { - Some(token) => match P::authenticate(auth, token, index) { - Some(filters) => match req.app_data::().cloned() { - Some(data) => ok(Self { - data, - filters, - _marker: PhantomData, - }), - None => err(AuthenticationError::IrretrievableState.into()), - }, - None => { - let token = token.to_string(); - err(AuthenticationError::InvalidToken(token).into()) - } - }, - None => { - err(AuthenticationError::InvalidToken("unknown".to_string()).into()) - } + Some(token) => Box::pin(Self::auth_bearer( + auth, + token.to_string(), + index.map(String::from), + req.app_data::().cloned(), + )), + None => Box::pin(err(AuthenticationError::InvalidToken.into())), } } - _otherwise => err(AuthenticationError::MissingAuthorizationHeader.into()), - }, - None => match P::authenticate(auth, "", None) { - Some(filters) => match req.app_data::().cloned() { - Some(data) => ok(Self { - data, - filters, - _marker: PhantomData, - }), - None => err(AuthenticationError::IrretrievableState.into()), - }, - None => err(AuthenticationError::MissingAuthorizationHeader.into()), + _otherwise => { + Box::pin(err(AuthenticationError::MissingAuthorizationHeader.into())) + } }, + None => Box::pin(Self::auth_token(auth, req.app_data::().cloned())), }, - None => err(AuthenticationError::IrretrievableState.into()), + None => Box::pin(err(AuthenticationError::IrretrievableState.into())), } } } @@ -94,21 +131,22 @@ pub trait Policy { } pub mod policies { - use chrono::Utc; - use jsonwebtoken::{dangerous_insecure_decode, decode, Algorithm, DecodingKey, Validation}; - use once_cell::sync::Lazy; + use jsonwebtoken::{decode, Algorithm, DecodingKey, Validation}; use serde::{Deserialize, Serialize}; + use time::OffsetDateTime; use crate::extractors::authentication::Policy; use meilisearch_auth::{Action, AuthController, AuthFilter, SearchRules}; // reexport actions in policies in order to be used in routes configuration. pub use meilisearch_auth::actions; - pub static TENANT_TOKEN_VALIDATION: Lazy = Lazy::new(|| Validation { - validate_exp: false, - algorithms: vec![Algorithm::HS256, Algorithm::HS384, Algorithm::HS512], - ..Default::default() - }); + fn tenant_token_validation() -> Validation { + let mut validation = Validation::default(); + validation.validate_exp = false; + validation.required_spec_claims.remove("exp"); + validation.algorithms = vec![Algorithm::HS256, Algorithm::HS384, Algorithm::HS512]; + validation + } pub struct MasterPolicy; @@ -167,12 +205,17 @@ pub mod policies { return None; } + let mut validation = tenant_token_validation(); + validation.insecure_disable_signature_validation(); + let dummy_key = DecodingKey::from_secret(b"secret"); + let token_data = decode::(token, &dummy_key, &validation).ok()?; + // get token fields without validating it. let Claims { search_rules, exp, api_key_prefix, - } = dangerous_insecure_decode::(token).ok()?.claims; + } = token_data.claims; // Check index access if an index restriction is provided. if let Some(index) = index { @@ -183,7 +226,7 @@ pub mod policies { // Check if token is expired. if let Some(exp) = exp { - if Utc::now().timestamp() > exp { + if OffsetDateTime::now_utc().unix_timestamp() > exp { return None; } } @@ -198,7 +241,7 @@ pub mod policies { decode::( token, &DecodingKey::from_secret(key.as_bytes()), - &TENANT_TOKEN_VALIDATION, + &tenant_token_validation(), ) .ok()?; diff --git a/meilisearch-http/src/extractors/mod.rs b/meilisearch-http/src/extractors/mod.rs index 09a56e4a0..98a22f8c9 100644 --- a/meilisearch-http/src/extractors/mod.rs +++ b/meilisearch-http/src/extractors/mod.rs @@ -1,3 +1,4 @@ pub mod payload; #[macro_use] pub mod authentication; +pub mod sequential_extractor; diff --git a/meilisearch-http/src/extractors/sequential_extractor.rs b/meilisearch-http/src/extractors/sequential_extractor.rs new file mode 100644 index 000000000..d6cee6083 --- /dev/null +++ b/meilisearch-http/src/extractors/sequential_extractor.rs @@ -0,0 +1,148 @@ +#![allow(non_snake_case)] +use std::{future::Future, pin::Pin, task::Poll}; + +use actix_web::{dev::Payload, FromRequest, Handler, HttpRequest}; +use pin_project_lite::pin_project; + +/// `SeqHandler` is an actix `Handler` that enforces that extractors errors are returned in the +/// same order as they are defined in the wrapped handler. This is needed because, by default, actix +/// resolves the extractors concurrently, whereas we always need the authentication extractor to +/// throw first. +#[derive(Clone)] +pub struct SeqHandler(pub H); + +pub struct SeqFromRequest(T); + +/// This macro implements `FromRequest` for arbitrary arity handler, except for one, which is +/// useless anyway. +macro_rules! gen_seq { + ($ty:ident; $($T:ident)+) => { + pin_project! { + pub struct $ty<$($T: FromRequest), +> { + $( + #[pin] + $T: ExtractFuture<$T::Future, $T, $T::Error>, + )+ + } + } + + impl<$($T: FromRequest), +> Future for $ty<$($T),+> { + type Output = Result, actix_web::Error>; + + fn poll(self: Pin<&mut Self>, cx: &mut std::task::Context<'_>) -> Poll { + let mut this = self.project(); + + let mut count_fut = 0; + let mut count_finished = 0; + + $( + count_fut += 1; + match this.$T.as_mut().project() { + ExtractProj::Future { fut } => match fut.poll(cx) { + Poll::Ready(Ok(output)) => { + count_finished += 1; + let _ = this + .$T + .as_mut() + .project_replace(ExtractFuture::Done { output }); + } + Poll::Ready(Err(error)) => { + count_finished += 1; + let _ = this + .$T + .as_mut() + .project_replace(ExtractFuture::Error { error }); + } + Poll::Pending => (), + }, + ExtractProj::Done { .. } => count_finished += 1, + ExtractProj::Error { .. } => { + // short circuit if all previous are finished and we had an error. + if count_finished == count_fut { + match this.$T.project_replace(ExtractFuture::Empty) { + ExtractReplaceProj::Error { error } => { + return Poll::Ready(Err(error.into())) + } + _ => unreachable!("Invalid future state"), + } + } else { + count_finished += 1; + } + } + ExtractProj::Empty => unreachable!("From request polled after being finished. {}", stringify!($T)), + } + )+ + + if count_fut == count_finished { + let result = ( + $( + match this.$T.project_replace(ExtractFuture::Empty) { + ExtractReplaceProj::Done { output } => output, + ExtractReplaceProj::Error { error } => return Poll::Ready(Err(error.into())), + _ => unreachable!("Invalid future state"), + }, + )+ + ); + + Poll::Ready(Ok(SeqFromRequest(result))) + } else { + Poll::Pending + } + } + } + + impl<$($T: FromRequest,)+> FromRequest for SeqFromRequest<($($T,)+)> { + type Error = actix_web::Error; + + type Future = $ty<$($T),+>; + + fn from_request(req: &HttpRequest, payload: &mut Payload) -> Self::Future { + $ty { + $( + $T: ExtractFuture::Future { + fut: $T::from_request(req, payload), + }, + )+ + } + } + } + + impl Handler> for SeqHandler + where + Han: Handler<($($T),+)>, + { + type Output = Han::Output; + type Future = Han::Future; + + fn call(&self, args: SeqFromRequest<($($T),+)>) -> Self::Future { + self.0.call(args.0) + } + } + }; +} + +// Not working for a single argument, but then, it is not really necessary. +// gen_seq! { SeqFromRequestFut1; A } +gen_seq! { SeqFromRequestFut2; A B } +gen_seq! { SeqFromRequestFut3; A B C } +gen_seq! { SeqFromRequestFut4; A B C D } +gen_seq! { SeqFromRequestFut5; A B C D E } +gen_seq! { SeqFromRequestFut6; A B C D E F } + +pin_project! { + #[project = ExtractProj] + #[project_replace = ExtractReplaceProj] + enum ExtractFuture { + Future { + #[pin] + fut: Fut, + }, + Done { + output: Res, + }, + Error { + error: Err, + }, + Empty, + } +} diff --git a/meilisearch-http/src/helpers/env.rs b/meilisearch-http/src/helpers/env.rs index 9bc81bc69..b76c9c8a7 100644 --- a/meilisearch-http/src/helpers/env.rs +++ b/meilisearch-http/src/helpers/env.rs @@ -1,10 +1,11 @@ +use meilisearch_lib::heed::Env; use walkdir::WalkDir; pub trait EnvSizer { fn size(&self) -> u64; } -impl EnvSizer for heed::Env { +impl EnvSizer for Env { fn size(&self) -> u64 { WalkDir::new(self.path()) .into_iter() diff --git a/meilisearch-http/src/lib.rs b/meilisearch-http/src/lib.rs index 71932dd9b..d1f5d9da1 100644 --- a/meilisearch-http/src/lib.rs +++ b/meilisearch-http/src/lib.rs @@ -32,7 +32,7 @@ pub fn setup_meilisearch(opt: &Opt) -> anyhow::Result { // enable autobatching? let _ = AUTOBATCHING_ENABLED.store( - opt.scheduler_options.enable_autobatching, + opt.scheduler_options.enable_auto_batching, std::sync::atomic::Ordering::Relaxed, ); diff --git a/meilisearch-http/src/option.rs b/meilisearch-http/src/option.rs index b6cc3db22..7284b4588 100644 --- a/meilisearch-http/src/option.rs +++ b/meilisearch-http/src/option.rs @@ -42,6 +42,7 @@ pub struct Opt { /// Do not send analytics to Meili. #[cfg(all(not(debug_assertions), feature = "analytics"))] + #[serde(skip)] // we can't send true #[clap(long, env = "MEILI_NO_ANALYTICS")] pub no_analytics: bool, @@ -148,6 +149,7 @@ pub struct Opt { #[clap(skip)] pub indexer_options: IndexerOpts, + #[serde(flatten)] #[clap(flatten)] pub scheduler_options: SchedulerConfig, } @@ -256,3 +258,13 @@ fn load_ocsp(filename: &Option) -> anyhow::Result> { Ok(ret) } + +#[cfg(test)] +mod test { + use super::*; + + #[test] + fn test_valid_opt() { + assert!(Opt::try_parse_from(Some("")).is_ok()); + } +} diff --git a/meilisearch-http/src/routes/api_key.rs b/meilisearch-http/src/routes/api_key.rs index 9e67c3195..310b09c4d 100644 --- a/meilisearch-http/src/routes/api_key.rs +++ b/meilisearch-http/src/routes/api_key.rs @@ -1,26 +1,29 @@ use std::str; use actix_web::{web, HttpRequest, HttpResponse}; -use chrono::SecondsFormat; -use meilisearch_auth::{Action, AuthController, Key}; +use meilisearch_auth::{error::AuthControllerError, Action, AuthController, Key}; use serde::{Deserialize, Serialize}; use serde_json::Value; +use time::OffsetDateTime; -use crate::extractors::authentication::{policies::*, GuardedData}; -use meilisearch_error::ResponseError; +use crate::extractors::{ + authentication::{policies::*, GuardedData}, + sequential_extractor::SeqHandler, +}; +use meilisearch_error::{Code, ResponseError}; pub fn configure(cfg: &mut web::ServiceConfig) { cfg.service( web::resource("") - .route(web::post().to(create_api_key)) - .route(web::get().to(list_api_keys)), + .route(web::post().to(SeqHandler(create_api_key))) + .route(web::get().to(SeqHandler(list_api_keys))), ) .service( web::resource("/{api_key}") - .route(web::get().to(get_api_key)) - .route(web::patch().to(patch_api_key)) - .route(web::delete().to(delete_api_key)), + .route(web::get().to(SeqHandler(get_api_key))) + .route(web::patch().to(SeqHandler(patch_api_key))) + .route(web::delete().to(SeqHandler(delete_api_key))), ); } @@ -29,8 +32,13 @@ pub async fn create_api_key( body: web::Json, _req: HttpRequest, ) -> Result { - let key = auth_controller.create_key(body.into_inner()).await?; - let res = KeyView::from_key(key, &auth_controller); + let v = body.into_inner(); + let res = tokio::task::spawn_blocking(move || -> Result<_, AuthControllerError> { + let key = auth_controller.create_key(v)?; + Ok(KeyView::from_key(key, &auth_controller)) + }) + .await + .map_err(|e| ResponseError::from_msg(e.to_string(), Code::Internal))??; Ok(HttpResponse::Created().json(res)) } @@ -39,11 +47,16 @@ pub async fn list_api_keys( auth_controller: GuardedData, _req: HttpRequest, ) -> Result { - let keys = auth_controller.list_keys().await?; - let res: Vec<_> = keys - .into_iter() - .map(|k| KeyView::from_key(k, &auth_controller)) - .collect(); + let res = tokio::task::spawn_blocking(move || -> Result<_, AuthControllerError> { + let keys = auth_controller.list_keys()?; + let res: Vec<_> = keys + .into_iter() + .map(|k| KeyView::from_key(k, &auth_controller)) + .collect(); + Ok(res) + }) + .await + .map_err(|e| ResponseError::from_msg(e.to_string(), Code::Internal))??; Ok(HttpResponse::Ok().json(KeyListView::from(res))) } @@ -52,8 +65,13 @@ pub async fn get_api_key( auth_controller: GuardedData, path: web::Path, ) -> Result { - let key = auth_controller.get_key(&path.api_key).await?; - let res = KeyView::from_key(key, &auth_controller); + let api_key = path.into_inner().api_key; + let res = tokio::task::spawn_blocking(move || -> Result<_, AuthControllerError> { + let key = auth_controller.get_key(&api_key)?; + Ok(KeyView::from_key(key, &auth_controller)) + }) + .await + .map_err(|e| ResponseError::from_msg(e.to_string(), Code::Internal))??; Ok(HttpResponse::Ok().json(res)) } @@ -63,10 +81,14 @@ pub async fn patch_api_key( body: web::Json, path: web::Path, ) -> Result { - let key = auth_controller - .update_key(&path.api_key, body.into_inner()) - .await?; - let res = KeyView::from_key(key, &auth_controller); + let api_key = path.into_inner().api_key; + let body = body.into_inner(); + let res = tokio::task::spawn_blocking(move || -> Result<_, AuthControllerError> { + let key = auth_controller.update_key(&api_key, body)?; + Ok(KeyView::from_key(key, &auth_controller)) + }) + .await + .map_err(|e| ResponseError::from_msg(e.to_string(), Code::Internal))??; Ok(HttpResponse::Ok().json(res)) } @@ -75,7 +97,10 @@ pub async fn delete_api_key( auth_controller: GuardedData, path: web::Path, ) -> Result { - auth_controller.delete_key(&path.api_key).await?; + let api_key = path.into_inner().api_key; + tokio::task::spawn_blocking(move || auth_controller.delete_key(&api_key)) + .await + .map_err(|e| ResponseError::from_msg(e.to_string(), Code::Internal))??; Ok(HttpResponse::NoContent().finish()) } @@ -92,9 +117,12 @@ struct KeyView { key: String, actions: Vec, indexes: Vec, - expires_at: Option, - created_at: String, - updated_at: String, + #[serde(serialize_with = "time::serde::rfc3339::option::serialize")] + expires_at: Option, + #[serde(serialize_with = "time::serde::rfc3339::serialize")] + created_at: OffsetDateTime, + #[serde(serialize_with = "time::serde::rfc3339::serialize")] + updated_at: OffsetDateTime, } impl KeyView { @@ -107,11 +135,9 @@ impl KeyView { key: generated_key, actions: key.actions, indexes: key.indexes, - expires_at: key - .expires_at - .map(|dt| dt.to_rfc3339_opts(SecondsFormat::Secs, true)), - created_at: key.created_at.to_rfc3339_opts(SecondsFormat::Secs, true), - updated_at: key.updated_at.to_rfc3339_opts(SecondsFormat::Secs, true), + expires_at: key.expires_at, + created_at: key.created_at, + updated_at: key.updated_at, } } } diff --git a/meilisearch-http/src/routes/dump.rs b/meilisearch-http/src/routes/dump.rs index 0627ea378..65cd7521f 100644 --- a/meilisearch-http/src/routes/dump.rs +++ b/meilisearch-http/src/routes/dump.rs @@ -7,10 +7,13 @@ use serde_json::json; use crate::analytics::Analytics; use crate::extractors::authentication::{policies::*, GuardedData}; +use crate::extractors::sequential_extractor::SeqHandler; pub fn configure(cfg: &mut web::ServiceConfig) { - cfg.service(web::resource("").route(web::post().to(create_dump))) - .service(web::resource("/{dump_uid}/status").route(web::get().to(get_dump_status))); + cfg.service(web::resource("").route(web::post().to(SeqHandler(create_dump)))) + .service( + web::resource("/{dump_uid}/status").route(web::get().to(SeqHandler(get_dump_status))), + ); } pub async fn create_dump( diff --git a/meilisearch-http/src/routes/indexes/documents.rs b/meilisearch-http/src/routes/indexes/documents.rs index d18c600af..66551ec77 100644 --- a/meilisearch-http/src/routes/indexes/documents.rs +++ b/meilisearch-http/src/routes/indexes/documents.rs @@ -20,6 +20,7 @@ use crate::analytics::Analytics; use crate::error::MeilisearchHttpError; use crate::extractors::authentication::{policies::*, GuardedData}; use crate::extractors::payload::Payload; +use crate::extractors::sequential_extractor::SeqHandler; use crate::task::SummarizedTaskView; const DEFAULT_RETRIEVE_DOCUMENTS_OFFSET: usize = 0; @@ -71,17 +72,17 @@ pub struct DocumentParam { pub fn configure(cfg: &mut web::ServiceConfig) { cfg.service( web::resource("") - .route(web::get().to(get_all_documents)) - .route(web::post().to(add_documents)) - .route(web::put().to(update_documents)) - .route(web::delete().to(clear_all_documents)), + .route(web::get().to(SeqHandler(get_all_documents))) + .route(web::post().to(SeqHandler(add_documents))) + .route(web::put().to(SeqHandler(update_documents))) + .route(web::delete().to(SeqHandler(clear_all_documents))), ) // this route needs to be before the /documents/{document_id} to match properly - .service(web::resource("/delete-batch").route(web::post().to(delete_documents))) + .service(web::resource("/delete-batch").route(web::post().to(SeqHandler(delete_documents)))) .service( web::resource("/{document_id}") - .route(web::get().to(get_document)) - .route(web::delete().to(delete_document)), + .route(web::get().to(SeqHandler(get_document))) + .route(web::delete().to(SeqHandler(delete_document))), ); } diff --git a/meilisearch-http/src/routes/indexes/mod.rs b/meilisearch-http/src/routes/indexes/mod.rs index fe7ba0b11..bd74fd724 100644 --- a/meilisearch-http/src/routes/indexes/mod.rs +++ b/meilisearch-http/src/routes/indexes/mod.rs @@ -1,14 +1,15 @@ use actix_web::{web, HttpRequest, HttpResponse}; -use chrono::{DateTime, Utc}; use log::debug; use meilisearch_error::ResponseError; use meilisearch_lib::index_controller::Update; use meilisearch_lib::MeiliSearch; use serde::{Deserialize, Serialize}; use serde_json::json; +use time::OffsetDateTime; use crate::analytics::Analytics; use crate::extractors::authentication::{policies::*, GuardedData}; +use crate::extractors::sequential_extractor::SeqHandler; use crate::task::SummarizedTaskView; pub mod documents; @@ -20,17 +21,17 @@ pub fn configure(cfg: &mut web::ServiceConfig) { cfg.service( web::resource("") .route(web::get().to(list_indexes)) - .route(web::post().to(create_index)), + .route(web::post().to(SeqHandler(create_index))), ) .service( web::scope("/{index_uid}") .service( web::resource("") - .route(web::get().to(get_index)) - .route(web::put().to(update_index)) - .route(web::delete().to(delete_index)), + .route(web::get().to(SeqHandler(get_index))) + .route(web::put().to(SeqHandler(update_index))) + .route(web::delete().to(SeqHandler(delete_index))), ) - .service(web::resource("/stats").route(web::get().to(get_index_stats))) + .service(web::resource("/stats").route(web::get().to(SeqHandler(get_index_stats)))) .service(web::scope("/documents").configure(documents::configure)) .service(web::scope("/search").configure(search::configure)) .service(web::scope("/tasks").configure(tasks::configure)) @@ -95,9 +96,12 @@ pub struct UpdateIndexRequest { pub struct UpdateIndexResponse { name: String, uid: String, - created_at: DateTime, - updated_at: DateTime, - primary_key: Option, + #[serde(serialize_with = "time::serde::rfc3339::serialize")] + created_at: OffsetDateTime, + #[serde(serialize_with = "time::serde::rfc3339::serialize")] + updated_at: OffsetDateTime, + #[serde(serialize_with = "time::serde::rfc3339::serialize")] + primary_key: OffsetDateTime, } pub async fn get_index( diff --git a/meilisearch-http/src/routes/indexes/search.rs b/meilisearch-http/src/routes/indexes/search.rs index a1695633e..14b3f74f5 100644 --- a/meilisearch-http/src/routes/indexes/search.rs +++ b/meilisearch-http/src/routes/indexes/search.rs @@ -9,12 +9,13 @@ use serde_json::Value; use crate::analytics::{Analytics, SearchAggregator}; use crate::extractors::authentication::{policies::*, GuardedData}; +use crate::extractors::sequential_extractor::SeqHandler; pub fn configure(cfg: &mut web::ServiceConfig) { cfg.service( web::resource("") - .route(web::get().to(search_with_url_query)) - .route(web::post().to(search_with_post)), + .route(web::get().to(SeqHandler(search_with_url_query))) + .route(web::post().to(SeqHandler(search_with_post))), ); } diff --git a/meilisearch-http/src/routes/indexes/settings.rs b/meilisearch-http/src/routes/indexes/settings.rs index 8b38072c4..eeb3e71b3 100644 --- a/meilisearch-http/src/routes/indexes/settings.rs +++ b/meilisearch-http/src/routes/indexes/settings.rs @@ -23,6 +23,7 @@ macro_rules! make_setting_route { use crate::analytics::Analytics; use crate::extractors::authentication::{policies::*, GuardedData}; + use crate::extractors::sequential_extractor::SeqHandler; use crate::task::SummarizedTaskView; use meilisearch_error::ResponseError; @@ -98,9 +99,9 @@ macro_rules! make_setting_route { pub fn resources() -> Resource { Resource::new($route) - .route(web::get().to(get)) - .route(web::post().to(update)) - .route(web::delete().to(delete)) + .route(web::get().to(SeqHandler(get))) + .route(web::post().to(SeqHandler(update))) + .route(web::delete().to(SeqHandler(delete))) } } }; @@ -226,11 +227,12 @@ make_setting_route!( macro_rules! generate_configure { ($($mod:ident),*) => { pub fn configure(cfg: &mut web::ServiceConfig) { + use crate::extractors::sequential_extractor::SeqHandler; cfg.service( web::resource("") - .route(web::post().to(update_all)) - .route(web::get().to(get_all)) - .route(web::delete().to(delete_all))) + .route(web::post().to(SeqHandler(update_all))) + .route(web::get().to(SeqHandler(get_all))) + .route(web::delete().to(SeqHandler(delete_all)))) $(.service($mod::resources()))*; } }; diff --git a/meilisearch-http/src/routes/indexes/tasks.rs b/meilisearch-http/src/routes/indexes/tasks.rs index f20a39d4a..01ed85db8 100644 --- a/meilisearch-http/src/routes/indexes/tasks.rs +++ b/meilisearch-http/src/routes/indexes/tasks.rs @@ -1,18 +1,19 @@ use actix_web::{web, HttpRequest, HttpResponse}; -use chrono::{DateTime, Utc}; use log::debug; use meilisearch_error::ResponseError; use meilisearch_lib::MeiliSearch; use serde::{Deserialize, Serialize}; use serde_json::json; +use time::OffsetDateTime; use crate::analytics::Analytics; use crate::extractors::authentication::{policies::*, GuardedData}; +use crate::extractors::sequential_extractor::SeqHandler; use crate::task::{TaskListView, TaskView}; pub fn configure(cfg: &mut web::ServiceConfig) { - cfg.service(web::resource("").route(web::get().to(get_all_tasks_status))) - .service(web::resource("{task_id}").route(web::get().to(get_task_status))); + cfg.service(web::resource("").route(web::get().to(SeqHandler(get_all_tasks_status)))) + .service(web::resource("{task_id}").route(web::get().to(SeqHandler(get_task_status)))); } #[derive(Debug, Serialize)] @@ -20,9 +21,12 @@ pub fn configure(cfg: &mut web::ServiceConfig) { pub struct UpdateIndexResponse { name: String, uid: String, - created_at: DateTime, - updated_at: DateTime, - primary_key: Option, + #[serde(serialize_with = "time::serde::rfc3339::serialize")] + created_at: OffsetDateTime, + #[serde(serialize_with = "time::serde::rfc3339::serialize")] + updated_at: OffsetDateTime, + #[serde(serialize_with = "time::serde::rfc3339::serialize")] + primary_key: OffsetDateTime, } #[derive(Deserialize)] diff --git a/meilisearch-http/src/routes/mod.rs b/meilisearch-http/src/routes/mod.rs index 0ebc77042..49397444f 100644 --- a/meilisearch-http/src/routes/mod.rs +++ b/meilisearch-http/src/routes/mod.rs @@ -1,7 +1,7 @@ use actix_web::{web, HttpResponse}; -use chrono::{DateTime, Utc}; use log::debug; use serde::{Deserialize, Serialize}; +use time::OffsetDateTime; use meilisearch_error::ResponseError; use meilisearch_lib::index::{Settings, Unchecked}; @@ -54,8 +54,10 @@ pub struct ProcessedUpdateResult { #[serde(rename = "type")] pub update_type: UpdateType, pub duration: f64, // in seconds - pub enqueued_at: DateTime, - pub processed_at: DateTime, + #[serde(with = "time::serde::rfc3339")] + pub enqueued_at: OffsetDateTime, + #[serde(with = "time::serde::rfc3339")] + pub processed_at: OffsetDateTime, } #[derive(Debug, Clone, Serialize, Deserialize)] @@ -66,8 +68,10 @@ pub struct FailedUpdateResult { pub update_type: UpdateType, pub error: ResponseError, pub duration: f64, // in seconds - pub enqueued_at: DateTime, - pub processed_at: DateTime, + #[serde(with = "time::serde::rfc3339")] + pub enqueued_at: OffsetDateTime, + #[serde(with = "time::serde::rfc3339")] + pub processed_at: OffsetDateTime, } #[derive(Debug, Clone, Serialize, Deserialize)] @@ -76,9 +80,13 @@ pub struct EnqueuedUpdateResult { pub update_id: u64, #[serde(rename = "type")] pub update_type: UpdateType, - pub enqueued_at: DateTime, - #[serde(skip_serializing_if = "Option::is_none")] - pub started_processing_at: Option>, + #[serde(with = "time::serde::rfc3339")] + pub enqueued_at: OffsetDateTime, + #[serde( + skip_serializing_if = "Option::is_none", + with = "time::serde::rfc3339::option" + )] + pub started_processing_at: Option, } #[derive(Debug, Clone, Serialize, Deserialize)] diff --git a/meilisearch-http/src/routes/tasks.rs b/meilisearch-http/src/routes/tasks.rs index 350cef3dc..ae932253a 100644 --- a/meilisearch-http/src/routes/tasks.rs +++ b/meilisearch-http/src/routes/tasks.rs @@ -7,11 +7,12 @@ use serde_json::json; use crate::analytics::Analytics; use crate::extractors::authentication::{policies::*, GuardedData}; +use crate::extractors::sequential_extractor::SeqHandler; use crate::task::{TaskListView, TaskView}; pub fn configure(cfg: &mut web::ServiceConfig) { - cfg.service(web::resource("").route(web::get().to(get_tasks))) - .service(web::resource("/{task_id}").route(web::get().to(get_task))); + cfg.service(web::resource("").route(web::get().to(SeqHandler(get_tasks)))) + .service(web::resource("/{task_id}").route(web::get().to(SeqHandler(get_task)))); } async fn get_tasks( diff --git a/meilisearch-http/src/task.rs b/meilisearch-http/src/task.rs index 9881854e3..7179b10db 100644 --- a/meilisearch-http/src/task.rs +++ b/meilisearch-http/src/task.rs @@ -1,4 +1,6 @@ -use chrono::{DateTime, Duration, Utc}; +use std::fmt::Write; +use std::write; + use meilisearch_error::ResponseError; use meilisearch_lib::index::{Settings, Unchecked}; use meilisearch_lib::milli::update::IndexDocumentsMethod; @@ -7,6 +9,7 @@ use meilisearch_lib::tasks::task::{ DocumentDeletion, Task, TaskContent, TaskEvent, TaskId, TaskResult, }; use serde::{Serialize, Serializer}; +use time::{Duration, OffsetDateTime}; use crate::AUTOBATCHING_ENABLED; @@ -79,14 +82,52 @@ enum TaskDetails { ClearAll { deleted_documents: Option }, } +/// Serialize a `time::Duration` as a best effort ISO 8601 while waiting for +/// https://github.com/time-rs/time/issues/378. +/// This code is a port of the old code of time that was removed in 0.2. fn serialize_duration( duration: &Option, serializer: S, ) -> Result { match duration { Some(duration) => { - let duration_str = duration.to_string(); - serializer.serialize_str(&duration_str) + // technically speaking, negative duration is not valid ISO 8601 + if duration.is_negative() { + return serializer.serialize_none(); + } + + const SECS_PER_DAY: i64 = Duration::DAY.whole_seconds(); + let secs = duration.whole_seconds(); + let days = secs / SECS_PER_DAY; + let secs = secs - days * SECS_PER_DAY; + let hasdate = days != 0; + let nanos = duration.subsec_nanoseconds(); + let hastime = (secs != 0 || nanos != 0) || !hasdate; + + // all the following unwrap can't fail + let mut res = String::new(); + write!(&mut res, "P").unwrap(); + + if hasdate { + write!(&mut res, "{}D", days).unwrap(); + } + + const NANOS_PER_MILLI: i32 = Duration::MILLISECOND.subsec_nanoseconds(); + const NANOS_PER_MICRO: i32 = Duration::MICROSECOND.subsec_nanoseconds(); + + if hastime { + if nanos == 0 { + write!(&mut res, "T{}S", secs).unwrap(); + } else if nanos % NANOS_PER_MILLI == 0 { + write!(&mut res, "T{}.{:03}S", secs, nanos / NANOS_PER_MILLI).unwrap(); + } else if nanos % NANOS_PER_MICRO == 0 { + write!(&mut res, "T{}.{:06}S", secs, nanos / NANOS_PER_MICRO).unwrap(); + } else { + write!(&mut res, "T{}.{:09}S", secs, nanos).unwrap(); + } + } + + serializer.serialize_str(&res) } None => serializer.serialize_none(), } @@ -106,9 +147,12 @@ pub struct TaskView { error: Option, #[serde(serialize_with = "serialize_duration")] duration: Option, - enqueued_at: DateTime, - started_at: Option>, - finished_at: Option>, + #[serde(serialize_with = "time::serde::rfc3339::serialize")] + enqueued_at: OffsetDateTime, + #[serde(serialize_with = "time::serde::rfc3339::option::serialize")] + started_at: Option, + #[serde(serialize_with = "time::serde::rfc3339::option::serialize")] + finished_at: Option, #[serde(skip_serializing_if = "Option::is_none")] batch_uid: Option>, } @@ -302,7 +346,8 @@ pub struct SummarizedTaskView { status: TaskStatus, #[serde(rename = "type")] task_type: TaskType, - enqueued_at: DateTime, + #[serde(serialize_with = "time::serde::rfc3339::serialize")] + enqueued_at: OffsetDateTime, } impl From for SummarizedTaskView { diff --git a/meilisearch-http/tests/auth/api_keys.rs b/meilisearch-http/tests/auth/api_keys.rs index 52915b96a..e9fb3d127 100644 --- a/meilisearch-http/tests/auth/api_keys.rs +++ b/meilisearch-http/tests/auth/api_keys.rs @@ -257,7 +257,7 @@ async fn error_add_api_key_missing_parameter() { "message": "`indexes` field is mandatory.", "code": "missing_parameter", "type": "invalid_request", - "link":"https://docs.meilisearch.com/errors#missing_parameter" + "link": "https://docs.meilisearch.com/errors#missing_parameter" }); assert_eq!(response, expected_response); @@ -275,7 +275,7 @@ async fn error_add_api_key_missing_parameter() { "message": "`actions` field is mandatory.", "code": "missing_parameter", "type": "invalid_request", - "link":"https://docs.meilisearch.com/errors#missing_parameter" + "link": "https://docs.meilisearch.com/errors#missing_parameter" }); assert_eq!(response, expected_response); @@ -293,7 +293,7 @@ async fn error_add_api_key_missing_parameter() { "message": "`expiresAt` field is mandatory.", "code": "missing_parameter", "type": "invalid_request", - "link":"https://docs.meilisearch.com/errors#missing_parameter" + "link": "https://docs.meilisearch.com/errors#missing_parameter" }); assert_eq!(response, expected_response); @@ -316,7 +316,7 @@ async fn error_add_api_key_invalid_parameters_description() { let (response, code) = server.add_api_key(content).await; let expected_response = json!({ - "message": r#"description field value `{"name":"products"}` is invalid. It should be a string or specified as a null value."#, + "message": r#"`description` field value `{"name":"products"}` is invalid. It should be a string or specified as a null value."#, "code": "invalid_api_key_description", "type": "invalid_request", "link": "https://docs.meilisearch.com/errors#invalid_api_key_description" @@ -342,7 +342,7 @@ async fn error_add_api_key_invalid_parameters_indexes() { let (response, code) = server.add_api_key(content).await; let expected_response = json!({ - "message": r#"indexes field value `{"name":"products"}` is invalid. It should be an array of string representing index names."#, + "message": r#"`indexes` field value `{"name":"products"}` is invalid. It should be an array of string representing index names."#, "code": "invalid_api_key_indexes", "type": "invalid_request", "link": "https://docs.meilisearch.com/errors#invalid_api_key_indexes" @@ -366,7 +366,7 @@ async fn error_add_api_key_invalid_parameters_actions() { let (response, code) = server.add_api_key(content).await; let expected_response = json!({ - "message": r#"actions field value `{"name":"products"}` is invalid. It should be an array of string representing action names."#, + "message": r#"`actions` field value `{"name":"products"}` is invalid. It should be an array of string representing action names."#, "code": "invalid_api_key_actions", "type": "invalid_request", "link": "https://docs.meilisearch.com/errors#invalid_api_key_actions" @@ -386,7 +386,7 @@ async fn error_add_api_key_invalid_parameters_actions() { let (response, code) = server.add_api_key(content).await; let expected_response = json!({ - "message": r#"actions field value `["doc.add"]` is invalid. It should be an array of string representing action names."#, + "message": r#"`actions` field value `["doc.add"]` is invalid. It should be an array of string representing action names."#, "code": "invalid_api_key_actions", "type": "invalid_request", "link": "https://docs.meilisearch.com/errors#invalid_api_key_actions" @@ -412,7 +412,7 @@ async fn error_add_api_key_invalid_parameters_expires_at() { let (response, code) = server.add_api_key(content).await; let expected_response = json!({ - "message": r#"expiresAt field value `{"name":"products"}` is invalid. It should be in ISO-8601 format to represents a date or datetime in the future or specified as a null value. e.g. 'YYYY-MM-DD' or 'YYYY-MM-DDTHH:MM:SS'."#, + "message": r#"`expiresAt` field value `{"name":"products"}` is invalid. It should follow the RFC 3339 format to represents a date or datetime in the future or specified as a null value. e.g. 'YYYY-MM-DD' or 'YYYY-MM-DD HH:MM:SS'."#, "code": "invalid_api_key_expires_at", "type": "invalid_request", "link": "https://docs.meilisearch.com/errors#invalid_api_key_expires_at" @@ -438,7 +438,7 @@ async fn error_add_api_key_invalid_parameters_expires_at_in_the_past() { let (response, code) = server.add_api_key(content).await; let expected_response = json!({ - "message": r#"expiresAt field value `"2010-11-13T00:00:00Z"` is invalid. It should be in ISO-8601 format to represents a date or datetime in the future or specified as a null value. e.g. 'YYYY-MM-DD' or 'YYYY-MM-DDTHH:MM:SS'."#, + "message": r#"`expiresAt` field value `"2010-11-13T00:00:00Z"` is invalid. It should follow the RFC 3339 format to represents a date or datetime in the future or specified as a null value. e.g. 'YYYY-MM-DD' or 'YYYY-MM-DD HH:MM:SS'."#, "code": "invalid_api_key_expires_at", "type": "invalid_request", "link": "https://docs.meilisearch.com/errors#invalid_api_key_expires_at" @@ -1213,7 +1213,7 @@ async fn error_patch_api_key_indexes_invalid_parameters() { let (response, code) = server.patch_api_key(&key, content).await; let expected_response = json!({ - "message": "description field value `13` is invalid. It should be a string or specified as a null value.", + "message": "`description` field value `13` is invalid. It should be a string or specified as a null value.", "code": "invalid_api_key_description", "type": "invalid_request", "link": "https://docs.meilisearch.com/errors#invalid_api_key_description" @@ -1230,7 +1230,7 @@ async fn error_patch_api_key_indexes_invalid_parameters() { let (response, code) = server.patch_api_key(&key, content).await; let expected_response = json!({ - "message": "indexes field value `13` is invalid. It should be an array of string representing index names.", + "message": "`indexes` field value `13` is invalid. It should be an array of string representing index names.", "code": "invalid_api_key_indexes", "type": "invalid_request", "link": "https://docs.meilisearch.com/errors#invalid_api_key_indexes" @@ -1246,7 +1246,7 @@ async fn error_patch_api_key_indexes_invalid_parameters() { let (response, code) = server.patch_api_key(&key, content).await; let expected_response = json!({ - "message": "actions field value `13` is invalid. It should be an array of string representing action names.", + "message": "`actions` field value `13` is invalid. It should be an array of string representing action names.", "code": "invalid_api_key_actions", "type": "invalid_request", "link": "https://docs.meilisearch.com/errors#invalid_api_key_actions" @@ -1262,7 +1262,7 @@ async fn error_patch_api_key_indexes_invalid_parameters() { let (response, code) = server.patch_api_key(&key, content).await; let expected_response = json!({ - "message": "expiresAt field value `13` is invalid. It should be in ISO-8601 format to represents a date or datetime in the future or specified as a null value. e.g. 'YYYY-MM-DD' or 'YYYY-MM-DDTHH:MM:SS'.", + "message": "`expiresAt` field value `13` is invalid. It should follow the RFC 3339 format to represents a date or datetime in the future or specified as a null value. e.g. 'YYYY-MM-DD' or 'YYYY-MM-DD HH:MM:SS'.", "code": "invalid_api_key_expires_at", "type": "invalid_request", "link": "https://docs.meilisearch.com/errors#invalid_api_key_expires_at" diff --git a/meilisearch-http/tests/auth/authorization.rs b/meilisearch-http/tests/auth/authorization.rs index de13c6194..30df2dd2d 100644 --- a/meilisearch-http/tests/auth/authorization.rs +++ b/meilisearch-http/tests/auth/authorization.rs @@ -1,9 +1,10 @@ use crate::common::Server; -use chrono::{Duration, Utc}; +use ::time::format_description::well_known::Rfc3339; use maplit::{hashmap, hashset}; use once_cell::sync::Lazy; use serde_json::{json, Value}; use std::collections::{HashMap, HashSet}; +use time::{Duration, OffsetDateTime}; pub static AUTHORIZATIONS: Lazy>> = Lazy::new(|| { @@ -76,7 +77,7 @@ async fn error_access_expired_key() { let content = json!({ "indexes": ["products"], "actions": ALL_ACTIONS.clone(), - "expiresAt": (Utc::now() + Duration::seconds(1)), + "expiresAt": (OffsetDateTime::now_utc() + Duration::seconds(1)).format(&Rfc3339).unwrap(), }); let (response, code) = server.add_api_key(content).await; @@ -106,7 +107,7 @@ async fn error_access_unauthorized_index() { let content = json!({ "indexes": ["sales"], "actions": ALL_ACTIONS.clone(), - "expiresAt": Utc::now() + Duration::hours(1), + "expiresAt": (OffsetDateTime::now_utc() + Duration::hours(1)).format(&Rfc3339).unwrap(), }); let (response, code) = server.add_api_key(content).await; @@ -137,7 +138,7 @@ async fn error_access_unauthorized_action() { let content = json!({ "indexes": ["products"], "actions": [], - "expiresAt": Utc::now() + Duration::hours(1), + "expiresAt": (OffsetDateTime::now_utc() + Duration::hours(1)).format(&Rfc3339).unwrap(), }); let (response, code) = server.add_api_key(content).await; @@ -174,7 +175,7 @@ async fn access_authorized_restricted_index() { let content = json!({ "indexes": ["products"], "actions": [], - "expiresAt": Utc::now() + Duration::hours(1), + "expiresAt": (OffsetDateTime::now_utc() + Duration::hours(1)).format(&Rfc3339).unwrap(), }); let (response, code) = server.add_api_key(content).await; @@ -213,7 +214,7 @@ async fn access_authorized_no_index_restriction() { let content = json!({ "indexes": ["*"], "actions": [], - "expiresAt": Utc::now() + Duration::hours(1), + "expiresAt": (OffsetDateTime::now_utc() + Duration::hours(1)).format(&Rfc3339).unwrap(), }); let (response, code) = server.add_api_key(content).await; @@ -263,7 +264,7 @@ async fn access_authorized_stats_restricted_index() { let content = json!({ "indexes": ["products"], "actions": ["stats.get"], - "expiresAt": Utc::now() + Duration::hours(1), + "expiresAt": (OffsetDateTime::now_utc() + Duration::hours(1)).format(&Rfc3339).unwrap(), }); let (response, code) = server.add_api_key(content).await; assert_eq!(code, 201); @@ -303,7 +304,7 @@ async fn access_authorized_stats_no_index_restriction() { let content = json!({ "indexes": ["*"], "actions": ["stats.get"], - "expiresAt": Utc::now() + Duration::hours(1), + "expiresAt": (OffsetDateTime::now_utc() + Duration::hours(1)).format(&Rfc3339).unwrap(), }); let (response, code) = server.add_api_key(content).await; assert_eq!(code, 201); @@ -343,7 +344,7 @@ async fn list_authorized_indexes_restricted_index() { let content = json!({ "indexes": ["products"], "actions": ["indexes.get"], - "expiresAt": Utc::now() + Duration::hours(1), + "expiresAt": (OffsetDateTime::now_utc() + Duration::hours(1)).format(&Rfc3339).unwrap(), }); let (response, code) = server.add_api_key(content).await; assert_eq!(code, 201); @@ -384,7 +385,7 @@ async fn list_authorized_indexes_no_index_restriction() { let content = json!({ "indexes": ["*"], "actions": ["indexes.get"], - "expiresAt": Utc::now() + Duration::hours(1), + "expiresAt": (OffsetDateTime::now_utc() + Duration::hours(1)).format(&Rfc3339).unwrap(), }); let (response, code) = server.add_api_key(content).await; assert_eq!(code, 201); @@ -424,7 +425,7 @@ async fn list_authorized_tasks_restricted_index() { let content = json!({ "indexes": ["products"], "actions": ["tasks.get"], - "expiresAt": Utc::now() + Duration::hours(1), + "expiresAt": (OffsetDateTime::now_utc() + Duration::hours(1)).format(&Rfc3339).unwrap(), }); let (response, code) = server.add_api_key(content).await; assert_eq!(code, 201); @@ -464,7 +465,7 @@ async fn list_authorized_tasks_no_index_restriction() { let content = json!({ "indexes": ["*"], "actions": ["tasks.get"], - "expiresAt": Utc::now() + Duration::hours(1), + "expiresAt": (OffsetDateTime::now_utc() + Duration::hours(1)).format(&Rfc3339).unwrap(), }); let (response, code) = server.add_api_key(content).await; assert_eq!(code, 201); diff --git a/meilisearch-http/tests/auth/tenant_token.rs b/meilisearch-http/tests/auth/tenant_token.rs index bad6de5e6..bb9224590 100644 --- a/meilisearch-http/tests/auth/tenant_token.rs +++ b/meilisearch-http/tests/auth/tenant_token.rs @@ -1,9 +1,10 @@ use crate::common::Server; -use chrono::{Duration, Utc}; +use ::time::format_description::well_known::Rfc3339; use maplit::hashmap; use once_cell::sync::Lazy; use serde_json::{json, Value}; use std::collections::HashMap; +use time::{Duration, OffsetDateTime}; use super::authorization::{ALL_ACTIONS, AUTHORIZATIONS}; @@ -63,22 +64,22 @@ static ACCEPTED_KEYS: Lazy> = Lazy::new(|| { json!({ "indexes": ["*"], "actions": ["*"], - "expiresAt": Utc::now() + Duration::days(1) + "expiresAt": (OffsetDateTime::now_utc() + Duration::days(1)).format(&Rfc3339).unwrap() }), json!({ "indexes": ["*"], "actions": ["search"], - "expiresAt": Utc::now() + Duration::days(1) + "expiresAt": (OffsetDateTime::now_utc() + Duration::days(1)).format(&Rfc3339).unwrap() }), json!({ "indexes": ["sales"], "actions": ["*"], - "expiresAt": Utc::now() + Duration::days(1) + "expiresAt": (OffsetDateTime::now_utc() + Duration::days(1)).format(&Rfc3339).unwrap() }), json!({ "indexes": ["sales"], "actions": ["search"], - "expiresAt": Utc::now() + Duration::days(1) + "expiresAt": (OffsetDateTime::now_utc() + Duration::days(1)).format(&Rfc3339).unwrap() }), ] }); @@ -89,23 +90,23 @@ static REFUSED_KEYS: Lazy> = Lazy::new(|| { json!({ "indexes": ["*"], "actions": ALL_ACTIONS.iter().cloned().filter(|a| *a != "search" && *a != "*").collect::>(), - "expiresAt": Utc::now() + Duration::days(1) + "expiresAt": (OffsetDateTime::now_utc() + Duration::days(1)).format(&Rfc3339).unwrap() }), json!({ "indexes": ["sales"], "actions": ALL_ACTIONS.iter().cloned().filter(|a| *a != "search" && *a != "*").collect::>(), - "expiresAt": Utc::now() + Duration::days(1) + "expiresAt": (OffsetDateTime::now_utc() + Duration::days(1)).format(&Rfc3339).unwrap() }), // bad index json!({ "indexes": ["products"], "actions": ["*"], - "expiresAt": Utc::now() + Duration::days(1) + "expiresAt": (OffsetDateTime::now_utc() + Duration::days(1)).format(&Rfc3339).unwrap() }), json!({ "indexes": ["products"], "actions": ["search"], - "expiresAt": Utc::now() + Duration::days(1) + "expiresAt": (OffsetDateTime::now_utc() + Duration::days(1)).format(&Rfc3339).unwrap() }), ] }); @@ -204,19 +205,19 @@ async fn search_authorized_simple_token() { let tenant_tokens = vec![ hashmap! { "searchRules" => json!({"*": {}}), - "exp" => json!((Utc::now() + Duration::hours(1)).timestamp()) + "exp" => json!((OffsetDateTime::now_utc() + Duration::hours(1)).unix_timestamp()) }, hashmap! { "searchRules" => json!(["*"]), - "exp" => json!((Utc::now() + Duration::hours(1)).timestamp()) + "exp" => json!((OffsetDateTime::now_utc() + Duration::hours(1)).unix_timestamp()) }, hashmap! { "searchRules" => json!({"sales": {}}), - "exp" => json!((Utc::now() + Duration::hours(1)).timestamp()) + "exp" => json!((OffsetDateTime::now_utc() + Duration::hours(1)).unix_timestamp()) }, hashmap! { "searchRules" => json!(["sales"]), - "exp" => json!((Utc::now() + Duration::hours(1)).timestamp()) + "exp" => json!((OffsetDateTime::now_utc() + Duration::hours(1)).unix_timestamp()) }, hashmap! { "searchRules" => json!({"*": {}}), @@ -253,19 +254,19 @@ async fn search_authorized_filter_token() { let tenant_tokens = vec![ hashmap! { "searchRules" => json!({"*": {"filter": "color = blue"}}), - "exp" => json!((Utc::now() + Duration::hours(1)).timestamp()) + "exp" => json!((OffsetDateTime::now_utc() + Duration::hours(1)).unix_timestamp()) }, hashmap! { "searchRules" => json!({"sales": {"filter": "color = blue"}}), - "exp" => json!((Utc::now() + Duration::hours(1)).timestamp()) + "exp" => json!((OffsetDateTime::now_utc() + Duration::hours(1)).unix_timestamp()) }, hashmap! { "searchRules" => json!({"*": {"filter": ["color = blue"]}}), - "exp" => json!((Utc::now() + Duration::hours(1)).timestamp()) + "exp" => json!((OffsetDateTime::now_utc() + Duration::hours(1)).unix_timestamp()) }, hashmap! { "searchRules" => json!({"sales": {"filter": ["color = blue"]}}), - "exp" => json!((Utc::now() + Duration::hours(1)).timestamp()) + "exp" => json!((OffsetDateTime::now_utc() + Duration::hours(1)).unix_timestamp()) }, // filter on sales should override filters on * hashmap! { @@ -273,28 +274,28 @@ async fn search_authorized_filter_token() { "*": {"filter": "color = green"}, "sales": {"filter": "color = blue"} }), - "exp" => json!((Utc::now() + Duration::hours(1)).timestamp()) + "exp" => json!((OffsetDateTime::now_utc() + Duration::hours(1)).unix_timestamp()) }, hashmap! { "searchRules" => json!({ "*": {}, "sales": {"filter": "color = blue"} }), - "exp" => json!((Utc::now() + Duration::hours(1)).timestamp()) + "exp" => json!((OffsetDateTime::now_utc() + Duration::hours(1)).unix_timestamp()) }, hashmap! { "searchRules" => json!({ "*": {"filter": "color = green"}, "sales": {"filter": ["color = blue"]} }), - "exp" => json!((Utc::now() + Duration::hours(1)).timestamp()) + "exp" => json!((OffsetDateTime::now_utc() + Duration::hours(1)).unix_timestamp()) }, hashmap! { "searchRules" => json!({ "*": {}, "sales": {"filter": ["color = blue"]} }), - "exp" => json!((Utc::now() + Duration::hours(1)).timestamp()) + "exp" => json!((OffsetDateTime::now_utc() + Duration::hours(1)).unix_timestamp()) }, ]; @@ -307,19 +308,19 @@ async fn filter_search_authorized_filter_token() { let tenant_tokens = vec![ hashmap! { "searchRules" => json!({"*": {"filter": "color = blue"}}), - "exp" => json!((Utc::now() + Duration::hours(1)).timestamp()) + "exp" => json!((OffsetDateTime::now_utc() + Duration::hours(1)).unix_timestamp()) }, hashmap! { "searchRules" => json!({"sales": {"filter": "color = blue"}}), - "exp" => json!((Utc::now() + Duration::hours(1)).timestamp()) + "exp" => json!((OffsetDateTime::now_utc() + Duration::hours(1)).unix_timestamp()) }, hashmap! { "searchRules" => json!({"*": {"filter": ["color = blue"]}}), - "exp" => json!((Utc::now() + Duration::hours(1)).timestamp()) + "exp" => json!((OffsetDateTime::now_utc() + Duration::hours(1)).unix_timestamp()) }, hashmap! { "searchRules" => json!({"sales": {"filter": ["color = blue"]}}), - "exp" => json!((Utc::now() + Duration::hours(1)).timestamp()) + "exp" => json!((OffsetDateTime::now_utc() + Duration::hours(1)).unix_timestamp()) }, // filter on sales should override filters on * hashmap! { @@ -327,28 +328,28 @@ async fn filter_search_authorized_filter_token() { "*": {"filter": "color = green"}, "sales": {"filter": "color = blue"} }), - "exp" => json!((Utc::now() + Duration::hours(1)).timestamp()) + "exp" => json!((OffsetDateTime::now_utc() + Duration::hours(1)).unix_timestamp()) }, hashmap! { "searchRules" => json!({ "*": {}, "sales": {"filter": "color = blue"} }), - "exp" => json!((Utc::now() + Duration::hours(1)).timestamp()) + "exp" => json!((OffsetDateTime::now_utc() + Duration::hours(1)).unix_timestamp()) }, hashmap! { "searchRules" => json!({ "*": {"filter": "color = green"}, "sales": {"filter": ["color = blue"]} }), - "exp" => json!((Utc::now() + Duration::hours(1)).timestamp()) + "exp" => json!((OffsetDateTime::now_utc() + Duration::hours(1)).unix_timestamp()) }, hashmap! { "searchRules" => json!({ "*": {}, "sales": {"filter": ["color = blue"]} }), - "exp" => json!((Utc::now() + Duration::hours(1)).timestamp()) + "exp" => json!((OffsetDateTime::now_utc() + Duration::hours(1)).unix_timestamp()) }, ]; @@ -361,27 +362,27 @@ async fn error_search_token_forbidden_parent_key() { let tenant_tokens = vec![ hashmap! { "searchRules" => json!({"*": {}}), - "exp" => json!((Utc::now() + Duration::hours(1)).timestamp()) + "exp" => json!((OffsetDateTime::now_utc() + Duration::hours(1)).unix_timestamp()) }, hashmap! { "searchRules" => json!({"*": Value::Null}), - "exp" => json!((Utc::now() + Duration::hours(1)).timestamp()) + "exp" => json!((OffsetDateTime::now_utc() + Duration::hours(1)).unix_timestamp()) }, hashmap! { "searchRules" => json!(["*"]), - "exp" => json!((Utc::now() + Duration::hours(1)).timestamp()) + "exp" => json!((OffsetDateTime::now_utc() + Duration::hours(1)).unix_timestamp()) }, hashmap! { "searchRules" => json!({"sales": {}}), - "exp" => json!((Utc::now() + Duration::hours(1)).timestamp()) + "exp" => json!((OffsetDateTime::now_utc() + Duration::hours(1)).unix_timestamp()) }, hashmap! { "searchRules" => json!({"sales": Value::Null}), - "exp" => json!((Utc::now() + Duration::hours(1)).timestamp()) + "exp" => json!((OffsetDateTime::now_utc() + Duration::hours(1)).unix_timestamp()) }, hashmap! { "searchRules" => json!(["sales"]), - "exp" => json!((Utc::now() + Duration::hours(1)).timestamp()) + "exp" => json!((OffsetDateTime::now_utc() + Duration::hours(1)).unix_timestamp()) }, ]; @@ -395,11 +396,11 @@ async fn error_search_forbidden_token() { // bad index hashmap! { "searchRules" => json!({"products": {}}), - "exp" => json!((Utc::now() + Duration::hours(1)).timestamp()) + "exp" => json!((OffsetDateTime::now_utc() + Duration::hours(1)).unix_timestamp()) }, hashmap! { "searchRules" => json!(["products"]), - "exp" => json!((Utc::now() + Duration::hours(1)).timestamp()) + "exp" => json!((OffsetDateTime::now_utc() + Duration::hours(1)).unix_timestamp()) }, hashmap! { "searchRules" => json!({"products": {}}), @@ -416,27 +417,27 @@ async fn error_search_forbidden_token() { // expired token hashmap! { "searchRules" => json!({"*": {}}), - "exp" => json!((Utc::now() - Duration::hours(1)).timestamp()) + "exp" => json!((OffsetDateTime::now_utc() - Duration::hours(1)).unix_timestamp()) }, hashmap! { "searchRules" => json!({"*": Value::Null}), - "exp" => json!((Utc::now() - Duration::hours(1)).timestamp()) + "exp" => json!((OffsetDateTime::now_utc() - Duration::hours(1)).unix_timestamp()) }, hashmap! { "searchRules" => json!(["*"]), - "exp" => json!((Utc::now() - Duration::hours(1)).timestamp()) + "exp" => json!((OffsetDateTime::now_utc() - Duration::hours(1)).unix_timestamp()) }, hashmap! { "searchRules" => json!({"sales": {}}), - "exp" => json!((Utc::now() - Duration::hours(1)).timestamp()) + "exp" => json!((OffsetDateTime::now_utc() - Duration::hours(1)).unix_timestamp()) }, hashmap! { "searchRules" => json!({"sales": Value::Null}), - "exp" => json!((Utc::now() - Duration::hours(1)).timestamp()) + "exp" => json!((OffsetDateTime::now_utc() - Duration::hours(1)).unix_timestamp()) }, hashmap! { "searchRules" => json!(["sales"]), - "exp" => json!((Utc::now() - Duration::hours(1)).timestamp()) + "exp" => json!((OffsetDateTime::now_utc() - Duration::hours(1)).unix_timestamp()) }, ]; @@ -452,7 +453,7 @@ async fn error_access_forbidden_routes() { let content = json!({ "indexes": ["*"], "actions": ["*"], - "expiresAt": (Utc::now() + Duration::hours(1)), + "expiresAt": (OffsetDateTime::now_utc() + Duration::hours(1)).format(&Rfc3339).unwrap(), }); let (response, code) = server.add_api_key(content).await; @@ -463,7 +464,7 @@ async fn error_access_forbidden_routes() { let tenant_token = hashmap! { "searchRules" => json!(["*"]), - "exp" => json!((Utc::now() + Duration::hours(1)).timestamp()) + "exp" => json!((OffsetDateTime::now_utc() + Duration::hours(1)).unix_timestamp()) }; let web_token = generate_tenant_token(&key, tenant_token); server.use_api_key(&web_token); @@ -487,7 +488,7 @@ async fn error_access_expired_parent_key() { let content = json!({ "indexes": ["*"], "actions": ["*"], - "expiresAt": (Utc::now() + Duration::seconds(1)), + "expiresAt": (OffsetDateTime::now_utc() + Duration::seconds(1)).format(&Rfc3339).unwrap(), }); let (response, code) = server.add_api_key(content).await; @@ -498,7 +499,7 @@ async fn error_access_expired_parent_key() { let tenant_token = hashmap! { "searchRules" => json!(["*"]), - "exp" => json!((Utc::now() + Duration::hours(1)).timestamp()) + "exp" => json!((OffsetDateTime::now_utc() + Duration::hours(1)).unix_timestamp()) }; let web_token = generate_tenant_token(&key, tenant_token); server.use_api_key(&web_token); @@ -529,7 +530,7 @@ async fn error_access_modified_token() { let content = json!({ "indexes": ["*"], "actions": ["*"], - "expiresAt": (Utc::now() + Duration::hours(1)), + "expiresAt": (OffsetDateTime::now_utc() + Duration::hours(1)).format(&Rfc3339).unwrap(), }); let (response, code) = server.add_api_key(content).await; @@ -540,7 +541,7 @@ async fn error_access_modified_token() { let tenant_token = hashmap! { "searchRules" => json!(["products"]), - "exp" => json!((Utc::now() + Duration::hours(1)).timestamp()) + "exp" => json!((OffsetDateTime::now_utc() + Duration::hours(1)).unix_timestamp()) }; let web_token = generate_tenant_token(&key, tenant_token); server.use_api_key(&web_token); @@ -554,7 +555,7 @@ async fn error_access_modified_token() { let tenant_token = hashmap! { "searchRules" => json!(["*"]), - "exp" => json!((Utc::now() + Duration::hours(1)).timestamp()) + "exp" => json!((OffsetDateTime::now_utc() + Duration::hours(1)).unix_timestamp()) }; let alt = generate_tenant_token(&key, tenant_token); diff --git a/meilisearch-http/tests/documents/add_documents.rs b/meilisearch-http/tests/documents/add_documents.rs index f61c2f3c6..34ff24ac2 100644 --- a/meilisearch-http/tests/documents/add_documents.rs +++ b/meilisearch-http/tests/documents/add_documents.rs @@ -1,8 +1,8 @@ use crate::common::{GetAllDocumentsOptions, Server}; use actix_web::test; -use chrono::DateTime; use meilisearch_http::{analytics, create_app}; use serde_json::{json, Value}; +use time::{format_description::well_known::Rfc3339, OffsetDateTime}; /// This is the basic usage of our API and every other tests uses the content-type application/json #[actix_rt::test] @@ -568,9 +568,9 @@ async fn add_documents_no_index_creation() { assert_eq!(response["details"]["indexedDocuments"], 1); let processed_at = - DateTime::parse_from_rfc3339(response["finishedAt"].as_str().unwrap()).unwrap(); + OffsetDateTime::parse(response["finishedAt"].as_str().unwrap(), &Rfc3339).unwrap(); let enqueued_at = - DateTime::parse_from_rfc3339(response["enqueuedAt"].as_str().unwrap()).unwrap(); + OffsetDateTime::parse(response["enqueuedAt"].as_str().unwrap(), &Rfc3339).unwrap(); assert!(processed_at > enqueued_at); // index was created, and primary key was infered. diff --git a/meilisearch-http/tests/index/update_index.rs b/meilisearch-http/tests/index/update_index.rs index 0246b55ef..1896f731f 100644 --- a/meilisearch-http/tests/index/update_index.rs +++ b/meilisearch-http/tests/index/update_index.rs @@ -1,6 +1,6 @@ use crate::common::Server; -use chrono::DateTime; use serde_json::json; +use time::{format_description::well_known::Rfc3339, OffsetDateTime}; #[actix_rt::test] async fn update_primary_key() { @@ -25,8 +25,10 @@ async fn update_primary_key() { assert!(response.get("createdAt").is_some()); assert!(response.get("updatedAt").is_some()); - let created_at = DateTime::parse_from_rfc3339(response["createdAt"].as_str().unwrap()).unwrap(); - let updated_at = DateTime::parse_from_rfc3339(response["updatedAt"].as_str().unwrap()).unwrap(); + let created_at = + OffsetDateTime::parse(response["createdAt"].as_str().unwrap(), &Rfc3339).unwrap(); + let updated_at = + OffsetDateTime::parse(response["updatedAt"].as_str().unwrap(), &Rfc3339).unwrap(); assert!(created_at < updated_at); assert_eq!(response["primaryKey"], "primary"); diff --git a/meilisearch-http/tests/stats/mod.rs b/meilisearch-http/tests/stats/mod.rs index e89d145e1..b9d185ca3 100644 --- a/meilisearch-http/tests/stats/mod.rs +++ b/meilisearch-http/tests/stats/mod.rs @@ -1,4 +1,5 @@ use serde_json::json; +use time::{format_description::well_known::Rfc3339, OffsetDateTime}; use crate::common::Server; @@ -57,11 +58,15 @@ async fn stats() { index.wait_task(1).await; + let timestamp = OffsetDateTime::now_utc(); let (response, code) = server.stats().await; assert_eq!(code, 200); assert!(response["databaseSize"].as_u64().unwrap() > 0); - assert!(response.get("lastUpdate").is_some()); + let last_update = + OffsetDateTime::parse(response["lastUpdate"].as_str().unwrap(), &Rfc3339).unwrap(); + assert!(last_update - timestamp < time::Duration::SECOND); + assert_eq!(response["indexes"]["test"]["numberOfDocuments"], 2); assert!(response["indexes"]["test"]["isIndexing"] == false); assert_eq!(response["indexes"]["test"]["fieldDistribution"]["id"], 2); diff --git a/meilisearch-http/tests/tasks/mod.rs b/meilisearch-http/tests/tasks/mod.rs index 3edb89376..167b7b05f 100644 --- a/meilisearch-http/tests/tasks/mod.rs +++ b/meilisearch-http/tests/tasks/mod.rs @@ -1,6 +1,7 @@ use crate::common::Server; -use chrono::{DateTime, Utc}; use serde_json::json; +use time::format_description::well_known::Rfc3339; +use time::OffsetDateTime; #[actix_rt::test] async fn error_get_task_unexisting_index() { @@ -98,7 +99,8 @@ macro_rules! assert_valid_summarized_task { assert_eq!($response["status"], "enqueued"); assert_eq!($response["type"], $task_type); let date = $response["enqueuedAt"].as_str().expect("missing date"); - date.parse::>().unwrap(); + + OffsetDateTime::parse(date, &Rfc3339).unwrap(); }}; } diff --git a/meilisearch-lib/Cargo.toml b/meilisearch-lib/Cargo.toml index 71b08919e..399e7a352 100644 --- a/meilisearch-lib/Cargo.toml +++ b/meilisearch-lib/Cargo.toml @@ -6,62 +6,60 @@ edition = "2021" # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html [dependencies] -actix-web = { version = "4", default-features = false } -anyhow = { version = "1.0.43", features = ["backtrace"] } -async-stream = "0.3.2" -async-trait = "0.1.51" -byte-unit = { version = "4.0.12", default-features = false, features = ["std"] } +actix-web = { version = "4.0.1", default-features = false } +anyhow = { version = "1.0.56", features = ["backtrace"] } +async-stream = "0.3.3" +async-trait = "0.1.52" +atomic_refcell = "0.1.8" +byte-unit = { version = "4.0.14", default-features = false, features = ["std"] } bytes = "1.1.0" -chrono = { version = "0.4.19", features = ["serde"] } +clap = { version = "3.1.6", features = ["derive", "env"] } +crossbeam-channel = "0.5.2" csv = "1.1.6" -crossbeam-channel = "0.5.1" +derivative = "2.2.0" either = "1.6.1" -flate2 = "1.0.21" +flate2 = "1.0.22" +fs_extra = "1.2.0" fst = "0.4.7" -futures = "0.3.17" -futures-util = "0.3.17" -heed = { git = "https://github.com/Kerollmops/heed", tag = "v0.12.1" } -http = "0.2.4" -indexmap = { version = "1.7.0", features = ["serde-1"] } -itertools = "0.10.1" +futures = "0.3.21" +futures-util = "0.3.21" +http = "0.2.6" +indexmap = { version = "1.8.0", features = ["serde-1"] } +itertools = "0.10.3" lazy_static = "1.4.0" log = "0.4.14" -meilisearch-error = { path = "../meilisearch-error" } meilisearch-auth = { path = "../meilisearch-auth" } -milli = { git = "https://github.com/meilisearch/milli.git", tag = "v0.22.1" } +meilisearch-error = { path = "../meilisearch-error" } +milli = { git = "https://github.com/meilisearch/milli.git", tag = "v0.24.0" } mime = "0.3.16" -num_cpus = "1.13.0" -once_cell = "1.8.0" -parking_lot = "0.11.2" -rand = "0.8.4" +num_cpus = "1.13.1" +obkv = "0.2.0" +once_cell = "1.10.0" +parking_lot = "0.12.0" +rand = "0.8.5" rayon = "1.5.1" -regex = "1.5.4" -rustls = "0.19.1" -serde = { version = "1.0.130", features = ["derive"] } -serde_json = { version = "1.0.67", features = ["preserve_order"] } -siphasher = "0.3.7" -slice-group-by = "0.2.6" -clap = { version = "3.0", features = ["derive", "env"] } -tar = "0.4.37" -tempfile = "3.2.0" -thiserror = "1.0.28" -tokio = { version = "1.11.0", features = ["full"] } +regex = "1.5.5" +reqwest = { version = "0.11.9", features = ["json", "rustls-tls"], default-features = false, optional = true } +rustls = "0.20.4" +serde = { version = "1.0.136", features = ["derive"] } +serde_json = { version = "1.0.79", features = ["preserve_order"] } +siphasher = "0.3.10" +slice-group-by = "0.3.0" +sysinfo = "0.23.5" +tar = "0.4.38" +tempfile = "3.3.0" +thiserror = "1.0.30" +time = { version = "0.3.7", features = ["serde-well-known", "formatting", "parsing", "macros"] } +tokio = { version = "1.17.0", features = ["full"] } uuid = { version = "0.8.2", features = ["serde"] } walkdir = "2.3.2" -obkv = "0.2.0" -pin-project = "1.0.8" -whoami = { version = "1.1.3", optional = true } -reqwest = { version = "0.11.4", features = ["json", "rustls-tls"], default-features = false, optional = true } -sysinfo = "0.20.2" -derivative = "2.2.0" -fs_extra = "1.2.0" -atomic_refcell = "0.1.8" +whoami = { version = "1.2.1", optional = true } [dev-dependencies] -actix-rt = "2.2.0" -mockall = "0.10.2" -paste = "1.0.5" -nelson = { git = "https://github.com/MarinPostma/nelson.git", rev = "675f13885548fb415ead8fbb447e9e6d9314000a"} +actix-rt = "2.7.0" meilisearch-error = { path = "../meilisearch-error", features = ["test-traits"] } +mockall = "0.11.0" +nelson = { git = "https://github.com/MarinPostma/nelson.git", rev = "675f13885548fb415ead8fbb447e9e6d9314000a"} +paste = "1.0.6" proptest = "1.0.0" proptest-derive = "0.3.0" diff --git a/meilisearch-lib/src/index/dump.rs b/meilisearch-lib/src/index/dump.rs index 153b724b9..fea133c37 100644 --- a/meilisearch-lib/src/index/dump.rs +++ b/meilisearch-lib/src/index/dump.rs @@ -3,9 +3,9 @@ use std::io::{BufReader, Seek, SeekFrom, Write}; use std::path::Path; use anyhow::Context; -use heed::{EnvOpenOptions, RoTxn}; use indexmap::IndexMap; use milli::documents::DocumentBatchReader; +use milli::heed::{EnvOpenOptions, RoTxn}; use milli::update::{IndexDocumentsConfig, IndexerConfig}; use serde::{Deserialize, Serialize}; diff --git a/meilisearch-lib/src/index/error.rs b/meilisearch-lib/src/index/error.rs index f8dcc0dc8..89a12a41f 100644 --- a/meilisearch-lib/src/index/error.rs +++ b/meilisearch-lib/src/index/error.rs @@ -21,7 +21,7 @@ pub enum IndexError { internal_error!( IndexError: std::io::Error, - heed::Error, + milli::heed::Error, fst::Error, serde_json::Error, update_file_store::UpdateFileStoreError, diff --git a/meilisearch-lib/src/index/index.rs b/meilisearch-lib/src/index/index.rs index 597c1a283..cfc867c7d 100644 --- a/meilisearch-lib/src/index/index.rs +++ b/meilisearch-lib/src/index/index.rs @@ -5,12 +5,12 @@ use std::ops::Deref; use std::path::Path; use std::sync::Arc; -use chrono::{DateTime, Utc}; -use heed::{EnvOpenOptions, RoTxn}; +use milli::heed::{EnvOpenOptions, RoTxn}; use milli::update::{IndexerConfig, Setting}; use milli::{obkv_to_json, FieldDistribution, FieldId}; use serde::{Deserialize, Serialize}; use serde_json::{Map, Value}; +use time::OffsetDateTime; use uuid::Uuid; use crate::EnvSizer; @@ -24,8 +24,10 @@ pub type Document = Map; #[derive(Debug, Serialize, Deserialize, Clone)] #[serde(rename_all = "camelCase")] pub struct IndexMeta { - pub created_at: DateTime, - pub updated_at: DateTime, + #[serde(with = "time::serde::rfc3339")] + pub created_at: OffsetDateTime, + #[serde(with = "time::serde::rfc3339")] + pub updated_at: OffsetDateTime, pub primary_key: Option, } @@ -35,7 +37,7 @@ impl IndexMeta { Self::new_txn(index, &txn) } - pub fn new_txn(index: &Index, txn: &heed::RoTxn) -> Result { + pub fn new_txn(index: &Index, txn: &milli::heed::RoTxn) -> Result { let created_at = index.created_at(txn)?; let updated_at = index.updated_at(txn)?; let primary_key = index.primary_key(txn)?.map(String::from); @@ -248,7 +250,7 @@ impl Index { fn fields_to_display>( &self, - txn: &heed::RoTxn, + txn: &milli::heed::RoTxn, attributes_to_retrieve: &Option>, fields_ids_map: &milli::FieldsIdsMap, ) -> Result> { @@ -276,7 +278,7 @@ impl Index { let _txn = self.write_txn()?; self.inner .env - .copy_to_path(dst, heed::CompactionOption::Enabled)?; + .copy_to_path(dst, milli::heed::CompactionOption::Enabled)?; Ok(()) } } diff --git a/meilisearch-lib/src/index/updates.rs b/meilisearch-lib/src/index/updates.rs index 07bb0da0e..6c8ab6e40 100644 --- a/meilisearch-lib/src/index/updates.rs +++ b/meilisearch-lib/src/index/updates.rs @@ -176,7 +176,7 @@ pub struct Facets { impl Index { fn update_primary_key_txn<'a, 'b>( &'a self, - txn: &mut heed::RwTxn<'a, 'b>, + txn: &mut milli::heed::RwTxn<'a, 'b>, primary_key: String, ) -> Result { let mut builder = milli::update::Settings::new(txn, self, self.indexer_config.as_ref()); diff --git a/meilisearch-lib/src/index_controller/dump_actor/actor.rs b/meilisearch-lib/src/index_controller/dump_actor/actor.rs index c9b871c0e..48fc077ca 100644 --- a/meilisearch-lib/src/index_controller/dump_actor/actor.rs +++ b/meilisearch-lib/src/index_controller/dump_actor/actor.rs @@ -3,9 +3,10 @@ use std::path::{Path, PathBuf}; use std::sync::Arc; use async_stream::stream; -use chrono::Utc; use futures::{lock::Mutex, stream::StreamExt}; use log::{error, trace}; +use time::macros::format_description; +use time::OffsetDateTime; use tokio::sync::{mpsc, oneshot, RwLock}; use super::error::{DumpActorError, Result}; @@ -29,7 +30,11 @@ pub struct DumpActor { /// Generate uid from creation date fn generate_uid() -> String { - Utc::now().format("%Y%m%d-%H%M%S%3f").to_string() + OffsetDateTime::now_utc() + .format(format_description!( + "[year repr:full][month repr:numerical][day padding:zero]-[hour padding:zero][minute padding:zero][second padding:zero][subsecond digits:3]" + )) + .unwrap() } impl DumpActor { @@ -154,3 +159,33 @@ impl DumpActor { } } } + +#[cfg(test)] +mod test { + use super::*; + + #[test] + fn test_generate_uid() { + let current = OffsetDateTime::now_utc(); + + let uid = generate_uid(); + let (date, time) = uid.split_once('-').unwrap(); + + let date = time::Date::parse( + date, + &format_description!("[year repr:full][month repr:numerical][day padding:zero]"), + ) + .unwrap(); + let time = time::Time::parse( + time, + &format_description!( + "[hour padding:zero][minute padding:zero][second padding:zero][subsecond digits:3]" + ), + ) + .unwrap(); + let datetime = time::PrimitiveDateTime::new(date, time); + let datetime = datetime.assume_utc(); + + assert!(current - datetime < time::Duration::SECOND); + } +} diff --git a/meilisearch-lib/src/index_controller/dump_actor/compat/v2.rs b/meilisearch-lib/src/index_controller/dump_actor/compat/v2.rs index 9af0f11b5..a30e24794 100644 --- a/meilisearch-lib/src/index_controller/dump_actor/compat/v2.rs +++ b/meilisearch-lib/src/index_controller/dump_actor/compat/v2.rs @@ -1,8 +1,8 @@ use anyhow::bail; -use chrono::{DateTime, Utc}; use meilisearch_error::Code; use milli::update::IndexDocumentsMethod; use serde::{Deserialize, Serialize}; +use time::OffsetDateTime; use uuid::Uuid; use crate::index::{Settings, Unchecked}; @@ -51,7 +51,8 @@ pub enum UpdateMeta { pub struct Enqueued { pub update_id: u64, pub meta: UpdateMeta, - pub enqueued_at: DateTime, + #[serde(with = "time::serde::rfc3339")] + pub enqueued_at: OffsetDateTime, pub content: Option, } @@ -59,7 +60,8 @@ pub struct Enqueued { #[serde(rename_all = "camelCase")] pub struct Processed { pub success: UpdateResult, - pub processed_at: DateTime, + #[serde(with = "time::serde::rfc3339")] + pub processed_at: OffsetDateTime, #[serde(flatten)] pub from: Processing, } @@ -69,7 +71,8 @@ pub struct Processed { pub struct Processing { #[serde(flatten)] pub from: Enqueued, - pub started_processing_at: DateTime, + #[serde(with = "time::serde::rfc3339")] + pub started_processing_at: OffsetDateTime, } #[derive(Debug, Serialize, Deserialize, Clone)] @@ -77,7 +80,8 @@ pub struct Processing { pub struct Aborted { #[serde(flatten)] pub from: Enqueued, - pub aborted_at: DateTime, + #[serde(with = "time::serde::rfc3339")] + pub aborted_at: OffsetDateTime, } #[derive(Debug, Serialize, Deserialize)] @@ -86,7 +90,8 @@ pub struct Failed { #[serde(flatten)] pub from: Processing, pub error: ResponseError, - pub failed_at: DateTime, + #[serde(with = "time::serde::rfc3339")] + pub failed_at: OffsetDateTime, } #[derive(Debug, Serialize, Deserialize)] diff --git a/meilisearch-lib/src/index_controller/dump_actor/compat/v3.rs b/meilisearch-lib/src/index_controller/dump_actor/compat/v3.rs index 597c11fe0..7cd670bad 100644 --- a/meilisearch-lib/src/index_controller/dump_actor/compat/v3.rs +++ b/meilisearch-lib/src/index_controller/dump_actor/compat/v3.rs @@ -1,7 +1,7 @@ -use chrono::{DateTime, Utc}; use meilisearch_error::{Code, ResponseError}; use milli::update::IndexDocumentsMethod; use serde::{Deserialize, Serialize}; +use time::OffsetDateTime; use uuid::Uuid; use crate::index::{Settings, Unchecked}; @@ -107,7 +107,8 @@ pub enum UpdateMeta { pub struct Enqueued { pub update_id: u64, pub meta: Update, - pub enqueued_at: DateTime, + #[serde(with = "time::serde::rfc3339")] + pub enqueued_at: OffsetDateTime, } impl Enqueued { @@ -122,7 +123,8 @@ impl Enqueued { #[serde(rename_all = "camelCase")] pub struct Processed { pub success: v2::UpdateResult, - pub processed_at: DateTime, + #[serde(with = "time::serde::rfc3339")] + pub processed_at: OffsetDateTime, #[serde(flatten)] pub from: Processing, } @@ -144,7 +146,8 @@ impl Processed { pub struct Processing { #[serde(flatten)] pub from: Enqueued, - pub started_processing_at: DateTime, + #[serde(with = "time::serde::rfc3339")] + pub started_processing_at: OffsetDateTime, } impl Processing { @@ -163,7 +166,8 @@ pub struct Failed { pub from: Processing, pub msg: String, pub code: Code, - pub failed_at: DateTime, + #[serde(with = "time::serde::rfc3339")] + pub failed_at: OffsetDateTime, } impl Failed { diff --git a/meilisearch-lib/src/index_controller/dump_actor/error.rs b/meilisearch-lib/src/index_controller/dump_actor/error.rs index 73faf1bbb..f72b6d1dd 100644 --- a/meilisearch-lib/src/index_controller/dump_actor/error.rs +++ b/meilisearch-lib/src/index_controller/dump_actor/error.rs @@ -18,7 +18,7 @@ pub enum DumpActorError { } internal_error!( - DumpActorError: heed::Error, + DumpActorError: milli::heed::Error, std::io::Error, tokio::task::JoinError, tokio::sync::oneshot::error::RecvError, diff --git a/meilisearch-lib/src/index_controller/dump_actor/loaders/v4.rs b/meilisearch-lib/src/index_controller/dump_actor/loaders/v4.rs index d342f010f..38d61f146 100644 --- a/meilisearch-lib/src/index_controller/dump_actor/loaders/v4.rs +++ b/meilisearch-lib/src/index_controller/dump_actor/loaders/v4.rs @@ -1,9 +1,9 @@ use std::path::Path; use std::sync::Arc; -use heed::EnvOpenOptions; use log::info; use meilisearch_auth::AuthController; +use milli::heed::EnvOpenOptions; use crate::analytics; use crate::index_controller::dump_actor::Metadata; diff --git a/meilisearch-lib/src/index_controller/dump_actor/mod.rs b/meilisearch-lib/src/index_controller/dump_actor/mod.rs index 2c0f464d2..16e328e3b 100644 --- a/meilisearch-lib/src/index_controller/dump_actor/mod.rs +++ b/meilisearch-lib/src/index_controller/dump_actor/mod.rs @@ -3,9 +3,9 @@ use std::path::{Path, PathBuf}; use std::sync::Arc; use anyhow::bail; -use chrono::{DateTime, Utc}; use log::{info, trace}; use serde::{Deserialize, Serialize}; +use time::OffsetDateTime; pub use actor::DumpActor; pub use handle_impl::*; @@ -40,7 +40,8 @@ pub struct Metadata { db_version: String, index_db_size: usize, update_db_size: usize, - dump_date: DateTime, + #[serde(with = "time::serde::rfc3339")] + dump_date: OffsetDateTime, } impl Metadata { @@ -49,7 +50,7 @@ impl Metadata { db_version: env!("CARGO_PKG_VERSION").to_string(), index_db_size, update_db_size, - dump_date: Utc::now(), + dump_date: OffsetDateTime::now_utc(), } } } @@ -144,7 +145,7 @@ impl MetadataVersion { } } - pub fn dump_date(&self) -> Option<&DateTime> { + pub fn dump_date(&self) -> Option<&OffsetDateTime> { match self { MetadataVersion::V1(_) => None, MetadataVersion::V2(meta) | MetadataVersion::V3(meta) | MetadataVersion::V4(meta) => { @@ -169,9 +170,13 @@ pub struct DumpInfo { pub status: DumpStatus, #[serde(skip_serializing_if = "Option::is_none")] pub error: Option, - started_at: DateTime, - #[serde(skip_serializing_if = "Option::is_none")] - finished_at: Option>, + #[serde(with = "time::serde::rfc3339")] + started_at: OffsetDateTime, + #[serde( + skip_serializing_if = "Option::is_none", + with = "time::serde::rfc3339::option" + )] + finished_at: Option, } impl DumpInfo { @@ -180,19 +185,19 @@ impl DumpInfo { uid, status, error: None, - started_at: Utc::now(), + started_at: OffsetDateTime::now_utc(), finished_at: None, } } pub fn with_error(&mut self, error: String) { self.status = DumpStatus::Failed; - self.finished_at = Some(Utc::now()); + self.finished_at = Some(OffsetDateTime::now_utc()); self.error = Some(error); } pub fn done(&mut self) { - self.finished_at = Some(Utc::now()); + self.finished_at = Some(OffsetDateTime::now_utc()); self.status = DumpStatus::Done; } diff --git a/meilisearch-lib/src/index_controller/mod.rs b/meilisearch-lib/src/index_controller/mod.rs index 34e37be82..70a59be62 100644 --- a/meilisearch-lib/src/index_controller/mod.rs +++ b/meilisearch-lib/src/index_controller/mod.rs @@ -8,11 +8,11 @@ use std::time::Duration; use actix_web::error::PayloadError; use bytes::Bytes; -use chrono::{DateTime, Utc}; use futures::Stream; use futures::StreamExt; use milli::update::IndexDocumentsMethod; use serde::{Deserialize, Serialize}; +use time::OffsetDateTime; use tokio::sync::{mpsc, RwLock}; use tokio::task::spawn_blocking; use tokio::time::sleep; @@ -48,8 +48,8 @@ pub type Payload = Box< dyn Stream> + Send + Sync + 'static + Unpin, >; -pub fn open_meta_env(path: &Path, size: usize) -> heed::Result { - let mut options = heed::EnvOpenOptions::new(); +pub fn open_meta_env(path: &Path, size: usize) -> milli::heed::Result { + let mut options = milli::heed::EnvOpenOptions::new(); options.map_size(size); options.max_dbs(20); options.open(path) @@ -114,7 +114,8 @@ impl fmt::Display for DocumentAdditionFormat { #[serde(rename_all = "camelCase")] pub struct Stats { pub database_size: u64, - pub last_update: Option>, + #[serde(serialize_with = "time::serde::rfc3339::option::serialize")] + pub last_update: Option, pub indexes: BTreeMap, } @@ -582,7 +583,7 @@ where } pub async fn get_all_stats(&self, search_rules: &SearchRules) -> Result { - let mut last_task: Option> = None; + let mut last_task: Option = None; let mut indexes = BTreeMap::new(); let mut database_size = 0; let processing_tasks = self.scheduler.read().await.get_processing_tasks().await?; diff --git a/meilisearch-lib/src/index_resolver/error.rs b/meilisearch-lib/src/index_resolver/error.rs index 9ac607a58..6c86aa6b8 100644 --- a/meilisearch-lib/src/index_resolver/error.rs +++ b/meilisearch-lib/src/index_resolver/error.rs @@ -45,7 +45,7 @@ impl From for IndexResolverError { } internal_error!( - IndexResolverError: heed::Error, + IndexResolverError: milli::heed::Error, uuid::Error, std::io::Error, tokio::task::JoinError, diff --git a/meilisearch-lib/src/index_resolver/meta_store.rs b/meilisearch-lib/src/index_resolver/meta_store.rs index 6ca615dbf..f53f9cae9 100644 --- a/meilisearch-lib/src/index_resolver/meta_store.rs +++ b/meilisearch-lib/src/index_resolver/meta_store.rs @@ -4,8 +4,8 @@ use std::io::{BufRead, BufReader, Write}; use std::path::{Path, PathBuf}; use std::sync::Arc; -use heed::types::{SerdeBincode, Str}; -use heed::{CompactionOption, Database, Env}; +use milli::heed::types::{SerdeBincode, Str}; +use milli::heed::{CompactionOption, Database, Env}; use serde::{Deserialize, Serialize}; use uuid::Uuid; @@ -56,7 +56,7 @@ impl Drop for HeedMetaStore { } impl HeedMetaStore { - pub fn new(env: Arc) -> Result { + pub fn new(env: Arc) -> Result { let db = env.create_database(Some("uuids"))?; Ok(Self { env, db }) } @@ -153,7 +153,7 @@ impl HeedMetaStore { Ok(()) } - pub fn load_dump(src: impl AsRef, env: Arc) -> Result<()> { + pub fn load_dump(src: impl AsRef, env: Arc) -> Result<()> { let src_indexes = src.as_ref().join(UUIDS_DB_PATH).join("data.jsonl"); let indexes = File::open(&src_indexes)?; let mut indexes = BufReader::new(indexes); diff --git a/meilisearch-lib/src/index_resolver/mod.rs b/meilisearch-lib/src/index_resolver/mod.rs index 48201d39a..8ca3efdc6 100644 --- a/meilisearch-lib/src/index_resolver/mod.rs +++ b/meilisearch-lib/src/index_resolver/mod.rs @@ -6,14 +6,14 @@ use std::convert::{TryFrom, TryInto}; use std::path::Path; use std::sync::Arc; -use chrono::Utc; use error::{IndexResolverError, Result}; -use heed::Env; use index_store::{IndexStore, MapIndexStore}; use meilisearch_error::ResponseError; use meta_store::{HeedMetaStore, IndexMetaStore}; +use milli::heed::Env; use milli::update::{DocumentDeletionResult, IndexerConfig}; use serde::{Deserialize, Serialize}; +use time::OffsetDateTime; use tokio::sync::oneshot; use tokio::task::spawn_blocking; use uuid::Uuid; @@ -39,7 +39,7 @@ pub fn create_index_resolver( path: impl AsRef, index_size: usize, indexer_opts: &IndexerOpts, - meta_env: Arc, + meta_env: Arc, file_store: UpdateFileStore, ) -> anyhow::Result { let uuid_store = HeedMetaStore::new(meta_env)?; @@ -115,18 +115,19 @@ where self.process_document_addition_batch(batch).await } else { if let Some(task) = batch.tasks.first_mut() { - task.events.push(TaskEvent::Processing(Utc::now())); + task.events + .push(TaskEvent::Processing(OffsetDateTime::now_utc())); match self.process_task(task).await { Ok(success) => { task.events.push(TaskEvent::Succeded { result: success, - timestamp: Utc::now(), + timestamp: OffsetDateTime::now_utc(), }); } Err(err) => task.events.push(TaskEvent::Failed { error: err.into(), - timestamp: Utc::now(), + timestamp: OffsetDateTime::now_utc(), }), } } @@ -225,7 +226,7 @@ where // If the index doesn't exist and we are not allowed to create it with the first // task, we must fails the whole batch. - let now = Utc::now(); + let now = OffsetDateTime::now_utc(); let index = match index { Ok(index) => index, Err(e) => { @@ -253,17 +254,17 @@ where let event = match result { Ok(Ok(result)) => TaskEvent::Succeded { - timestamp: Utc::now(), + timestamp: OffsetDateTime::now_utc(), result: TaskResult::DocumentAddition { indexed_documents: result.indexed_documents, }, }, Ok(Err(e)) => TaskEvent::Failed { - timestamp: Utc::now(), + timestamp: OffsetDateTime::now_utc(), error: e.into(), }, Err(e) => TaskEvent::Failed { - timestamp: Utc::now(), + timestamp: OffsetDateTime::now_utc(), error: IndexResolverError::from(e).into(), }, }; @@ -524,7 +525,7 @@ mod test { }; if primary_key.is_some() { mocker.when::>("update_primary_key") - .then(move |_| Ok(IndexMeta{ created_at: Utc::now(), updated_at: Utc::now(), primary_key: None })); + .then(move |_| Ok(IndexMeta{ created_at: OffsetDateTime::now_utc(), updated_at: OffsetDateTime::now_utc(), primary_key: None })); } mocker.when::<(IndexDocumentsMethod, Option, UpdateFileStore, IntoIter), IndexResult>("update_documents") .then(move |(_, _, _, _)| result()); @@ -569,7 +570,7 @@ mod test { | TaskContent::IndexCreation { primary_key } => { if primary_key.is_some() { let result = move || if !index_op_fails { - Ok(IndexMeta{ created_at: Utc::now(), updated_at: Utc::now(), primary_key: None }) + Ok(IndexMeta{ created_at: OffsetDateTime::now_utc(), updated_at: OffsetDateTime::now_utc(), primary_key: None }) } else { // return this error because it's easy to generate... Err(IndexError::DocumentNotFound("a doc".into())) @@ -640,7 +641,7 @@ mod test { let update_file_store = UpdateFileStore::mock(mocker); let index_resolver = IndexResolver::new(uuid_store, index_store, update_file_store); - let batch = Batch { id: 1, created_at: Utc::now(), tasks: vec![task.clone()] }; + let batch = Batch { id: 1, created_at: OffsetDateTime::now_utc(), tasks: vec![task.clone()] }; let result = index_resolver.process_batch(batch).await; // Test for some expected output scenarios: diff --git a/meilisearch-lib/src/lib.rs b/meilisearch-lib/src/lib.rs index 21b8eb8c3..1161340ba 100644 --- a/meilisearch-lib/src/lib.rs +++ b/meilisearch-lib/src/lib.rs @@ -13,8 +13,8 @@ mod update_file_store; use std::path::Path; pub use index_controller::MeiliSearch; - pub use milli; +pub use milli::heed; mod compression; pub mod document_formats; @@ -25,7 +25,7 @@ pub trait EnvSizer { fn size(&self) -> u64; } -impl EnvSizer for heed::Env { +impl EnvSizer for milli::heed::Env { fn size(&self) -> u64 { WalkDir::new(self.path()) .into_iter() diff --git a/meilisearch-lib/src/options.rs b/meilisearch-lib/src/options.rs index d6657cae6..195576799 100644 --- a/meilisearch-lib/src/options.rs +++ b/meilisearch-lib/src/options.rs @@ -48,24 +48,24 @@ pub struct IndexerOpts { pub struct SchedulerConfig { /// enable the autobatching experimental feature #[clap(long, hide = true)] - pub enable_autobatching: bool, + pub enable_auto_batching: bool, // The maximum number of updates of the same type that can be batched together. // If unspecified, this is unlimited. A value of 0 is interpreted as 1. - #[clap(long, requires = "enable-autobatching", hide = true)] + #[clap(long, requires = "enable-auto-batching", hide = true)] pub max_batch_size: Option, // The maximum number of documents in a document batch. Since batches must contain at least one // update for the scheduler to make progress, the number of documents in a batch will be at // least the number of documents of its first update. - #[clap(long, requires = "enable-autobatching", hide = true)] + #[clap(long, requires = "enable-auto-batching", hide = true)] pub max_documents_per_batch: Option, /// Debounce duration in seconds /// /// When a new task is enqueued, the scheduler waits for `debounce_duration_sec` seconds for new updates before /// starting to process a batch of updates. - #[clap(long, requires = "enable-autobatching", hide = true)] + #[clap(long, requires = "enable-auto-batching", hide = true)] pub debounce_duration_sec: Option, } diff --git a/meilisearch-lib/src/snapshot.rs b/meilisearch-lib/src/snapshot.rs index 3667d1021..6c27ad2f0 100644 --- a/meilisearch-lib/src/snapshot.rs +++ b/meilisearch-lib/src/snapshot.rs @@ -149,7 +149,7 @@ impl SnapshotJob { let env = open_meta_env(&self.src_path, self.meta_env_size)?; let dst = path.join("data.mdb"); - env.copy_to_path(dst, heed::CompactionOption::Enabled)?; + env.copy_to_path(dst, milli::heed::CompactionOption::Enabled)?; Ok(()) } @@ -180,12 +180,12 @@ impl SnapshotJob { let dst = dst.join("data.mdb"); - let mut options = heed::EnvOpenOptions::new(); + let mut options = milli::heed::EnvOpenOptions::new(); options.map_size(self.index_size); let index = milli::Index::new(options, entry.path())?; index .env - .copy_to_path(dst, heed::CompactionOption::Enabled)?; + .copy_to_path(dst, milli::heed::CompactionOption::Enabled)?; } Ok(()) @@ -198,7 +198,7 @@ impl SnapshotJob { let dst = dst.join("data.mdb"); let env = open_auth_store_env(&auth_path)?; - env.copy_to_path(dst, heed::CompactionOption::Enabled)?; + env.copy_to_path(dst, milli::heed::CompactionOption::Enabled)?; Ok(()) } diff --git a/meilisearch-lib/src/tasks/batch.rs b/meilisearch-lib/src/tasks/batch.rs index eff81acc5..4a8cf7907 100644 --- a/meilisearch-lib/src/tasks/batch.rs +++ b/meilisearch-lib/src/tasks/batch.rs @@ -1,4 +1,4 @@ -use chrono::{DateTime, Utc}; +use time::OffsetDateTime; use super::task::Task; @@ -7,7 +7,7 @@ pub type BatchId = u64; #[derive(Debug)] pub struct Batch { pub id: BatchId, - pub created_at: DateTime, + pub created_at: OffsetDateTime, pub tasks: Vec, } diff --git a/meilisearch-lib/src/tasks/error.rs b/meilisearch-lib/src/tasks/error.rs index 38561314f..d849b4c10 100644 --- a/meilisearch-lib/src/tasks/error.rs +++ b/meilisearch-lib/src/tasks/error.rs @@ -16,7 +16,7 @@ pub enum TaskError { } internal_error!( - TaskError: heed::Error, + TaskError: milli::heed::Error, JoinError, std::io::Error, serde_json::Error, diff --git a/meilisearch-lib/src/tasks/scheduler.rs b/meilisearch-lib/src/tasks/scheduler.rs index 695f6c11f..0e540a646 100644 --- a/meilisearch-lib/src/tasks/scheduler.rs +++ b/meilisearch-lib/src/tasks/scheduler.rs @@ -6,8 +6,8 @@ use std::sync::Arc; use std::time::Duration; use atomic_refcell::AtomicRefCell; -use chrono::Utc; use milli::update::IndexDocumentsMethod; +use time::OffsetDateTime; use tokio::sync::{watch, RwLock}; use crate::options::SchedulerConfig; @@ -218,7 +218,7 @@ impl Scheduler { let debounce_time = config.debounce_duration_sec; // Disable autobatching - if !config.enable_autobatching { + if !config.enable_auto_batching { config.max_batch_size = Some(1); } @@ -357,7 +357,7 @@ impl Scheduler { tasks.iter_mut().for_each(|t| { t.events.push(TaskEvent::Batched { batch_id: id, - timestamp: Utc::now(), + timestamp: OffsetDateTime::now_utc(), }) }); @@ -365,7 +365,7 @@ impl Scheduler { let batch = Batch { id, - created_at: Utc::now(), + created_at: OffsetDateTime::now_utc(), tasks, }; diff --git a/meilisearch-lib/src/tasks/task.rs b/meilisearch-lib/src/tasks/task.rs index f5d6687cd..ecbd4ca62 100644 --- a/meilisearch-lib/src/tasks/task.rs +++ b/meilisearch-lib/src/tasks/task.rs @@ -1,9 +1,9 @@ use std::path::PathBuf; -use chrono::{DateTime, Utc}; use meilisearch_error::ResponseError; use milli::update::{DocumentAdditionResult, IndexDocumentsMethod}; use serde::{Deserialize, Serialize}; +use time::OffsetDateTime; use tokio::sync::oneshot; use uuid::Uuid; @@ -36,22 +36,33 @@ impl From for TaskResult { #[derive(Clone, Debug, Serialize, Deserialize, PartialEq, Eq)] #[cfg_attr(test, derive(proptest_derive::Arbitrary))] pub enum TaskEvent { - Created(#[cfg_attr(test, proptest(strategy = "test::datetime_strategy()"))] DateTime), + Created( + #[cfg_attr(test, proptest(strategy = "test::datetime_strategy()"))] + #[serde(with = "time::serde::rfc3339")] + OffsetDateTime, + ), Batched { #[cfg_attr(test, proptest(strategy = "test::datetime_strategy()"))] - timestamp: DateTime, + #[serde(with = "time::serde::rfc3339")] + timestamp: OffsetDateTime, batch_id: BatchId, }, - Processing(#[cfg_attr(test, proptest(strategy = "test::datetime_strategy()"))] DateTime), + Processing( + #[cfg_attr(test, proptest(strategy = "test::datetime_strategy()"))] + #[serde(with = "time::serde::rfc3339")] + OffsetDateTime, + ), Succeded { result: TaskResult, #[cfg_attr(test, proptest(strategy = "test::datetime_strategy()"))] - timestamp: DateTime, + #[serde(with = "time::serde::rfc3339")] + timestamp: OffsetDateTime, }, Failed { error: ResponseError, #[cfg_attr(test, proptest(strategy = "test::datetime_strategy()"))] - timestamp: DateTime, + #[serde(with = "time::serde::rfc3339")] + timestamp: OffsetDateTime, }, } @@ -165,7 +176,7 @@ mod test { ] } - pub(super) fn datetime_strategy() -> impl Strategy> { - Just(Utc::now()) + pub(super) fn datetime_strategy() -> impl Strategy { + Just(OffsetDateTime::now_utc()) } } diff --git a/meilisearch-lib/src/tasks/task_store/mod.rs b/meilisearch-lib/src/tasks/task_store/mod.rs index 88f12ddd1..bdcd13f37 100644 --- a/meilisearch-lib/src/tasks/task_store/mod.rs +++ b/meilisearch-lib/src/tasks/task_store/mod.rs @@ -5,9 +5,9 @@ use std::io::{BufWriter, Write}; use std::path::Path; use std::sync::Arc; -use chrono::Utc; -use heed::{Env, RwTxn}; use log::debug; +use milli::heed::{Env, RwTxn}; +use time::OffsetDateTime; use super::error::TaskError; use super::task::{Task, TaskContent, TaskId}; @@ -61,7 +61,7 @@ impl Clone for TaskStore { } impl TaskStore { - pub fn new(env: Arc) -> Result { + pub fn new(env: Arc) -> Result { let store = Arc::new(Store::new(env)?); Ok(Self { store }) } @@ -72,7 +72,7 @@ impl TaskStore { let task = tokio::task::spawn_blocking(move || -> Result { let mut txn = store.wtxn()?; let next_task_id = store.next_task_id(&mut txn)?; - let created_at = TaskEvent::Created(Utc::now()); + let created_at = TaskEvent::Created(OffsetDateTime::now_utc()); let task = Task { id: next_task_id, index_uid, @@ -248,7 +248,7 @@ pub mod test { } impl MockTaskStore { - pub fn new(env: Arc) -> Result { + pub fn new(env: Arc) -> Result { Ok(Self::Real(TaskStore::new(env)?)) } diff --git a/meilisearch-lib/src/tasks/task_store/store.rs b/meilisearch-lib/src/tasks/task_store/store.rs index 582cfe27c..4ff986d8b 100644 --- a/meilisearch-lib/src/tasks/task_store/store.rs +++ b/meilisearch-lib/src/tasks/task_store/store.rs @@ -1,5 +1,5 @@ #[allow(clippy::upper_case_acronyms)] -type BEU64 = heed::zerocopy::U64; +type BEU64 = milli::heed::zerocopy::U64; const UID_TASK_IDS: &str = "uid_task_id"; const TASKS: &str = "tasks"; @@ -12,8 +12,8 @@ use std::ops::Range; use std::result::Result as StdResult; use std::sync::Arc; -use heed::types::{ByteSlice, OwnedType, SerdeJson, Unit}; -use heed::{BytesDecode, BytesEncode, Database, Env, RoTxn, RwTxn}; +use milli::heed::types::{ByteSlice, OwnedType, SerdeJson, Unit}; +use milli::heed::{BytesDecode, BytesEncode, Database, Env, RoTxn, RwTxn}; use crate::tasks::task::{Task, TaskId}; @@ -73,7 +73,7 @@ impl Store { /// be in an invalid state, with dangling processing tasks. /// You want to patch all un-finished tasks and put them in your pending /// queue with the `reset_and_return_unfinished_update` method. - pub fn new(env: Arc) -> Result { + pub fn new(env: Arc) -> Result { let uids_task_ids = env.create_database(Some(UID_TASK_IDS))?; let tasks = env.create_database(Some(TASKS))?; @@ -130,7 +130,7 @@ impl Store { let range = from..limit .map(|limit| (limit as u64).saturating_add(from)) .unwrap_or(u64::MAX); - let iter: Box>> = match filter { + let iter: Box>> = match filter { Some( ref filter @ TaskFilter { indexes: Some(_), .. @@ -150,7 +150,7 @@ impl Store { ), }; - let apply_fitler = |task: &StdResult<_, heed::Error>| match task { + let apply_fitler = |task: &StdResult<_, milli::heed::Error>| match task { Ok(ref t) => filter .as_ref() .and_then(|filter| filter.filter_fn.as_ref()) @@ -162,7 +162,7 @@ impl Store { let tasks = iter .filter(apply_fitler) .take(limit.unwrap_or(usize::MAX)) - .try_fold::<_, _, StdResult<_, heed::Error>>(Vec::new(), |mut v, task| { + .try_fold::<_, _, StdResult<_, milli::heed::Error>>(Vec::new(), |mut v, task| { v.push(task?); Ok(v) })?; @@ -172,7 +172,7 @@ impl Store { fn compute_candidates( &self, - txn: &heed::RoTxn, + txn: &milli::heed::RoTxn, filter: &TaskFilter, range: Range, ) -> Result> { @@ -188,10 +188,10 @@ impl Store { self.uids_task_ids .remap_key_type::() .rev_prefix_iter(txn, &index_uid)? - .map(|entry| -> StdResult<_, heed::Error> { + .map(|entry| -> StdResult<_, milli::heed::Error> { let (key, _) = entry?; - let (_, id) = - IndexUidTaskIdCodec::bytes_decode(key).ok_or(heed::Error::Decoding)?; + let (_, id) = IndexUidTaskIdCodec::bytes_decode(key) + .ok_or(milli::heed::Error::Decoding)?; Ok(id) }) .skip_while(|entry| { @@ -212,7 +212,7 @@ impl Store { // if we encounter an error we returns true to collect it later .unwrap_or(true) }) - .try_for_each::<_, StdResult<(), heed::Error>>(|id| { + .try_for_each::<_, StdResult<(), milli::heed::Error>>(|id| { candidates.push(id?); Ok(()) })?; @@ -225,8 +225,8 @@ impl Store { #[cfg(test)] pub mod test { - use heed::EnvOpenOptions; use itertools::Itertools; + use milli::heed::EnvOpenOptions; use nelson::Mocker; use proptest::collection::vec; use proptest::prelude::*; @@ -244,10 +244,10 @@ pub mod test { Fake(Mocker), } - pub struct TmpEnv(TempDir, Arc); + pub struct TmpEnv(TempDir, Arc); impl TmpEnv { - pub fn env(&self) -> Arc { + pub fn env(&self) -> Arc { self.1.clone() } } @@ -264,7 +264,7 @@ pub mod test { } impl MockStore { - pub fn new(env: Arc) -> Result { + pub fn new(env: Arc) -> Result { Ok(Self::Real(Store::new(env)?)) } diff --git a/meilisearch-lib/src/tasks/update_loop.rs b/meilisearch-lib/src/tasks/update_loop.rs index 5cdbf1b46..b09811721 100644 --- a/meilisearch-lib/src/tasks/update_loop.rs +++ b/meilisearch-lib/src/tasks/update_loop.rs @@ -1,7 +1,7 @@ use std::sync::Arc; use std::time::Duration; -use chrono::Utc; +use time::OffsetDateTime; use tokio::sync::{watch, RwLock}; use tokio::time::interval_at; @@ -63,7 +63,8 @@ where match pending { Pending::Batch(mut batch) => { for task in &mut batch.tasks { - task.events.push(TaskEvent::Processing(Utc::now())); + task.events + .push(TaskEvent::Processing(OffsetDateTime::now_utc())); } batch.tasks = {