diff --git a/.github/ISSUE_TEMPLATE/bug_report.md b/.github/ISSUE_TEMPLATE/bug_report.md index cea573edf..4ce2db180 100644 --- a/.github/ISSUE_TEMPLATE/bug_report.md +++ b/.github/ISSUE_TEMPLATE/bug_report.md @@ -23,8 +23,8 @@ A clear and concise description of what you expected to happen. **Screenshots** If applicable, add screenshots to help explain your problem. -**MeiliSearch version:** [e.g. v0.20.0] +**Meilisearch version:** [e.g. v0.20.0] **Additional context** Additional information that may be relevant to the issue. -[e.g. architecture, device, OS, browser] \ No newline at end of file +[e.g. architecture, device, OS, browser] diff --git a/.github/ISSUE_TEMPLATE/config.yml b/.github/ISSUE_TEMPLATE/config.yml index c48a05c91..4997861fb 100644 --- a/.github/ISSUE_TEMPLATE/config.yml +++ b/.github/ISSUE_TEMPLATE/config.yml @@ -6,5 +6,5 @@ contact_links: url: https://github.com/meilisearch/documentation/issues/new about: For documentation issues, open an issue or a PR in the documentation repository - name: Support questions & other - url: https://github.com/meilisearch/MeiliSearch/discussions/new + url: https://github.com/meilisearch/meilisearch/discussions/new about: For any other question, open a discussion in this repository diff --git a/.github/is-latest-release.sh b/.github/is-latest-release.sh index b30c6138b..77e3ad9a0 100644 --- a/.github/is-latest-release.sh +++ b/.github/is-latest-release.sh @@ -74,7 +74,7 @@ semverLT() { # Returns the tag of the latest stable release (in terms of semver and not of release date) get_latest() { temp_file='temp_file' # temp_file needed because the grep would start before the download is over - curl -s 'https://api.github.com/repos/meilisearch/MeiliSearch/releases' > "$temp_file" + curl -s 'https://api.github.com/repos/meilisearch/meiliSearch/releases' > "$temp_file" releases=$(cat "$temp_file" | \ grep -E "tag_name|draft|prerelease" \ | tr -d ',"' | cut -d ':' -f2 | tr -d ' ') diff --git a/.github/workflows/README.md b/.github/workflows/README.md index 32c32c7d6..ffb401a6c 100644 --- a/.github/workflows/README.md +++ b/.github/workflows/README.md @@ -1,4 +1,4 @@ -# GitHub Actions Workflow for MeiliSearch +# GitHub Actions Workflow for Meilisearch > **Note:** diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index cae1e3ab3..c2674c4d1 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -1,7 +1,10 @@ # Contributing -First, thank you for contributing to MeiliSearch! The goal of this document is to provide everything you need to start contributing to MeiliSearch. +First, thank you for contributing to Meilisearch! The goal of this document is to provide everything you need to start contributing to Meilisearch. +Remember that there are many ways to contribute other than writing code: writing [tutorials or blog posts](https://github.com/meilisearch/awesome-meilisearch), improving [the documentation](https://github.com/meilisearch/documentation), submitting [bug reports](https://github.com/meilisearch/meilisearch/issues/new?assignees=&labels=&template=bug_report.md&title=) and [feature requests](https://github.com/meilisearch/product/discussions/categories/feedback-feature-proposal)... + +## Table of Contents - [Assumptions](#assumptions) - [How to Contribute](#how-to-contribute) - [Development Workflow](#development-workflow) @@ -10,8 +13,8 @@ First, thank you for contributing to MeiliSearch! The goal of this document is t ## Assumptions 1. **You're familiar with [Github](https://github.com) and the [Pull Requests](https://help.github.com/en/github/collaborating-with-issues-and-pull-requests/about-pull-requests)(PR) workflow.** -2. **You've read the MeiliSearch [documentation](https://docs.meilisearch.com).** -3. **You know about the [MeiliSearch community](https://docs.meilisearch.com/learn/what_is_meilisearch/contact.html). +2. **You've read the Meilisearch [documentation](https://docs.meilisearch.com).** +3. **You know about the [Meilisearch community](https://docs.meilisearch.com/learn/what_is_meilisearch/contact.html). Please use this for help.** ## How to Contribute @@ -19,21 +22,21 @@ First, thank you for contributing to MeiliSearch! The goal of this document is t 1. Ensure your change has an issue! Find an [existing issue](https://github.com/meilisearch/meilisearch/issues/) or [open a new issue](https://github.com/meilisearch/meilisearch/issues/new). * This is where you can get a feel if the change will be accepted or not. -2. Once approved, [fork the MeiliSearch repository](https://help.github.com/en/github/getting-started-with-github/fork-a-repo) in your own Github account. +2. Once approved, [fork the Meilisearch repository](https://help.github.com/en/github/getting-started-with-github/fork-a-repo) in your own Github account. 3. [Create a new Git branch](https://help.github.com/en/github/collaborating-with-issues-and-pull-requests/creating-and-deleting-branches-within-your-repository) 4. Review the [Development Workflow](#development-workflow) section that describes the steps to maintain the repository. 5. Make your changes on your branch. -6. [Submit the branch as a Pull Request](https://help.github.com/en/github/collaborating-with-issues-and-pull-requests/creating-a-pull-request-from-a-fork) pointing to the `main` branch of the MeiliSearch repository. A maintainer should comment and/or review your Pull Request within a few days. Although depending on the circumstances, it may take longer. +6. [Submit the branch as a Pull Request](https://help.github.com/en/github/collaborating-with-issues-and-pull-requests/creating-a-pull-request-from-a-fork) pointing to the `main` branch of the Meilisearch repository. A maintainer should comment and/or review your Pull Request within a few days. Although depending on the circumstances, it may take longer. ## Development Workflow -### Setup and run MeiliSearch +### Setup and run Meilisearch ```bash cargo run --release ``` -We recommend using the `--release` flag to test the full performance of MeiliSearch. +We recommend using the `--release` flag to test the full performance of Meilisearch. ### Test diff --git a/Cargo.lock b/Cargo.lock index 671d39894..55273a62f 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -4,9 +4,9 @@ version = 3 [[package]] name = "actix-codec" -version = "0.4.1" +version = "0.4.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "13895df506faee81e423febbae3a33b27fca71831b96bb3d60adf16ebcfea952" +checksum = "a36c014a3e811624313b51a227b775ecba55d36ef9462bbaac7d4f13e54c9271" dependencies = [ "bitflags", "bytes", @@ -21,22 +21,25 @@ dependencies = [ [[package]] name = "actix-cors" -version = "0.5.4" -source = "git+https://github.com/MarinPostma/actix-extras.git?rev=963ac94d#963ac94d33fb0f59d8c9ed8b9409e4270fc36912" +version = "0.6.0-beta.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d4f1bd0e31c745df129f0e94efd374d21f2a455bcc386c15d78ed9a9e7d4dd50" dependencies = [ + "actix-service", + "actix-utils", "actix-web", "derive_more", "futures-util", "log", "once_cell", - "tinyvec", + "smallvec", ] [[package]] name = "actix-http" -version = "3.0.0-beta.10" +version = "3.0.0-beta.19" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dd38a862fa7fead2b47ee55e550982aba583ebc7365ccf0155b49934ad6f16f9" +checksum = "ae58d21721388ea9b2cd0d4c11756b0f34424cdcd6e5cc74c3ce37b4641c8af0" dependencies = [ "actix-codec", "actix-rt", @@ -46,33 +49,27 @@ dependencies = [ "ahash 0.7.6", "base64", "bitflags", - "brotli2", + "brotli", "bytes", "bytestring", "derive_more", "encoding_rs", "flate2", "futures-core", - "futures-util", "h2", "http", "httparse", - "itoa", + "httpdate", + "itoa 1.0.1", "language-tags", "local-channel", "log", "mime", - "once_cell", "percent-encoding", - "pin-project", "pin-project-lite", "rand", - "regex", - "serde", - "sha-1", + "sha-1 0.10.0", "smallvec", - "time 0.2.27", - "tokio", "zstd", ] @@ -82,15 +79,15 @@ version = "0.2.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "465a6172cf69b960917811022d8f29bc0b7fa1398bc4f78b3c466673db1213b6" dependencies = [ - "quote 1.0.10", - "syn 1.0.82", + "quote 1.0.14", + "syn 1.0.86", ] [[package]] name = "actix-router" -version = "0.5.0-beta.2" +version = "0.5.0-rc.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "36b95ce0d76d1aa2f98b681702807475ade0f99bd4552546a6843a966d42ea3d" +checksum = "5e0b59ad08167ffbb686ddb495846707231e96908b829b1fc218198ec581e2ad" dependencies = [ "bytestring", "firestorm", @@ -102,9 +99,9 @@ dependencies = [ [[package]] name = "actix-rt" -version = "2.5.0" +version = "2.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "05c2f80ce8d0c990941c7a7a931f69fd0701b76d521f8d36298edf59cd3fbf1f" +checksum = "cdf3f2183be1241ed4dd22611850b85d38de0b08a09f1f7bcccbd0809084b359" dependencies = [ "actix-macros", "futures-core", @@ -113,9 +110,9 @@ dependencies = [ [[package]] name = "actix-server" -version = "2.0.0-beta.9" +version = "2.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "411dd3296dd317ff5eff50baa13f31923ea40ec855dd7f2d3ed8639948f0195f" +checksum = "d9e7472ac180abb0a8e592b653744345983a7a14f44691c8394a799d0df4dbbf" dependencies = [ "actix-rt", "actix-service", @@ -123,7 +120,7 @@ dependencies = [ "futures-core", "futures-util", "log", - "mio", + "mio 0.8.0", "num_cpus", "socket2", "tokio", @@ -131,9 +128,9 @@ dependencies = [ [[package]] name = "actix-service" -version = "2.0.1" +version = "2.0.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8d3dc6a618b082974a08d7a4781d24d4691cba51500059bfebe6656a61ebfe1e" +checksum = "3b894941f818cfdc7ccc4b9e60fa7e53b5042a2e8567270f9147d5591893373a" dependencies = [ "futures-core", "paste", @@ -142,9 +139,9 @@ dependencies = [ [[package]] name = "actix-tls" -version = "3.0.0-beta.5" +version = "3.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "65b7bb60840962ef0332f7ea01a57d73a24d2cb663708511ff800250bbfef569" +checksum = "b161450ff646361005a300716e85856780ddc2fde569fd81335cc3c15b2e0933" dependencies = [ "actix-codec", "actix-rt", @@ -152,8 +149,8 @@ dependencies = [ "actix-utils", "derive_more", "futures-core", - "http", "log", + "pin-project-lite", "tokio-rustls", "tokio-util", "webpki-roots", @@ -171,9 +168,9 @@ dependencies = [ [[package]] name = "actix-web" -version = "4.0.0-beta.9" +version = "4.0.0-beta.21" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d34aa2b23ec9c7c9a799b3cf9258f67c91b18ac3f0f5f484e175c7ac46739bb5" +checksum = "606fc29a9bde2907243086ceb93ce56df7584276c2c46abc64a524f645c63c5e" dependencies = [ "actix-codec", "actix-http", @@ -190,51 +187,46 @@ dependencies = [ "cfg-if 1.0.0", "cookie", "derive_more", - "either", "encoding_rs", "futures-core", "futures-util", - "itoa", + "itoa 1.0.1", "language-tags", "log", "mime", "once_cell", - "paste", - "pin-project", + "pin-project-lite", "regex", "serde", "serde_json", "serde_urlencoded", "smallvec", "socket2", - "time 0.2.27", + "time 0.3.6", "url", ] [[package]] name = "actix-web-codegen" -version = "0.5.0-beta.5" +version = "0.5.0-rc.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dfe80a8828fa88a0420dc8fdd4c16b8207326c917f17701881b063eadc2a8d3b" +checksum = "98a793e4a7bd059e06e1bc1bd9943b57a47f806de3599d2437441682292c333e" dependencies = [ "actix-router", - "proc-macro2 1.0.32", - "quote 1.0.10", - "syn 1.0.82", + "proc-macro2 1.0.36", + "quote 1.0.14", + "syn 1.0.86", ] [[package]] name = "actix-web-static-files" version = "3.0.5" -source = "git+https://github.com/MarinPostma/actix-web-static-files.git?rev=39d8006#39d8006a8c1c3319d8d9edfa4d917c2ba6655f1f" +source = "git+https://github.com/robjtede/actix-web-static-files.git?rev=ed74153#ed741539d0c72507f4ebe419306c45fdcaff4a09" dependencies = [ - "actix-service", "actix-web", - "change-detection", "derive_more", - "futures", - "mime_guess", - "path-slash", + "futures-util", + "static-files", ] [[package]] @@ -279,19 +271,25 @@ dependencies = [ ] [[package]] -name = "ansi_term" -version = "0.12.1" +name = "alloc-no-stdlib" +version = "2.0.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d52a9bb7ec0cf484c551830a7ce27bd20d67eac647e1befb56b0be4ee39a55d2" +checksum = "35ef4730490ad1c4eae5c4325b2a95f521d023e5c885853ff7aca0a6a1631db3" + +[[package]] +name = "alloc-stdlib" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "697ed7edc0f1711de49ce108c541623a0af97c6c60b2f6e2b65229847ac843c2" dependencies = [ - "winapi", + "alloc-no-stdlib", ] [[package]] name = "anyhow" -version = "1.0.51" +version = "1.0.52" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8b26702f315f53b6071259e15dd9d64528213b44d61de1ec926eca7715d62203" +checksum = "84450d0b4a8bd1ba4144ce8ce718fbc5d071358b1e5384bace6536b3d1f2d5b3" dependencies = [ "backtrace", ] @@ -310,7 +308,7 @@ checksum = "45403b49e3954a4b8428a0ac21a4b7afadccf92bfd96273f1a58cd4812496ae0" dependencies = [ "generic-array 0.12.4", "generic-array 0.13.3", - "generic-array 0.14.4", + "generic-array 0.14.5", "stable_deref_trait", ] @@ -340,20 +338,20 @@ version = "0.3.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "648ed8c8d2ce5409ccd57453d9d1b214b342a0d69376a6feda1fd6cae3299308" dependencies = [ - "proc-macro2 1.0.32", - "quote 1.0.10", - "syn 1.0.82", + "proc-macro2 1.0.36", + "quote 1.0.14", + "syn 1.0.86", ] [[package]] name = "async-trait" -version = "0.1.51" +version = "0.1.52" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "44318e776df68115a881de9a8fd1b9e53368d7a4a5ce4cc48517da3393233a5e" +checksum = "061a7acccaa286c011ddc30970520b98fa40e00c9d644633fb26b5fc63a265e3" dependencies = [ - "proc-macro2 1.0.32", - "quote 1.0.10", - "syn 1.0.82", + "proc-macro2 1.0.36", + "quote 1.0.14", + "syn 1.0.86", ] [[package]] @@ -388,12 +386,6 @@ dependencies = [ "rustc-demangle", ] -[[package]] -name = "base-x" -version = "0.2.8" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a4521f3e3d031370679b3b140beb36dfe4801b09ac77e30c61941f97df3ef28b" - [[package]] name = "base64" version = "0.13.0" @@ -445,27 +437,37 @@ version = "0.9.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "4152116fd6e9dadb291ae18fc1ec3575ed6d84c29642d97890f4b4a3417297e4" dependencies = [ - "generic-array 0.14.4", + "generic-array 0.14.5", ] [[package]] -name = "brotli-sys" -version = "0.3.2" +name = "block-buffer" +version = "0.10.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4445dea95f4c2b41cde57cc9fee236ae4dbae88d8fcbdb4750fc1bb5d86aaecd" +checksum = "f1d36a02058e76b040de25a4464ba1c80935655595b661505c8b39b664828b95" dependencies = [ - "cc", - "libc", + "generic-array 0.14.5", ] [[package]] -name = "brotli2" -version = "0.3.2" +name = "brotli" +version = "3.3.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0cb036c3eade309815c15ddbacec5b22c4d1f3983a774ab2eac2e3e9ea85568e" +checksum = "f838e47a451d5a8fa552371f80024dd6ace9b7acdf25c4c3d0f9bc6816fb1c39" dependencies = [ - "brotli-sys", - "libc", + "alloc-no-stdlib", + "alloc-stdlib", + "brotli-decompressor", +] + +[[package]] +name = "brotli-decompressor" +version = "2.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "59ad2d4653bf5ca36ae797b1f4bb4dbddb60ce49ca4aed8a2ce4829f60425b80" +dependencies = [ + "alloc-no-stdlib", + "alloc-stdlib", ] [[package]] @@ -482,9 +484,9 @@ dependencies = [ [[package]] name = "bumpalo" -version = "3.8.0" +version = "3.9.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8f1e260c3a9040a7c19a12468758f4c16f31a81a1fe087482be9570ec864bb6c" +checksum = "a4a45a46ab1f2412e53d3a0ade76ffad2025804294569aae387231a0cd6e0899" [[package]] name = "byte-unit" @@ -492,6 +494,7 @@ version = "4.0.13" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "956ffc5b0ec7d7a6949e3f21fd63ba5af4cffdc2ba1e0b7bf62b481458c4ae7f" dependencies = [ + "serde", "utf8-width", ] @@ -503,9 +506,9 @@ checksum = "72feb31ffc86498dacdbd0fcebb56138e7177a8cc5cea4516031d15ae85a742e" [[package]] name = "bytemuck" -version = "1.7.2" +version = "1.7.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "72957246c41db82b8ef88a5486143830adeb8227ef9837740bdec67724cf2c5b" +checksum = "439989e6b8c38d1b6570a384ef1e49c8848128f5a97f3914baef02920842712f" dependencies = [ "bytemuck_derive", ] @@ -516,9 +519,9 @@ version = "1.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8e215f8c2f9f79cb53c8335e687ffd07d5bfcb6fe5fc80723762d0be46e7cc54" dependencies = [ - "proc-macro2 1.0.32", - "quote 1.0.10", - "syn 1.0.82", + "proc-macro2 1.0.36", + "quote 1.0.14", + "syn 1.0.86", ] [[package]] @@ -639,17 +642,32 @@ dependencies = [ [[package]] name = "clap" -version = "2.34.0" +version = "3.0.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a0610544180c38b88101fecf2dd634b174a62eef6946f84dfc6a7127512b381c" +checksum = "7a30c3bf9ff12dfe5dae53f0a96e0febcd18420d1c0e7fad77796d9d5c4b5375" dependencies = [ - "ansi_term", "atty", "bitflags", + "clap_derive", + "indexmap", + "lazy_static", + "os_str_bytes", "strsim", + "termcolor", "textwrap", - "unicode-width", - "vec_map", +] + +[[package]] +name = "clap_derive" +version = "3.0.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "517358c28fcef6607bf6f76108e02afad7e82297d132a6b846dcc1fc3efcd153" +dependencies = [ + "heck", + "proc-macro-error", + "proc-macro2 1.0.36", + "quote 1.0.14", + "syn 1.0.86", ] [[package]] @@ -658,17 +676,11 @@ version = "0.1.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1df715824eb382e34b7afb7463b0247bf41538aeba731fba05241ecdb5dc3747" dependencies = [ - "proc-macro2 1.0.32", - "quote 1.0.10", - "syn 1.0.82", + "proc-macro2 1.0.36", + "quote 1.0.14", + "syn 1.0.86", ] -[[package]] -name = "const_fn" -version = "0.4.8" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f92cfa0fd5690b3cf8c1ef2cabbd9b7ef22fa53cf5e1f92b05103f6d5d1cf6e7" - [[package]] name = "convert_case" version = "0.4.0" @@ -677,12 +689,12 @@ checksum = "6245d59a3e82a7fc217c5828a6692dbc6dfb63a0c8c90495621f7b9d79704a0e" [[package]] name = "cookie" -version = "0.15.1" +version = "0.16.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d5f1c7727e460397e56abc4bddc1d49e07a1ad78fc98eb2e1c8f032a58a2f80d" +checksum = "94d4706de1b0fa5b132270cddffa8585166037822e260a944fe161acd137ca05" dependencies = [ "percent-encoding", - "time 0.2.27", + "time 0.3.6", "version_check", ] @@ -709,21 +721,21 @@ dependencies = [ [[package]] name = "crc32fast" -version = "1.2.2" +version = "1.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3825b1e8580894917dc4468cb634a1b4e9745fddc854edad72d9c04644c0319f" +checksum = "a2209c310e29876f7f0b2721e7e26b84aff178aa3da5d091f9bfbf47669e60e3" dependencies = [ "cfg-if 1.0.0", ] [[package]] name = "crossbeam-channel" -version = "0.5.1" +version = "0.5.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "06ed27e177f16d65f0f0c22a213e17c696ace5dd64b14258b52f9417ccb52db4" +checksum = "e54ea8bc3fb1ee042f5aace6e3c6e025d3874866da222930f70ce62aceba0bfa" dependencies = [ "cfg-if 1.0.0", - "crossbeam-utils 0.8.5", + "crossbeam-utils 0.8.6", ] [[package]] @@ -734,17 +746,17 @@ checksum = "6455c0ca19f0d2fbf751b908d5c55c1f5cbc65e03c4225427254b46890bdde1e" dependencies = [ "cfg-if 1.0.0", "crossbeam-epoch", - "crossbeam-utils 0.8.5", + "crossbeam-utils 0.8.6", ] [[package]] name = "crossbeam-epoch" -version = "0.9.5" +version = "0.9.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4ec02e091aa634e2c3ada4a392989e7c3116673ef0ac5b72232439094d73b7fd" +checksum = "97242a70df9b89a65d0b6df3c4bf5b9ce03c5b7309019777fbde37e7537f8762" dependencies = [ "cfg-if 1.0.0", - "crossbeam-utils 0.8.5", + "crossbeam-utils 0.8.6", "lazy_static", "memoffset", "scopeguard", @@ -771,14 +783,23 @@ dependencies = [ [[package]] name = "crossbeam-utils" -version = "0.8.5" +version = "0.8.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d82cfc11ce7f2c3faef78d8a684447b40d503d9681acebed6cb728d45940c4db" +checksum = "cfcae03edb34f947e64acdb1c33ec169824e20657e9ecb61cef6c8c74dcb8120" dependencies = [ "cfg-if 1.0.0", "lazy_static", ] +[[package]] +name = "crypto-common" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "683d6b536309245c849479fba3da410962a43ed8e51c26b729208ec0ac2798d0" +dependencies = [ + "generic-array 0.14.5", +] + [[package]] name = "csv" version = "1.1.6" @@ -787,7 +808,7 @@ checksum = "22813a6dc45b335f9bade10bf7271dc477e81113e89eb251a0bc2a8a81c536e1" dependencies = [ "bstr", "csv-core", - "itoa", + "itoa 0.4.8", "ryu", "serde", ] @@ -807,9 +828,9 @@ version = "2.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "fcc3dd5e9e9c0b295d6e1e4d811fb6f157d5ffd784b8d202fc62eac8035a770b" dependencies = [ - "proc-macro2 1.0.32", - "quote 1.0.10", - "syn 1.0.82", + "proc-macro2 1.0.36", + "quote 1.0.14", + "syn 1.0.86", ] [[package]] @@ -819,10 +840,10 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "4fb810d30a7c1953f91334de7244731fc3f3c10d7fe163338a35b9f640960321" dependencies = [ "convert_case", - "proc-macro2 1.0.32", - "quote 1.0.10", - "rustc_version 0.4.0", - "syn 1.0.82", + "proc-macro2 1.0.36", + "quote 1.0.14", + "rustc_version", + "syn 1.0.86", ] [[package]] @@ -843,7 +864,18 @@ version = "0.9.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d3dd60d1080a57a05ab032377049e0591415d2b31afd7028356dbf3cc6dcb066" dependencies = [ - "generic-array 0.14.4", + "generic-array 0.14.5", +] + +[[package]] +name = "digest" +version = "0.10.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b697d66081d42af4fba142d56918a3cb21dc8eb63372c6b85d14f44fb9c5979b" +dependencies = [ + "block-buffer 0.10.0", + "crypto-common", + "generic-array 0.14.5", ] [[package]] @@ -867,12 +899,6 @@ dependencies = [ "winapi", ] -[[package]] -name = "discard" -version = "1.0.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "212d0f5754cb6769937f4501cc0e67f4f4483c8d2c3e1e922ee9edbe4ab4c7c0" - [[package]] name = "downcast" version = "0.10.0" @@ -887,9 +913,9 @@ checksum = "e78d4f1cc4ae33bbfc157ed5d5a5ef3bc29227303d595861deb238fcec4e9457" [[package]] name = "encoding_rs" -version = "0.8.29" +version = "0.8.30" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a74ea89a0a1b98f6332de42c95baff457ada66d1cb4030f9ff151b2041a1c746" +checksum = "7896dc8abb250ffdda33912550faa54c88ec8b998dec0b2c55ab224921ce11df" dependencies = [ "cfg-if 1.0.0", ] @@ -909,9 +935,9 @@ version = "0.7.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c134c37760b27a871ba422106eedbb8247da973a09e82558bf26d619c882b159" dependencies = [ - "proc-macro2 1.0.32", - "quote 1.0.10", - "syn 1.0.82", + "proc-macro2 1.0.36", + "quote 1.0.14", + "syn 1.0.86", ] [[package]] @@ -927,6 +953,15 @@ dependencies = [ "termcolor", ] +[[package]] +name = "fastrand" +version = "1.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "779d043b6a0b90cc4c0ed7ee380a6504394cee7efd7db050e3774eee387324b2" +dependencies = [ + "instant", +] + [[package]] name = "filetime" version = "0.2.15" @@ -950,9 +985,9 @@ dependencies = [ [[package]] name = "firestorm" -version = "0.4.6" +version = "0.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "31586bda1b136406162e381a3185a506cdfc1631708dd40cba2f6628d8634499" +checksum = "4d3d6188b8804df28032815ea256b6955c9625c24da7525f387a7af02fbb8f01" [[package]] name = "flate2" @@ -993,9 +1028,9 @@ dependencies = [ [[package]] name = "fragile" -version = "1.0.0" +version = "1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "69a039c3498dc930fe810151a34ba0c1c70b02b8625035592e74432f678591f2" +checksum = "8da1b8f89c5b5a5b7e59405cfcf0bb9588e5ed19f0b57a4cd542bbba3f164a6d" [[package]] name = "fs_extra" @@ -1011,9 +1046,9 @@ checksum = "7ab85b9b05e3978cc9a9cf8fea7f01b494e1a09ed3037e16ba39edc7a29eb61a" [[package]] name = "futures" -version = "0.3.18" +version = "0.3.19" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8cd0210d8c325c245ff06fd95a3b13689a1a276ac8cfa8e8720cb840bfb84b9e" +checksum = "28560757fe2bb34e79f907794bb6b22ae8b0e5c669b638a1132f2592b19035b4" dependencies = [ "futures-channel", "futures-core", @@ -1026,9 +1061,9 @@ dependencies = [ [[package]] name = "futures-channel" -version = "0.3.18" +version = "0.3.19" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7fc8cd39e3dbf865f7340dce6a2d401d24fd37c6fe6c4f0ee0de8bfca2252d27" +checksum = "ba3dda0b6588335f360afc675d0564c17a77a2bda81ca178a4b6081bd86c7f0b" dependencies = [ "futures-core", "futures-sink", @@ -1036,15 +1071,15 @@ dependencies = [ [[package]] name = "futures-core" -version = "0.3.18" +version = "0.3.19" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "629316e42fe7c2a0b9a65b47d159ceaa5453ab14e8f0a3c5eedbb8cd55b4a445" +checksum = "d0c8ff0461b82559810cdccfde3215c3f373807f5e5232b71479bff7bb2583d7" [[package]] name = "futures-executor" -version = "0.3.18" +version = "0.3.19" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7b808bf53348a36cab739d7e04755909b9fcaaa69b7d7e588b37b6ec62704c97" +checksum = "29d6d2ff5bb10fb95c85b8ce46538a2e5f5e7fdc755623a7d4529ab8a4ed9d2a" dependencies = [ "futures-core", "futures-task", @@ -1053,38 +1088,38 @@ dependencies = [ [[package]] name = "futures-io" -version = "0.3.18" +version = "0.3.19" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e481354db6b5c353246ccf6a728b0c5511d752c08da7260546fc0933869daa11" +checksum = "b1f9d34af5a1aac6fb380f735fe510746c38067c5bf16c7fd250280503c971b2" [[package]] name = "futures-macro" -version = "0.3.18" +version = "0.3.19" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a89f17b21645bc4ed773c69af9c9a0effd4a3f1a3876eadd453469f8854e7fdd" +checksum = "6dbd947adfffb0efc70599b3ddcf7b5597bb5fa9e245eb99f62b3a5f7bb8bd3c" dependencies = [ - "proc-macro2 1.0.32", - "quote 1.0.10", - "syn 1.0.82", + "proc-macro2 1.0.36", + "quote 1.0.14", + "syn 1.0.86", ] [[package]] name = "futures-sink" -version = "0.3.18" +version = "0.3.19" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "996c6442437b62d21a32cd9906f9c41e7dc1e19a9579843fad948696769305af" +checksum = "e3055baccb68d74ff6480350f8d6eb8fcfa3aa11bdc1a1ae3afdd0514617d508" [[package]] name = "futures-task" -version = "0.3.18" +version = "0.3.19" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dabf1872aaab32c886832f2276d2f5399887e2bd613698a02359e4ea83f8de12" +checksum = "6ee7c6485c30167ce4dfb83ac568a849fe53274c831081476ee13e0dce1aad72" [[package]] name = "futures-util" -version = "0.3.18" +version = "0.3.19" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "41d22213122356472061ac0f1ab2cee28d2bac8491410fd68c2af53d1cedb83e" +checksum = "d9b5cf40b47a271f77a8b1bec03ca09044d99d2372c0de244e66430761127164" dependencies = [ "futures-channel", "futures-core", @@ -1127,9 +1162,9 @@ dependencies = [ [[package]] name = "generic-array" -version = "0.14.4" +version = "0.14.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "501466ecc8a30d1d3b7fc9229b122b2ce8ed6e9d9223f1138d4babb253e51817" +checksum = "fd48d33ec7f05fbfa152300fdad764757cbded343c1aa1cff2fbaf4134851803" dependencies = [ "typenum", "version_check", @@ -1143,9 +1178,9 @@ checksum = "9e006f616a407d396ace1d2ebb3f43ed73189db8b098079bd129928d7645dd1e" [[package]] name = "getrandom" -version = "0.2.3" +version = "0.2.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7fcd999463524c52659517fe2cea98493cfe485d10565e7b0fb07dbba7ad2753" +checksum = "418d37c8b1d42553c93648be529cb70f920d3baf8ef469b74b9638df426e0b4c" dependencies = [ "cfg-if 1.0.0", "libc", @@ -1159,9 +1194,9 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e45727250e75cc04ff2846a66397da8ef2b3db8e40e0cef4df67950a07621eb9" dependencies = [ "proc-macro-error", - "proc-macro2 1.0.32", - "quote 1.0.10", - "syn 1.0.82", + "proc-macro2 1.0.36", + "quote 1.0.14", + "syn 1.0.86", ] [[package]] @@ -1172,9 +1207,9 @@ checksum = "78cc372d058dcf6d5ecd98510e7fbc9e5aec4d21de70f65fea8fecebcd881bd4" [[package]] name = "git2" -version = "0.13.24" +version = "0.13.25" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "845e007a28f1fcac035715988a234e8ec5458fd825b20a20c7dec74237ef341f" +checksum = "f29229cc1b24c0e6062f6e742aa3e256492a5323365e5ed3413599f8a5eff7d6" dependencies = [ "bitflags", "libc", @@ -1202,9 +1237,9 @@ dependencies = [ [[package]] name = "h2" -version = "0.3.7" +version = "0.3.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7fd819562fcebdac5afc5c113c3ec36f902840b70fd4fc458799c8ce4607ae55" +checksum = "0c9de88456263e249e241fcd211d3954e2c9b0ef7ccfc235a444eb367cae3689" dependencies = [ "bytes", "fnv", @@ -1251,19 +1286,16 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "634bd4d29cbf24424d0a4bfcbf80c6960129dc24424752a7d1d1390607023422" dependencies = [ "as-slice", - "generic-array 0.14.4", + "generic-array 0.14.5", "hash32", "stable_deref_trait", ] [[package]] name = "heck" -version = "0.3.3" +version = "0.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6d621efb26863f0e9924c6ac577e8275e5e6b77455db64ffa6c65c904e9e132c" -dependencies = [ - "unicode-segmentation", -] +checksum = "2540771e65fc8cb83cd6e8a237f70c319bd5c29f78ed1084ba5d50eeac86f7f9" [[package]] name = "heed" @@ -1317,13 +1349,13 @@ checksum = "7f24254aa9a54b5c858eaee2f5bccdb46aaf0e486a595ed5fd8f86ba55232a70" [[package]] name = "http" -version = "0.2.5" +version = "0.2.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1323096b05d41827dadeaee54c9981958c0f94e670bc94ed80037d1a7b8b186b" +checksum = "31f4c6746584866f0feabcc69893c5b51beef3831656a968ed7ae254cdc4fd03" dependencies = [ "bytes", "fnv", - "itoa", + "itoa 1.0.1", ] [[package]] @@ -1363,9 +1395,9 @@ checksum = "9a3a5bfb195931eeb336b2a7b4d761daec841b97f947d34394601737a7bba5e4" [[package]] name = "hyper" -version = "0.14.15" +version = "0.14.16" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "436ec0091e4f20e655156a30a0df3770fe2900aa301e548e08446ec794b6953c" +checksum = "b7ec3e62bdc98a2f0393a5048e4c30ef659440ea6e0e572965103e72bd836f55" dependencies = [ "bytes", "futures-channel", @@ -1376,7 +1408,7 @@ dependencies = [ "http-body", "httparse", "httpdate", - "itoa", + "itoa 0.4.8", "pin-project-lite", "socket2", "tokio", @@ -1387,17 +1419,15 @@ dependencies = [ [[package]] name = "hyper-rustls" -version = "0.22.1" +version = "0.23.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5f9f7a97316d44c0af9b0301e65010573a853a9fc97046d7331d7f6bc0fd5a64" +checksum = "d87c48c02e0dc5e3b849a2041db3029fd066650f8f717c07bf8ed78ccb895cac" dependencies = [ - "futures-util", + "http", "hyper", - "log", - "rustls", + "rustls 0.20.2", "tokio", "tokio-rustls", - "webpki", ] [[package]] @@ -1413,9 +1443,9 @@ dependencies = [ [[package]] name = "indexmap" -version = "1.7.0" +version = "1.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bc633605454125dec4b66843673f01c7df2b89479b32e0ed634e43a91cff62a5" +checksum = "282a6247722caba404c065016bbfa522806e51714c34f5dfc3e4a3a46fcb4223" dependencies = [ "autocfg", "hashbrown 0.11.2", @@ -1439,9 +1469,9 @@ checksum = "68f2d64f2edebec4ce84ad108148e67e1064789bee435edc5b60ad398714a3a9" [[package]] name = "itertools" -version = "0.10.1" +version = "0.10.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "69ddb889f9d0d08a67338271fa9b62996bc788c7796a5c18cf057420aaed5eaf" +checksum = "a9a9d19fa1e79b6215ff29b9d6880b706147f16e9b1dbb1e4e5947b5b02bc5e3" dependencies = [ "either", ] @@ -1452,6 +1482,12 @@ version = "0.4.8" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b71991ff56294aa922b450139ee08b3bfc70982c6b2c7562771375cf73542dd4" +[[package]] +name = "itoa" +version = "1.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1aab8fc367588b89dcee83ab0fd66b72b50b72fa1904d7095045ace2b0c81c35" + [[package]] name = "jieba-rs" version = "0.6.6" @@ -1478,9 +1514,9 @@ dependencies = [ [[package]] name = "js-sys" -version = "0.3.55" +version = "0.3.56" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7cc9ffccd38c451a86bf13657df244e9c3f37493cce8e5e21e940963777acc84" +checksum = "a38fc24e30fd564ce974c02bf1d337caddff65be6cc4735a1f7eab22a7440f04" dependencies = [ "wasm-bindgen", ] @@ -1508,15 +1544,15 @@ dependencies = [ [[package]] name = "libc" -version = "0.2.108" +version = "0.2.113" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8521a1b57e76b1ec69af7599e75e38e7b7fad6610f037db8c79b127201b5d119" +checksum = "eef78b64d87775463c549fbd80e19249ef436ea3bf1de2a1eb7e717ec7fab1e9" [[package]] name = "libgit2-sys" -version = "0.12.25+1.3.0" +version = "0.12.26+1.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8f68169ef08d6519b2fe133ecc637408d933c0174b23b80bb2f79828966fbaab" +checksum = "19e1c899248e606fbfe68dcb31d8b0176ebab833b103824af31bddf4b7457494" dependencies = [ "cc", "libc", @@ -1566,9 +1602,9 @@ dependencies = [ [[package]] name = "local-waker" -version = "0.1.1" +version = "0.1.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "84f9a2d3e27ce99ce2c3aad0b09b1a7b916293ea9b2bf624c13fe646fadd8da4" +checksum = "902eb695eb0591864543cbfbf6d742510642a605a61fc5e97fe6ceb5a30ac4fb" [[package]] name = "lock_api" @@ -1590,9 +1626,9 @@ dependencies = [ [[package]] name = "logging_timer" -version = "1.0.0" +version = "1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "40d0c249955c17c2f8f86b5f501b16d2509ebbe775f7b1d1d2b1ba85ade2a793" +checksum = "64e96f261d684b7089aa576bb74e823241dccd994b27d30fabf1dcb3af284fe9" dependencies = [ "log", "logging_timer_proc_macros", @@ -1600,14 +1636,14 @@ dependencies = [ [[package]] name = "logging_timer_proc_macros" -version = "1.0.0" +version = "1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "482c2c28e6bcfe7c4274f82f701774d755e6aa873edfd619460fcd0966e0eb07" +checksum = "10a9062912d7952c5588cc474795e0b9ee008e7e6781127945b85413d4b99d81" dependencies = [ "log", - "proc-macro2 0.4.30", - "quote 0.6.13", - "syn 0.15.44", + "proc-macro2 1.0.36", + "quote 1.0.14", + "syn 1.0.86", ] [[package]] @@ -1641,7 +1677,6 @@ dependencies = [ name = "meilisearch-error" version = "0.25.2" dependencies = [ - "actix-http", "actix-web", "proptest", "proptest-derive", @@ -1655,7 +1690,6 @@ version = "0.25.2" dependencies = [ "actix-cors", "actix-rt", - "actix-tls", "actix-web", "actix-web-static-files", "anyhow", @@ -1668,6 +1702,7 @@ dependencies = [ "bytes", "cargo_toml", "chrono", + "clap", "crossbeam-channel", "either", "env_logger", @@ -1697,16 +1732,17 @@ dependencies = [ "rayon", "regex", "reqwest", - "rustls", + "rustls 0.20.2", + "rustls-pemfile", "segment", "serde", "serde_json", "serde_url_params", - "sha-1", + "sha-1 0.9.8", "sha2", "siphasher", "slice-group-by", - "structopt", + "static-files", "sysinfo", "tar", "tempfile", @@ -1727,13 +1763,13 @@ version = "0.25.2" dependencies = [ "actix-rt", "actix-web", - "actix-web-static-files", "anyhow", "async-stream", "async-trait", "byte-unit", "bytes", "chrono", + "clap", "crossbeam-channel", "csv", "derivative", @@ -1767,12 +1803,11 @@ dependencies = [ "rayon", "regex", "reqwest", - "rustls", + "rustls 0.19.1", "serde", "serde_json", "siphasher", "slice-group-by", - "structopt", "sysinfo", "tar", "tempfile", @@ -1807,18 +1842,18 @@ checksum = "308cc39be01b73d0d18f82a0e7b2a3df85245f84af96fdddc5d202d27e47b86a" [[package]] name = "memmap2" -version = "0.5.0" +version = "0.5.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4647a11b578fead29cdbb34d4adef8dd3dc35b876c9c6d5240d83f205abfe96e" +checksum = "fe3179b85e1fd8b14447cbebadb75e45a1002f541b925f0bfec366d56a81c56d" dependencies = [ "libc", ] [[package]] name = "memoffset" -version = "0.6.4" +version = "0.6.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "59accc507f1338036a0477ef61afdae33cde60840f4dfe481319ce3ad116ddf9" +checksum = "5aa361d4faea93603064a027415f07bd8e1d5c88c9fbf68bf56a285428fd79ce" dependencies = [ "autocfg", ] @@ -1912,6 +1947,19 @@ dependencies = [ "winapi", ] +[[package]] +name = "mio" +version = "0.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ba272f85fa0b41fc91872be579b3bbe0f56b792aa361a380eb669469f68dafb2" +dependencies = [ + "libc", + "log", + "miow", + "ntapi", + "winapi", +] + [[package]] name = "miow" version = "0.3.7" @@ -1943,9 +1991,9 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e7e25b214433f669161f414959594216d8e6ba83b6679d3db96899c0b4639033" dependencies = [ "cfg-if 1.0.0", - "proc-macro2 1.0.32", - "quote 1.0.10", - "syn 1.0.82", + "proc-macro2 1.0.36", + "quote 1.0.14", + "syn 1.0.86", ] [[package]] @@ -2011,14 +2059,23 @@ dependencies = [ [[package]] name = "num_cpus" -version = "1.13.0" +version = "1.13.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "05499f3756671c15885fee9034446956fff3f243d6077b91e5767df161f766b3" +checksum = "19e64526ebdee182341572e50e9ad03965aa510cd94427a4549448f285e957a1" dependencies = [ "hermit-abi", "libc", ] +[[package]] +name = "num_threads" +version = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "71a1eb3a36534514077c1e079ada2fb170ef30c47d203aa6916138cf882ecd52" +dependencies = [ + "libc", +] + [[package]] name = "object" version = "0.27.1" @@ -2036,9 +2093,9 @@ checksum = "f69e48cd7c8e5bb52a1da1287fdbfd877c32673176583ce664cd63b201aba385" [[package]] name = "once_cell" -version = "1.8.0" +version = "1.9.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "692fcb63b64b1758029e0a96ee63e049ce8c5948587f2f7208df04625e5f6b56" +checksum = "da32515d9f6e6e489d7bc9d84c71b060db7247dc035bbe44eac88cf87486d8d5" [[package]] name = "opaque-debug" @@ -2048,13 +2105,22 @@ checksum = "624a8340c38c1b80fd549087862da4ba43e08858af025b236e509b6649fc13d5" [[package]] name = "ordered-float" -version = "2.8.0" +version = "2.10.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "97c9d06878b3a851e8026ef94bf7fef9ba93062cd412601da4d9cf369b1cc62d" +checksum = "7940cf2ca942593318d07fcf2596cdca60a85c9e7fab408a5e21a4f9dcd40d87" dependencies = [ "num-traits", ] +[[package]] +name = "os_str_bytes" +version = "6.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8e22443d1643a904602595ba1cd8f7d896afe56d26712531c5ff73a15b2fbf64" +dependencies = [ + "memchr", +] + [[package]] name = "page_size" version = "0.4.2" @@ -2125,9 +2191,9 @@ checksum = "d4fd5641d01c8f18a23da7b6fe29298ff4b55afcccdf78973b24cf3175fee32e" [[package]] name = "phf" -version = "0.10.0" +version = "0.10.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b9fc3db1018c4b59d7d582a739436478b6035138b6aecbce989fc91c3e98409f" +checksum = "fabbf1ead8a5bcbc20f5f8b939ee3f5b0f6f281b6ad3468b84656b658b455259" dependencies = [ "phf_shared", ] @@ -2163,29 +2229,29 @@ dependencies = [ [[package]] name = "pin-project" -version = "1.0.8" +version = "1.0.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "576bc800220cc65dac09e99e97b08b358cfab6e17078de8dc5fee223bd2d0c08" +checksum = "58ad3879ad3baf4e44784bc6a718a8698867bb991f8ce24d1bcbe2cfb4c3a75e" dependencies = [ "pin-project-internal", ] [[package]] name = "pin-project-internal" -version = "1.0.8" +version = "1.0.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6e8fe8163d14ce7f0cdac2e040116f22eac817edabff0be91e8aff7e9accf389" +checksum = "744b6f092ba29c3650faf274db506afd39944f48420f6c86b17cfe0ee1cb36bb" dependencies = [ - "proc-macro2 1.0.32", - "quote 1.0.10", - "syn 1.0.82", + "proc-macro2 1.0.36", + "quote 1.0.14", + "syn 1.0.86", ] [[package]] name = "pin-project-lite" -version = "0.2.7" +version = "0.2.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8d31d11c69a6b52a174b42bdc0c30e5e11670f90788b2c471c31c1d17d449443" +checksum = "e280fbe77cc62c91527259e9442153f4688736748d24660126286329742b4c6c" [[package]] name = "pin-utils" @@ -2195,9 +2261,9 @@ checksum = "8b870d8c151b6f2fb93e84a13146138f05d02ed11c7e7c54f8826aaaf7c9f184" [[package]] name = "pkg-config" -version = "0.3.22" +version = "0.3.24" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "12295df4f294471248581bc09bef3c38a5e46f1e36d6a37353621a0c6c357e1f" +checksum = "58893f751c9b0412871a09abd62ecd2a00298c6c83befa223ef98c52aef40cbe" [[package]] name = "platform-dirs" @@ -2210,9 +2276,9 @@ dependencies = [ [[package]] name = "ppv-lite86" -version = "0.2.15" +version = "0.2.16" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ed0cfbc8191465bed66e1718596ee0b0b35d5ee1f41c5df2189d0fe8bde535ba" +checksum = "eb9f9e6e233e5c4a35559a617bf40a4ec447db2e84c20b55a6f83167b7e57872" [[package]] name = "predicates" @@ -2229,15 +2295,15 @@ dependencies = [ [[package]] name = "predicates-core" -version = "1.0.2" +version = "1.0.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "57e35a3326b75e49aa85f5dc6ec15b41108cf5aee58eabb1f274dd18b73c2451" +checksum = "da1c2388b1513e1b605fcec39a95e0a9e8ef088f71443ef37099fa9ae6673fcb" [[package]] name = "predicates-tree" -version = "1.0.4" +version = "1.0.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "338c7be2905b732ae3984a2f40032b5e94fd8f52505b186c7d4d68d193445df7" +checksum = "4d86de6de25020a36c6d3643a86d9a6a9f552107c0559c60ea03551b5e16c032" dependencies = [ "predicates-core", "termtree", @@ -2250,9 +2316,9 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "da25490ff9892aab3fcf7c36f08cfb902dd3e71ca0f9f9517bea02a73a5ce38c" dependencies = [ "proc-macro-error-attr", - "proc-macro2 1.0.32", - "quote 1.0.10", - "syn 1.0.82", + "proc-macro2 1.0.36", + "quote 1.0.14", + "syn 1.0.86", "version_check", ] @@ -2262,17 +2328,11 @@ version = "1.0.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a1be40180e52ecc98ad80b184934baf3d0d29f979574e439af5a55274b35f869" dependencies = [ - "proc-macro2 1.0.32", - "quote 1.0.10", + "proc-macro2 1.0.36", + "quote 1.0.14", "version_check", ] -[[package]] -name = "proc-macro-hack" -version = "0.5.19" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dbf0c48bc1d91375ae5c3cd81e3722dff1abcf81a30960240640d223f59fe0e5" - [[package]] name = "proc-macro2" version = "0.4.30" @@ -2284,9 +2344,9 @@ dependencies = [ [[package]] name = "proc-macro2" -version = "1.0.32" +version = "1.0.36" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ba508cc11742c0dc5c1659771673afbab7a0efab23aa17e854cbab0837ed0b43" +checksum = "c7342d5883fbccae1cc37a2353b09c87c9b0f3afd73f5fb9bba687a1f733b029" dependencies = [ "unicode-xid 0.2.2", ] @@ -2345,11 +2405,11 @@ dependencies = [ [[package]] name = "quote" -version = "1.0.10" +version = "1.0.14" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "38bc8cc6a5f2e3655e0899c1b848643b2562f853f114bfec7be120678e3ace05" +checksum = "47aa80447ce4daf1717500037052af176af5d38cc3e571d9ec1c7353fc10c87d" dependencies = [ - "proc-macro2 1.0.32", + "proc-macro2 1.0.36", ] [[package]] @@ -2421,7 +2481,7 @@ checksum = "d78120e2c850279833f1dd3582f730c4ab53ed95aeaaaa862a2a5c71b1656d8e" dependencies = [ "crossbeam-channel", "crossbeam-deque", - "crossbeam-utils 0.8.5", + "crossbeam-utils 0.8.6", "lazy_static", "num_cpus", ] @@ -2479,15 +2539,16 @@ dependencies = [ [[package]] name = "reqwest" -version = "0.11.6" +version = "0.11.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "66d2927ca2f685faf0fc620ac4834690d29e7abb153add10f5812eef20b5e280" +checksum = "87f242f1488a539a79bac6dbe7c8609ae43b7914b7736210f239a37cccb32525" dependencies = [ "base64", "bytes", "encoding_rs", "futures-core", "futures-util", + "h2", "http", "http-body", "hyper", @@ -2499,7 +2560,8 @@ dependencies = [ "mime", "percent-encoding", "pin-project-lite", - "rustls", + "rustls 0.20.2", + "rustls-pemfile", "serde", "serde_json", "serde_urlencoded", @@ -2515,9 +2577,9 @@ dependencies = [ [[package]] name = "retain_mut" -version = "0.1.4" +version = "0.1.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "448296241d034b96c11173591deaa1302f2c17b56092106c1f92c1bc0183a8c9" +checksum = "11000e6ba5020e53e7cc26f73b91ae7d5496b4977851479edb66b694c0675c21" [[package]] name = "ring" @@ -2564,22 +2626,13 @@ version = "0.1.21" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7ef03e0a2b150c7a90d01faf6254c9c48a41e95fb2a8c2ac1c6f0d2b9aefc342" -[[package]] -name = "rustc_version" -version = "0.2.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "138e3e0acb6c9fb258b19b67cb8abd63c00679d2851805ea151465464fe9030a" -dependencies = [ - "semver 0.9.0", -] - [[package]] name = "rustc_version" version = "0.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "bfa0f585226d2e68097d4f95d113b15b83a82e819ab25717ec0590d9584ef366" dependencies = [ - "semver 1.0.4", + "semver", ] [[package]] @@ -2591,15 +2644,36 @@ dependencies = [ "base64", "log", "ring", - "sct", - "webpki", + "sct 0.6.1", + "webpki 0.21.4", +] + +[[package]] +name = "rustls" +version = "0.20.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d37e5e2290f3e040b594b1a9e04377c2c671f1a1cfd9bfdef82106ac1c113f84" +dependencies = [ + "log", + "ring", + "sct 0.7.0", + "webpki 0.22.0", +] + +[[package]] +name = "rustls-pemfile" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5eebeaeb360c87bfb72e84abdb3447159c0eaececf1bef2aecd65a8be949d1c9" +dependencies = [ + "base64", ] [[package]] name = "rustversion" -version = "1.0.5" +version = "1.0.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "61b3909d758bb75c79f23d4736fac9433868679d3ad2ea7a61e3c25cfda9a088" +checksum = "f2cc38e8fa666e2de3c4aba7edeb5ffc5246c1c2ed0e3d17e560aeeba736b23f" [[package]] name = "rusty-fork" @@ -2615,9 +2689,9 @@ dependencies = [ [[package]] name = "ryu" -version = "1.0.6" +version = "1.0.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3c9613b5a66ab9ba26415184cfc41156594925a9cf3a2057e57f31ff145f6568" +checksum = "73b4b750c782965c211b42f022f59af1fbceabdd026623714f104152f1ec149f" [[package]] name = "same-file" @@ -2644,6 +2718,16 @@ dependencies = [ "untrusted", ] +[[package]] +name = "sct" +version = "0.7.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d53dcdb7c9f8158937a7981b48accfd39a43af418591a5d008c7b22b5e1b7ca4" +dependencies = [ + "ring", + "untrusted", +] + [[package]] name = "segment" version = "0.1.2" @@ -2658,55 +2742,40 @@ dependencies = [ "thiserror", ] -[[package]] -name = "semver" -version = "0.9.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1d7eb9ef2c18661902cc47e535f9bc51b78acd254da71d375c2f6720d9a40403" -dependencies = [ - "semver-parser", -] - [[package]] name = "semver" version = "1.0.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "568a8e6258aa33c13358f81fd834adb854c6f7c9468520910a9b1e8fac068012" -[[package]] -name = "semver-parser" -version = "0.7.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "388a1df253eca08550bef6c72392cfe7c30914bf41df5269b68cbd6ff8f570a3" - [[package]] name = "serde" -version = "1.0.130" +version = "1.0.134" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f12d06de37cf59146fbdecab66aa99f9fe4f78722e3607577a5375d66bd0c913" +checksum = "96b3c34c1690edf8174f5b289a336ab03f568a4460d8c6df75f2f3a692b3bc6a" dependencies = [ "serde_derive", ] [[package]] name = "serde_derive" -version = "1.0.130" +version = "1.0.134" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d7bc1a1ab1961464eae040d96713baa5a724a8152c1222492465b54322ec508b" +checksum = "784ed1fbfa13fe191077537b0d70ec8ad1e903cfe04831da608aa36457cb653d" dependencies = [ - "proc-macro2 1.0.32", - "quote 1.0.10", - "syn 1.0.82", + "proc-macro2 1.0.36", + "quote 1.0.14", + "syn 1.0.86", ] [[package]] name = "serde_json" -version = "1.0.72" +version = "1.0.75" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d0ffa0837f2dfa6fb90868c2b5468cad482e175f7dad97e7421951e663f2b527" +checksum = "c059c05b48c5c0067d4b4b2b4f0732dd65feb52daf7e0ea09cd87e7dadc1af79" dependencies = [ "indexmap", - "itoa", + "itoa 1.0.1", "ryu", "serde", ] @@ -2723,12 +2792,12 @@ dependencies = [ [[package]] name = "serde_urlencoded" -version = "0.7.0" +version = "0.7.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "edfa57a7f8d9c1d260a549e7224100f6c43d43f9103e06dd8b4095a9b2b43ce9" +checksum = "d3491c14715ca2294c4d6a88f15e84739788c1d030eed8c110436aafdaa2f3fd" dependencies = [ "form_urlencoded", - "itoa", + "itoa 1.0.1", "ryu", "serde", ] @@ -2739,29 +2808,34 @@ version = "0.9.8" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "99cd6713db3cf16b6c84e06321e049a9b9f699826e16096d23bbcc44d15d51a6" dependencies = [ - "block-buffer", + "block-buffer 0.9.0", "cfg-if 1.0.0", "cpufeatures", - "digest", + "digest 0.9.0", "opaque-debug", ] [[package]] -name = "sha1" -version = "0.6.0" +name = "sha-1" +version = "0.10.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2579985fda508104f7587689507983eadd6a6e84dd35d6d115361f530916fa0d" +checksum = "028f48d513f9678cda28f6e4064755b3fbb2af6acd672f2c209b62323f7aea0f" +dependencies = [ + "cfg-if 1.0.0", + "cpufeatures", + "digest 0.10.1", +] [[package]] name = "sha2" -version = "0.9.8" +version = "0.9.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b69f9a4c9740d74c5baa3fd2e547f9525fa8088a8a958e0ca2409a514e33f5fa" +checksum = "4d58a1e1bf39749807d89cf2d98ac2dfa0ff1cb3faa38fbb64dd88ac8013d800" dependencies = [ - "block-buffer", + "block-buffer 0.9.0", "cfg-if 1.0.0", "cpufeatures", - "digest", + "digest 0.9.0", "opaque-debug", ] @@ -2776,9 +2850,9 @@ dependencies = [ [[package]] name = "siphasher" -version = "0.3.7" +version = "0.3.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "533494a8f9b724d33625ab53c6c4800f7cc445895924a8ef649222dcb76e938b" +checksum = "a86232ab60fa71287d7f2ddae4a7073f6b7aac33631c3015abb556f08c6d0a3e" [[package]] name = "slab" @@ -2804,15 +2878,15 @@ dependencies = [ [[package]] name = "smallvec" -version = "1.7.0" +version = "1.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1ecab6c735a6bb4139c0caafd0cc3635748bbb3acf4550e8138122099251f309" +checksum = "f2dd574626839106c320a323308629dcb1acfc96e32a8cba364ddc61ac23ee83" [[package]] name = "socket2" -version = "0.4.2" +version = "0.4.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5dc90fe6c7be1a323296982db1836d1ea9e47b6839496dde9a541bc496df3516" +checksum = "0f82496b90c36d70af5fcd482edaa2e0bd16fade569de1330405fecbbdac736b" dependencies = [ "libc", "winapi", @@ -2831,92 +2905,21 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a8f112729512f8e442d81f95a8a7ddf2b7c6b8a1a6f509a95864142b30cab2d3" [[package]] -name = "standback" -version = "0.2.17" +name = "static-files" +version = "0.2.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e113fb6f3de07a243d434a56ec6f186dfd51cb08448239fe7bcae73f87ff28ff" +checksum = "64712ea1e3e140010e1d9605872ba205afa2ab5bd38191cc6ebd248ae1f6a06b" dependencies = [ - "version_check", + "change-detection", + "mime_guess", + "path-slash", ] -[[package]] -name = "stdweb" -version = "0.4.20" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d022496b16281348b52d0e30ae99e01a73d737b2f45d38fed4edf79f9325a1d5" -dependencies = [ - "discard", - "rustc_version 0.2.3", - "stdweb-derive", - "stdweb-internal-macros", - "stdweb-internal-runtime", - "wasm-bindgen", -] - -[[package]] -name = "stdweb-derive" -version = "0.5.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c87a60a40fccc84bef0652345bbbbbe20a605bf5d0ce81719fc476f5c03b50ef" -dependencies = [ - "proc-macro2 1.0.32", - "quote 1.0.10", - "serde", - "serde_derive", - "syn 1.0.82", -] - -[[package]] -name = "stdweb-internal-macros" -version = "0.2.9" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "58fa5ff6ad0d98d1ffa8cb115892b6e69d67799f6763e162a1c9db421dc22e11" -dependencies = [ - "base-x", - "proc-macro2 1.0.32", - "quote 1.0.10", - "serde", - "serde_derive", - "serde_json", - "sha1", - "syn 1.0.82", -] - -[[package]] -name = "stdweb-internal-runtime" -version = "0.1.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "213701ba3370744dcd1a12960caa4843b3d68b4d1c0a5d575e0d65b2ee9d16c0" - [[package]] name = "strsim" -version = "0.8.0" +version = "0.10.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8ea5119cdb4c55b55d432abb513a0429384878c15dde60cc77b1c99de1a95a6a" - -[[package]] -name = "structopt" -version = "0.3.25" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "40b9788f4202aa75c240ecc9c15c65185e6a39ccdeb0fd5d008b98825464c87c" -dependencies = [ - "clap", - "lazy_static", - "structopt-derive", -] - -[[package]] -name = "structopt-derive" -version = "0.4.18" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dcb5ae327f9cc13b68763b5749770cb9e048a99bd9dfdfa58d0cf05d5f64afe0" -dependencies = [ - "heck", - "proc-macro-error", - "proc-macro2 1.0.32", - "quote 1.0.10", - "syn 1.0.82", -] +checksum = "73473c0e59e6d5812c5dfe2a064a6444949f089e20eec9a2e5506596494e4623" [[package]] name = "syn" @@ -2931,12 +2934,12 @@ dependencies = [ [[package]] name = "syn" -version = "1.0.82" +version = "1.0.86" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8daf5dd0bb60cbd4137b1b587d2fc0ae729bc07cf01cd70b36a1ed5ade3b9d59" +checksum = "8a65b3f4ffa0092e9887669db0eae07941f023991ab58ea44da8fe8e2d511c6b" dependencies = [ - "proc-macro2 1.0.32", - "quote 1.0.10", + "proc-macro2 1.0.36", + "quote 1.0.14", "unicode-xid 0.2.2", ] @@ -2955,9 +2958,9 @@ version = "0.12.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f36bdaa60a83aca3921b5259d5400cbf5e90fc51931376a9bd4a0eb79aa7210f" dependencies = [ - "proc-macro2 1.0.32", - "quote 1.0.10", - "syn 1.0.82", + "proc-macro2 1.0.36", + "quote 1.0.14", + "syn 1.0.86", "unicode-xid 0.2.2", ] @@ -2978,9 +2981,9 @@ dependencies = [ [[package]] name = "tar" -version = "0.4.37" +version = "0.4.38" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d6f5515d3add52e0bbdcad7b83c388bb36ba7b754dda3b5f5bc2d38640cdba5c" +checksum = "4b55807c0344e1e6c04d7c965f5289c39a8d94ae23ed5c0b57aabac549f871c6" dependencies = [ "filetime", "libc", @@ -2989,13 +2992,13 @@ dependencies = [ [[package]] name = "tempfile" -version = "3.2.0" +version = "3.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dac1c663cfc93810f88aed9b8941d48cabf856a1b111c29a40439018d870eb22" +checksum = "5cdb1ef4eaeeaddc8fbd371e5017057064af0911902ef36b39801f67cc6d79e4" dependencies = [ "cfg-if 1.0.0", + "fastrand", "libc", - "rand", "redox_syscall", "remove_dir_all", "winapi", @@ -3012,18 +3015,15 @@ dependencies = [ [[package]] name = "termtree" -version = "0.2.3" +version = "0.2.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "13a4ec180a2de59b57434704ccfad967f789b12737738798fa08798cd5824c16" +checksum = "507e9898683b6c43a9aa55b64259b721b52ba226e0f3779137e50ad114a4c90b" [[package]] name = "textwrap" -version = "0.11.0" +version = "0.14.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d326610f408c7a4eb6f51c37c330e496b08506c9457c9d34287ecc38809fb060" -dependencies = [ - "unicode-width", -] +checksum = "0066c8d12af8b5acd21e00547c3797fde4e8677254a7ee429176ccebbe93dd80" [[package]] name = "thiserror" @@ -3040,9 +3040,9 @@ version = "1.0.30" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "aa32fd3f627f367fe16f893e2597ae3c05020f8bba2666a4e6ea73d377e5714b" dependencies = [ - "proc-macro2 1.0.32", - "quote 1.0.10", - "syn 1.0.82", + "proc-macro2 1.0.36", + "quote 1.0.14", + "syn 1.0.86", ] [[package]] @@ -3079,41 +3079,21 @@ dependencies = [ [[package]] name = "time" -version = "0.2.27" +version = "0.3.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4752a97f8eebd6854ff91f1c1824cd6160626ac4bd44287f7f4ea2035a02a242" +checksum = "c8d54b9298e05179c335de2b9645d061255bcd5155f843b3e328d2cfe0a5b413" dependencies = [ - "const_fn", + "itoa 1.0.1", "libc", - "standback", - "stdweb", + "num_threads", "time-macros", - "version_check", - "winapi", ] [[package]] name = "time-macros" -version = "0.1.1" +version = "0.2.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "957e9c6e26f12cb6d0dd7fc776bb67a706312e7299aed74c8dd5b17ebb27e2f1" -dependencies = [ - "proc-macro-hack", - "time-macros-impl", -] - -[[package]] -name = "time-macros-impl" -version = "0.1.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fd3c141a1b43194f3f56a1411225df8646c55781d5f26db825b3d98507eb482f" -dependencies = [ - "proc-macro-hack", - "proc-macro2 1.0.32", - "quote 1.0.10", - "standback", - "syn 1.0.82", -] +checksum = "25eb0ca3468fc0acc11828786797f6ef9aa1555e4a211a60d64cc8e4d1be47d6" [[package]] name = "tinyvec" @@ -3132,15 +3112,14 @@ checksum = "cda74da7e1a664f795bb1f8a87ec406fb89a02522cf6e50620d016add6dbbf5c" [[package]] name = "tokio" -version = "1.14.0" +version = "1.15.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "70e992e41e0d2fb9f755b37446f20900f64446ef54874f40a60c78f021ac6144" +checksum = "fbbf1c778ec206785635ce8ad57fe52b3009ae9e0c9f574a728f3049d3e55838" dependencies = [ - "autocfg", "bytes", "libc", "memchr", - "mio", + "mio 0.7.14", "num_cpus", "once_cell", "parking_lot", @@ -3152,24 +3131,24 @@ dependencies = [ [[package]] name = "tokio-macros" -version = "1.6.0" +version = "1.7.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c9efc1aba077437943f7515666aa2b882dfabfbfdf89c819ea75a8d6e9eaba5e" +checksum = "b557f72f448c511a979e2564e55d74e6c4432fc96ff4f6241bc6bded342643b7" dependencies = [ - "proc-macro2 1.0.32", - "quote 1.0.10", - "syn 1.0.82", + "proc-macro2 1.0.36", + "quote 1.0.14", + "syn 1.0.86", ] [[package]] name = "tokio-rustls" -version = "0.22.0" +version = "0.23.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bc6844de72e57df1980054b38be3a9f4702aba4858be64dd700181a8a6d0e1b6" +checksum = "a27d5f2b839802bd8267fa19b0530f5a08b9c08cd417976be2a65d130fe1c11b" dependencies = [ - "rustls", + "rustls 0.20.2", "tokio", - "webpki", + "webpki 0.22.0", ] [[package]] @@ -3240,9 +3219,9 @@ checksum = "59547bce71d9c38b83d9c0e92b6066c4253371f15005def0c30d9657f50c7642" [[package]] name = "typenum" -version = "1.14.0" +version = "1.15.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b63708a265f51345575b27fe43f9500ad611579e764c79edbc2037b1121959ec" +checksum = "dcf81ac59edc17cc8697ff311e8f5ef2d99fcbd9817b34cec66f90b6c3dfd987" [[package]] name = "unicase" @@ -3274,12 +3253,6 @@ version = "1.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8895849a949e7845e06bd6dc1aa51731a103c42707010a5b591c0038fb73385b" -[[package]] -name = "unicode-width" -version = "0.1.9" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3ed742d4ea2bd1176e236172c8429aaf54486e7ac098db29ffe6529e0ce50973" - [[package]] name = "unicode-xid" version = "0.1.0" @@ -3338,17 +3311,11 @@ version = "0.2.15" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "accd4ea62f7bb7a82fe23066fb0957d48ef677f6eeb8215f372f52e48bb32426" -[[package]] -name = "vec_map" -version = "0.8.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f1bddf1187be692e79c5ffeab891132dfb0f236ed36a43c7ed39f1165ee20191" - [[package]] name = "vergen" -version = "5.1.18" +version = "5.1.17" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1d48696c0fbbdafd9553e14c4584b4b9583931e9474a3ae506f1872b890d0b47" +checksum = "6cf88d94e969e7956d924ba70741316796177fa0c79a2c9f4ab04998d96e966e" dependencies = [ "anyhow", "cfg-if 1.0.0", @@ -3362,9 +3329,9 @@ dependencies = [ [[package]] name = "version_check" -version = "0.9.3" +version = "0.9.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5fecdca9a5291cc2b8dcf7dc02453fee791a280f3743cb0905f8822ae463b3fe" +checksum = "49874b5167b65d7193b8aba1567f5c7d93d001cafc34600cee003eda787e483f" [[package]] name = "wait-timeout" @@ -3404,9 +3371,9 @@ checksum = "1a143597ca7c7793eff794def352d41792a93c481eb1042423ff7ff72ba2c31f" [[package]] name = "wasm-bindgen" -version = "0.2.78" +version = "0.2.79" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "632f73e236b219150ea279196e54e610f5dbafa5d61786303d4da54f84e47fce" +checksum = "25f1af7423d8588a3d840681122e72e6a24ddbcb3f0ec385cac0d12d24256c06" dependencies = [ "cfg-if 1.0.0", "wasm-bindgen-macro", @@ -3414,24 +3381,24 @@ dependencies = [ [[package]] name = "wasm-bindgen-backend" -version = "0.2.78" +version = "0.2.79" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a317bf8f9fba2476b4b2c85ef4c4af8ff39c3c7f0cdfeed4f82c34a880aa837b" +checksum = "8b21c0df030f5a177f3cba22e9bc4322695ec43e7257d865302900290bcdedca" dependencies = [ "bumpalo", "lazy_static", "log", - "proc-macro2 1.0.32", - "quote 1.0.10", - "syn 1.0.82", + "proc-macro2 1.0.36", + "quote 1.0.14", + "syn 1.0.86", "wasm-bindgen-shared", ] [[package]] name = "wasm-bindgen-futures" -version = "0.4.28" +version = "0.4.29" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8e8d7523cb1f2a4c96c1317ca690031b714a51cc14e05f712446691f413f5d39" +checksum = "2eb6ec270a31b1d3c7e266b999739109abce8b6c87e4b31fcfcd788b65267395" dependencies = [ "cfg-if 1.0.0", "js-sys", @@ -3441,38 +3408,38 @@ dependencies = [ [[package]] name = "wasm-bindgen-macro" -version = "0.2.78" +version = "0.2.79" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d56146e7c495528bf6587663bea13a8eb588d39b36b679d83972e1a2dbbdacf9" +checksum = "2f4203d69e40a52ee523b2529a773d5ffc1dc0071801c87b3d270b471b80ed01" dependencies = [ - "quote 1.0.10", + "quote 1.0.14", "wasm-bindgen-macro-support", ] [[package]] name = "wasm-bindgen-macro-support" -version = "0.2.78" +version = "0.2.79" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7803e0eea25835f8abdc585cd3021b3deb11543c6fe226dcd30b228857c5c5ab" +checksum = "bfa8a30d46208db204854cadbb5d4baf5fcf8071ba5bf48190c3e59937962ebc" dependencies = [ - "proc-macro2 1.0.32", - "quote 1.0.10", - "syn 1.0.82", + "proc-macro2 1.0.36", + "quote 1.0.14", + "syn 1.0.86", "wasm-bindgen-backend", "wasm-bindgen-shared", ] [[package]] name = "wasm-bindgen-shared" -version = "0.2.78" +version = "0.2.79" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0237232789cf037d5480773fe568aac745bfe2afbc11a863e97901780a6b47cc" +checksum = "3d958d035c4438e28c70e4321a2911302f10135ce78a9c7834c0cab4123d06a2" [[package]] name = "web-sys" -version = "0.3.55" +version = "0.3.56" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "38eb105f1c59d9eaa6b5cdc92b859d85b926e82cb2e0945cd0c9259faa6fe9fb" +checksum = "c060b319f29dd25724f09a2ba1418f142f539b2be99fbf4d2d5a8f7330afb8eb" dependencies = [ "js-sys", "wasm-bindgen", @@ -3489,12 +3456,22 @@ dependencies = [ ] [[package]] -name = "webpki-roots" -version = "0.21.1" +name = "webpki" +version = "0.22.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "aabe153544e473b775453675851ecc86863d2a81d786d741f6b76778f2a48940" +checksum = "f095d78192e208183081cc07bc5515ef55216397af48b873e5edcd72637fa1bd" dependencies = [ - "webpki", + "ring", + "untrusted", +] + +[[package]] +name = "webpki-roots" +version = "0.22.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "552ceb903e957524388c4d3475725ff2c8b7960922063af6ce53c9a43da07449" +dependencies = [ + "webpki 0.22.0", ] [[package]] @@ -3581,8 +3558,8 @@ version = "0.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d498dbd1fd7beb83c86709ae1c33ca50942889473473d287d56ce4770a18edfb" dependencies = [ - "proc-macro2 1.0.32", - "syn 1.0.82", + "proc-macro2 1.0.36", + "syn 1.0.86", "synstructure", ] @@ -3602,18 +3579,18 @@ dependencies = [ [[package]] name = "zstd" -version = "0.7.0+zstd.1.4.9" +version = "0.9.3+zstd.1.5.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9428752481d8372e15b1bf779ea518a179ad6c771cca2d2c60e4fbff3cc2cd52" +checksum = "377f9c6801b6cbb254c3055266be42698b5bc6563c56b37e5fcca637a68eba95" dependencies = [ "zstd-safe", ] [[package]] name = "zstd-safe" -version = "3.1.0+zstd.1.4.9" +version = "4.1.4+zstd.1.5.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5aa1926623ad7fe406e090555387daf73db555b948134b4d73eac5eb08fb666d" +checksum = "2f7cd17c9af1a4d6c24beb1cc54b17e2ef7b593dc92f19e9d9acad8b182bbaee" dependencies = [ "libc", "zstd-sys", @@ -3621,9 +3598,9 @@ dependencies = [ [[package]] name = "zstd-sys" -version = "1.5.0+zstd.1.4.9" +version = "1.6.3+zstd.1.5.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4e6c094340240369025fc6b731b054ee2a834328fa584310ac96aa4baebdc465" +checksum = "fc49afa5c8d634e75761feda8c592051e7eeb4683ba827211eb0d731d3402ea8" dependencies = [ "cc", "libc", diff --git a/Cargo.toml b/Cargo.toml index 5e68244d5..65fa6fe13 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -5,5 +5,3 @@ members = [ "meilisearch-lib", "meilisearch-auth", ] - -resolver = "2" diff --git a/README.md b/README.md index 31f8c773b..9efb5a937 100644 --- a/README.md +++ b/README.md @@ -1,8 +1,8 @@

- MeiliSearch + Meilisearch

-

MeiliSearch

+

Meilisearch

Website | @@ -15,17 +15,17 @@

- Build Status - Dependency status - License - Slack - + Build Status + Dependency status + License + Slack + Bors enabled

⚡ Lightning Fast, Ultra Relevant, and Typo-Tolerant Search Engine 🔍

-**MeiliSearch** is a powerful, fast, open-source, easy to use and deploy search engine. Both searching and indexing are highly customizable. Features such as typo-tolerance, filters, and synonyms are provided out-of-the-box. +**Meilisearch** is a powerful, fast, open-source, easy to use and deploy search engine. Both searching and indexing are highly customizable. Features such as typo-tolerance, filters, and synonyms are provided out-of-the-box. For more information about features go to [our documentation](https://docs.meilisearch.com/).

@@ -61,13 +61,13 @@ meilisearch docker run -p 7700:7700 -v "$(pwd)/data.ms:/data.ms" getmeili/meilisearch ``` -#### Announcing a cloud-hosted MeiliSearch +#### Announcing a cloud-hosted Meilisearch Join the closed beta by filling out this [form](https://meilisearch.typeform.com/to/FtnzvZfh). -#### Try MeiliSearch in our Sandbox +#### Try Meilisearch in our Sandbox -Create a MeiliSearch instance in [MeiliSearch Sandbox](https://sandbox.meilisearch.com/). This instance is free, and will be active for 48 hours. +Create a Meilisearch instance in [Meilisearch Sandbox](https://sandbox.meilisearch.com/). This instance is free, and will be active for 48 hours. #### Run on Digital Ocean @@ -99,8 +99,8 @@ curl -L https://install.meilisearch.com | sh If you have the latest stable Rust toolchain installed on your local system, clone the repository and change it to your working directory. ```bash -git clone https://github.com/meilisearch/MeiliSearch.git -cd MeiliSearch +git clone https://github.com/meilisearch/meilisearch.git +cd meilisearch cargo run --release ``` @@ -161,19 +161,19 @@ curl 'http://127.0.0.1:7700/indexes/movies/search?q=botman+robin&limit=2' | jq #### Use the Web Interface -We also deliver an **out-of-the-box [web interface](https://github.com/meilisearch/mini-dashboard)** in which you can test MeiliSearch interactively. +We also deliver an **out-of-the-box [web interface](https://github.com/meilisearch/mini-dashboard)** in which you can test Meilisearch interactively. -You can access the web interface in your web browser at the root of the server. The default URL is [http://127.0.0.1:7700](http://127.0.0.1:7700). All you need to do is open your web browser and enter MeiliSearch’s address to visit it. This will lead you to a web page with a search bar that will allow you to search in the selected index. +You can access the web interface in your web browser at the root of the server. The default URL is [http://127.0.0.1:7700](http://127.0.0.1:7700). All you need to do is open your web browser and enter Meilisearch’s address to visit it. This will lead you to a web page with a search bar that will allow you to search in the selected index. | [See the gif above](#demo) ## Documentation -Now that your MeiliSearch server is up and running, you can learn more about how to tune your search engine in [the documentation](https://docs.meilisearch.com). +Now that your Meilisearch server is up and running, you can learn more about how to tune your search engine in [the documentation](https://docs.meilisearch.com). ## Contributing -Hey! We're glad you're thinking about contributing to MeiliSearch! Feel free to pick an [issue labeled as `good first issue`](https://github.com/meilisearch/MeiliSearch/issues?q=is%3Aissue+is%3Aopen+label%3A%22good+first+issue%22), and to ask any question you need. Some points might not be clear and we are available to help you! +Hey! We're glad you're thinking about contributing to Meilisearch! Feel free to pick an [issue labeled as `good first issue`](https://github.com/meilisearch/meilisearch/issues?q=is%3Aissue+is%3Aopen+label%3A%22good+first+issue%22), and to ask any question you need. Some points might not be clear and we are available to help you! Also, we recommend following the [CONTRIBUTING](./CONTRIBUTING.md) to create your PR. @@ -184,8 +184,8 @@ The code in this repository is only concerned with managing multiple indexes, ha Search and indexation are the domain of our core engine, [`milli`](https://github.com/meilisearch/milli), while tokenization is handled by [our `tokenizer` library](https://github.com/meilisearch/tokenizer/). ## Telemetry -MeiliSearch collects anonymous data regarding general usage. -This helps us better understand developers' usage of MeiliSearch features. +Meilisearch collects anonymous data regarding general usage. +This helps us better understand developers' usage of Meilisearch features. To find out more on what information we're retrieving, please see our documentation on [Telemetry](https://docs.meilisearch.com/learn/what_is_meilisearch/telemetry.html). @@ -193,7 +193,7 @@ This program is optional, you can disable these analytics by using the `MEILI_NO ## Feature request -The feature requests are not managed in this repository. Please visit our [dedicated repository](https://github.com/meilisearch/product) to see our work about the MeiliSearch product. +The feature requests are not managed in this repository. Please visit our [dedicated repository](https://github.com/meilisearch/product) to see our work about the Meilisearch product. If you have a feature request or any feedback about an existing feature, please open [a discussion](https://github.com/meilisearch/product/discussions). Also, feel free to participate in the current discussions, we are looking forward to reading your comments. @@ -202,4 +202,4 @@ Also, feel free to participate in the current discussions, we are looking forwar Please visit [this page](https://docs.meilisearch.com/learn/what_is_meilisearch/contact.html#contact-us). -MeiliSearch is developed by [Meili](https://www.meilisearch.com), a young company. To know more about us, you can [read our blog](https://blog.meilisearch.com). Any suggestion or feedback is highly appreciated. Thank you for your support! +Meilisearch is developed by [Meili](https://www.meilisearch.com), a young company. To know more about us, you can [read our blog](https://blog.meilisearch.com). Any suggestion or feedback is highly appreciated. Thank you for your support! diff --git a/SECURITY.md b/SECURITY.md index 28775c485..63bc15a40 100644 --- a/SECURITY.md +++ b/SECURITY.md @@ -1,16 +1,16 @@ # Security -MeiliSearch takes the security of our software products and services seriously. +Meilisearch takes the security of our software products and services seriously. -If you believe you have found a security vulnerability in any MeiliSearch-owned repository, please report it to us as described below. +If you believe you have found a security vulnerability in any Meilisearch-owned repository, please report it to us as described below. ## Suported versions -As long as we are pre-v1.0, only the latest version of MeiliSearch will be supported with security updates. +As long as we are pre-v1.0, only the latest version of Meilisearch will be supported with security updates. ## Reporting security issues -⚠️ Please do not report security vulnerabilities through public GitHub issues. ⚠️ +⚠️ Please do not report security vulnerabilities through public GitHub issues. ⚠️ Instead, please kindly email us at security@meilisearch.com diff --git a/assets/logo.svg b/assets/logo.svg index e61b86003..a11654929 100644 --- a/assets/logo.svg +++ b/assets/logo.svg @@ -1,17 +1,19 @@ - - - - - - + + + + - - - + + + - - - + + + + + + + diff --git a/download-latest.sh b/download-latest.sh index 5001103e6..4e88c1828 100644 --- a/download-latest.sh +++ b/download-latest.sh @@ -74,9 +74,9 @@ get_latest() { temp_file='temp_file' # temp_file needed because the grep would start before the download is over if [ -z "$GITHUB_PAT" ]; then - curl -s 'https://api.github.com/repos/meilisearch/MeiliSearch/releases' > "$temp_file" || return 1 + curl -s 'https://api.github.com/repos/meilisearch/meilisearch/releases' > "$temp_file" || return 1 else - curl -H "Authorization: token $GITHUB_PAT" -s 'https://api.github.com/repos/meilisearch/MeiliSearch/releases' > "$temp_file" || return 1 + curl -H "Authorization: token $GITHUB_PAT" -s 'https://api.github.com/repos/meilisearch/meilisearch/releases' > "$temp_file" || return 1 fi releases=$(cat "$temp_file" | \ @@ -161,7 +161,7 @@ get_archi() { } success_usage() { - printf "$GREEN%s\n$DEFAULT" "MeiliSearch $latest binary successfully downloaded as '$binary_name' file." + printf "$GREEN%s\n$DEFAULT" "Meilisearch $latest binary successfully downloaded as '$binary_name' file." echo '' echo 'Run it:' echo ' $ ./meilisearch' @@ -170,7 +170,7 @@ success_usage() { } failure_usage() { - printf "$RED%s\n$DEFAULT" 'ERROR: MeiliSearch binary is not available for your OS distribution or your architecture yet.' + printf "$RED%s\n$DEFAULT" 'ERROR: Meilisearch binary is not available for your OS distribution or your architecture yet.' echo '' echo 'However, you can easily compile the binary from the source files.' echo 'Follow the steps at the page ("Source" tab): https://docs.meilisearch.com/learn/getting_started/installation.html' @@ -181,8 +181,8 @@ latest="$(get_latest)" if [ "$latest" = '' ]; then echo '' - echo 'Impossible to get the latest stable version of MeiliSearch.' - echo 'Please let us know about this issue: https://github.com/meilisearch/MeiliSearch/issues/new/choose' + echo 'Impossible to get the latest stable version of Meilisearch.' + echo 'Please let us know about this issue: https://github.com/meilisearch/meilisearch/issues/new/choose' exit 1 fi @@ -196,7 +196,7 @@ if ! get_archi; then exit 1 fi -echo "Downloading MeiliSearch binary $latest for $os, architecture $archi..." +echo "Downloading Meilisearch binary $latest for $os, architecture $archi..." case "$os" in 'windows') release_file="meilisearch-$os-$archi.exe" @@ -208,7 +208,7 @@ case "$os" in binary_name='meilisearch' esac -link="https://github.com/meilisearch/MeiliSearch/releases/download/$latest/$release_file" +link="https://github.com/meilisearch/meilisearch/releases/download/$latest/$release_file" curl -OL "$link" mv "$release_file" "$binary_name" chmod 744 "$binary_name" diff --git a/meilisearch-auth/Cargo.toml b/meilisearch-auth/Cargo.toml index 84a11360b..3b5379d8f 100644 --- a/meilisearch-auth/Cargo.toml +++ b/meilisearch-auth/Cargo.toml @@ -1,7 +1,7 @@ [package] name = "meilisearch-auth" version = "0.25.0" -edition = "2018" +edition = "2021" [dependencies] enum-iterator = "0.7.0" diff --git a/meilisearch-auth/src/store.rs b/meilisearch-auth/src/store.rs index e1501af30..061b4add3 100644 --- a/meilisearch-auth/src/store.rs +++ b/meilisearch-auth/src/store.rs @@ -6,6 +6,7 @@ use std::convert::TryInto; use std::fs::create_dir_all; use std::path::Path; use std::str; +use std::sync::Arc; use chrono::{DateTime, Utc}; use heed::types::{ByteSlice, DecodeIgnore, SerdeJson}; @@ -24,11 +25,19 @@ pub type KeyId = [u8; KEY_ID_LENGTH]; #[derive(Clone)] pub struct HeedAuthStore { - env: Env, + env: Arc, keys: Database>, action_keyid_index_expiration: Database>>>, } +impl Drop for HeedAuthStore { + fn drop(&mut self) { + if Arc::strong_count(&self.env) == 1 { + self.env.as_ref().clone().prepare_for_closing(); + } + } +} + impl HeedAuthStore { pub fn new(path: impl AsRef) -> Result { let path = path.as_ref().join(AUTH_DB_PATH); @@ -36,7 +45,7 @@ impl HeedAuthStore { let mut options = EnvOpenOptions::new(); options.map_size(AUTH_STORE_SIZE); // 1GB options.max_dbs(2); - let env = options.open(path)?; + let env = Arc::new(options.open(path)?); let keys = env.create_database(Some(KEY_DB_NAME))?; let action_keyid_index_expiration = env.create_database(Some(KEY_ID_ACTION_INDEX_EXPIRATION_DB_NAME))?; diff --git a/meilisearch-error/Cargo.toml b/meilisearch-error/Cargo.toml index 981aab747..ed2d82baf 100644 --- a/meilisearch-error/Cargo.toml +++ b/meilisearch-error/Cargo.toml @@ -2,11 +2,10 @@ name = "meilisearch-error" version = "0.25.2" authors = ["marin "] -edition = "2018" +edition = "2021" [dependencies] -actix-http = "=3.0.0-beta.10" -actix-web = "4.0.0-beta.9" +actix-web = { version = "4.0.0-beta.21", 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"] } diff --git a/meilisearch-error/src/lib.rs b/meilisearch-error/src/lib.rs index 609851305..81371eb6d 100644 --- a/meilisearch-error/src/lib.rs +++ b/meilisearch-error/src/lib.rs @@ -1,7 +1,6 @@ use std::fmt; -use actix_http::{body::Body, http::StatusCode}; -use actix_web::{self as aweb, HttpResponseBuilder}; +use actix_web::{self as aweb, http::StatusCode, HttpResponseBuilder}; use serde::{Deserialize, Serialize}; #[derive(Debug, Serialize, Deserialize, Clone, PartialEq, Eq)] @@ -59,7 +58,7 @@ where } impl aweb::error::ResponseError for ResponseError { - fn error_response(&self) -> aweb::HttpResponse { + fn error_response(&self) -> aweb::HttpResponse { let json = serde_json::to_vec(self).unwrap(); HttpResponseBuilder::new(self.status_code()) .content_type("application/json") diff --git a/meilisearch-http/Cargo.toml b/meilisearch-http/Cargo.toml index 64766bcc5..025c05aec 100644 --- a/meilisearch-http/Cargo.toml +++ b/meilisearch-http/Cargo.toml @@ -1,7 +1,7 @@ [package] authors = ["Quentin de Quelen ", "Clément Renault "] -description = "MeiliSearch HTTP server" -edition = "2018" +description = "Meilisearch HTTP server" +edition = "2021" license = "MIT" name = "meilisearch-http" version = "0.25.2" @@ -11,7 +11,7 @@ name = "meilisearch" path = "src/main.rs" [build-dependencies] -actix-web-static-files = { git = "https://github.com/MarinPostma/actix-web-static-files.git", rev = "39d8006", optional = true } +static-files = { version = "0.2.1", optional = true } anyhow = { version = "1.0.43", optional = true } cargo_toml = { version = "0.9", optional = true } hex = { version = "0.4.3", optional = true } @@ -22,17 +22,15 @@ vergen = { version = "5.1.15", default-features = false, features = ["git"] } zip = { version = "0.5.13", optional = true } [dependencies] -actix-cors = { git = "https://github.com/MarinPostma/actix-extras.git", rev = "963ac94d" } -actix-web = { version = "4.0.0-beta.9", features = ["rustls"] } -actix-web-static-files = { git = "https://github.com/MarinPostma/actix-web-static-files.git", rev = "39d8006", optional = true } -# TODO: specifying this dependency so semver doesn't bump to next beta -actix-tls = "=3.0.0-beta.5" +actix-cors = "0.6.0-beta.8" +actix-web = { version = "4.0.0-beta.21", features = ["rustls"] } +actix-web-static-files = { git = "https://github.com/robjtede/actix-web-static-files.git", rev = "ed74153", optional = true } anyhow = { version = "1.0.43", features = ["backtrace"] } arc-swap = "1.3.2" async-stream = "0.3.2" async-trait = "0.1.51" bstr = "0.2.17" -byte-unit = { version = "4.0.12", default-features = false, features = ["std"] } +byte-unit = { version = "4.0.12", default-features = false, features = ["std", "serde"] } bytes = "1.1.0" chrono = { version = "0.4.19", features = ["serde"] } crossbeam-channel = "0.5.1" @@ -60,14 +58,16 @@ platform-dirs = "0.3.0" rand = "0.8.4" rayon = "1.5.1" regex = "1.5.4" -rustls = "0.19.1" +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" -structopt = "0.3.25" +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" @@ -88,6 +88,7 @@ urlencoding = "2.1.0" [features] mini-dashboard = [ "actix-web-static-files", + "static-files", "anyhow", "cargo_toml", "hex", diff --git a/meilisearch-http/build.rs b/meilisearch-http/build.rs index 41f429ba1..1822cae00 100644 --- a/meilisearch-http/build.rs +++ b/meilisearch-http/build.rs @@ -16,11 +16,11 @@ mod mini_dashboard { use std::io::{Cursor, Read, Write}; use std::path::PathBuf; - use actix_web_static_files::resource_dir; use anyhow::Context; use cargo_toml::Manifest; use reqwest::blocking::get; use sha1::{Digest, Sha1}; + use static_files::resource_dir; pub fn setup_mini_dashboard() -> anyhow::Result<()> { let cargo_manifest_dir = PathBuf::from(env::var("CARGO_MANIFEST_DIR").unwrap()); diff --git a/meilisearch-http/src/analytics/mod.rs b/meilisearch-http/src/analytics/mod.rs index f777a293e..caeb7b7c0 100644 --- a/meilisearch-http/src/analytics/mod.rs +++ b/meilisearch-http/src/analytics/mod.rs @@ -29,12 +29,12 @@ pub type SegmentAnalytics = segment_analytics::SegmentAnalytics; #[cfg(all(not(debug_assertions), feature = "analytics"))] pub type SearchAggregator = segment_analytics::SearchAggregator; -/// The MeiliSearch config dir: -/// `~/.config/MeiliSearch` on *NIX or *BSD. +/// The Meilisearch config dir: +/// `~/.config/Meilisearch` on *NIX or *BSD. /// `~/Library/ApplicationSupport` on macOS. /// `%APPDATA` (= `C:\Users%USERNAME%\AppData\Roaming`) on windows. static MEILISEARCH_CONFIG_PATH: Lazy> = - Lazy::new(|| AppDirs::new(Some("MeiliSearch"), false).map(|appdir| appdir.config_dir)); + Lazy::new(|| AppDirs::new(Some("Meilisearch"), false).map(|appdir| appdir.config_dir)); fn config_user_id_path(db_path: &Path) -> Option { db_path @@ -50,7 +50,7 @@ fn config_user_id_path(db_path: &Path) -> Option { .map(|(filename, config_path)| config_path.join(filename.trim_start_matches('-'))) } -/// Look for the instance-uid in the `data.ms` or in `~/.config/MeiliSearch/path-to-db-instance-uid` +/// Look for the instance-uid in the `data.ms` or in `~/.config/Meilisearch/path-to-db-instance-uid` fn find_user_id(db_path: &Path) -> Option { fs::read_to_string(db_path.join("instance-uid")) .ok() diff --git a/meilisearch-http/src/analytics/segment_analytics.rs b/meilisearch-http/src/analytics/segment_analytics.rs index 86be0f432..86eb8f29e 100644 --- a/meilisearch-http/src/analytics/segment_analytics.rs +++ b/meilisearch-http/src/analytics/segment_analytics.rs @@ -1,11 +1,12 @@ use std::collections::{BinaryHeap, HashMap, HashSet}; use std::fs; -use std::path::Path; +use std::path::{Path, PathBuf}; use std::sync::Arc; 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_lib::index::{SearchQuery, SearchResult}; use meilisearch_lib::index_controller::Stats; @@ -77,7 +78,7 @@ impl SegmentAnalytics { let user = User::UserId { user_id }; let mut batcher = AutoBatcher::new(client, Batcher::new(None), SEGMENT_API_KEY.to_string()); - // If MeiliSearch is Launched for the first time: + // If Meilisearch is Launched for the first time: // 1. Send an event Launched associated to the user `total_launch`. // 2. Batch an event Launched with the real instance-id and send it in one hour. if first_time_run { @@ -210,10 +211,30 @@ impl Segment { "server_provider": std::env::var("MEILI_SERVER_PROVIDER").ok(), }) }); - let infos = json!({ - "env": opt.env.clone(), - "has_snapshot": opt.schedule_snapshot, - }); + // The infos are all cli option except every option containing sensitive information. + // We consider an information as sensible if it contains a path, an address or a key. + let infos = { + // First we see if any sensitive fields were used. + let db_path = opt.db_path != PathBuf::from("./data.ms"); + let import_dump = opt.import_dump.is_some(); + let dumps_dir = opt.dumps_dir != PathBuf::from("dumps/"); + let import_snapshot = opt.import_snapshot.is_some(); + let snapshots_dir = opt.snapshot_dir != PathBuf::from("snapshots/"); + let http_addr = opt.http_addr != "127.0.0.1:7700"; + + let mut infos = serde_json::to_value(opt).unwrap(); + + // Then we overwrite all sensitive field with a boolean representing if + // the feature was used or not. + infos["db_path"] = json!(db_path); + infos["import_dump"] = json!(import_dump); + infos["dumps_dir"] = json!(dumps_dir); + infos["import_snapshot"] = json!(import_snapshot); + infos["snapshot_dir"] = json!(snapshots_dir); + infos["http_addr"] = json!(http_addr); + + infos + }; let number_of_documents = stats .indexes @@ -301,6 +322,8 @@ impl Segment { #[derive(Default)] pub struct SearchAggregator { + timestamp: Option>, + // context user_agents: HashSet, @@ -336,6 +359,8 @@ 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.total_received = 1; ret.user_agents = extract_user_agents(request).into_iter().collect(); @@ -389,6 +414,10 @@ impl SearchAggregator { /// Aggregate one [SearchAggregator] into another. pub fn aggregate(&mut self, mut other: Self) { + if self.timestamp.is_none() { + self.timestamp = other.timestamp; + } + // context for user_agent in other.user_agents.into_iter() { self.user_agents.insert(user_agent); @@ -462,6 +491,7 @@ impl SearchAggregator { }); Some(Track { + timestamp: self.timestamp, user: user.clone(), event: event_name.to_string(), properties, @@ -473,6 +503,8 @@ impl SearchAggregator { #[derive(Default)] pub struct DocumentsAggregator { + timestamp: Option>, + // set to true when at least one request was received updated: bool, @@ -491,6 +523,7 @@ impl DocumentsAggregator { request: &HttpRequest, ) -> Self { let mut ret = Self::default(); + ret.timestamp = Some(chrono::offset::Utc::now()); ret.updated = true; ret.user_agents = extract_user_agents(request).into_iter().collect(); @@ -511,6 +544,10 @@ impl DocumentsAggregator { /// Aggregate one [DocumentsAggregator] into another. pub fn aggregate(&mut self, other: Self) { + if self.timestamp.is_none() { + self.timestamp = other.timestamp; + } + self.updated |= other.updated; // we can't create a union because there is no `into_union` method for user_agent in other.user_agents.into_iter() { @@ -537,6 +574,7 @@ impl DocumentsAggregator { }); Some(Track { + timestamp: self.timestamp, user: user.clone(), event: event_name.to_string(), properties, diff --git a/meilisearch-http/src/extractors/authentication/mod.rs b/meilisearch-http/src/extractors/authentication/mod.rs index 2c960578a..73b2bb45c 100644 --- a/meilisearch-http/src/extractors/authentication/mod.rs +++ b/meilisearch-http/src/extractors/authentication/mod.rs @@ -32,8 +32,6 @@ impl Deref for GuardedData { } impl FromRequest for GuardedData { - type Config = (); - type Error = ResponseError; type Future = Ready>; diff --git a/meilisearch-http/src/extractors/payload.rs b/meilisearch-http/src/extractors/payload.rs index e8a1efb64..6cd8df190 100644 --- a/meilisearch-http/src/extractors/payload.rs +++ b/meilisearch-http/src/extractors/payload.rs @@ -28,8 +28,6 @@ impl Default for PayloadConfig { } impl FromRequest for Payload { - type Config = PayloadConfig; - type Error = PayloadError; type Future = Ready>; @@ -39,7 +37,7 @@ impl FromRequest for Payload { let limit = req .app_data::() .map(|c| c.limit) - .unwrap_or(Self::Config::default().limit); + .unwrap_or(PayloadConfig::default().limit); ready(Ok(Payload { payload: payload.take(), limit, diff --git a/meilisearch-http/src/lib.rs b/meilisearch-http/src/lib.rs index f8e2357fd..a8abdae49 100644 --- a/meilisearch-http/src/lib.rs +++ b/meilisearch-http/src/lib.rs @@ -30,11 +30,15 @@ pub fn setup_meilisearch(opt: &Opt) -> anyhow::Result { meilisearch .set_max_index_size(opt.max_index_size.get_bytes() as usize) .set_max_task_store_size(opt.max_task_db_size.get_bytes() as usize) + // snapshot .set_ignore_missing_snapshot(opt.ignore_missing_snapshot) .set_ignore_snapshot_if_db_exists(opt.ignore_snapshot_if_db_exists) - .set_dump_dst(opt.dumps_dir.clone()) .set_snapshot_interval(Duration::from_secs(opt.snapshot_interval_sec)) - .set_snapshot_dir(opt.snapshot_dir.clone()); + .set_snapshot_dir(opt.snapshot_dir.clone()) + // dump + .set_ignore_missing_dump(opt.ignore_missing_dump) + .set_ignore_dump_if_db_exists(opt.ignore_dump_if_db_exists) + .set_dump_dst(opt.dumps_dir.clone()); if let Some(ref path) = opt.import_snapshot { meilisearch.set_import_snapshot(path.clone()); @@ -90,7 +94,7 @@ pub fn configure_data( #[cfg(feature = "mini-dashboard")] pub fn dashboard(config: &mut web::ServiceConfig, enable_frontend: bool) { use actix_web::HttpResponse; - use actix_web_static_files::Resource; + use static_files::Resource; mod generated { include!(concat!(env!("OUT_DIR"), "/generated.rs")); diff --git a/meilisearch-http/src/main.rs b/meilisearch-http/src/main.rs index 955321a6f..498bbb82d 100644 --- a/meilisearch-http/src/main.rs +++ b/meilisearch-http/src/main.rs @@ -2,12 +2,12 @@ use std::env; use std::sync::Arc; use actix_web::HttpServer; +use clap::Parser; use meilisearch_auth::AuthController; use meilisearch_http::analytics; use meilisearch_http::analytics::Analytics; use meilisearch_http::{create_app, setup_meilisearch, Opt}; use meilisearch_lib::MeiliSearch; -use structopt::StructOpt; #[cfg(target_os = "linux")] #[global_allocator] @@ -29,7 +29,7 @@ fn setup(opt: &Opt) -> anyhow::Result<()> { #[actix_web::main] async fn main() -> anyhow::Result<()> { - let opt = Opt::from_args(); + let opt = Opt::parse(); setup(&opt)?; @@ -50,7 +50,7 @@ async fn main() -> anyhow::Result<()> { let auth_controller = AuthController::new(&opt.db_path, &opt.master_key)?; #[cfg(all(not(debug_assertions), feature = "analytics"))] - let (analytics, user) = if opt.analytics() { + let (analytics, user) = if !opt.no_analytics { analytics::SegmentAnalytics::new(&opt, &meilisearch).await } else { analytics::MockAnalytics::new(&opt) @@ -101,14 +101,14 @@ pub fn print_launch_resume(opt: &Opt, user: &str) { let commit_date = option_env!("VERGEN_GIT_COMMIT_TIMESTAMP").unwrap_or("unknown"); let ascii_name = r#" -888b d888 d8b 888 d8b .d8888b. 888 -8888b d8888 Y8P 888 Y8P d88P Y88b 888 -88888b.d88888 888 Y88b. 888 -888Y88888P888 .d88b. 888 888 888 "Y888b. .d88b. 8888b. 888d888 .d8888b 88888b. -888 Y888P 888 d8P Y8b 888 888 888 "Y88b. d8P Y8b "88b 888P" d88P" 888 "88b -888 Y8P 888 88888888 888 888 888 "888 88888888 .d888888 888 888 888 888 -888 " 888 Y8b. 888 888 888 Y88b d88P Y8b. 888 888 888 Y88b. 888 888 -888 888 "Y8888 888 888 888 "Y8888P" "Y8888 "Y888888 888 "Y8888P 888 888 +888b d888 d8b 888 d8b 888 +8888b d8888 Y8P 888 Y8P 888 +88888b.d88888 888 888 +888Y88888P888 .d88b. 888 888 888 .d8888b .d88b. 8888b. 888d888 .d8888b 88888b. +888 Y888P 888 d8P Y8b 888 888 888 88K d8P Y8b "88b 888P" d88P" 888 "88b +888 Y8P 888 88888888 888 888 888 "Y8888b. 88888888 .d888888 888 888 888 888 +888 " 888 Y8b. 888 888 888 X88 Y8b. 888 888 888 Y88b. 888 888 +888 888 "Y8888 888 888 888 88888P' "Y8888 "Y888888 888 "Y8888P 888 888 "#; eprintln!("{}", ascii_name); @@ -125,10 +125,10 @@ pub fn print_launch_resume(opt: &Opt, user: &str) { #[cfg(all(not(debug_assertions), feature = "analytics"))] { - if opt.analytics() { + if !opt.no_analytics { eprintln!( " -Thank you for using MeiliSearch! +Thank you for using Meilisearch! We collect anonymized analytics to improve our product and your experience. To learn more, including how to turn off analytics, visit our dedicated documentation page: https://docs.meilisearch.com/learn/what_is_meilisearch/telemetry.html @@ -146,7 +146,7 @@ Anonymous telemetry:\t\"Enabled\"" eprintln!(); if opt.master_key.is_some() { - eprintln!("A Master Key has been set. Requests to MeiliSearch won't be authorized unless you provide an authentication key."); + eprintln!("A Master Key has been set. Requests to Meilisearch won't be authorized unless you provide an authentication key."); } else { eprintln!("No master key found; The server will accept unidentified requests. \ If you need some protection in development mode, please export a key: export MEILI_MASTER_KEY=xxx"); diff --git a/meilisearch-http/src/option.rs b/meilisearch-http/src/option.rs index c6f783074..d59fd48d6 100644 --- a/meilisearch-http/src/option.rs +++ b/meilisearch-http/src/option.rs @@ -4,144 +4,157 @@ use std::path::PathBuf; use std::sync::Arc; use byte_unit::Byte; +use clap::Parser; use meilisearch_lib::options::IndexerOpts; -use rustls::internal::pemfile::{certs, pkcs8_private_keys, rsa_private_keys}; use rustls::{ - AllowAnyAnonymousOrAuthenticatedClient, AllowAnyAuthenticatedClient, NoClientAuth, + server::{ + AllowAnyAnonymousOrAuthenticatedClient, AllowAnyAuthenticatedClient, + ServerSessionMemoryCache, + }, RootCertStore, }; -use structopt::StructOpt; +use rustls_pemfile::{certs, pkcs8_private_keys, rsa_private_keys}; +use serde::Serialize; const POSSIBLE_ENV: [&str; 2] = ["development", "production"]; -#[derive(Debug, Clone, StructOpt)] +#[derive(Debug, Clone, Parser, Serialize)] pub struct Opt { /// The destination where the database must be created. - #[structopt(long, env = "MEILI_DB_PATH", default_value = "./data.ms")] + #[clap(long, env = "MEILI_DB_PATH", default_value = "./data.ms")] pub db_path: PathBuf, /// The address on which the http server will listen. - #[structopt(long, env = "MEILI_HTTP_ADDR", default_value = "127.0.0.1:7700")] + #[clap(long, env = "MEILI_HTTP_ADDR", default_value = "127.0.0.1:7700")] pub http_addr: String, /// The master key allowing you to do everything on the server. - #[structopt(long, env = "MEILI_MASTER_KEY")] + #[serde(skip)] + #[clap(long, env = "MEILI_MASTER_KEY")] pub master_key: Option, /// This environment variable must be set to `production` if you are running in production. /// If the server is running in development mode more logs will be displayed, /// and the master key can be avoided which implies that there is no security on the updates routes. /// This is useful to debug when integrating the engine with another service. - #[structopt(long, env = "MEILI_ENV", default_value = "development", possible_values = &POSSIBLE_ENV)] + #[clap(long, env = "MEILI_ENV", default_value = "development", possible_values = &POSSIBLE_ENV)] pub env: String, /// Do not send analytics to Meili. #[cfg(all(not(debug_assertions), feature = "analytics"))] - #[structopt(long, env = "MEILI_NO_ANALYTICS")] - pub no_analytics: Option>, + #[clap(long, env = "MEILI_NO_ANALYTICS")] + pub no_analytics: bool, /// The maximum size, in bytes, of the main lmdb database directory - #[structopt(long, env = "MEILI_MAX_INDEX_SIZE", default_value = "100 GiB")] + #[clap(long, env = "MEILI_MAX_INDEX_SIZE", default_value = "100 GiB")] pub max_index_size: Byte, /// The maximum size, in bytes, of the update lmdb database directory - #[structopt(long, env = "MEILI_MAX_TASK_DB_SIZE", default_value = "100 GiB")] + #[clap(long, env = "MEILI_MAX_TASK_DB_SIZE", default_value = "100 GiB")] pub max_task_db_size: Byte, /// The maximum size, in bytes, of accepted JSON payloads - #[structopt(long, env = "MEILI_HTTP_PAYLOAD_SIZE_LIMIT", default_value = "100 MB")] + #[clap(long, env = "MEILI_HTTP_PAYLOAD_SIZE_LIMIT", default_value = "100 MB")] pub http_payload_size_limit: Byte, /// Read server certificates from CERTFILE. /// This should contain PEM-format certificates /// in the right order (the first certificate should /// certify KEYFILE, the last should be a root CA). - #[structopt(long, env = "MEILI_SSL_CERT_PATH", parse(from_os_str))] + #[serde(skip)] + #[clap(long, env = "MEILI_SSL_CERT_PATH", parse(from_os_str))] pub ssl_cert_path: Option, /// Read private key from KEYFILE. This should be a RSA /// private key or PKCS8-encoded private key, in PEM format. - #[structopt(long, env = "MEILI_SSL_KEY_PATH", parse(from_os_str))] + #[serde(skip)] + #[clap(long, env = "MEILI_SSL_KEY_PATH", parse(from_os_str))] pub ssl_key_path: Option, /// Enable client authentication, and accept certificates /// signed by those roots provided in CERTFILE. - #[structopt(long, env = "MEILI_SSL_AUTH_PATH", parse(from_os_str))] + #[clap(long, env = "MEILI_SSL_AUTH_PATH", parse(from_os_str))] + #[serde(skip)] pub ssl_auth_path: Option, /// Read DER-encoded OCSP response from OCSPFILE and staple to certificate. /// Optional - #[structopt(long, env = "MEILI_SSL_OCSP_PATH", parse(from_os_str))] + #[serde(skip)] + #[clap(long, env = "MEILI_SSL_OCSP_PATH", parse(from_os_str))] pub ssl_ocsp_path: Option, /// Send a fatal alert if the client does not complete client authentication. - #[structopt(long, env = "MEILI_SSL_REQUIRE_AUTH")] + #[serde(skip)] + #[clap(long, env = "MEILI_SSL_REQUIRE_AUTH")] pub ssl_require_auth: bool, /// SSL support session resumption - #[structopt(long, env = "MEILI_SSL_RESUMPTION")] + #[serde(skip)] + #[clap(long, env = "MEILI_SSL_RESUMPTION")] pub ssl_resumption: bool, /// SSL support tickets. - #[structopt(long, env = "MEILI_SSL_TICKETS")] + #[serde(skip)] + #[clap(long, env = "MEILI_SSL_TICKETS")] pub ssl_tickets: bool, /// Defines the path of the snapshot file to import. /// This option will, by default, stop the process if a database already exist or if no snapshot exists at /// the given path. If this option is not specified no snapshot is imported. - #[structopt(long)] + #[clap(long)] pub import_snapshot: Option, /// The engine will ignore a missing snapshot and not return an error in such case. - #[structopt(long, requires = "import-snapshot")] + #[clap(long, requires = "import-snapshot")] pub ignore_missing_snapshot: bool, /// The engine will skip snapshot importation and not return an error in such case. - #[structopt(long, requires = "import-snapshot")] + #[clap(long, requires = "import-snapshot")] pub ignore_snapshot_if_db_exists: bool, /// Defines the directory path where meilisearch will create snapshot each snapshot_time_gap. - #[structopt(long, env = "MEILI_SNAPSHOT_DIR", default_value = "snapshots/")] + #[clap(long, env = "MEILI_SNAPSHOT_DIR", default_value = "snapshots/")] pub snapshot_dir: PathBuf, /// Activate snapshot scheduling. - #[structopt(long, env = "MEILI_SCHEDULE_SNAPSHOT")] + #[clap(long, env = "MEILI_SCHEDULE_SNAPSHOT")] pub schedule_snapshot: bool, /// Defines time interval, in seconds, between each snapshot creation. - #[structopt(long, env = "MEILI_SNAPSHOT_INTERVAL_SEC", default_value = "86400")] // 24h + #[clap(long, env = "MEILI_SNAPSHOT_INTERVAL_SEC", default_value = "86400")] // 24h pub snapshot_interval_sec: u64, - /// Folder where dumps are created when the dump route is called. - #[structopt(long, env = "MEILI_DUMPS_DIR", default_value = "dumps/")] - pub dumps_dir: PathBuf, - /// Import a dump from the specified path, must be a `.dump` file. - #[structopt(long, conflicts_with = "import-snapshot")] + #[clap(long, conflicts_with = "import-snapshot")] pub import_dump: Option, + /// If the dump doesn't exists, load or create the database specified by `db-path` instead. + #[clap(long, requires = "import-dump")] + pub ignore_missing_dump: bool, + + /// Ignore the dump if a database already exists, and load that database instead. + #[clap(long, requires = "import-dump")] + pub ignore_dump_if_db_exists: bool, + + /// Folder where dumps are created when the dump route is called. + #[clap(long, env = "MEILI_DUMPS_DIR", default_value = "dumps/")] + pub dumps_dir: PathBuf, + /// Set the log level - #[structopt(long, env = "MEILI_LOG_LEVEL", default_value = "info")] + #[clap(long, env = "MEILI_LOG_LEVEL", default_value = "info")] pub log_level: String, - #[structopt(skip)] + #[serde(skip)] + #[clap(skip)] pub indexer_options: IndexerOpts, } impl Opt { - /// Wether analytics should be enabled or not. - #[cfg(all(not(debug_assertions), feature = "analytics"))] - pub fn analytics(&self) -> bool { - match self.no_analytics { - None => true, - Some(None) => false, - Some(Some(disabled)) => !disabled, - } - } - pub fn get_ssl_config(&self) -> anyhow::Result> { if let (Some(cert_path), Some(key_path)) = (&self.ssl_cert_path, &self.ssl_key_path) { - let client_auth = match &self.ssl_auth_path { + let config = rustls::ServerConfig::builder().with_safe_defaults(); + + let config = match &self.ssl_auth_path { Some(auth_path) => { let roots = load_certs(auth_path.to_path_buf())?; let mut client_auth_roots = RootCertStore::empty(); @@ -149,30 +162,32 @@ impl Opt { client_auth_roots.add(&root).unwrap(); } if self.ssl_require_auth { - AllowAnyAuthenticatedClient::new(client_auth_roots) + let verifier = AllowAnyAuthenticatedClient::new(client_auth_roots); + config.with_client_cert_verifier(verifier) } else { - AllowAnyAnonymousOrAuthenticatedClient::new(client_auth_roots) + let verifier = + AllowAnyAnonymousOrAuthenticatedClient::new(client_auth_roots); + config.with_client_cert_verifier(verifier) } } - None => NoClientAuth::new(), + None => config.with_no_client_auth(), }; - let mut config = rustls::ServerConfig::new(client_auth); - config.key_log = Arc::new(rustls::KeyLogFile::new()); - let certs = load_certs(cert_path.to_path_buf())?; let privkey = load_private_key(key_path.to_path_buf())?; let ocsp = load_ocsp(&self.ssl_ocsp_path)?; - config - .set_single_cert_with_ocsp_and_sct(certs, privkey, ocsp, vec![]) + let mut config = config + .with_single_cert_with_ocsp_and_sct(certs, privkey, ocsp, vec![]) .map_err(|_| anyhow::anyhow!("bad certificates/private key"))?; + config.key_log = Arc::new(rustls::KeyLogFile::new()); + if self.ssl_resumption { - config.set_persistence(rustls::ServerSessionMemoryCache::new(256)); + config.session_storage = ServerSessionMemoryCache::new(256); } if self.ssl_tickets { - config.ticketer = rustls::Ticketer::new(); + config.ticketer = rustls::Ticketer::new().unwrap(); } Ok(Some(config)) @@ -186,7 +201,9 @@ fn load_certs(filename: PathBuf) -> anyhow::Result> { let certfile = fs::File::open(filename).map_err(|_| anyhow::anyhow!("cannot open certificate file"))?; let mut reader = BufReader::new(certfile); - certs(&mut reader).map_err(|_| anyhow::anyhow!("cannot read certificate file")) + certs(&mut reader) + .map(|certs| certs.into_iter().map(rustls::Certificate).collect()) + .map_err(|_| anyhow::anyhow!("cannot read certificate file")) } fn load_private_key(filename: PathBuf) -> anyhow::Result { @@ -211,10 +228,10 @@ fn load_private_key(filename: PathBuf) -> anyhow::Result { // prefer to load pkcs8 keys if !pkcs8_keys.is_empty() { - Ok(pkcs8_keys[0].clone()) + Ok(rustls::PrivateKey(pkcs8_keys[0].clone())) } else { assert!(!rsa_keys.is_empty()); - Ok(rsa_keys[0].clone()) + Ok(rustls::PrivateKey(rsa_keys[0].clone())) } } diff --git a/meilisearch-http/src/routes/mod.rs b/meilisearch-http/src/routes/mod.rs index c859dc68f..5ec9cfee4 100644 --- a/meilisearch-http/src/routes/mod.rs +++ b/meilisearch-http/src/routes/mod.rs @@ -117,11 +117,11 @@ impl IndexUpdateResponse { /// Always return a 200 with: /// ```json /// { -/// "status": "MeiliSearch is running" +/// "status": "Meilisearch is running" /// } /// ``` pub async fn running() -> HttpResponse { - HttpResponse::Ok().json(serde_json::json!({ "status": "MeiliSearch is running" })) + HttpResponse::Ok().json(serde_json::json!({ "status": "Meilisearch is running" })) } async fn get_stats( diff --git a/meilisearch-http/tests/auth/authorization.rs b/meilisearch-http/tests/auth/authorization.rs index 85b37bdc2..7ea232f0b 100644 --- a/meilisearch-http/tests/auth/authorization.rs +++ b/meilisearch-http/tests/auth/authorization.rs @@ -1,56 +1,61 @@ use crate::common::Server; use chrono::{Duration, Utc}; -use maplit::hashmap; +use maplit::{hashmap, hashset}; use once_cell::sync::Lazy; use serde_json::{json, Value}; use std::collections::{HashMap, HashSet}; -static AUTHORIZATIONS: Lazy> = +static AUTHORIZATIONS: Lazy>> = Lazy::new(|| { hashmap! { - ("POST", "/indexes/products/search") => "search", - ("GET", "/indexes/products/search") => "search", - ("POST", "/indexes/products/documents") => "documents.add", - ("GET", "/indexes/products/documents") => "documents.get", - ("GET", "/indexes/products/documents/0") => "documents.get", - ("DELETE", "/indexes/products/documents/0") => "documents.delete", - ("GET", "/tasks") => "tasks.get", - ("GET", "/indexes/products/tasks") => "tasks.get", - ("GET", "/indexes/products/tasks/0") => "tasks.get", - ("PUT", "/indexes/products/") => "indexes.update", - ("GET", "/indexes/products/") => "indexes.get", - ("DELETE", "/indexes/products/") => "indexes.delete", - ("POST", "/indexes") => "indexes.create", - ("GET", "/indexes") => "indexes.get", - ("GET", "/indexes/products/settings") => "settings.get", - ("GET", "/indexes/products/settings/displayed-attributes") => "settings.get", - ("GET", "/indexes/products/settings/distinct-attribute") => "settings.get", - ("GET", "/indexes/products/settings/filterable-attributes") => "settings.get", - ("GET", "/indexes/products/settings/ranking-rules") => "settings.get", - ("GET", "/indexes/products/settings/searchable-attributes") => "settings.get", - ("GET", "/indexes/products/settings/sortable-attributes") => "settings.get", - ("GET", "/indexes/products/settings/stop-words") => "settings.get", - ("GET", "/indexes/products/settings/synonyms") => "settings.get", - ("DELETE", "/indexes/products/settings") => "settings.update", - ("POST", "/indexes/products/settings") => "settings.update", - ("POST", "/indexes/products/settings/displayed-attributes") => "settings.update", - ("POST", "/indexes/products/settings/distinct-attribute") => "settings.update", - ("POST", "/indexes/products/settings/filterable-attributes") => "settings.update", - ("POST", "/indexes/products/settings/ranking-rules") => "settings.update", - ("POST", "/indexes/products/settings/searchable-attributes") => "settings.update", - ("POST", "/indexes/products/settings/sortable-attributes") => "settings.update", - ("POST", "/indexes/products/settings/stop-words") => "settings.update", - ("POST", "/indexes/products/settings/synonyms") => "settings.update", - ("GET", "/indexes/products/stats") => "stats.get", - ("GET", "/stats") => "stats.get", - ("POST", "/dumps") => "dumps.create", - ("GET", "/dumps/0/status") => "dumps.get", - ("GET", "/version") => "version", + ("POST", "/indexes/products/search") => hashset!{"search", "*"}, + ("GET", "/indexes/products/search") => hashset!{"search", "*"}, + ("POST", "/indexes/products/documents") => hashset!{"documents.add", "*"}, + ("GET", "/indexes/products/documents") => hashset!{"documents.get", "*"}, + ("GET", "/indexes/products/documents/0") => hashset!{"documents.get", "*"}, + ("DELETE", "/indexes/products/documents/0") => hashset!{"documents.delete", "*"}, + ("GET", "/tasks") => hashset!{"tasks.get", "*"}, + ("GET", "/indexes/products/tasks") => hashset!{"tasks.get", "*"}, + ("GET", "/indexes/products/tasks/0") => hashset!{"tasks.get", "*"}, + ("PUT", "/indexes/products/") => hashset!{"indexes.update", "*"}, + ("GET", "/indexes/products/") => hashset!{"indexes.get", "*"}, + ("DELETE", "/indexes/products/") => hashset!{"indexes.delete", "*"}, + ("POST", "/indexes") => hashset!{"indexes.create", "*"}, + ("GET", "/indexes") => hashset!{"indexes.get", "*"}, + ("GET", "/indexes/products/settings") => hashset!{"settings.get", "*"}, + ("GET", "/indexes/products/settings/displayed-attributes") => hashset!{"settings.get", "*"}, + ("GET", "/indexes/products/settings/distinct-attribute") => hashset!{"settings.get", "*"}, + ("GET", "/indexes/products/settings/filterable-attributes") => hashset!{"settings.get", "*"}, + ("GET", "/indexes/products/settings/ranking-rules") => hashset!{"settings.get", "*"}, + ("GET", "/indexes/products/settings/searchable-attributes") => hashset!{"settings.get", "*"}, + ("GET", "/indexes/products/settings/sortable-attributes") => hashset!{"settings.get", "*"}, + ("GET", "/indexes/products/settings/stop-words") => hashset!{"settings.get", "*"}, + ("GET", "/indexes/products/settings/synonyms") => hashset!{"settings.get", "*"}, + ("DELETE", "/indexes/products/settings") => hashset!{"settings.update", "*"}, + ("POST", "/indexes/products/settings") => hashset!{"settings.update", "*"}, + ("POST", "/indexes/products/settings/displayed-attributes") => hashset!{"settings.update", "*"}, + ("POST", "/indexes/products/settings/distinct-attribute") => hashset!{"settings.update", "*"}, + ("POST", "/indexes/products/settings/filterable-attributes") => hashset!{"settings.update", "*"}, + ("POST", "/indexes/products/settings/ranking-rules") => hashset!{"settings.update", "*"}, + ("POST", "/indexes/products/settings/searchable-attributes") => hashset!{"settings.update", "*"}, + ("POST", "/indexes/products/settings/sortable-attributes") => hashset!{"settings.update", "*"}, + ("POST", "/indexes/products/settings/stop-words") => hashset!{"settings.update", "*"}, + ("POST", "/indexes/products/settings/synonyms") => hashset!{"settings.update", "*"}, + ("GET", "/indexes/products/stats") => hashset!{"stats.get", "*"}, + ("GET", "/stats") => hashset!{"stats.get", "*"}, + ("POST", "/dumps") => hashset!{"dumps.create", "*"}, + ("GET", "/dumps/0/status") => hashset!{"dumps.get", "*"}, + ("GET", "/version") => hashset!{"version", "*"}, } }); -static ALL_ACTIONS: Lazy> = - Lazy::new(|| AUTHORIZATIONS.values().cloned().collect()); +static ALL_ACTIONS: Lazy> = Lazy::new(|| { + AUTHORIZATIONS + .values() + .cloned() + .reduce(|l, r| l.union(&r).cloned().collect()) + .unwrap() +}); static INVALID_RESPONSE: Lazy = Lazy::new(|| { json!({"message": "The provided API key is invalid.", @@ -61,6 +66,7 @@ static INVALID_RESPONSE: Lazy = Lazy::new(|| { }); #[actix_rt::test] +#[cfg_attr(target_os = "windows", ignore)] async fn error_access_expired_key() { use std::{thread, time}; @@ -92,6 +98,7 @@ async fn error_access_expired_key() { } #[actix_rt::test] +#[cfg_attr(target_os = "windows", ignore)] async fn error_access_unauthorized_index() { let mut server = Server::new_auth().await; server.use_api_key("MASTER_KEY"); @@ -122,6 +129,7 @@ async fn error_access_unauthorized_index() { } #[actix_rt::test] +#[cfg_attr(target_os = "windows", ignore)] async fn error_access_unauthorized_action() { let mut server = Server::new_auth().await; server.use_api_key("MASTER_KEY"); @@ -144,7 +152,7 @@ async fn error_access_unauthorized_action() { // Patch API key letting all rights but the needed one. let content = json!({ - "actions": ALL_ACTIONS.iter().cloned().filter(|a| a != action).collect::>(), + "actions": ALL_ACTIONS.difference(action).collect::>(), }); let (_, code) = server.patch_api_key(&key, content).await; assert_eq!(code, 200); @@ -158,6 +166,7 @@ async fn error_access_unauthorized_action() { } #[actix_rt::test] +#[cfg_attr(target_os = "windows", ignore)] async fn access_authorized_restricted_index() { let mut server = Server::new_auth().await; server.use_api_key("MASTER_KEY"); @@ -175,40 +184,28 @@ async fn access_authorized_restricted_index() { let key = response["key"].as_str().unwrap(); server.use_api_key(&key); - for ((method, route), action) in AUTHORIZATIONS.iter() { - // Patch API key letting only the needed action. - let content = json!({ - "actions": [action], - }); + for ((method, route), actions) in AUTHORIZATIONS.iter() { + for action in actions { + // Patch API key letting only the needed action. + let content = json!({ + "actions": [action], + }); - server.use_api_key("MASTER_KEY"); - let (_, code) = server.patch_api_key(&key, content).await; - assert_eq!(code, 200); + server.use_api_key("MASTER_KEY"); + let (_, code) = server.patch_api_key(&key, content).await; + assert_eq!(code, 200); - server.use_api_key(&key); - let (response, code) = server.dummy_request(method, route).await; + server.use_api_key(&key); + let (response, code) = server.dummy_request(method, route).await; - assert_ne!(response, INVALID_RESPONSE.clone()); - assert_ne!(code, 403); - - // Patch API key using action all action. - let content = json!({ - "actions": ["*"], - }); - - server.use_api_key("MASTER_KEY"); - let (_, code) = server.patch_api_key(&key, content).await; - assert_eq!(code, 200); - - server.use_api_key(&key); - let (response, code) = server.dummy_request(method, route).await; - - assert_ne!(response, INVALID_RESPONSE.clone()); - assert_ne!(code, 403); + assert_ne!(response, INVALID_RESPONSE.clone()); + assert_ne!(code, 403); + } } } #[actix_rt::test] +#[cfg_attr(target_os = "windows", ignore)] async fn access_authorized_no_index_restriction() { let mut server = Server::new_auth().await; server.use_api_key("MASTER_KEY"); @@ -226,40 +223,28 @@ async fn access_authorized_no_index_restriction() { let key = response["key"].as_str().unwrap(); server.use_api_key(&key); - for ((method, route), action) in AUTHORIZATIONS.iter() { - server.use_api_key("MASTER_KEY"); + for ((method, route), actions) in AUTHORIZATIONS.iter() { + for action in actions { + server.use_api_key("MASTER_KEY"); - // Patch API key letting only the needed action. - let content = json!({ - "actions": [action], - }); - let (_, code) = server.patch_api_key(&key, content).await; - assert_eq!(code, 200); + // Patch API key letting only the needed action. + let content = json!({ + "actions": [action], + }); + let (_, code) = server.patch_api_key(&key, content).await; + assert_eq!(code, 200); - server.use_api_key(&key); - let (response, code) = server.dummy_request(method, route).await; + server.use_api_key(&key); + let (response, code) = server.dummy_request(method, route).await; - assert_ne!(response, INVALID_RESPONSE.clone()); - assert_ne!(code, 403); - - // Patch API key using action all action. - let content = json!({ - "actions": ["*"], - }); - - server.use_api_key("MASTER_KEY"); - let (_, code) = server.patch_api_key(&key, content).await; - assert_eq!(code, 200); - - server.use_api_key(&key); - let (response, code) = server.dummy_request(method, route).await; - - assert_ne!(response, INVALID_RESPONSE.clone()); - assert_ne!(code, 403); + assert_ne!(response, INVALID_RESPONSE.clone()); + assert_ne!(code, 403); + } } } #[actix_rt::test] +#[cfg_attr(target_os = "windows", ignore)] async fn access_authorized_stats_restricted_index() { let mut server = Server::new_auth().await; server.use_api_key("MASTER_KEY"); @@ -299,6 +284,7 @@ async fn access_authorized_stats_restricted_index() { } #[actix_rt::test] +#[cfg_attr(target_os = "windows", ignore)] async fn access_authorized_stats_no_index_restriction() { let mut server = Server::new_auth().await; server.use_api_key("MASTER_KEY"); @@ -338,6 +324,7 @@ async fn access_authorized_stats_no_index_restriction() { } #[actix_rt::test] +#[cfg_attr(target_os = "windows", ignore)] async fn list_authorized_indexes_restricted_index() { let mut server = Server::new_auth().await; server.use_api_key("MASTER_KEY"); @@ -378,6 +365,7 @@ async fn list_authorized_indexes_restricted_index() { } #[actix_rt::test] +#[cfg_attr(target_os = "windows", ignore)] async fn list_authorized_indexes_no_index_restriction() { let mut server = Server::new_auth().await; server.use_api_key("MASTER_KEY"); @@ -505,7 +493,8 @@ async fn error_creating_index_without_action() { // create key with access on all indexes. let content = json!({ "indexes": ["*"], - "actions": ALL_ACTIONS.iter().cloned().filter(|a| *a != "indexes.create").collect::>(), + // Give all action but the ones allowing to create an index. + "actions": ALL_ACTIONS.iter().cloned().filter(|a| !AUTHORIZATIONS.get(&("POST","/indexes")).unwrap().contains(a)).collect::>(), "expiresAt": "2050-11-13T00:00:00Z" }); let (response, code) = server.add_api_key(content).await; diff --git a/meilisearch-http/tests/common/server.rs b/meilisearch-http/tests/common/server.rs index 0fb5eacfb..bdaf75ac1 100644 --- a/meilisearch-http/tests/common/server.rs +++ b/meilisearch-http/tests/common/server.rs @@ -130,7 +130,7 @@ pub fn default_settings(dir: impl AsRef) -> Opt { master_key: None, env: "development".to_owned(), #[cfg(all(not(debug_assertions), feature = "analytics"))] - no_analytics: Some(Some(true)), + no_analytics: true, max_index_size: Byte::from_unit(4.0, ByteUnit::GiB).unwrap(), max_task_db_size: Byte::from_unit(4.0, ByteUnit::GiB).unwrap(), http_payload_size_limit: Byte::from_unit(10.0, ByteUnit::MiB).unwrap(), @@ -148,6 +148,8 @@ pub fn default_settings(dir: impl AsRef) -> Opt { schedule_snapshot: false, snapshot_interval_sec: 0, import_dump: None, + ignore_missing_dump: false, + ignore_dump_if_db_exists: false, indexer_options: IndexerOpts { // memory has to be unlimited because several meilisearch are running in test context. max_memory: MaxMemory::unlimited(), diff --git a/meilisearch-http/tests/documents/add_documents.rs b/meilisearch-http/tests/documents/add_documents.rs index f6d55409d..a8340096c 100644 --- a/meilisearch-http/tests/documents/add_documents.rs +++ b/meilisearch-http/tests/documents/add_documents.rs @@ -710,20 +710,11 @@ async fn replace_document() { } #[actix_rt::test] -async fn error_add_no_documents() { +async fn add_no_documents() { let server = Server::new().await; let index = server.index("test"); - let (response, code) = index.add_documents(json!([]), None).await; - - let expected_response = json!({ - "message": "The `json` payload must contain at least one document.", - "code": "malformed_payload", - "type": "invalid_request", - "link": "https://docs.meilisearch.com/errors#malformed_payload" - }); - - assert_eq!(response, expected_response); - assert_eq!(code, 400); + let (_response, code) = index.add_documents(json!([]), None).await; + assert_eq!(code, 202); } #[actix_rt::test] diff --git a/meilisearch-http/tests/index/delete_index.rs b/meilisearch-http/tests/index/delete_index.rs index 8c6c03b62..0674d0afd 100644 --- a/meilisearch-http/tests/index/delete_index.rs +++ b/meilisearch-http/tests/index/delete_index.rs @@ -43,8 +43,8 @@ async fn error_delete_unexisting_index() { assert_eq!(response["error"], expected_response); } -#[cfg(not(windows))] #[actix_rt::test] +#[cfg_attr(target_os = "windows", ignore)] async fn loop_delete_add_documents() { let server = Server::new().await; let index = server.index("test"); diff --git a/meilisearch-lib/Cargo.toml b/meilisearch-lib/Cargo.toml index d38cfd5df..154dbfc68 100644 --- a/meilisearch-lib/Cargo.toml +++ b/meilisearch-lib/Cargo.toml @@ -1,14 +1,12 @@ [package] name = "meilisearch-lib" version = "0.25.2" -edition = "2018" -resolver = "2" +edition = "2021" # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html [dependencies] -actix-web = { version = "4.0.0-beta.9", features = ["rustls"] } -actix-web-static-files = { git = "https://github.com/MarinPostma/actix-web-static-files.git", rev = "39d8006", optional = true } +actix-web = { version = "4.0.0-beta.21", default-features = false } anyhow = { version = "1.0.43", features = ["backtrace"] } async-stream = "0.3.2" async-trait = "0.1.51" @@ -43,7 +41,7 @@ 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" -structopt = "0.3.23" +clap = { version = "3.0", features = ["derive", "env"] } tar = "0.4.37" tempfile = "3.2.0" thiserror = "1.0.28" diff --git a/meilisearch-lib/src/document_formats.rs b/meilisearch-lib/src/document_formats.rs index d711fdde9..cfd73038e 100644 --- a/meilisearch-lib/src/document_formats.rs +++ b/meilisearch-lib/src/document_formats.rs @@ -32,8 +32,6 @@ pub enum DocumentFormatError { Box, PayloadType, ), - #[error("The `{0}` payload must contain at least one document.")] - EmptyPayload(PayloadType), } impl From<(PayloadType, milli::documents::Error)> for DocumentFormatError { @@ -50,7 +48,6 @@ impl ErrorCode for DocumentFormatError { match self { DocumentFormatError::Internal(_) => Code::Internal, DocumentFormatError::MalformedPayload(_, _) => Code::MalformedPayload, - DocumentFormatError::EmptyPayload(_) => Code::MalformedPayload, } } } @@ -63,10 +60,6 @@ pub fn read_csv(input: impl Read, writer: impl Write + Seek) -> Result { let builder = DocumentBatchBuilder::from_csv(input, writer).map_err(|e| (PayloadType::Csv, e))?; - if builder.len() == 0 { - return Err(DocumentFormatError::EmptyPayload(PayloadType::Csv)); - } - let count = builder.finish().map_err(|e| (PayloadType::Csv, e))?; Ok(count) @@ -81,16 +74,17 @@ pub fn read_ndjson(input: impl Read, writer: impl Write + Seek) -> Result let mut buf = String::new(); while reader.read_line(&mut buf)? > 0 { + // skip empty lines + if buf == "\n" { + buf.clear(); + continue; + } builder .extend_from_json(Cursor::new(&buf.as_bytes())) .map_err(|e| (PayloadType::Ndjson, e))?; buf.clear(); } - if builder.len() == 0 { - return Err(DocumentFormatError::EmptyPayload(PayloadType::Ndjson)); - } - let count = builder.finish().map_err(|e| (PayloadType::Ndjson, e))?; Ok(count) @@ -104,10 +98,6 @@ pub fn read_json(input: impl Read, writer: impl Write + Seek) -> Result { .extend_from_json(input) .map_err(|e| (PayloadType::Json, e))?; - if builder.len() == 0 { - return Err(DocumentFormatError::EmptyPayload(PayloadType::Json)); - } - let count = builder.finish().map_err(|e| (PayloadType::Json, e))?; Ok(count) diff --git a/meilisearch-lib/src/index/dump.rs b/meilisearch-lib/src/index/dump.rs index 2c20adda2..661aefa79 100644 --- a/meilisearch-lib/src/index/dump.rs +++ b/meilisearch-lib/src/index/dump.rs @@ -8,7 +8,7 @@ use indexmap::IndexMap; use milli::documents::DocumentBatchReader; use serde::{Deserialize, Serialize}; -use crate::document_formats::{read_ndjson, DocumentFormatError}; +use crate::document_formats::read_ndjson; use crate::index::update_handler::UpdateHandler; use crate::index::updates::apply_settings_to_builder; @@ -128,8 +128,8 @@ impl Index { let empty = match read_ndjson(reader, &mut tmp_doc_file) { // if there was no document in the file it's because the index was empty + Ok(0) => true, Ok(_) => false, - Err(DocumentFormatError::EmptyPayload(_)) => true, Err(e) => return Err(e.into()), }; diff --git a/meilisearch-lib/src/index/search.rs b/meilisearch-lib/src/index/search.rs index 3f05e7dc1..99c4e8bf3 100644 --- a/meilisearch-lib/src/index/search.rs +++ b/meilisearch-lib/src/index/search.rs @@ -877,7 +877,7 @@ mod test { assert_eq!(value["publication_year"], "1937"); } - /// https://github.com/meilisearch/MeiliSearch/issues/1368 + /// https://github.com/meilisearch/meilisearch/issues/1368 #[test] fn formatted_with_highlight_emoji() { let stop_words = fst::Set::default(); 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 1c9c5d769..d342f010f 100644 --- a/meilisearch-lib/src/index_controller/dump_actor/loaders/v4.rs +++ b/meilisearch-lib/src/index_controller/dump_actor/loaders/v4.rs @@ -1,4 +1,5 @@ use std::path::Path; +use std::sync::Arc; use heed::EnvOpenOptions; use log::info; @@ -27,7 +28,7 @@ pub fn load_dump( let mut options = EnvOpenOptions::new(); options.map_size(meta_env_size); options.max_dbs(100); - let env = options.open(&dst)?; + let env = Arc::new(options.open(&dst)?); IndexResolver::load_dump( src.as_ref(), diff --git a/meilisearch-lib/src/index_controller/dump_actor/mod.rs b/meilisearch-lib/src/index_controller/dump_actor/mod.rs index 6351a3d0d..2fcc34077 100644 --- a/meilisearch-lib/src/index_controller/dump_actor/mod.rs +++ b/meilisearch-lib/src/index_controller/dump_actor/mod.rs @@ -1,14 +1,16 @@ use std::fs::File; use std::path::{Path, PathBuf}; +use anyhow::bail; use chrono::{DateTime, Utc}; -use log::{info, trace, warn}; +use log::{info, trace}; use serde::{Deserialize, Serialize}; pub use actor::DumpActor; pub use handle_impl::*; use meilisearch_auth::AuthController; pub use message::DumpMsg; +use tempfile::TempDir; use tokio::fs::create_dir_all; use tokio::sync::oneshot; @@ -79,6 +81,47 @@ pub enum MetadataVersion { } impl MetadataVersion { + pub fn load_dump( + self, + src: impl AsRef, + dst: impl AsRef, + index_db_size: usize, + meta_env_size: usize, + indexing_options: &IndexerOpts, + ) -> anyhow::Result<()> { + match self { + MetadataVersion::V1(_meta) => { + anyhow::bail!("The version 1 of the dumps is not supported anymore. You can re-export your dump from a version between 0.21 and 0.24, or start fresh from a version 0.25 onwards.") + } + MetadataVersion::V2(meta) => v2::load_dump( + meta, + src, + dst, + index_db_size, + meta_env_size, + indexing_options, + )?, + MetadataVersion::V3(meta) => v3::load_dump( + meta, + src, + dst, + index_db_size, + meta_env_size, + indexing_options, + )?, + MetadataVersion::V4(meta) => v4::load_dump( + meta, + src, + dst, + index_db_size, + meta_env_size, + indexing_options, + )?, + } + + Ok(()) + } + pub fn new_v4(index_db_size: usize, update_db_size: usize) -> Self { let meta = Metadata::new(index_db_size, update_db_size); Self::V4(meta) @@ -160,10 +203,46 @@ impl DumpInfo { pub fn load_dump( dst_path: impl AsRef, src_path: impl AsRef, + ignore_dump_if_db_exists: bool, + ignore_missing_dump: bool, index_db_size: usize, update_db_size: usize, indexer_opts: &IndexerOpts, ) -> anyhow::Result<()> { + let empty_db = crate::is_empty_db(&dst_path); + let src_path_exists = src_path.as_ref().exists(); + + if empty_db && src_path_exists { + let (tmp_src, tmp_dst, meta) = extract_dump(&dst_path, &src_path)?; + meta.load_dump( + tmp_src.path(), + tmp_dst.path(), + index_db_size, + update_db_size, + indexer_opts, + )?; + persist_dump(&dst_path, tmp_dst)?; + Ok(()) + } else if !empty_db && !ignore_dump_if_db_exists { + bail!( + "database already exists at {:?}, try to delete it or rename it", + dst_path + .as_ref() + .canonicalize() + .unwrap_or_else(|_| dst_path.as_ref().to_owned()) + ) + } else if !src_path_exists && !ignore_missing_dump { + bail!("dump doesn't exist at {:?}", src_path.as_ref()) + } else { + // there is nothing to do + Ok(()) + } +} + +fn extract_dump( + dst_path: impl AsRef, + src_path: impl AsRef, +) -> anyhow::Result<(TempDir, TempDir, MetadataVersion)> { // Setup a temp directory path in the same path as the database, to prevent cross devices // references. let temp_path = dst_path @@ -186,7 +265,11 @@ pub fn load_dump( let mut meta_file = File::open(&meta_path)?; let meta: MetadataVersion = serde_json::from_reader(&mut meta_file)?; - let tmp_dst = tempfile::tempdir()?; + if !dst_path.as_ref().exists() { + std::fs::create_dir_all(dst_path.as_ref())?; + } + + let tmp_dst = tempfile::tempdir_in(dst_path.as_ref())?; info!( "Loading dump {}, dump database version: {}, dump version: {}", @@ -197,43 +280,37 @@ pub fn load_dump( meta.version() ); - match meta { - MetadataVersion::V1(_meta) => { - anyhow::bail!("The version 1 of the dumps is not supported anymore. You can re-export your dump from a version between 0.21 and 0.24, or start fresh from a version 0.25 onwards.") - } - MetadataVersion::V2(meta) => v2::load_dump( - meta, - &tmp_src_path, - tmp_dst.path(), - index_db_size, - update_db_size, - indexer_opts, - )?, - MetadataVersion::V3(meta) => v3::load_dump( - meta, - &tmp_src_path, - tmp_dst.path(), - index_db_size, - update_db_size, - indexer_opts, - )?, - MetadataVersion::V4(meta) => v4::load_dump( - meta, - &tmp_src_path, - tmp_dst.path(), - index_db_size, - update_db_size, - indexer_opts, - )?, - } - // Persist and atomically rename the db + Ok((tmp_src, tmp_dst, meta)) +} + +fn persist_dump(dst_path: impl AsRef, tmp_dst: TempDir) -> anyhow::Result<()> { let persisted_dump = tmp_dst.into_path(); + + // Delete everything in the `data.ms` except the tempdir. if dst_path.as_ref().exists() { - warn!("Overwriting database at {}", dst_path.as_ref().display()); - std::fs::remove_dir_all(&dst_path)?; + for file in dst_path.as_ref().read_dir().unwrap() { + let file = file.unwrap().path(); + if file.file_name() == persisted_dump.file_name() { + continue; + } + + if file.is_file() { + std::fs::remove_file(&file)?; + } else { + std::fs::remove_dir_all(&file)?; + } + } } - std::fs::rename(&persisted_dump, &dst_path)?; + // Move the whole content of the tempdir into the `data.ms`. + for file in persisted_dump.read_dir().unwrap() { + let file = file.unwrap().path(); + + std::fs::rename(&file, &dst_path.as_ref().join(file.file_name().unwrap()))?; + } + + // Delete the empty tempdir. + std::fs::remove_dir_all(&persisted_dump)?; Ok(()) } @@ -281,6 +358,7 @@ impl DumpJob { AuthController::dump(&self.db_path, &temp_dump_path)?; let dump_path = tokio::task::spawn_blocking(move || -> Result { + let _ = &self; // for now we simply copy the updates/updates_files // FIXME: We may copy more files than necessary, if new files are added while we are // performing the dump. We need a way to filter them out. diff --git a/meilisearch-lib/src/index_controller/mod.rs b/meilisearch-lib/src/index_controller/mod.rs index 0cbdbb159..8e163517a 100644 --- a/meilisearch-lib/src/index_controller/mod.rs +++ b/meilisearch-lib/src/index_controller/mod.rs @@ -150,6 +150,8 @@ pub struct IndexControllerBuilder { schedule_snapshot: bool, dump_src: Option, dump_dst: Option, + ignore_dump_if_db_exists: bool, + ignore_missing_dump: bool, } impl IndexControllerBuilder { @@ -186,6 +188,8 @@ impl IndexControllerBuilder { load_dump( db_path.as_ref(), src_path, + self.ignore_dump_if_db_exists, + self.ignore_missing_dump, index_size, task_store_size, &indexer_options, @@ -198,7 +202,7 @@ impl IndexControllerBuilder { options.map_size(task_store_size); options.max_dbs(20); - let meta_env = options.open(&db_path)?; + let meta_env = Arc::new(options.open(&db_path)?); let update_file_store = UpdateFileStore::new(&db_path)?; // Create or overwrite the version file for this DB @@ -296,18 +300,6 @@ impl IndexControllerBuilder { self } - /// Set the index controller builder's dump src. - pub fn set_dump_src(&mut self, dump_src: PathBuf) -> &mut Self { - self.dump_src.replace(dump_src); - self - } - - /// Set the index controller builder's dump dst. - pub fn set_dump_dst(&mut self, dump_dst: PathBuf) -> &mut Self { - self.dump_dst.replace(dump_dst); - self - } - /// Set the index controller builder's import snapshot. pub fn set_import_snapshot(&mut self, import_snapshot: PathBuf) -> &mut Self { self.import_snapshot.replace(import_snapshot); @@ -325,6 +317,30 @@ impl IndexControllerBuilder { self.schedule_snapshot = true; self } + + /// Set the index controller builder's dump src. + pub fn set_dump_src(&mut self, dump_src: PathBuf) -> &mut Self { + self.dump_src.replace(dump_src); + self + } + + /// Set the index controller builder's dump dst. + pub fn set_dump_dst(&mut self, dump_dst: PathBuf) -> &mut Self { + self.dump_dst.replace(dump_dst); + self + } + + /// Set the index controller builder's ignore dump if db exists. + pub fn set_ignore_dump_if_db_exists(&mut self, ignore_dump_if_db_exists: bool) -> &mut Self { + self.ignore_dump_if_db_exists = ignore_dump_if_db_exists; + self + } + + /// Set the index controller builder's ignore missing dump. + pub fn set_ignore_missing_dump(&mut self, ignore_missing_dump: bool) -> &mut Self { + self.ignore_missing_dump = ignore_missing_dump; + self + } } impl IndexController diff --git a/meilisearch-lib/src/index_controller/versioning/error.rs b/meilisearch-lib/src/index_controller/versioning/error.rs index 8c29e267b..ba284ec91 100644 --- a/meilisearch-lib/src/index_controller/versioning/error.rs +++ b/meilisearch-lib/src/index_controller/versioning/error.rs @@ -1,11 +1,14 @@ #[derive(thiserror::Error, Debug)] pub enum VersionFileError { - #[error("Version file is missing or the previous MeiliSearch engine version was below 0.24.0. Use a dump to update MeiliSearch.")] + #[error( + "Meilisearch (v{}) failed to infer the version of the database. Please consider using a dump to load your data.", + env!("CARGO_PKG_VERSION").to_string() + )] MissingVersionFile, - #[error("Version file is corrupted and thus MeiliSearch is unable to determine the version of the database.")] + #[error("Version file is corrupted and thus Meilisearch is unable to determine the version of the database.")] MalformedVersionFile, #[error( - "Expected MeiliSearch engine version: {major}.{minor}.{patch}, current engine version: {}. To update MeiliSearch use a dump.", + "Expected Meilisearch engine version: {major}.{minor}.{patch}, current engine version: {}. To update Meilisearch use a dump.", env!("CARGO_PKG_VERSION").to_string() )] VersionMismatch { diff --git a/meilisearch-lib/src/index_controller/versioning/mod.rs b/meilisearch-lib/src/index_controller/versioning/mod.rs index 4de894ebb..f2c83bdad 100644 --- a/meilisearch-lib/src/index_controller/versioning/mod.rs +++ b/meilisearch-lib/src/index_controller/versioning/mod.rs @@ -12,7 +12,7 @@ static VERSION_MAJOR: &str = env!("CARGO_PKG_VERSION_MAJOR"); static VERSION_MINOR: &str = env!("CARGO_PKG_VERSION_MINOR"); static VERSION_PATCH: &str = env!("CARGO_PKG_VERSION_PATCH"); -// Persists the version of the current MeiliSearch binary to a VERSION file +// Persists the version of the current Meilisearch binary to a VERSION file pub fn create_version_file(db_path: &Path) -> anyhow::Result<()> { let version_path = db_path.join(VERSION_FILE_NAME); fs::write( @@ -23,7 +23,7 @@ pub fn create_version_file(db_path: &Path) -> anyhow::Result<()> { Ok(()) } -// Ensures MeiliSearch version is compatible with the database, returns an error versions mismatch. +// Ensures Meilisearch version is compatible with the database, returns an error versions mismatch. pub fn check_version_file(db_path: &Path) -> anyhow::Result<()> { let version_path = db_path.join(VERSION_FILE_NAME); diff --git a/meilisearch-lib/src/index_resolver/meta_store.rs b/meilisearch-lib/src/index_resolver/meta_store.rs index 30df1d9eb..6ca615dbf 100644 --- a/meilisearch-lib/src/index_resolver/meta_store.rs +++ b/meilisearch-lib/src/index_resolver/meta_store.rs @@ -2,6 +2,7 @@ use std::collections::HashSet; use std::fs::{create_dir_all, File}; 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}; @@ -42,12 +43,20 @@ pub struct IndexMeta { #[derive(Clone)] pub struct HeedMetaStore { - env: Env, + env: Arc, db: Database>, } +impl Drop for HeedMetaStore { + fn drop(&mut self) { + if Arc::strong_count(&self.env) == 1 { + self.env.as_ref().clone().prepare_for_closing(); + } + } +} + impl HeedMetaStore { - pub fn new(env: heed::Env) -> Result { + pub fn new(env: Arc) -> Result { let db = env.create_database(Some("uuids"))?; Ok(Self { env, db }) } @@ -144,7 +153,7 @@ impl HeedMetaStore { Ok(()) } - pub fn load_dump(src: impl AsRef, env: heed::Env) -> 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 7b61983fe..c8b498d70 100644 --- a/meilisearch-lib/src/index_resolver/mod.rs +++ b/meilisearch-lib/src/index_resolver/mod.rs @@ -4,6 +4,7 @@ pub mod meta_store; use std::convert::TryInto; use std::path::Path; +use std::sync::Arc; use chrono::Utc; use error::{IndexResolverError, Result}; @@ -16,13 +17,11 @@ use serde::{Deserialize, Serialize}; use tokio::task::spawn_blocking; use uuid::Uuid; -use crate::index::update_handler::UpdateHandler; -use crate::index::{error::Result as IndexResult, Index}; +use crate::index::{error::Result as IndexResult, update_handler::UpdateHandler, Index}; use crate::options::IndexerOpts; use crate::tasks::batch::Batch; use crate::tasks::task::{DocumentDeletion, Job, Task, TaskContent, TaskEvent, TaskId, TaskResult}; -use crate::tasks::Pending; -use crate::tasks::TaskPerformer; +use crate::tasks::{Pending, TaskPerformer}; use crate::update_file_store::UpdateFileStore; use self::meta_store::IndexMeta; @@ -39,7 +38,7 @@ pub fn create_index_resolver( path: impl AsRef, index_size: usize, indexer_opts: &IndexerOpts, - meta_env: heed::Env, + meta_env: Arc, file_store: UpdateFileStore, ) -> anyhow::Result { let uuid_store = HeedMetaStore::new(meta_env)?; @@ -153,7 +152,7 @@ impl IndexResolver { src: impl AsRef, dst: impl AsRef, index_db_size: usize, - env: Env, + env: Arc, indexer_opts: &IndexerOpts, ) -> anyhow::Result<()> { HeedMetaStore::load_dump(&src, env)?; diff --git a/meilisearch-lib/src/lib.rs b/meilisearch-lib/src/lib.rs index ed1942c94..21b8eb8c3 100644 --- a/meilisearch-lib/src/lib.rs +++ b/meilisearch-lib/src/lib.rs @@ -10,6 +10,8 @@ mod snapshot; pub mod tasks; mod update_file_store; +use std::path::Path; + pub use index_controller::MeiliSearch; pub use milli; @@ -33,3 +35,19 @@ impl EnvSizer for heed::Env { .fold(0, |acc, m| acc + m.len()) } } + +/// Check if a db is empty. It does not provide any information on the +/// validity of the data in it. +/// We consider a database as non empty when it's a non empty directory. +pub fn is_empty_db(db_path: impl AsRef) -> bool { + let db_path = db_path.as_ref(); + + if !db_path.exists() { + true + // if we encounter an error or if the db is a file we consider the db non empty + } else if let Ok(dir) = db_path.read_dir() { + dir.count() == 0 + } else { + true + } +} diff --git a/meilisearch-lib/src/options.rs b/meilisearch-lib/src/options.rs index 0e59392d6..0c2dea56a 100644 --- a/meilisearch-lib/src/options.rs +++ b/meilisearch-lib/src/options.rs @@ -2,19 +2,19 @@ use core::fmt; use std::{ops::Deref, str::FromStr}; use byte_unit::{Byte, ByteError}; +use clap::Parser; use milli::CompressionType; -use structopt::StructOpt; use sysinfo::{RefreshKind, System, SystemExt}; -#[derive(Debug, Clone, StructOpt)] +#[derive(Debug, Clone, Parser)] pub struct IndexerOpts { /// The amount of documents to skip before printing /// a log regarding the indexing advancement. - #[structopt(long, default_value = "100000")] // 100k + #[clap(long, default_value = "100000")] // 100k pub log_every_n: usize, /// Grenad max number of chunks in bytes. - #[structopt(long)] + #[clap(long)] pub max_nb_chunks: Option, /// The maximum amount of memory the indexer will use. It defaults to 2/3 @@ -24,22 +24,22 @@ pub struct IndexerOpts { /// In case the engine is unable to retrieve the available memory the engine will /// try to use the memory it needs but without real limit, this can lead to /// Out-Of-Memory issues and it is recommended to specify the amount of memory to use. - #[structopt(long, default_value)] + #[clap(long, default_value_t)] pub max_memory: MaxMemory, /// The name of the compression algorithm to use when compressing intermediate /// Grenad chunks while indexing documents. /// /// Choosing a fast algorithm will make the indexing faster but may consume more memory. - #[structopt(long, default_value = "snappy", possible_values = &["snappy", "zlib", "lz4", "lz4hc", "zstd"])] + #[clap(long, default_value = "snappy", possible_values = &["snappy", "zlib", "lz4", "lz4hc", "zstd"])] pub chunk_compression_type: CompressionType, /// The level of compression of the chosen algorithm. - #[structopt(long, requires = "chunk-compression-type")] + #[clap(long, requires = "chunk-compression-type")] pub chunk_compression_level: Option, /// Number of parallel jobs for indexing, defaults to # of CPUs. - #[structopt(long)] + #[clap(long)] pub indexing_jobs: Option, } diff --git a/meilisearch-lib/src/snapshot.rs b/meilisearch-lib/src/snapshot.rs index d35922a68..2e34d5427 100644 --- a/meilisearch-lib/src/snapshot.rs +++ b/meilisearch-lib/src/snapshot.rs @@ -49,7 +49,10 @@ pub fn load_snapshot( ignore_snapshot_if_db_exists: bool, ignore_missing_snapshot: bool, ) -> anyhow::Result<()> { - if !db_path.as_ref().exists() && snapshot_path.as_ref().exists() { + let empty_db = crate::is_empty_db(&db_path); + let snapshot_path_exists = snapshot_path.as_ref().exists(); + + if empty_db && snapshot_path_exists { match from_tar_gz(snapshot_path, &db_path) { Ok(()) => Ok(()), Err(e) => { @@ -58,7 +61,7 @@ pub fn load_snapshot( Err(e) } } - } else if db_path.as_ref().exists() && !ignore_snapshot_if_db_exists { + } else if !empty_db && !ignore_snapshot_if_db_exists { bail!( "database already exists at {:?}, try to delete it or rename it", db_path @@ -66,14 +69,8 @@ pub fn load_snapshot( .canonicalize() .unwrap_or_else(|_| db_path.as_ref().to_owned()) ) - } else if !snapshot_path.as_ref().exists() && !ignore_missing_snapshot { - bail!( - "snapshot doesn't exist at {:?}", - snapshot_path - .as_ref() - .canonicalize() - .unwrap_or_else(|_| snapshot_path.as_ref().to_owned()) - ) + } else if !snapshot_path_exists && !ignore_missing_snapshot { + bail!("snapshot doesn't exist at {:?}", snapshot_path.as_ref()) } else { Ok(()) } diff --git a/meilisearch-lib/src/tasks/mod.rs b/meilisearch-lib/src/tasks/mod.rs index fea5aa085..9d6de324a 100644 --- a/meilisearch-lib/src/tasks/mod.rs +++ b/meilisearch-lib/src/tasks/mod.rs @@ -32,7 +32,7 @@ pub trait TaskPerformer: Sync + Send + 'static { async fn finish(&self, batch: &Batch); } -pub fn create_task_store

(env: heed::Env, performer: Arc

) -> Result +pub fn create_task_store

(env: Arc, performer: Arc

) -> Result where P: TaskPerformer, { diff --git a/meilisearch-lib/src/tasks/task.rs b/meilisearch-lib/src/tasks/task.rs index add07f2ad..f5dd8d9be 100644 --- a/meilisearch-lib/src/tasks/task.rs +++ b/meilisearch-lib/src/tasks/task.rs @@ -55,7 +55,7 @@ pub enum TaskEvent { }, } -/// A task represents an operation that MeiliSearch must do. +/// A task represents an operation that Meilisearch must do. /// It's stored on disk and executed from the lowest to highest Task id. /// Everytime a new task is created it has a higher Task id than the previous one. /// See also `Job`. @@ -91,7 +91,7 @@ impl Task { /// A job is like a volatile priority `Task`. /// It should be processed as fast as possible and is not stored on disk. -/// This means, when MeiliSearch is closed all your unprocessed jobs will disappear. +/// This means, when Meilisearch is closed all your unprocessed jobs will disappear. #[derive(Debug, derivative::Derivative)] #[derivative(PartialEq)] pub enum Job { diff --git a/meilisearch-lib/src/tasks/task_store/mod.rs b/meilisearch-lib/src/tasks/task_store/mod.rs index 46b1c9cd1..d8e286ff3 100644 --- a/meilisearch-lib/src/tasks/task_store/mod.rs +++ b/meilisearch-lib/src/tasks/task_store/mod.rs @@ -114,7 +114,7 @@ impl Clone for TaskStore { } impl TaskStore { - pub fn new(env: heed::Env) -> Result { + pub fn new(env: Arc) -> Result { let mut store = Store::new(env)?; let unfinished_tasks = store.reset_and_return_unfinished_tasks()?; let store = Arc::new(store); @@ -293,7 +293,7 @@ impl TaskStore { Ok(()) } - pub fn load_dump(src: impl AsRef, env: Env) -> anyhow::Result<()> { + pub fn load_dump(src: impl AsRef, env: Arc) -> anyhow::Result<()> { // create a dummy update field store, since it is not needed right now. let store = Self::new(env.clone())?; @@ -340,7 +340,7 @@ pub mod test { } impl MockTaskStore { - pub fn new(env: heed::Env) -> Result { + pub fn new(env: Arc) -> Result { Ok(Self::Real(TaskStore::new(env)?)) } @@ -432,7 +432,7 @@ pub mod test { } } - pub fn load_dump(path: impl AsRef, env: Env) -> anyhow::Result<()> { + pub fn load_dump(path: impl AsRef, env: Arc) -> anyhow::Result<()> { TaskStore::load_dump(path, env) } } diff --git a/meilisearch-lib/src/tasks/task_store/store.rs b/meilisearch-lib/src/tasks/task_store/store.rs index 311eeaf98..49413f167 100644 --- a/meilisearch-lib/src/tasks/task_store/store.rs +++ b/meilisearch-lib/src/tasks/task_store/store.rs @@ -10,6 +10,7 @@ use std::convert::TryInto; use std::mem::size_of; 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}; @@ -53,18 +54,26 @@ impl<'a> BytesDecode<'a> for IndexUidTaskIdCodec { } pub struct Store { - env: Env, + env: Arc, uids_task_ids: Database, tasks: Database, SerdeJson>, } +impl Drop for Store { + fn drop(&mut self) { + if Arc::strong_count(&self.env) == 1 { + self.env.as_ref().clone().prepare_for_closing(); + } + } +} + impl Store { /// Create a new store from the specified `Path`. /// Be really cautious when calling this function, the returned `Store` may /// 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: heed::Env) -> 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))?; @@ -78,7 +87,7 @@ impl Store { /// This function should be called *right after* creating the store. /// It put back all unfinished update in the `Created` state. This /// allow us to re-enqueue an update that didn't had the time to finish - /// when MeiliSearch closed. + /// when Meilisearch closed. pub fn reset_and_return_unfinished_tasks(&mut self) -> Result>> { let mut unfinished_tasks: BinaryHeap> = BinaryHeap::new(); @@ -257,10 +266,10 @@ pub mod test { Fake(Mocker), } - pub struct TmpEnv(TempDir, heed::Env); + pub struct TmpEnv(TempDir, Arc); impl TmpEnv { - pub fn env(&self) -> heed::Env { + pub fn env(&self) -> Arc { self.1.clone() } } @@ -271,13 +280,13 @@ pub mod test { let mut options = EnvOpenOptions::new(); options.map_size(4096 * 100000); options.max_dbs(1000); - let env = options.open(tmp.path()).unwrap(); + let env = Arc::new(options.open(tmp.path()).unwrap()); TmpEnv(tmp, env) } impl MockStore { - pub fn new(env: heed::Env) -> Result { + pub fn new(env: Arc) -> Result { Ok(Self::Real(Store::new(env)?)) }