diff --git a/Cargo.lock b/Cargo.lock
index 6ec692e433..40d03882bd 100644
--- a/Cargo.lock
+++ b/Cargo.lock
@@ -10,9 +10,9 @@ checksum = "8b5ace29ee3216de37c0546865ad08edef58b0f9e76838ed8959a84a990e58c5"
[[package]]
name = "addr2line"
-version = "0.19.0"
+version = "0.21.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "a76fd60b23679b7d19bd066031410fb7e458ccc5e958eb5c325888ce4baedc97"
+checksum = "8a30b2e23b9e17a9f90641c7ab1549cd9b44f296d3ccbf309d2863cfe398a0cb"
dependencies = [
"gimli",
]
@@ -29,16 +29,16 @@ version = "0.7.7"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5a824f2aa7e75a0c98c5a504fceb80649e9c35265d44525b5f94de4771a395cd"
dependencies = [
- "getrandom 0.2.9",
+ "getrandom 0.2.11",
"once_cell",
"version_check",
]
[[package]]
name = "ahash"
-version = "0.8.5"
+version = "0.8.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "cd7d5a2cecb58716e47d67d5703a249964b14c7be1ec3cad3affc295b2d1c35d"
+checksum = "91429305e9f0a25f6205c5b8e0d2db09e0708a7a6df0f42212bb56c32c8ac97a"
dependencies = [
"cfg-if",
"once_cell",
@@ -48,13 +48,25 @@ dependencies = [
[[package]]
name = "aho-corasick"
-version = "1.0.1"
+version = "1.1.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "67fc08ce920c31afb70f013dcce1bfc3a3195de6a228474e45e1f145b36f8d04"
+checksum = "b2969dcb958b36655471fc61f7e416fa76033bdd4bfed0678d8fee1e2d07a1f0"
dependencies = [
"memchr",
]
+[[package]]
+name = "allocator-api2"
+version = "0.2.16"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "0942ffc6dcaadf03badf6e6a2d0228460359d5e34b57ccdc720b7382dfbd5ec5"
+
+[[package]]
+name = "android-tzdata"
+version = "0.1.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "e999941b234f3131b00bc13c22d06e8c5ff726d1b6318ac7eb276997bbb4fef0"
+
[[package]]
name = "android_system_properties"
version = "0.1.5"
@@ -72,30 +84,29 @@ checksum = "4b46cbb362ab8752921c97e041f5e366ee6297bd428a31275b9fcf1e380f7299"
[[package]]
name = "anstream"
-version = "0.3.2"
+version = "0.6.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "0ca84f3628370c59db74ee214b3263d58f9aadd9b4fe7e711fd87dc452b7f163"
+checksum = "2ab91ebe16eb252986481c5b62f6098f3b698a45e34b5b98200cf20dd2484a44"
dependencies = [
"anstyle",
"anstyle-parse",
"anstyle-query",
"anstyle-wincon",
"colorchoice",
- "is-terminal",
"utf8parse",
]
[[package]]
name = "anstyle"
-version = "1.0.0"
+version = "1.0.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "41ed9a86bf92ae6580e0a31281f65a1b1d867c0cc68d5346e2ae128dddfa6a7d"
+checksum = "7079075b41f533b8c61d2a4d073c4676e1f8b249ff94a393b0595db304e0dd87"
[[package]]
name = "anstyle-parse"
-version = "0.2.0"
+version = "0.2.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "e765fd216e48e067936442276d1d57399e37bce53c264d6fefbe298080cb57ee"
+checksum = "317b9a89c1868f5ea6ff1d9539a69f45dffc21ce321ac1fd1160dfa48c8e2140"
dependencies = [
"utf8parse",
]
@@ -111,9 +122,9 @@ dependencies = [
[[package]]
name = "anstyle-wincon"
-version = "1.0.1"
+version = "3.0.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "180abfa45703aebe0093f79badacc01b8fd4ea2e35118747e5811127f926e188"
+checksum = "f0699d10d2f4d628a98ee7b57b289abbc98ff3bad977cb3152709d4bf2330628"
dependencies = [
"anstyle",
"windows-sys 0.48.0",
@@ -121,9 +132,9 @@ dependencies = [
[[package]]
name = "anyhow"
-version = "1.0.71"
+version = "1.0.75"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "9c7d0618f0e0b7e8ff11427422b64564d5fb0be1940354bfe2e0529b18a9d9b8"
+checksum = "a4668cab20f66d8d020e1fbc0ebe47217433c1b6c8f2040faf858554e394ace6"
dependencies = [
"backtrace",
]
@@ -201,17 +212,17 @@ dependencies = [
[[package]]
name = "async-compression"
-version = "0.4.0"
+version = "0.4.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "5b0122885821398cc923ece939e24d1056a2384ee719432397fa9db87230ff11"
+checksum = "bc2d0cfb2a7388d34f590e76686704c494ed7aaceed62ee1ba35cbf363abc2a5"
dependencies = [
"flate2",
"futures-core",
"memchr",
"pin-project-lite",
"tokio",
- "zstd",
- "zstd-safe",
+ "zstd 0.13.0",
+ "zstd-safe 7.0.0",
]
[[package]]
@@ -242,25 +253,25 @@ checksum = "16e62a023e7c117e27523144c5d2459f4397fcc3cab0085af8e2224f643a0193"
dependencies = [
"proc-macro2",
"quote",
- "syn 2.0.28",
+ "syn 2.0.39",
]
[[package]]
name = "async-trait"
-version = "0.1.68"
+version = "0.1.74"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "b9ccdd8f2a161be9bd5c023df56f1b2a0bd1d83872ae53b71a84a12c9bf6e842"
+checksum = "a66537f1bb974b254c98ed142ff995236e81b9d0fe4db0575f46612cb15eb0f9"
dependencies = [
"proc-macro2",
"quote",
- "syn 2.0.28",
+ "syn 2.0.39",
]
[[package]]
name = "atomic-polyfill"
-version = "1.0.2"
+version = "1.0.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "c314e70d181aa6053b26e3f7fbf86d1dfff84f816a6175b967666b3506ef7289"
+checksum = "8cf2bce30dfe09ef0bfaef228b9d414faaf7e563035494d7fe092dba54b300f4"
dependencies = [
"critical-section",
]
@@ -284,72 +295,68 @@ checksum = "d468802bab17cbc0cc575e9b053f41e72aa36bfa6b7f55e3529ffa43161b97fa"
[[package]]
name = "aws-config"
-version = "0.56.0"
+version = "1.0.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "de3d533e0263bf453cc80af4c8bcc4d64e2aca293bd16f81633a36f1bf4a97cb"
+checksum = "80c950a809d39bc9480207cb1cfc879ace88ea7e3a4392a8e9999e45d6e5692e"
dependencies = [
"aws-credential-types",
"aws-http",
+ "aws-runtime",
"aws-sdk-sso",
+ "aws-sdk-ssooidc",
"aws-sdk-sts",
"aws-smithy-async",
- "aws-smithy-client",
"aws-smithy-http",
- "aws-smithy-http-tower",
"aws-smithy-json",
+ "aws-smithy-runtime",
+ "aws-smithy-runtime-api",
"aws-smithy-types",
"aws-types",
"bytes",
- "fastrand 2.0.0",
+ "fastrand 2.0.1",
"hex",
"http",
"hyper",
- "ring",
+ "ring 0.17.6",
"time",
"tokio",
- "tower",
"tracing",
"zeroize",
]
[[package]]
name = "aws-credential-types"
-version = "0.56.0"
+version = "1.0.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "e4834ba01c5ad1ed9740aa222de62190e3c565d11ab7e72cc68314a258994567"
+checksum = "8c1317e1a3514b103cf7d5828bbab3b4d30f56bd22d684f8568bc51b6cfbbb1c"
dependencies = [
"aws-smithy-async",
+ "aws-smithy-runtime-api",
"aws-smithy-types",
- "fastrand 2.0.0",
- "tokio",
- "tracing",
"zeroize",
]
[[package]]
name = "aws-http"
-version = "0.56.0"
+version = "0.60.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "72badf9de83cc7d66b21b004f09241836823b8302afb25a24708769e576a8d8f"
+checksum = "361c4310fdce94328cc2d1ca0c8a48c13f43009c61d3367585685a50ca8c66b6"
dependencies = [
- "aws-credential-types",
- "aws-smithy-http",
+ "aws-smithy-runtime-api",
"aws-smithy-types",
"aws-types",
"bytes",
"http",
"http-body",
- "lazy_static",
- "percent-encoding",
"pin-project-lite",
"tracing",
]
[[package]]
name = "aws-runtime"
-version = "0.56.0"
+version = "1.0.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "cf832f522111225c02547e1e1c28137e840e4b082399d93a236e4b29193a4667"
+checksum = "1ed7ef604a15fd0d4d9e43701295161ea6b504b63c44990ead352afea2bc15e9"
dependencies = [
"aws-credential-types",
"aws-http",
@@ -360,18 +367,18 @@ dependencies = [
"aws-smithy-runtime-api",
"aws-smithy-types",
"aws-types",
- "fastrand 2.0.0",
+ "fastrand 2.0.1",
"http",
"percent-encoding",
"tracing",
- "uuid 1.3.3",
+ "uuid 1.6.1",
]
[[package]]
name = "aws-sdk-s3"
-version = "0.29.0"
+version = "1.4.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "1e30370b61599168d38190ad272bb91842cd81870a6ca035c05dd5726d22832c"
+checksum = "9dcafc2fe52cc30b2d56685e2fa6a879ba50d79704594852112337a472ddbd24"
dependencies = [
"aws-credential-types",
"aws-http",
@@ -379,7 +386,6 @@ dependencies = [
"aws-sigv4",
"aws-smithy-async",
"aws-smithy-checksums",
- "aws-smithy-client",
"aws-smithy-eventstream",
"aws-smithy-http",
"aws-smithy-json",
@@ -394,22 +400,20 @@ dependencies = [
"once_cell",
"percent-encoding",
"regex",
- "tokio-stream",
"tracing",
"url",
]
[[package]]
name = "aws-sdk-sso"
-version = "0.29.0"
+version = "1.3.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "f41bf2c28d32dbb9894a8fcfcb148265d034d3f4a170552a47553a09de890895"
+checksum = "0619ab97a5ca8982e7de073cdc66f93e5f6a1b05afc09e696bec1cb3607cd4df"
dependencies = [
"aws-credential-types",
"aws-http",
"aws-runtime",
"aws-smithy-async",
- "aws-smithy-client",
"aws-smithy-http",
"aws-smithy-json",
"aws-smithy-runtime",
@@ -419,21 +423,41 @@ dependencies = [
"bytes",
"http",
"regex",
- "tokio-stream",
"tracing",
]
[[package]]
-name = "aws-sdk-sts"
-version = "0.29.0"
+name = "aws-sdk-ssooidc"
+version = "1.3.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "79e21aa1a5b0853969a1ef96ccfaa8ff5d57c761549786a4d5f86c1902b2586a"
+checksum = "f04b9f5474cc0f35d829510b2ec8c21e352309b46bf9633c5a81fb9321e9b1c7"
+dependencies = [
+ "aws-credential-types",
+ "aws-http",
+ "aws-runtime",
+ "aws-smithy-async",
+ "aws-smithy-http",
+ "aws-smithy-json",
+ "aws-smithy-runtime",
+ "aws-smithy-runtime-api",
+ "aws-smithy-types",
+ "aws-types",
+ "bytes",
+ "http",
+ "regex",
+ "tracing",
+]
+
+[[package]]
+name = "aws-sdk-sts"
+version = "1.3.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "798c8d82203af9e15a8b406574e0b36da91dd6db533028b74676489a1bc8bc7d"
dependencies = [
"aws-credential-types",
"aws-http",
"aws-runtime",
"aws-smithy-async",
- "aws-smithy-client",
"aws-smithy-http",
"aws-smithy-json",
"aws-smithy-query",
@@ -449,42 +473,49 @@ dependencies = [
[[package]]
name = "aws-sigv4"
-version = "0.56.0"
+version = "1.0.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "2cb40a93429794065f41f0581734fc56a345f6a38d8e2e3c25c7448d930cd132"
+checksum = "380adcc8134ad8bbdfeb2ace7626a869914ee266322965276cbc54066186d236"
dependencies = [
+ "aws-credential-types",
"aws-smithy-eventstream",
"aws-smithy-http",
+ "aws-smithy-runtime-api",
+ "aws-smithy-types",
"bytes",
+ "crypto-bigint 0.5.5",
"form_urlencoded",
"hex",
"hmac",
"http",
"once_cell",
+ "p256",
"percent-encoding",
"regex",
+ "ring 0.17.6",
"sha2",
+ "subtle",
"time",
"tracing",
+ "zeroize",
]
[[package]]
name = "aws-smithy-async"
-version = "0.56.0"
+version = "1.0.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "6ee6d17d487c8b579423067718b3580c0908d0f01d7461813f94ec4323bad623"
+checksum = "3e37ca17d25fe1e210b6d4bdf59b81caebfe99f986201a1228cb5061233b4b13"
dependencies = [
"futures-util",
"pin-project-lite",
"tokio",
- "tokio-stream",
]
[[package]]
name = "aws-smithy-checksums"
-version = "0.56.0"
+version = "0.60.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "0d1849fd5916904513fb0862543b36f8faab43c07984dbc476132b7da1aed056"
+checksum = "c5a373ec01aede3dd066ec018c1bc4e8f5dd11b2c11c59c8eef1a5c68101f397"
dependencies = [
"aws-smithy-http",
"aws-smithy-types",
@@ -501,35 +532,11 @@ dependencies = [
"tracing",
]
-[[package]]
-name = "aws-smithy-client"
-version = "0.56.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "bdbe0a3ad15283cc5f863a68cb6adc8e256e7c109c43c01bdd09be407219a1e9"
-dependencies = [
- "aws-smithy-async",
- "aws-smithy-http",
- "aws-smithy-http-tower",
- "aws-smithy-types",
- "bytes",
- "fastrand 2.0.0",
- "http",
- "http-body",
- "hyper",
- "hyper-rustls",
- "lazy_static",
- "pin-project-lite",
- "rustls",
- "tokio",
- "tower",
- "tracing",
-]
-
[[package]]
name = "aws-smithy-eventstream"
-version = "0.56.0"
+version = "0.60.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "a56afef1aa766f512b4970b4c3150b9bf2df8035939723830df4b30267e2d7cb"
+checksum = "1c669e1e5fc0d79561bf7a122b118bd50c898758354fe2c53eb8f2d31507cbc3"
dependencies = [
"aws-smithy-types",
"bytes",
@@ -538,57 +545,39 @@ dependencies = [
[[package]]
name = "aws-smithy-http"
-version = "0.56.0"
+version = "0.60.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "34dc313472d727f5ef44fdda93e668ebfe17380c99dee512c403e3ca51863bb9"
+checksum = "5b1de8aee22f67de467b2e3d0dd0fb30859dc53f579a63bd5381766b987db644"
dependencies = [
"aws-smithy-eventstream",
+ "aws-smithy-runtime-api",
"aws-smithy-types",
"bytes",
"bytes-utils",
"futures-core",
"http",
"http-body",
- "hyper",
"once_cell",
"percent-encoding",
"pin-project-lite",
"pin-utils",
- "tokio",
- "tokio-util",
- "tracing",
-]
-
-[[package]]
-name = "aws-smithy-http-tower"
-version = "0.56.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "1dd50fca5a4ea4ec3771689ee93bf06b32de02a80af01ed93a8f8a4ed90e8483"
-dependencies = [
- "aws-smithy-http",
- "aws-smithy-types",
- "bytes",
- "http",
- "http-body",
- "pin-project-lite",
- "tower",
"tracing",
]
[[package]]
name = "aws-smithy-json"
-version = "0.56.0"
+version = "0.60.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "3591dd7c2fe01ab8025e4847a0a0f6d0c2b2269714688ffb856f9cf6c6d465cf"
+checksum = "6a46dd338dc9576d6a6a5b5a19bd678dcad018ececee11cf28ecd7588bd1a55c"
dependencies = [
"aws-smithy-types",
]
[[package]]
name = "aws-smithy-query"
-version = "0.56.0"
+version = "0.60.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "dbabb1145e65dd57ae72d91a2619d3f5fba40b68a5f40ba009c30571dfd60aff"
+checksum = "feb5b8c7a86d4b6399169670723b7e6f21a39fc833a30f5c5a2f997608178129"
dependencies = [
"aws-smithy-types",
"urlencoding",
@@ -596,74 +585,86 @@ dependencies = [
[[package]]
name = "aws-smithy-runtime"
-version = "0.56.0"
+version = "1.0.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "3687fb838d4ad1c883b62eb59115bc9fb02c4f308aac49a7df89627067f6eb0d"
+checksum = "273479291efc55e7b0bce985b139d86b6031adb8e50f65c1f712f20ba38f6388"
dependencies = [
"aws-smithy-async",
- "aws-smithy-client",
"aws-smithy-http",
"aws-smithy-runtime-api",
"aws-smithy-types",
"bytes",
- "fastrand 2.0.0",
+ "fastrand 2.0.1",
+ "h2",
"http",
"http-body",
+ "hyper",
+ "hyper-rustls",
"once_cell",
"pin-project-lite",
"pin-utils",
+ "rustls",
"tokio",
"tracing",
]
[[package]]
name = "aws-smithy-runtime-api"
-version = "0.56.0"
+version = "1.0.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "5cfbf1e5c2108b41f5ca607cde40dd5109fecc448f5d30c8e614b61f36dce704"
+checksum = "c6cebff0d977b6b6feed2fd07db52aac58ba3ccaf26cdd49f1af4add5061bef9"
dependencies = [
"aws-smithy-async",
- "aws-smithy-http",
"aws-smithy-types",
"bytes",
"http",
+ "pin-project-lite",
"tokio",
"tracing",
+ "zeroize",
]
[[package]]
name = "aws-smithy-types"
-version = "0.56.0"
+version = "1.0.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "eed0a94eefd845a2a78677f1b72f02fa75802d38f7f59be675add140279aa8bf"
+checksum = "d7f48b3f27ddb40ab19892a5abda331f403e3cb877965e4e51171447807104af"
dependencies = [
"base64-simd",
+ "bytes",
+ "bytes-utils",
+ "futures-core",
+ "http",
+ "http-body",
"itoa",
"num-integer",
+ "pin-project-lite",
+ "pin-utils",
"ryu",
"serde",
"time",
+ "tokio",
+ "tokio-util",
]
[[package]]
name = "aws-smithy-xml"
-version = "0.56.0"
+version = "0.60.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "c88052c812f696143ad7ba729c63535209ff0e0f49e31a6d2b1205208ea6ea79"
+checksum = "0ec40d74a67fd395bc3f6b4ccbdf1543672622d905ef3f979689aea5b730cb95"
dependencies = [
"xmlparser",
]
[[package]]
name = "aws-types"
-version = "0.56.0"
+version = "1.0.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "6bceb8cf724ad057ad7f327d0d256d7147b3eac777b39849a26189e003dc9782"
+checksum = "8403fc56b1f3761e8efe45771ddc1165e47ec3417c68e68a4519b5cb030159ca"
dependencies = [
"aws-credential-types",
"aws-smithy-async",
- "aws-smithy-client",
- "aws-smithy-http",
+ "aws-smithy-runtime-api",
"aws-smithy-types",
"http",
"rustc_version",
@@ -678,8 +679,8 @@ checksum = "3b829e4e32b91e643de6eafe82b1d90675f5874230191a4ffbc1b336dec4d6bf"
dependencies = [
"async-trait",
"axum-core",
- "base64 0.21.1",
- "bitflags",
+ "base64 0.21.5",
+ "bitflags 1.3.2",
"bytes",
"futures-util",
"http",
@@ -729,11 +730,11 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8e29286b9edfdd6f2c7e9d970bb5b015df8621258acab9ecfcea09b2d7692467"
dependencies = [
"async-trait",
- "base64 0.21.1",
+ "base64 0.21.5",
"bytes",
"dyn-clone",
"futures",
- "getrandom 0.2.9",
+ "getrandom 0.2.11",
"http-types",
"log",
"paste",
@@ -746,7 +747,7 @@ dependencies = [
"serde_json",
"time",
"url",
- "uuid 1.3.3",
+ "uuid 1.6.1",
]
[[package]]
@@ -767,7 +768,7 @@ dependencies = [
"time",
"tz-rs",
"url",
- "uuid 1.3.3",
+ "uuid 1.6.1",
]
[[package]]
@@ -789,7 +790,7 @@ dependencies = [
"sha2",
"time",
"url",
- "uuid 1.3.3",
+ "uuid 1.6.1",
]
[[package]]
@@ -809,24 +810,30 @@ dependencies = [
"serde_json",
"time",
"url",
- "uuid 1.3.3",
+ "uuid 1.6.1",
]
[[package]]
name = "backtrace"
-version = "0.3.67"
+version = "0.3.69"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "233d376d6d185f2a3093e58f283f60f880315b6c60075b01f36b3b85154564ca"
+checksum = "2089b7e3f35b9dd2d0ed921ead4f6d318c27680d4a5bd167b3ee120edb105837"
dependencies = [
"addr2line",
"cc",
"cfg-if",
"libc",
- "miniz_oxide 0.6.2",
+ "miniz_oxide",
"object",
"rustc-demangle",
]
+[[package]]
+name = "base16ct"
+version = "0.1.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "349a06037c7bf932dd7e7d1f653678b2038b9ad46a74102f1fc7bd7872678cce"
+
[[package]]
name = "base64"
version = "0.13.1"
@@ -841,9 +848,9 @@ checksum = "0ea22880d78093b0cbe17c89f64a7d457941e65759157ec6cb31a31d652b05e5"
[[package]]
name = "base64"
-version = "0.21.1"
+version = "0.21.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "3f1e31e207a6b8fb791a38ea3105e6cb541f55e4d029902d3039a4ad07cc4105"
+checksum = "35636a1494ede3b646cc98f74f8e62c773a38a659ebc777a2cf26b9b74171df9"
[[package]]
name = "base64-simd"
@@ -876,20 +883,20 @@ version = "0.65.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "cfdf7b466f9a4903edc73f95d6d2bcd5baf8ae620638762244d3f60143643cc5"
dependencies = [
- "bitflags",
+ "bitflags 1.3.2",
"cexpr",
"clang-sys",
"lazy_static",
"lazycell",
"log",
"peeking_take_while",
- "prettyplease 0.2.6",
+ "prettyplease 0.2.15",
"proc-macro2",
"quote",
"regex",
"rustc-hash",
"shlex",
- "syn 2.0.28",
+ "syn 2.0.39",
"which",
]
@@ -899,6 +906,12 @@ version = "1.3.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a"
+[[package]]
+name = "bitflags"
+version = "2.4.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "327762f6e5a765692301e5bb513e0d9fef63be86bbc14528052b1cd3e6f03e07"
+
[[package]]
name = "block-buffer"
version = "0.10.4"
@@ -910,21 +923,20 @@ dependencies = [
[[package]]
name = "bstr"
-version = "1.5.0"
+version = "1.8.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "a246e68bb43f6cd9db24bea052a53e40405417c5fb372e3d1a8a7f770a564ef5"
+checksum = "542f33a8835a0884b006a0c3df3dadd99c0c3f296ed26c2fdc8028e01ad6230c"
dependencies = [
"memchr",
- "once_cell",
- "regex-automata",
+ "regex-automata 0.4.3",
"serde",
]
[[package]]
name = "bumpalo"
-version = "3.13.0"
+version = "3.14.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "a3e2c3daef883ecc1b5d58c15adae93470a91d425f3532ba1695849656af3fc1"
+checksum = "7f30e7476521f6f8af1a1c4c0b8cc94f0bee37d91763d0ca2665f299b6cd8aec"
[[package]]
name = "bytemuck"
@@ -934,24 +946,24 @@ checksum = "374d28ec25809ee0e23827c2ab573d729e293f281dfe393500e7ad618baa61c6"
[[package]]
name = "byteorder"
-version = "1.4.3"
+version = "1.5.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "14c189c53d098945499cdfa7ecc63567cf3886b3332b312a5b4585d8d3a6a610"
+checksum = "1fd0f2584146f6f2ef48085050886acf353beff7305ebd1ae69500e27c67f64b"
[[package]]
name = "bytes"
-version = "1.4.0"
+version = "1.5.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "89b2fd2a0dcf38d7971e2194b6b6eebab45ae01067456a7fd93d5547a61b70be"
+checksum = "a2bd12c1caf447e69cd4528f47f94d203fd2582878ecb9e9465484c4148a8223"
dependencies = [
"serde",
]
[[package]]
name = "bytes-utils"
-version = "0.1.3"
+version = "0.1.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "e47d3a8076e283f3acd27400535992edb3ba4b5bb72f8891ad8fbe7932a7d4b9"
+checksum = "7dafe3a8757b027e2be6e4e5601ed563c55989fcf1546e933c66c8eb3a058d35"
dependencies = [
"bytes",
"either",
@@ -965,9 +977,9 @@ checksum = "c59e92b5a388f549b863a7bea62612c09f24c8393560709a54558a9abdfb3b9c"
[[package]]
name = "camino-tempfile"
-version = "1.0.2"
+version = "1.1.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "d2ab15a83d13f75dbd86f082bdefd160b628476ef58d3b900a0ef74e001bb097"
+checksum = "cb905055fa81e4d427f919b2cd0d76a998267de7d225ea767a1894743a5263c2"
dependencies = [
"camino",
"tempfile",
@@ -981,11 +993,12 @@ checksum = "37b2a672a2cb129a2e41c10b1224bb368f9f37a2b16b612598138befd7b37eb5"
[[package]]
name = "cc"
-version = "1.0.79"
+version = "1.0.83"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "50d30906286121d95be3d479533b458f87493b30a4b5f79a607db8f5d11aa91f"
+checksum = "f1174fb0b6ec23863f8b971027804a42614e347eafb0a95bf0b12cdae21fc4d0"
dependencies = [
"jobserver",
+ "libc",
]
[[package]]
@@ -1005,9 +1018,9 @@ checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd"
[[package]]
name = "cgroups-rs"
-version = "0.3.3"
+version = "0.3.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "1fb3af90c8d48ad5f432d8afb521b5b40c2a2fce46dd60e05912de51c47fba64"
+checksum = "6db7c2f5545da4c12c5701455d9471da5f07db52e49b9cccb4f5512226dd0836"
dependencies = [
"libc",
"log",
@@ -1018,17 +1031,17 @@ dependencies = [
[[package]]
name = "chrono"
-version = "0.4.24"
+version = "0.4.31"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "4e3c5919066adf22df73762e50cffcde3a758f2a848b113b586d1f86728b673b"
+checksum = "7f2c685bad3eb3d45a01354cedb7d5faa66194d1d58ba6e267a8de788f79db38"
dependencies = [
+ "android-tzdata",
"iana-time-zone",
"js-sys",
- "num-integer",
"num-traits",
"serde",
"wasm-bindgen",
- "winapi",
+ "windows-targets 0.48.5",
]
[[package]]
@@ -1071,45 +1084,43 @@ dependencies = [
[[package]]
name = "clap"
-version = "4.3.0"
+version = "4.4.10"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "93aae7a4192245f70fe75dd9157fc7b4a5bf53e88d30bd4396f7d8f9284d5acc"
+checksum = "41fffed7514f420abec6d183b1d3acfd9099c79c3a10a06ade4f8203f1411272"
dependencies = [
"clap_builder",
"clap_derive",
- "once_cell",
]
[[package]]
name = "clap_builder"
-version = "4.3.0"
+version = "4.4.9"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "4f423e341edefb78c9caba2d9c7f7687d0e72e89df3ce3394554754393ac3990"
+checksum = "63361bae7eef3771745f02d8d892bec2fee5f6e34af316ba556e7f97a7069ff1"
dependencies = [
"anstream",
"anstyle",
- "bitflags",
"clap_lex",
"strsim",
]
[[package]]
name = "clap_derive"
-version = "4.3.0"
+version = "4.4.7"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "191d9573962933b4027f932c600cd252ce27a8ad5979418fe78e43c07996f27b"
+checksum = "cf9804afaaf59a91e75b022a30fb7229a7901f60c755489cc61c9b423b836442"
dependencies = [
"heck",
"proc-macro2",
"quote",
- "syn 2.0.28",
+ "syn 2.0.39",
]
[[package]]
name = "clap_lex"
-version = "0.5.0"
+version = "0.6.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "2da6da31387c7e4ef160ffab6d5e7f00c42626fe39aea70a7b0f1773f7dd6c1b"
+checksum = "702fc72eb24e5a1e48ce58027a675bc24edd52096d5397d4aea7c6dd9eca0bd1"
[[package]]
name = "close_fds"
@@ -1129,9 +1140,9 @@ checksum = "acbf1af155f9b9ef647e42cdc158db4b64a1b61f743629225fde6f3e0be2a7c7"
[[package]]
name = "comfy-table"
-version = "6.1.4"
+version = "6.2.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "6e7b787b0dc42e8111badfdbe4c3059158ccb2db8780352fa1b01e8ccf45cc4d"
+checksum = "7e959d788268e3bf9d35ace83e81b124190378e4c91c9067524675e33394b8ba"
dependencies = [
"crossterm",
"strum",
@@ -1190,7 +1201,7 @@ dependencies = [
"utils",
"vm_monitor",
"workspace_hack",
- "zstd",
+ "zstd 0.12.4",
]
[[package]]
@@ -1202,6 +1213,12 @@ dependencies = [
"crossbeam-utils",
]
+[[package]]
+name = "const-oid"
+version = "0.9.5"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "28c122c3980598d243d63d9a704629a2d748d101f278052ff068be5a4423ab6f"
+
[[package]]
name = "const_fn"
version = "0.4.9"
@@ -1210,18 +1227,18 @@ checksum = "fbdcdcb6d86f71c5e97409ad45898af11cbc995b4ee8112d59095a28d376c935"
[[package]]
name = "const_format"
-version = "0.2.30"
+version = "0.2.32"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "7309d9b4d3d2c0641e018d449232f2e28f1b22933c137f157d3dbc14228b8c0e"
+checksum = "e3a214c7af3d04997541b18d432afaff4c455e79e2029079647e72fc2bd27673"
dependencies = [
"const_format_proc_macros",
]
[[package]]
name = "const_format_proc_macros"
-version = "0.2.29"
+version = "0.2.32"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "d897f47bf7270cf70d370f8f98c1abb6d2d4cf60a6845d30e05bfb90c6568650"
+checksum = "c7f6ff08fd20f4f299298a28e2dfa8a8ba1036e6cd2460ac1de7b425d76f2500"
dependencies = [
"proc-macro2",
"quote",
@@ -1253,7 +1270,7 @@ dependencies = [
"git-version",
"hex",
"hyper",
- "nix 0.26.2",
+ "nix 0.26.4",
"once_cell",
"pageserver_api",
"postgres",
@@ -1278,9 +1295,9 @@ dependencies = [
[[package]]
name = "core-foundation"
-version = "0.9.3"
+version = "0.9.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "194a7a9e6de53fa55116934067c844d9d749312f75c6f6d0980e8c252f8c2146"
+checksum = "91e195e091a93c46f7102ec7818a2aa394e1e1771c3ab4825963fa03e45afb8f"
dependencies = [
"core-foundation-sys",
"libc",
@@ -1288,9 +1305,9 @@ dependencies = [
[[package]]
name = "core-foundation-sys"
-version = "0.8.4"
+version = "0.8.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "e496a50fda8aacccc86d7529e2c1e0892dbd0f898a6b5645b5561b89c3210efa"
+checksum = "06ea2b9bc92be3c2baa9334a323ebca2d6f074ff852cd1d7b11064035cd3868f"
[[package]]
name = "cpp_demangle"
@@ -1303,18 +1320,18 @@ dependencies = [
[[package]]
name = "cpufeatures"
-version = "0.2.9"
+version = "0.2.11"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "a17b76ff3a4162b0b27f354a0c87015ddad39d35f9c0c36607a3bdd175dde1f1"
+checksum = "ce420fe07aecd3e67c5f910618fe65e94158f6dcc0adf44e00d69ce2bdfe0fd0"
dependencies = [
"libc",
]
[[package]]
name = "crc32c"
-version = "0.6.3"
+version = "0.6.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "3dfea2db42e9927a3845fb268a10a72faed6d416065f77873f05e411457c363e"
+checksum = "d8f48d60e5b4d2c53d5c2b1d8a58c849a70ae5e5509b08a48d047e3b65714a74"
dependencies = [
"rustc_version",
]
@@ -1366,9 +1383,9 @@ dependencies = [
[[package]]
name = "critical-section"
-version = "1.1.1"
+version = "1.1.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "6548a0ad5d2549e111e1f6a11a6c2e2d00ce6a3dafe22948d67c2b443f775e52"
+checksum = "7059fff8937831a9ae6f0fe4d658ffabf58f2ca96aa9dec1c889f936f705f216"
[[package]]
name = "crossbeam-channel"
@@ -1393,33 +1410,33 @@ dependencies = [
[[package]]
name = "crossbeam-epoch"
-version = "0.9.14"
+version = "0.9.15"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "46bd5f3f85273295a9d14aedfb86f6aadbff6d8f5295c4a9edb08e819dcf5695"
+checksum = "ae211234986c545741a7dc064309f67ee1e5ad243d0e48335adc0484d960bcc7"
dependencies = [
"autocfg",
"cfg-if",
"crossbeam-utils",
- "memoffset 0.8.0",
+ "memoffset 0.9.0",
"scopeguard",
]
[[package]]
name = "crossbeam-utils"
-version = "0.8.15"
+version = "0.8.16"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "3c063cd8cc95f5c377ed0d4b49a4b21f632396ff690e8470c29b3359b346984b"
+checksum = "5a22b2d63d4d1dc0b7f1b6b2747dd0088008a9be28b6ddf0b1e7d335e3037294"
dependencies = [
"cfg-if",
]
[[package]]
name = "crossterm"
-version = "0.25.0"
+version = "0.26.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "e64e6c0fbe2c17357405f7c758c1ef960fce08bdfb2c03d88d2a18d7e09c4b67"
+checksum = "a84cda67535339806297f1b331d6dd6320470d2a0fe65381e79ee9e156dd3d13"
dependencies = [
- "bitflags",
+ "bitflags 1.3.2",
"crossterm_winapi",
"libc",
"mio",
@@ -1431,13 +1448,35 @@ dependencies = [
[[package]]
name = "crossterm_winapi"
-version = "0.9.0"
+version = "0.9.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "2ae1b35a484aa10e07fe0638d02301c5ad24de82d310ccbd2f3693da5f09bf1c"
+checksum = "acdd7c62a3665c7f6830a51635d9ac9b23ed385797f70a83bb8bafe9c572ab2b"
dependencies = [
"winapi",
]
+[[package]]
+name = "crypto-bigint"
+version = "0.4.9"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "ef2b4b23cddf68b89b8f8069890e8c270d54e2d5fe1b143820234805e4cb17ef"
+dependencies = [
+ "generic-array",
+ "rand_core 0.6.4",
+ "subtle",
+ "zeroize",
+]
+
+[[package]]
+name = "crypto-bigint"
+version = "0.5.5"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "0dc92fb57ca44df6db8059111ab3af99a63d5d0f8375d9972e319a379c6bab76"
+dependencies = [
+ "rand_core 0.6.4",
+ "subtle",
+]
+
[[package]]
name = "crypto-common"
version = "0.1.6"
@@ -1450,9 +1489,9 @@ dependencies = [
[[package]]
name = "darling"
-version = "0.20.1"
+version = "0.20.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "0558d22a7b463ed0241e993f76f09f30b126687447751a8638587b864e4b3944"
+checksum = "0209d94da627ab5605dcccf08bb18afa5009cfbef48d8a8b7d7bdbc79be25c5e"
dependencies = [
"darling_core",
"darling_macro",
@@ -1460,47 +1499,47 @@ dependencies = [
[[package]]
name = "darling_core"
-version = "0.20.1"
+version = "0.20.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "ab8bfa2e259f8ee1ce5e97824a3c55ec4404a0d772ca7fa96bf19f0752a046eb"
+checksum = "177e3443818124b357d8e76f53be906d60937f0d3a90773a664fa63fa253e621"
dependencies = [
"fnv",
"ident_case",
"proc-macro2",
"quote",
"strsim",
- "syn 2.0.28",
+ "syn 2.0.39",
]
[[package]]
name = "darling_macro"
-version = "0.20.1"
+version = "0.20.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "29a358ff9f12ec09c3e61fef9b5a9902623a695a46a917b07f269bff1445611a"
+checksum = "836a9bbc7ad63342d6d6e7b815ccab164bc77a2d95d84bc3117a8c0d5c98e2d5"
dependencies = [
"darling_core",
"quote",
- "syn 2.0.28",
+ "syn 2.0.39",
]
[[package]]
name = "dashmap"
-version = "5.5.0"
+version = "5.5.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "6943ae99c34386c84a470c499d3414f66502a41340aa895406e0d2e4a207b91d"
+checksum = "978747c1d849a7d2ee5e8adc0159961c48fb7e5db2f06af6723b80123bb53856"
dependencies = [
"cfg-if",
- "hashbrown 0.14.0",
+ "hashbrown 0.14.3",
"lock_api",
"once_cell",
- "parking_lot_core 0.9.8",
+ "parking_lot_core 0.9.9",
]
[[package]]
name = "data-encoding"
-version = "2.4.0"
+version = "2.5.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "c2e66c9d817f1720209181c316d28635c050fa304f9c79e47a520882661b7308"
+checksum = "7e962a19be5cfc3f3bf6dd8f61eb50107f356ad6270fbb3ed41476571db78be5"
[[package]]
name = "debugid"
@@ -1518,7 +1557,17 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "bef552e6f588e446098f6ba40d89ac146c8c7b64aade83c051ee00bb5d2bc18d"
dependencies = [
"serde",
- "uuid 1.3.3",
+ "uuid 1.6.1",
+]
+
+[[package]]
+name = "der"
+version = "0.6.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "f1a467a65c5e759bce6e65eaf91cc29f466cdc57cb65777bd646872a8a1fd4de"
+dependencies = [
+ "const-oid",
+ "zeroize",
]
[[package]]
@@ -1535,6 +1584,16 @@ dependencies = [
"rusticata-macros",
]
+[[package]]
+name = "deranged"
+version = "0.3.9"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "0f32d04922c60427da6f9fef14d042d9edddef64cb9d4ce0d64d0685fbeb1fd3"
+dependencies = [
+ "powerfmt",
+ "serde",
+]
+
[[package]]
name = "digest"
version = "0.10.7"
@@ -1554,55 +1613,87 @@ checksum = "487585f4d0c6655fe74905e2504d8ad6908e4db67f744eb140876906c2f3175d"
dependencies = [
"proc-macro2",
"quote",
- "syn 2.0.28",
+ "syn 2.0.39",
]
[[package]]
name = "dyn-clone"
-version = "1.0.14"
+version = "1.0.16"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "23d2f3407d9a573d666de4b5bdf10569d73ca9478087346697dcbae6244bfbcd"
+checksum = "545b22097d44f8a9581187cdf93de7a71e4722bf51200cfaba810865b49a495d"
+
+[[package]]
+name = "ecdsa"
+version = "0.14.8"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "413301934810f597c1d19ca71c8710e99a3f1ba28a0d2ebc01551a2daeea3c5c"
+dependencies = [
+ "der",
+ "elliptic-curve",
+ "rfc6979",
+ "signature",
+]
[[package]]
name = "either"
-version = "1.8.1"
+version = "1.9.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "7fcaabb2fef8c910e7f4c7ce9f67a1283a1715879a7c230ca9d6d1ae31f16d91"
+checksum = "a26ae43d7bcc3b814de94796a5e736d4029efb0ee900c12e2d54c993ad1a1e07"
+
+[[package]]
+name = "elliptic-curve"
+version = "0.12.3"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "e7bb888ab5300a19b8e5bceef25ac745ad065f3c9f7efc6de1b91958110891d3"
+dependencies = [
+ "base16ct",
+ "crypto-bigint 0.4.9",
+ "der",
+ "digest",
+ "ff",
+ "generic-array",
+ "group",
+ "pkcs8",
+ "rand_core 0.6.4",
+ "sec1",
+ "subtle",
+ "zeroize",
+]
[[package]]
name = "encoding_rs"
-version = "0.8.32"
+version = "0.8.33"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "071a31f4ee85403370b58aca746f01041ede6f0da2730960ad001edc2b71b394"
+checksum = "7268b386296a025e474d5140678f75d6de9493ae55a5d709eeb9dd08149945e1"
dependencies = [
"cfg-if",
]
[[package]]
name = "enum-map"
-version = "2.5.0"
+version = "2.7.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "988f0d17a0fa38291e5f41f71ea8d46a5d5497b9054d5a759fae2cbb819f2356"
+checksum = "6866f3bfdf8207509a033af1a75a7b08abda06bbaaeae6669323fd5a097df2e9"
dependencies = [
"enum-map-derive",
]
[[package]]
name = "enum-map-derive"
-version = "0.11.0"
+version = "0.17.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "2a4da76b3b6116d758c7ba93f7ec6a35d2e2cf24feda76c6e38a375f4d5c59f2"
+checksum = "f282cfdfe92516eb26c2af8589c274c7c17681f5ecc03c18255fe741c6aa64eb"
dependencies = [
"proc-macro2",
"quote",
- "syn 1.0.109",
+ "syn 2.0.39",
]
[[package]]
name = "enumset"
-version = "1.1.2"
+version = "1.1.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "e875f1719c16de097dee81ed675e2d9bb63096823ed3f0ca827b7dea3028bbbb"
+checksum = "226c0da7462c13fb57e5cc9e0dc8f0635e7d27f276a3a7fd30054647f669007d"
dependencies = [
"enumset_derive",
]
@@ -1616,14 +1707,14 @@ dependencies = [
"darling",
"proc-macro2",
"quote",
- "syn 2.0.28",
+ "syn 2.0.39",
]
[[package]]
name = "env_logger"
-version = "0.10.0"
+version = "0.10.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "85cdab6a89accf66733ad5a1693a4dcced6aeff64602b634530dd73c1f3ee9f0"
+checksum = "95b3f3e67048839cb0d0781f445682a35113da7121f7c949db0e2be96a4fbece"
dependencies = [
"humantime",
"is-terminal",
@@ -1633,24 +1724,19 @@ dependencies = [
]
[[package]]
-name = "errno"
-version = "0.3.1"
+name = "equivalent"
+version = "1.0.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "4bcfec3a70f97c962c307b2d2c56e358cf1d00b558d74262b5f929ee8cc7e73a"
-dependencies = [
- "errno-dragonfly",
- "libc",
- "windows-sys 0.48.0",
-]
+checksum = "5443807d6dff69373d433ab9ef5378ad8df50ca6298caf15de6e52e24aaf54d5"
[[package]]
-name = "errno-dragonfly"
-version = "0.1.2"
+name = "errno"
+version = "0.3.8"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "aa68f1b12764fab894d2755d2518754e71b4fd80ecfb822714a1206c2aab39bf"
+checksum = "a258e46cdc063eb8519c00b9fc845fc47bcfca4130e2f08e88665ceda8474245"
dependencies = [
- "cc",
"libc",
+ "windows-sys 0.52.0",
]
[[package]]
@@ -1687,19 +1773,29 @@ dependencies = [
[[package]]
name = "fastrand"
-version = "2.0.0"
+version = "2.0.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "6999dc1837253364c2ebb0704ba97994bd874e8f195d665c50b7548f6ea92764"
+checksum = "25cbce373ec4653f1a01a31e8a5e5ec0c622dc27ff9c4e6606eefef5cbbed4a5"
+
+[[package]]
+name = "ff"
+version = "0.12.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "d013fc25338cc558c5c2cfbad646908fb23591e2404481826742b651c9af7160"
+dependencies = [
+ "rand_core 0.6.4",
+ "subtle",
+]
[[package]]
name = "filetime"
-version = "0.2.21"
+version = "0.2.22"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "5cbc844cecaee9d4443931972e1289c8ff485cb4cc2767cb03ca139ed6885153"
+checksum = "d4029edd3e734da6fe05b6cd7bd2960760a616bd2ddd0d59a0124746d6272af0"
dependencies = [
"cfg-if",
"libc",
- "redox_syscall 0.2.16",
+ "redox_syscall 0.3.5",
"windows-sys 0.48.0",
]
@@ -1715,6 +1811,12 @@ dependencies = [
"winapi",
]
+[[package]]
+name = "finl_unicode"
+version = "1.2.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "8fcfdc7a0362c9f4444381a9e697c79d435fe65b52a37466fc2c1184cee9edc6"
+
[[package]]
name = "fixedbitset"
version = "0.4.2"
@@ -1723,12 +1825,12 @@ checksum = "0ce7134b9999ecaf8bcd65542e436736ef32ddca1b3e06094cb6ec5755203b80"
[[package]]
name = "flate2"
-version = "1.0.26"
+version = "1.0.28"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "3b9429470923de8e8cbd4d2dc513535400b4b3fef0319fb5c4e1f520a7bef743"
+checksum = "46303f565772937ffe1d394a4fac6f411c6013172fadde9dcdb1e147a086940e"
dependencies = [
"crc32fast",
- "miniz_oxide 0.7.1",
+ "miniz_oxide",
]
[[package]]
@@ -1754,9 +1856,9 @@ checksum = "00b0228411908ca8685dba7fc2cdd70ec9990a6e753e89b6ac91a84c40fbaf4b"
[[package]]
name = "form_urlencoded"
-version = "1.1.0"
+version = "1.2.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "a9c384f161156f5260c24a097c56119f9be8c798586aecc13afbcbe7b7e26bf8"
+checksum = "e13624c2627564efccf4934284bdd98cbaa14e79b0b5a141218e507b3a823456"
dependencies = [
"percent-encoding",
]
@@ -1782,9 +1884,9 @@ dependencies = [
[[package]]
name = "futures"
-version = "0.3.28"
+version = "0.3.29"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "23342abe12aba583913b2e62f22225ff9c950774065e4bfb61a19cd9770fec40"
+checksum = "da0290714b38af9b4a7b094b8a37086d1b4e61f2df9122c3cad2577669145335"
dependencies = [
"futures-channel",
"futures-core",
@@ -1797,9 +1899,9 @@ dependencies = [
[[package]]
name = "futures-channel"
-version = "0.3.28"
+version = "0.3.29"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "955518d47e09b25bbebc7a18df10b81f0c766eaf4c4f1cccef2fca5f2a4fb5f2"
+checksum = "ff4dd66668b557604244583e3e1e1eada8c5c2e96a6d0d6653ede395b78bbacb"
dependencies = [
"futures-core",
"futures-sink",
@@ -1807,15 +1909,15 @@ dependencies = [
[[package]]
name = "futures-core"
-version = "0.3.28"
+version = "0.3.29"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "4bca583b7e26f571124fe5b7561d49cb2868d79116cfa0eefce955557c6fee8c"
+checksum = "eb1d22c66e66d9d72e1758f0bd7d4fd0bee04cad842ee34587d68c07e45d088c"
[[package]]
name = "futures-executor"
-version = "0.3.28"
+version = "0.3.29"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "ccecee823288125bd88b4d7f565c9e58e41858e47ab72e8ea2d64e93624386e0"
+checksum = "0f4fb8693db0cf099eadcca0efe2a5a22e4550f98ed16aba6c48700da29597bc"
dependencies = [
"futures-core",
"futures-task",
@@ -1824,9 +1926,9 @@ dependencies = [
[[package]]
name = "futures-io"
-version = "0.3.28"
+version = "0.3.29"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "4fff74096e71ed47f8e023204cfd0aa1289cd54ae5430a9523be060cdb849964"
+checksum = "8bf34a163b5c4c52d0478a4d757da8fb65cabef42ba90515efee0f6f9fa45aaa"
[[package]]
name = "futures-lite"
@@ -1845,26 +1947,26 @@ dependencies = [
[[package]]
name = "futures-macro"
-version = "0.3.28"
+version = "0.3.29"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "89ca545a94061b6365f2c7355b4b32bd20df3ff95f02da9329b34ccc3bd6ee72"
+checksum = "53b153fd91e4b0147f4aced87be237c98248656bb01050b96bf3ee89220a8ddb"
dependencies = [
"proc-macro2",
"quote",
- "syn 2.0.28",
+ "syn 2.0.39",
]
[[package]]
name = "futures-sink"
-version = "0.3.28"
+version = "0.3.29"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "f43be4fe21a13b9781a69afa4985b0f6ee0e1afab2c6f454a8cf30e2b2237b6e"
+checksum = "e36d3378ee38c2a36ad710c5d30c2911d752cb941c00c72dbabfb786a7970817"
[[package]]
name = "futures-task"
-version = "0.3.28"
+version = "0.3.29"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "76d3d132be6c0e6aa1534069c705a74a5997a356c0dc2f86a47765e5617c5b65"
+checksum = "efd193069b0ddadc69c46389b740bbccdd97203899b48d09c5f7969591d6bae2"
[[package]]
name = "futures-timer"
@@ -1874,9 +1976,9 @@ checksum = "e64b03909df88034c26dc1547e8970b91f98bdb65165d6a4e9110d94263dbb2c"
[[package]]
name = "futures-util"
-version = "0.3.28"
+version = "0.3.29"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "26b01e40b772d54cf6c6d721c1d1abd0647a0106a12ecaa1c186273392a69533"
+checksum = "a19526d624e703a3179b3d322efec918b6246ea0fa51d41124525f00f1cc8104"
dependencies = [
"futures-channel",
"futures-core",
@@ -1913,9 +2015,9 @@ dependencies = [
[[package]]
name = "getrandom"
-version = "0.2.9"
+version = "0.2.11"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "c85e1d9ab2eadba7e5040d4e09cbd6d072b76a557ad64e797c2cb9d4da21d7e4"
+checksum = "fe9006bed769170c11f845cf00c7c1e9092aeb3f268e007c3e760ac68008070f"
dependencies = [
"cfg-if",
"js-sys",
@@ -1926,30 +2028,28 @@ dependencies = [
[[package]]
name = "gimli"
-version = "0.27.2"
+version = "0.28.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "ad0a93d233ebf96623465aad4046a8d3aa4da22d4f4beba5388838c8a434bbb4"
+checksum = "4271d37baee1b8c7e4b708028c57d816cf9d2434acb33a549475f78c181f6253"
[[package]]
name = "git-version"
-version = "0.3.5"
+version = "0.3.8"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "f6b0decc02f4636b9ccad390dcbe77b722a77efedfa393caf8379a51d5c61899"
+checksum = "13ad01ffa8221f7fe8b936d6ffb2a3e7ad428885a04fad51866a5f33eafda57c"
dependencies = [
"git-version-macro",
- "proc-macro-hack",
]
[[package]]
name = "git-version-macro"
-version = "0.3.5"
+version = "0.3.8"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "fe69f1cbdb6e28af2bac214e943b99ce8a0a06b447d15d3e61161b0423139f3f"
+checksum = "84488ccbdb24ad6f56dc1863b4a8154a7856cd3c6c7610401634fab3cb588dae"
dependencies = [
- "proc-macro-hack",
"proc-macro2",
"quote",
- "syn 1.0.109",
+ "syn 2.0.39",
]
[[package]]
@@ -1959,10 +2059,21 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d2fabcfbdc87f4758337ca535fb41a6d701b65693ce38287d856d1674551ec9b"
[[package]]
-name = "h2"
-version = "0.3.19"
+name = "group"
+version = "0.12.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "d357c7ae988e7d2182f7d7871d0b963962420b0678b0997ce7de72001aeab782"
+checksum = "5dfbfb3a6cfbd390d5c9564ab283a0349b9b9fcd46a706c1eb10e0db70bfbac7"
+dependencies = [
+ "ff",
+ "rand_core 0.6.4",
+ "subtle",
+]
+
+[[package]]
+name = "h2"
+version = "0.3.22"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "4d6250322ef6e60f93f9a2162799302cd6f68f79f6e5d85c8c16f14d1d958178"
dependencies = [
"bytes",
"fnv",
@@ -1970,7 +2081,7 @@ dependencies = [
"futures-sink",
"futures-util",
"http",
- "indexmap",
+ "indexmap 2.1.0",
"slab",
"tokio",
"tokio-util",
@@ -2004,22 +2115,26 @@ version = "0.13.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "43a3c133739dddd0d2990f9a4bdf8eb4b21ef50e4851ca85ab661199821d510e"
dependencies = [
- "ahash 0.8.5",
+ "ahash 0.8.6",
]
[[package]]
name = "hashbrown"
-version = "0.14.0"
+version = "0.14.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "2c6201b9ff9fd90a5a3bac2e56a830d0caa509576f0e503818ee82c181b3437a"
+checksum = "290f1a1d9242c78d09ce40a5e87e7554ee637af1351968159f4952f028f75604"
+dependencies = [
+ "ahash 0.8.6",
+ "allocator-api2",
+]
[[package]]
name = "hashlink"
-version = "0.8.2"
+version = "0.8.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "0761a1b9491c4f2e3d66aa0f62d0fba0af9a0e2852e4d48ea506632a4b56e6aa"
+checksum = "e8094feaf31ff591f651a2664fb9cfd92bba7a60ce3197265e9482ebe753c8f7"
dependencies = [
- "hashbrown 0.13.2",
+ "hashbrown 0.14.3",
]
[[package]]
@@ -2089,6 +2204,15 @@ dependencies = [
"digest",
]
+[[package]]
+name = "home"
+version = "0.5.5"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "5444c27eef6923071f7ebcc33e3444508466a76f7a2b93da00ed6e19f30c1ddb"
+dependencies = [
+ "windows-sys 0.48.0",
+]
+
[[package]]
name = "hostname"
version = "0.3.1"
@@ -2102,9 +2226,9 @@ dependencies = [
[[package]]
name = "http"
-version = "0.2.9"
+version = "0.2.11"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "bd6effc99afb63425aff9b05836f029929e345a6148a14b7ecd5ab67af944482"
+checksum = "8947b1a6fad4393052c7ba1f4cd97bed3e953a95c79c92ad9b051a04611d9fbb"
dependencies = [
"bytes",
"fnv",
@@ -2150,9 +2274,9 @@ checksum = "d897f394bad6a705d5f4104762e116a75639e470d80901eed05a860a95cb1904"
[[package]]
name = "httpdate"
-version = "1.0.2"
+version = "1.0.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "c4a1e36c821dbe04574f602848a19f742f4fb3c98d40449f11bcad18d6b17421"
+checksum = "df3b46402a9d5adb4c86a0cf463f42e19994e3ee891101b1841f30a545cb49a9"
[[package]]
name = "humantime"
@@ -2172,9 +2296,9 @@ dependencies = [
[[package]]
name = "hyper"
-version = "0.14.26"
+version = "0.14.27"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "ab302d72a6f11a3b910431ff93aae7e773078c769f0a3ef15fb9ec692ed147d4"
+checksum = "ffb1cfd654a8219eaef89881fdb3bb3b1cdc5fa75ded05d6933b2b382e395468"
dependencies = [
"bytes",
"futures-channel",
@@ -2187,7 +2311,7 @@ dependencies = [
"httpdate",
"itoa",
"pin-project-lite",
- "socket2 0.4.9",
+ "socket2 0.4.10",
"tokio",
"tower-service",
"tracing",
@@ -2196,10 +2320,11 @@ dependencies = [
[[package]]
name = "hyper-rustls"
-version = "0.24.0"
+version = "0.24.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "0646026eb1b3eea4cd9ba47912ea5ce9cc07713d105b1a14698f4e6433d348b7"
+checksum = "ec3efd23720e2049821a693cbc7e65ea87c72f1c58ff2f9522ff332b1491e590"
dependencies = [
+ "futures-util",
"http",
"hyper",
"log",
@@ -2249,16 +2374,16 @@ dependencies = [
[[package]]
name = "iana-time-zone"
-version = "0.1.56"
+version = "0.1.58"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "0722cd7114b7de04316e7ea5456a0bbb20e4adb46fd27a3697adb812cff0f37c"
+checksum = "8326b86b6cff230b97d0d312a6c40a60726df3332e721f72a1b035f451663b20"
dependencies = [
"android_system_properties",
"core-foundation-sys",
"iana-time-zone-haiku",
"js-sys",
"wasm-bindgen",
- "windows",
+ "windows-core",
]
[[package]]
@@ -2278,9 +2403,9 @@ checksum = "b9e0384b61958566e926dc50660321d12159025e767c18e043daf26b70104c39"
[[package]]
name = "idna"
-version = "0.3.0"
+version = "0.5.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "e14ddfc70884202db2244c223200c204c2bda1bc6e0998d11b5e024d657209e6"
+checksum = "634d9b1461af396cad843f47fdba5597a4f9e6ddd4bfb6ff5d85028c25cb12f6"
dependencies = [
"unicode-bidi",
"unicode-normalization",
@@ -2297,6 +2422,16 @@ dependencies = [
"serde",
]
+[[package]]
+name = "indexmap"
+version = "2.1.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "d530e1a18b1cb4c484e6e34556a0d948706958449fca0cab753d649f2bce3d1f"
+dependencies = [
+ "equivalent",
+ "hashbrown 0.14.3",
+]
+
[[package]]
name = "infer"
version = "0.2.3"
@@ -2311,7 +2446,7 @@ checksum = "de3886428c6400486522cf44b8626e7b94ad794c14390290f2a274dcf728a58f"
dependencies = [
"ahash 0.7.7",
"atty",
- "indexmap",
+ "indexmap 1.9.3",
"itoa",
"lazy_static",
"log",
@@ -2327,7 +2462,7 @@ version = "0.9.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f8069d3ec154eb856955c1c0fbffefbf5f3c40a104ec912d4797314c1801abff"
dependencies = [
- "bitflags",
+ "bitflags 1.3.2",
"inotify-sys",
"libc",
]
@@ -2338,7 +2473,7 @@ version = "0.10.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "fdd168d97690d0b8c412d6b6c10360277f4d7ee495c5d0d5d5fe0854923255cc"
dependencies = [
- "bitflags",
+ "bitflags 1.3.2",
"futures-core",
"inotify-sys",
"libc",
@@ -2379,19 +2514,18 @@ dependencies = [
[[package]]
name = "ipnet"
-version = "2.7.2"
+version = "2.9.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "12b6ee2129af8d4fb011108c73d99a1b83a85977f23b82460c0ae2e25bb4b57f"
+checksum = "8f518f335dce6725a761382244631d86cf0ccb2863413590b31338feb467f9c3"
[[package]]
name = "is-terminal"
-version = "0.4.7"
+version = "0.4.9"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "adcf93614601c8129ddf72e2d5633df827ba6551541c6d8c59520a371475be1f"
+checksum = "cb0889898416213fab133e1d33a0e5858a48177452750691bde3666d0fdbaf8b"
dependencies = [
"hermit-abi 0.3.3",
- "io-lifetimes",
- "rustix 0.37.25",
+ "rustix 0.38.26",
"windows-sys 0.48.0",
]
@@ -2406,24 +2540,24 @@ dependencies = [
[[package]]
name = "itoa"
-version = "1.0.6"
+version = "1.0.9"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "453ad9f582a441959e5f0d088b02ce04cfe8d51a8eaf077f12ac6d3e94164ca6"
+checksum = "af150ab688ff2122fcef229be89cb50dd66af9e01a4ff320cc137eecc9bacc38"
[[package]]
name = "jobserver"
-version = "0.1.26"
+version = "0.1.27"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "936cfd212a0155903bcbc060e316fb6cc7cbf2e1907329391ebadc1fe0ce77c2"
+checksum = "8c37f63953c4c63420ed5fd3d6d398c719489b9f872b9fa683262f8edd363c7d"
dependencies = [
"libc",
]
[[package]]
name = "js-sys"
-version = "0.3.63"
+version = "0.3.66"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "2f37a4a5928311ac501dee68b3c7613a1037d0edb30c8e5427bd832d55d1b790"
+checksum = "cee9c64da59eae3b50095c18d3e74f8b73c0b86d2792824ff01bbce68ba229ca"
dependencies = [
"wasm-bindgen",
]
@@ -2434,9 +2568,9 @@ version = "8.3.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "6971da4d9c3aa03c3d8f3ff0f4155b534aad021292003895a469716b2a230378"
dependencies = [
- "base64 0.21.1",
+ "base64 0.21.5",
"pem 1.1.1",
- "ring",
+ "ring 0.16.20",
"serde",
"serde_json",
"simple_asn1",
@@ -2444,9 +2578,9 @@ dependencies = [
[[package]]
name = "kqueue"
-version = "1.0.7"
+version = "1.0.8"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "2c8fc60ba15bf51257aa9807a48a61013db043fcf3a78cb0d916e8e396dcad98"
+checksum = "7447f1ca1b7b563588a205fe93dea8df60fd981423a768bc1c0ded35ed147d0c"
dependencies = [
"kqueue-sys",
"libc",
@@ -2454,11 +2588,11 @@ dependencies = [
[[package]]
name = "kqueue-sys"
-version = "1.0.3"
+version = "1.0.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "8367585489f01bc55dd27404dcf56b95e6da061a256a666ab23be9ba96a2e587"
+checksum = "ed9625ffda8729b85e45cf04090035ac368927b8cebc34898e7c120f52e4838b"
dependencies = [
- "bitflags",
+ "bitflags 1.3.2",
"libc",
]
@@ -2476,9 +2610,9 @@ checksum = "830d08ce1d1d941e6b30645f1a0eb5643013d835ce3779a5fc208261dbe10f55"
[[package]]
name = "libc"
-version = "0.2.144"
+version = "0.2.150"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "2b00cc1c228a6782d0f076e7b232802e0c5689d41bb5df366f2a6b6621cfdfe1"
+checksum = "89d92a4743f9a61002fae18374ed11e7973f530cb3a3255fb354818118b2203c"
[[package]]
name = "libloading"
@@ -2498,15 +2632,15 @@ checksum = "f051f77a7c8e6957c0696eac88f26b0117e54f52d3fc682ab19397a8812846a4"
[[package]]
name = "linux-raw-sys"
-version = "0.3.8"
+version = "0.4.12"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "ef53942eb7bf7ff43a617b3e2c1c4a5ecf5944a7c1bc12d7ee39bbb15e5c1519"
+checksum = "c4cd1a83af159aa67994778be9070f0ae1bd732942279cabb14f86f986a21456"
[[package]]
name = "lock_api"
-version = "0.4.10"
+version = "0.4.11"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "c1cc9717a20b1bb222f333e6a92fd32f7d8a18ddc5a3191a11af45dcbf4dcd16"
+checksum = "3c168f8615b12bc01f9c17e2eb0cc07dcae1940121185446edc3744920e8ef45"
dependencies = [
"autocfg",
"scopeguard",
@@ -2530,21 +2664,22 @@ version = "0.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8263075bb86c5a1b1427b5ae862e8889656f126e9f77c484496e8b47cf5c5558"
dependencies = [
- "regex-automata",
+ "regex-automata 0.1.10",
]
[[package]]
name = "matchit"
-version = "0.7.0"
+version = "0.7.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "b87248edafb776e59e6ee64a79086f65890d3510f2c656c000bf2a7e8a0aea40"
+checksum = "0e7465ac9959cc2b1404e8e2367b43684a6d13790fe23056cc8c6c5a6b7bcb94"
[[package]]
name = "md-5"
-version = "0.10.5"
+version = "0.10.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "6365506850d44bff6e2fbcb5176cf63650e48bd45ef2fe2665ae1570e0f4b9ca"
+checksum = "d89e7ee0cfbedfc4da3340218492196241d89eefb6dab27de5df917a6d2e78cf"
dependencies = [
+ "cfg-if",
"digest",
]
@@ -2556,9 +2691,9 @@ checksum = "490cc448043f947bae3cbee9c203358d62dbee0db12107a74be5c30ccfd09771"
[[package]]
name = "memchr"
-version = "2.5.0"
+version = "2.6.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "2dffe52ecf27772e601905b7522cb4ef790d2cc203488bbd0e2fe85fcb74566d"
+checksum = "f665ee40bc4a3c5590afb1e9677db74a508659dfd71e126420da8274909a0167"
[[package]]
name = "memmap2"
@@ -2596,6 +2731,15 @@ dependencies = [
"autocfg",
]
+[[package]]
+name = "memoffset"
+version = "0.9.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "5a634b1c61a95585bd15607c6ab0c4e5b226e695ff2800ba0cdccddf208c406c"
+dependencies = [
+ "autocfg",
+]
+
[[package]]
name = "metrics"
version = "0.1.0"
@@ -2629,15 +2773,6 @@ version = "0.2.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "68354c5c6bd36d73ff3feceb05efa59b6acb7626617f4962be322a825e61f79a"
-[[package]]
-name = "miniz_oxide"
-version = "0.6.2"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "b275950c28b37e794e8c55d88aeb5e139d0ce23fdbbeda68f8d7174abdf9e8fa"
-dependencies = [
- "adler",
-]
-
[[package]]
name = "miniz_oxide"
version = "0.7.1"
@@ -2649,14 +2784,14 @@ dependencies = [
[[package]]
name = "mio"
-version = "0.8.6"
+version = "0.8.9"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "5b9d9a46eff5b4ff64b45a9e316a6d1e0bc719ef429cbec4dc630684212bfdf9"
+checksum = "3dce281c5e46beae905d4de1870d8b1509a9142b62eedf18b443b011ca8343d0"
dependencies = [
"libc",
"log",
"wasi 0.11.0+wasi-snapshot-preview1",
- "windows-sys 0.45.0",
+ "windows-sys 0.48.0",
]
[[package]]
@@ -2689,7 +2824,7 @@ version = "0.23.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8f3790c00a0150112de0f4cd161e3d7fc4b2d8a5542ffc35f099a2562aecb35c"
dependencies = [
- "bitflags",
+ "bitflags 1.3.2",
"cc",
"cfg-if",
"libc",
@@ -2703,23 +2838,22 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f346ff70e7dbfd675fe90590b92d59ef2de15a8779ae305ebcbfd3f0caf59be4"
dependencies = [
"autocfg",
- "bitflags",
+ "bitflags 1.3.2",
"cfg-if",
"libc",
]
[[package]]
name = "nix"
-version = "0.26.2"
+version = "0.26.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "bfdda3d196821d6af13126e40375cdf7da646a96114af134d5f417a9a1dc8e1a"
+checksum = "598beaf3cc6fdd9a5dfb1630c2800c7acd31df7aaf0f565796fba2b53ca1af1b"
dependencies = [
- "bitflags",
+ "bitflags 1.3.2",
"cfg-if",
"libc",
"memoffset 0.7.1",
"pin-utils",
- "static_assertions",
]
[[package]]
@@ -2738,7 +2872,7 @@ version = "5.2.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "729f63e1ca555a43fe3efa4f3efdf4801c479da85b432242a7b726f353c88486"
dependencies = [
- "bitflags",
+ "bitflags 1.3.2",
"crossbeam-channel",
"filetime",
"fsevent-sys",
@@ -2761,9 +2895,9 @@ dependencies = [
[[package]]
name = "num-bigint"
-version = "0.4.3"
+version = "0.4.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "f93ab6289c7b344a8a9f60f88d80aa20032336fe78da341afc91c8a2341fc75f"
+checksum = "608e7659b5c3d7cba262d894801b9ec9d00de989e8a82bd4bef91d08da45cdc0"
dependencies = [
"autocfg",
"num-integer",
@@ -2792,9 +2926,9 @@ dependencies = [
[[package]]
name = "num-traits"
-version = "0.2.15"
+version = "0.2.17"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "578ede34cf02f8924ab9447f50c28075b4d3e5b269972345e7e0372b38c6cdcd"
+checksum = "39e3200413f237f41ab11ad6d161bc7239c84dcb631773ccd7de3dfe4b5c267c"
dependencies = [
"autocfg",
]
@@ -2826,7 +2960,7 @@ checksum = "c38841cdd844847e3e7c8d29cef9dcfed8877f8f56f9071f77843ecf3baf937f"
dependencies = [
"base64 0.13.1",
"chrono",
- "getrandom 0.2.9",
+ "getrandom 0.2.11",
"http",
"rand 0.8.5",
"serde",
@@ -2839,9 +2973,9 @@ dependencies = [
[[package]]
name = "object"
-version = "0.30.3"
+version = "0.32.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "ea86265d3d3dcb6a27fc51bd29a4bf387fae9d2986b823079d4986af253eb439"
+checksum = "9cf5f9dd3933bd50a9e1f149ec995f39ae2c496d31fd772c1fd45ebc27e902b0"
dependencies = [
"memchr",
]
@@ -2869,11 +3003,11 @@ checksum = "0ab1bc2a289d34bd04a330323ac98a1b4bc82c9d9fcb1e66b63caa84da26b575"
[[package]]
name = "openssl"
-version = "0.10.55"
+version = "0.10.60"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "345df152bc43501c5eb9e4654ff05f794effb78d4efe3d53abc158baddc0703d"
+checksum = "79a4c6c3a2b158f7f8f2a2fc5a969fa3a068df6fc9dbb4a43845436e3af7c800"
dependencies = [
- "bitflags",
+ "bitflags 2.4.1",
"cfg-if",
"foreign-types",
"libc",
@@ -2890,7 +3024,7 @@ checksum = "a948666b637a0f465e8564c73e89d4dde00d72d4d473cc972f390fc3dcee7d9c"
dependencies = [
"proc-macro2",
"quote",
- "syn 2.0.28",
+ "syn 2.0.39",
]
[[package]]
@@ -2901,9 +3035,9 @@ checksum = "ff011a302c396a5197692431fc1948019154afc178baf7d8e37367442a4601cf"
[[package]]
name = "openssl-sys"
-version = "0.9.90"
+version = "0.9.96"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "374533b0e45f3a7ced10fcaeccca020e66656bc03dac384f852e4e5a7a8104a6"
+checksum = "3812c071ba60da8b5677cc12bcb1d42989a65553772897a7e0355545a819838f"
dependencies = [
"cc",
"libc",
@@ -2983,7 +3117,7 @@ dependencies = [
"fnv",
"futures-channel",
"futures-util",
- "indexmap",
+ "indexmap 1.9.3",
"once_cell",
"pin-project-lite",
"thiserror",
@@ -3029,6 +3163,17 @@ version = "0.5.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "4030760ffd992bef45b0ae3f10ce1aba99e33464c90d14dd7c039884963ddc7a"
+[[package]]
+name = "p256"
+version = "0.11.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "51f44edd08f51e2ade572f141051021c5af22677e42b7dd28a88155151c33594"
+dependencies = [
+ "ecdsa",
+ "elliptic-curve",
+ "sha2",
+]
+
[[package]]
name = "pagectl"
version = "0.1.0"
@@ -3082,7 +3227,7 @@ dependencies = [
"hyper",
"itertools",
"metrics",
- "nix 0.26.2",
+ "nix 0.26.4",
"num-traits",
"num_cpus",
"once_cell",
@@ -3104,6 +3249,7 @@ dependencies = [
"scopeguard",
"serde",
"serde_json",
+ "serde_path_to_error",
"serde_with",
"signal-hook",
"smallvec",
@@ -3151,9 +3297,9 @@ dependencies = [
[[package]]
name = "parking"
-version = "2.1.1"
+version = "2.2.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "e52c774a4c39359c1d1c52e43f73dd91a75a614652c825408eec30c95a9b2067"
+checksum = "bb813b8af86854136c6922af0598d719255ecb2179515e6e7730d468f05c9cae"
[[package]]
name = "parking_lot"
@@ -3173,7 +3319,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "3742b2c103b9f06bc9fff0a37ff4912935851bee6d36f3c02bcc755bcfec228f"
dependencies = [
"lock_api",
- "parking_lot_core 0.9.8",
+ "parking_lot_core 0.9.9",
]
[[package]]
@@ -3192,15 +3338,15 @@ dependencies = [
[[package]]
name = "parking_lot_core"
-version = "0.9.8"
+version = "0.9.9"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "93f00c865fe7cabf650081affecd3871070f26767e7b2070a3ffae14c654b447"
+checksum = "4c42a9226546d68acdd9c0a280d17ce19bfe27a46bf68784e4066115788d008e"
dependencies = [
"cfg-if",
"libc",
- "redox_syscall 0.3.5",
+ "redox_syscall 0.4.1",
"smallvec",
- "windows-targets 0.48.0",
+ "windows-targets 0.48.5",
]
[[package]]
@@ -3222,9 +3368,9 @@ checksum = "de3145af08024dea9fa9914f381a17b8fc6034dfb00f3a84013f7ff43f29ed4c"
[[package]]
name = "pbkdf2"
-version = "0.12.1"
+version = "0.12.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "f0ca0b5a68607598bf3bad68f32227a8164f6254833f84eafaac409cd6746c31"
+checksum = "f8ed6a7761f76e3b9f92dfb0a60a6a6477c61024b775147ff0973a02653abaf2"
dependencies = [
"digest",
"hmac",
@@ -3249,66 +3395,66 @@ dependencies = [
[[package]]
name = "pem"
-version = "2.0.1"
+version = "3.0.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "6b13fe415cdf3c8e44518e18a7c95a13431d9bdf6d15367d82b23c377fdd441a"
+checksum = "3163d2912b7c3b52d651a055f2c7eec9ba5cd22d26ef75b8dd3a59980b185923"
dependencies = [
- "base64 0.21.1",
+ "base64 0.21.5",
"serde",
]
[[package]]
name = "percent-encoding"
-version = "2.2.0"
+version = "2.3.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "478c572c3d73181ff3c2539045f6eb99e5491218eae919370993b890cdbdd98e"
+checksum = "e3148f5046208a5d56bcfc03053e3ca6334e51da8dfb19b6cdc8b306fae3283e"
[[package]]
name = "petgraph"
-version = "0.6.3"
+version = "0.6.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "4dd7d28ee937e54fe3080c91faa1c3a46c06de6252988a7f4592ba2310ef22a4"
+checksum = "e1d3afd2628e69da2be385eb6f2fd57c8ac7977ceeff6dc166ff1657b0e386a9"
dependencies = [
"fixedbitset",
- "indexmap",
+ "indexmap 2.1.0",
]
[[package]]
name = "phf"
-version = "0.11.1"
+version = "0.11.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "928c6535de93548188ef63bb7c4036bd415cd8f36ad25af44b9789b2ee72a48c"
+checksum = "ade2d8b8f33c7333b51bcf0428d37e217e9f32192ae4772156f65063b8ce03dc"
dependencies = [
"phf_shared",
]
[[package]]
name = "phf_shared"
-version = "0.11.1"
+version = "0.11.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "e1fb5f6f826b772a8d4c0394209441e7d37cbbb967ae9c7e0e8134365c9ee676"
+checksum = "90fcb95eef784c2ac79119d1dd819e162b5da872ce6f3c3abe1e8ca1c082f72b"
dependencies = [
"siphasher",
]
[[package]]
name = "pin-project"
-version = "1.1.0"
+version = "1.1.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "c95a7476719eab1e366eaf73d0260af3021184f18177925b07f54b30089ceead"
+checksum = "fda4ed1c6c173e3fc7a83629421152e01d7b1f9b7f65fb301e490e8cfc656422"
dependencies = [
"pin-project-internal",
]
[[package]]
name = "pin-project-internal"
-version = "1.1.0"
+version = "1.1.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "39407670928234ebc5e6e580247dd567ad73a3578460c5990f9503df207e8f07"
+checksum = "4359fd9c9171ec6e8c62926d6faaf553a8dc3f64e1507e76da7911b4f6a04405"
dependencies = [
"proc-macro2",
"quote",
- "syn 2.0.28",
+ "syn 2.0.39",
]
[[package]]
@@ -3323,6 +3469,16 @@ version = "0.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8b870d8c151b6f2fb93e84a13146138f05d02ed11c7e7c54f8826aaaf7c9f184"
+[[package]]
+name = "pkcs8"
+version = "0.9.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "9eca2c590a5f85da82668fa685c09ce2888b9430e83299debf1f34b65fd4a4ba"
+dependencies = [
+ "der",
+ "spki",
+]
+
[[package]]
name = "pkg-config"
version = "0.3.27"
@@ -3331,9 +3487,9 @@ checksum = "26072860ba924cbfa98ea39c8c19b4dd6a4a25423dbdf219c1eca91aa0cf6964"
[[package]]
name = "plotters"
-version = "0.3.4"
+version = "0.3.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "2538b639e642295546c50fcd545198c9d64ee2a38620a628724a3b266d5fbf97"
+checksum = "d2c224ba00d7cadd4d5c660deaf2098e5e80e07846537c51f9cfa4be50c1fd45"
dependencies = [
"num-traits",
"plotters-backend",
@@ -3344,15 +3500,15 @@ dependencies = [
[[package]]
name = "plotters-backend"
-version = "0.3.4"
+version = "0.3.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "193228616381fecdc1224c62e96946dfbc73ff4384fba576e052ff8c1bea8142"
+checksum = "9e76628b4d3a7581389a35d5b6e2139607ad7c75b17aed325f210aa91f4a9609"
[[package]]
name = "plotters-svg"
-version = "0.3.3"
+version = "0.3.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "f9a81d2759aae1dae668f783c308bc5c8ebd191ff4184aaa1b37f65a6ae5a56f"
+checksum = "38f6d39893cca0701371e3c27294f09797214b86f1fb951b89ade8ec04e2abab"
dependencies = [
"plotters-backend",
]
@@ -3467,6 +3623,12 @@ dependencies = [
"workspace_hack",
]
+[[package]]
+name = "powerfmt"
+version = "0.2.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "439ee305def115ba05938db6eb1644ff94165c5ab5e9420d1c1bcedbba909391"
+
[[package]]
name = "pprof"
version = "0.6.1"
@@ -3519,25 +3681,19 @@ dependencies = [
[[package]]
name = "prettyplease"
-version = "0.2.6"
+version = "0.2.15"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "3b69d39aab54d069e7f2fe8cb970493e7834601ca2d8c65fd7bbd183578080d1"
+checksum = "ae005bd773ab59b4725093fd7df83fd7892f7d8eafb48dbd7de6e024e4215f9d"
dependencies = [
"proc-macro2",
- "syn 2.0.28",
+ "syn 2.0.39",
]
-[[package]]
-name = "proc-macro-hack"
-version = "0.5.20+deprecated"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "dc375e1527247fe1a97d8b7156678dfe7c1af2fc075c9a4db3690ecd2a148068"
-
[[package]]
name = "proc-macro2"
-version = "1.0.66"
+version = "1.0.70"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "18fb31db3f9bddb2ea821cde30a9f70117e3f119938b5ee630b7403aa6e2ead9"
+checksum = "39278fbbf5fb4f646ce651690877f89d1c5811a3d4acb27700c1cb3cdb78fd3b"
dependencies = [
"unicode-ident",
]
@@ -3548,11 +3704,11 @@ version = "0.14.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b1de8dacb0873f77e6aefc6d71e044761fcc68060290f5b1089fcdf84626bb69"
dependencies = [
- "bitflags",
+ "bitflags 1.3.2",
"byteorder",
"hex",
"lazy_static",
- "rustix 0.36.16",
+ "rustix 0.36.17",
]
[[package]]
@@ -3648,6 +3804,7 @@ dependencies = [
"humantime",
"hyper",
"hyper-tungstenite",
+ "ipnet",
"itertools",
"md5",
"metrics",
@@ -3678,7 +3835,8 @@ dependencies = [
"serde",
"serde_json",
"sha2",
- "socket2 0.5.3",
+ "smol_str",
+ "socket2 0.5.5",
"sync_wrapper",
"task-local-extensions",
"thiserror",
@@ -3694,8 +3852,8 @@ dependencies = [
"tracing-utils",
"url",
"utils",
- "uuid 1.3.3",
- "webpki-roots 0.25.2",
+ "uuid 1.6.1",
+ "webpki-roots",
"workspace_hack",
"x509-parser",
]
@@ -3721,9 +3879,9 @@ dependencies = [
[[package]]
name = "quote"
-version = "1.0.32"
+version = "1.0.33"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "50f3b39ccfb720540debaa0164757101c08ecb8d326b15358ce76a62c7e85965"
+checksum = "5267fca4496028628a95160fc423a33e8b2e6af8a5302579e322e4b520293cae"
dependencies = [
"proc-macro2",
]
@@ -3787,7 +3945,7 @@ version = "0.6.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ec0be4795e2f6a28069bec0b5ff3e2ac9bafc99e6a9a7dc3547996c5c816922c"
dependencies = [
- "getrandom 0.2.9",
+ "getrandom 0.2.11",
]
[[package]]
@@ -3801,9 +3959,9 @@ dependencies = [
[[package]]
name = "rayon"
-version = "1.7.0"
+version = "1.8.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "1d2df5196e37bcc87abebc0053e20787d73847bb33134a69841207dd0a47f03b"
+checksum = "9c27db03db7734835b3f53954b534c91069375ce6ccaa2e065441e07d9b6cdb1"
dependencies = [
"either",
"rayon-core",
@@ -3811,24 +3969,22 @@ dependencies = [
[[package]]
name = "rayon-core"
-version = "1.11.0"
+version = "1.12.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "4b8f95bd6966f5c87776639160a66bd8ab9895d9d4ab01ddba9fc60661aebe8d"
+checksum = "5ce3fb6ad83f861aac485e76e1985cd109d9a3713802152be56c3b1f0e0658ed"
dependencies = [
- "crossbeam-channel",
"crossbeam-deque",
"crossbeam-utils",
- "num_cpus",
]
[[package]]
name = "rcgen"
-version = "0.11.1"
+version = "0.11.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "4954fbc00dcd4d8282c987710e50ba513d351400dbdd00e803a05172a90d8976"
+checksum = "52c4f3084aa3bc7dfbba4eff4fab2a54db4324965d8872ab933565e6fbd83bc6"
dependencies = [
- "pem 2.0.1",
- "ring",
+ "pem 3.0.2",
+ "ring 0.16.20",
"time",
"yasna",
]
@@ -3839,7 +3995,7 @@ version = "0.2.16"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "fb5a58c1855b4b6819d59012155603f0b22ad30cad752600aadfcb695265519a"
dependencies = [
- "bitflags",
+ "bitflags 1.3.2",
]
[[package]]
@@ -3848,18 +4004,28 @@ version = "0.3.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "567664f262709473930a4bf9e51bf2ebf3348f2e748ccc50dea20646858f8f29"
dependencies = [
- "bitflags",
+ "bitflags 1.3.2",
+]
+
+[[package]]
+name = "redox_syscall"
+version = "0.4.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "4722d768eff46b75989dd134e5c353f0d6296e5aaa3132e776cbdb56be7731aa"
+dependencies = [
+ "bitflags 1.3.2",
]
[[package]]
name = "regex"
-version = "1.8.2"
+version = "1.10.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "d1a59b5d8e97dee33696bf13c5ba8ab85341c002922fba050069326b9c498974"
+checksum = "380b951a9c5e80ddfd6136919eef32310721aa4aacd4889a8d39124b026ab343"
dependencies = [
"aho-corasick",
"memchr",
- "regex-syntax 0.7.2",
+ "regex-automata 0.4.3",
+ "regex-syntax 0.8.2",
]
[[package]]
@@ -3871,6 +4037,17 @@ dependencies = [
"regex-syntax 0.6.29",
]
+[[package]]
+name = "regex-automata"
+version = "0.4.3"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "5f804c7828047e88b2d32e2d7fe5a105da8ee3264f01902f796c8e067dc2483f"
+dependencies = [
+ "aho-corasick",
+ "memchr",
+ "regex-syntax 0.8.2",
+]
+
[[package]]
name = "regex-syntax"
version = "0.6.29"
@@ -3879,9 +4056,15 @@ checksum = "f162c6dd7b008981e4d40210aca20b4bd0f9b60ca9271061b07f78537722f2e1"
[[package]]
name = "regex-syntax"
-version = "0.7.2"
+version = "0.7.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "436b050e76ed2903236f032a59761c1eb99e1b0aead2c257922771dab1fc8c78"
+checksum = "dbb5fb1acd8a1a18b3dd5be62d25485eb770e05afb408a9627d14d451bae12da"
+
+[[package]]
+name = "regex-syntax"
+version = "0.8.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "c08c74e62047bb2de4ff487b251e4a92e24f48745648451635cec7d591162d9f"
[[package]]
name = "relative-path"
@@ -3899,8 +4082,7 @@ dependencies = [
"aws-credential-types",
"aws-sdk-s3",
"aws-smithy-async",
- "aws-smithy-http",
- "aws-types",
+ "aws-smithy-types",
"azure_core",
"azure_identity",
"azure_storage",
@@ -3930,11 +4112,11 @@ dependencies = [
[[package]]
name = "reqwest"
-version = "0.11.19"
+version = "0.11.22"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "20b9b67e2ca7dd9e9f9285b759de30ff538aab981abaaf7bc9bd90b84a0126c3"
+checksum = "046cd98826c46c2ac8ddecae268eb5c2e58628688a5fc7a2643704a73faba95b"
dependencies = [
- "base64 0.21.1",
+ "base64 0.21.5",
"bytes",
"encoding_rs",
"futures-core",
@@ -3959,6 +4141,7 @@ dependencies = [
"serde",
"serde_json",
"serde_urlencoded",
+ "system-configuration",
"tokio",
"tokio-native-tls",
"tokio-rustls",
@@ -3969,15 +4152,15 @@ dependencies = [
"wasm-bindgen-futures",
"wasm-streams",
"web-sys",
- "webpki-roots 0.25.2",
+ "webpki-roots",
"winreg",
]
[[package]]
name = "reqwest-middleware"
-version = "0.2.2"
+version = "0.2.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "4531c89d50effe1fac90d095c8b133c20c5c714204feee0bfc3fd158e784209d"
+checksum = "88a3e86aa6053e59030e7ce2d2a3b258dd08fc2d337d52f73f6cb480f5858690"
dependencies = [
"anyhow",
"async-trait",
@@ -3990,15 +4173,15 @@ dependencies = [
[[package]]
name = "reqwest-retry"
-version = "0.2.2"
+version = "0.2.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "48d0fd6ef4c6d23790399fe15efc8d12cd9f3d4133958f9bd7801ee5cbaec6c4"
+checksum = "5c6a11c05102e5bec712c0619b8c7b7eda8b21a558a0bd981ceee15c38df8be4"
dependencies = [
"anyhow",
"async-trait",
"chrono",
"futures",
- "getrandom 0.2.9",
+ "getrandom 0.2.11",
"http",
"hyper",
"parking_lot 0.11.2",
@@ -4013,13 +4196,13 @@ dependencies = [
[[package]]
name = "reqwest-tracing"
-version = "0.4.5"
+version = "0.4.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "1b97ad83c2fc18113346b7158d79732242002427c30f620fa817c1f32901e0a8"
+checksum = "14b1e66540e0cac90acadaf7109bf99c90d95abcc94b4c096bfa16a2d7aa7a71"
dependencies = [
"anyhow",
"async-trait",
- "getrandom 0.2.9",
+ "getrandom 0.2.11",
"matchit",
"opentelemetry",
"reqwest",
@@ -4040,6 +4223,17 @@ dependencies = [
"rand 0.8.5",
]
+[[package]]
+name = "rfc6979"
+version = "0.3.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "7743f17af12fa0b03b803ba12cd6a8d9483a587e89c69445e3909655c0b9fabb"
+dependencies = [
+ "crypto-bigint 0.4.9",
+ "hmac",
+ "zeroize",
+]
+
[[package]]
name = "rgb"
version = "0.8.37"
@@ -4059,11 +4253,25 @@ dependencies = [
"libc",
"once_cell",
"spin 0.5.2",
- "untrusted",
+ "untrusted 0.7.1",
"web-sys",
"winapi",
]
+[[package]]
+name = "ring"
+version = "0.17.6"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "684d5e6e18f669ccebf64a92236bb7db9a34f07be010e3627368182027180866"
+dependencies = [
+ "cc",
+ "getrandom 0.2.11",
+ "libc",
+ "spin 0.9.8",
+ "untrusted 0.9.0",
+ "windows-sys 0.48.0",
+]
+
[[package]]
name = "routerify"
version = "3.0.0"
@@ -4111,7 +4319,7 @@ dependencies = [
"regex",
"relative-path",
"rustc_version",
- "syn 2.0.28",
+ "syn 2.0.39",
"unicode-ident",
]
@@ -4147,11 +4355,11 @@ dependencies = [
[[package]]
name = "rustix"
-version = "0.36.16"
+version = "0.36.17"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "6da3636faa25820d8648e0e31c5d519bbb01f72fdf57131f0f5f7da5fed36eab"
+checksum = "305efbd14fde4139eb501df5f136994bb520b033fa9fbdce287507dc23b8c7ed"
dependencies = [
- "bitflags",
+ "bitflags 1.3.2",
"errno",
"io-lifetimes",
"libc",
@@ -4161,35 +4369,34 @@ dependencies = [
[[package]]
name = "rustix"
-version = "0.37.25"
+version = "0.38.26"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "d4eb579851244c2c03e7c24f501c3432bed80b8f720af1d6e5b0e0f01555a035"
+checksum = "9470c4bf8246c8daf25f9598dca807fb6510347b1e1cfa55749113850c79d88a"
dependencies = [
- "bitflags",
+ "bitflags 2.4.1",
"errno",
- "io-lifetimes",
"libc",
- "linux-raw-sys 0.3.8",
- "windows-sys 0.48.0",
+ "linux-raw-sys 0.4.12",
+ "windows-sys 0.52.0",
]
[[package]]
name = "rustls"
-version = "0.21.6"
+version = "0.21.9"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "1d1feddffcfcc0b33f5c6ce9a29e341e4cd59c3f78e7ee45f4a40c038b1d6cbb"
+checksum = "629648aced5775d558af50b2b4c7b02983a04b312126d45eeead26e7caa498b9"
dependencies = [
"log",
- "ring",
- "rustls-webpki 0.101.4",
+ "ring 0.17.6",
+ "rustls-webpki",
"sct",
]
[[package]]
name = "rustls-native-certs"
-version = "0.6.2"
+version = "0.6.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "0167bac7a9f490495f3c33013e7722b53cb087ecbe082fb0c6387c96f634ea50"
+checksum = "a9aace74cb666635c918e9c12bc0d348266037aa8eb599b5cba565709a8dff00"
dependencies = [
"openssl-probe",
"rustls-pemfile",
@@ -4199,44 +4406,34 @@ dependencies = [
[[package]]
name = "rustls-pemfile"
-version = "1.0.2"
+version = "1.0.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "d194b56d58803a43635bdc398cd17e383d6f71f9182b9a192c127ca42494a59b"
+checksum = "1c74cae0a4cf6ccbbf5f359f08efdf8ee7e1dc532573bf0db71968cb56b1448c"
dependencies = [
- "base64 0.21.1",
+ "base64 0.21.5",
]
[[package]]
name = "rustls-webpki"
-version = "0.100.2"
+version = "0.101.7"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "e98ff011474fa39949b7e5c0428f9b4937eda7da7848bbb947786b7be0b27dab"
+checksum = "8b6275d1ee7a1cd780b64aca7726599a1dbc893b1e64144529e55c3c2f745765"
dependencies = [
- "ring",
- "untrusted",
-]
-
-[[package]]
-name = "rustls-webpki"
-version = "0.101.4"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "7d93931baf2d282fff8d3a532bbfd7653f734643161b87e3e01e59a04439bf0d"
-dependencies = [
- "ring",
- "untrusted",
+ "ring 0.17.6",
+ "untrusted 0.9.0",
]
[[package]]
name = "rustversion"
-version = "1.0.12"
+version = "1.0.14"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "4f3208ce4d8448b3f3e7d168a73f5e0c43a61e32930de3bceeccedb388b6bf06"
+checksum = "7ffc183a10b4478d04cbbbfc96d0873219d962dd5accaff2ffbd4ceb7df837f4"
[[package]]
name = "ryu"
-version = "1.0.13"
+version = "1.0.15"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "f91339c0467de62360649f8d3e185ca8de4224ff281f66000de5eb2a77a79041"
+checksum = "1ad4cc8da4ef723ed60bced201181d83791ad433213d8c24efffda1eec85d741"
[[package]]
name = "s3_scrubber"
@@ -4246,8 +4443,6 @@ dependencies = [
"async-stream",
"aws-config",
"aws-sdk-s3",
- "aws-smithy-http",
- "aws-types",
"bincode",
"bytes",
"chrono",
@@ -4310,6 +4505,7 @@ dependencies = [
"reqwest",
"safekeeper_api",
"scopeguard",
+ "sd-notify",
"serde",
"serde_json",
"serde_with",
@@ -4349,36 +4545,56 @@ dependencies = [
[[package]]
name = "schannel"
-version = "0.1.21"
+version = "0.1.22"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "713cfb06c7059f3588fb8044c0fad1d09e3c01d225e25b9220dbfdcf16dbb1b3"
+checksum = "0c3733bf4cf7ea0880754e19cb5a462007c4a8c1914bff372ccc95b464f1df88"
dependencies = [
- "windows-sys 0.42.0",
+ "windows-sys 0.48.0",
]
[[package]]
name = "scopeguard"
-version = "1.1.0"
+version = "1.2.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "d29ab0c6d3fc0ee92fe66e2d99f700eab17a8d57d1c1d3b748380fb20baa78cd"
+checksum = "94143f37725109f92c262ed2cf5e59bce7498c01bcc1502d7b9afe439a4e9f49"
[[package]]
name = "sct"
-version = "0.7.0"
+version = "0.7.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "d53dcdb7c9f8158937a7981b48accfd39a43af418591a5d008c7b22b5e1b7ca4"
+checksum = "da046153aa2352493d6cb7da4b6e5c0c057d8a1d0a9aa8560baffdd945acd414"
dependencies = [
- "ring",
- "untrusted",
+ "ring 0.17.6",
+ "untrusted 0.9.0",
+]
+
+[[package]]
+name = "sd-notify"
+version = "0.4.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "621e3680f3e07db4c9c2c3fb07c6223ab2fab2e54bd3c04c3ae037990f428c32"
+
+[[package]]
+name = "sec1"
+version = "0.3.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "3be24c1842290c45df0a7bf069e0c268a747ad05a192f2fd7dcfdbc1cba40928"
+dependencies = [
+ "base16ct",
+ "der",
+ "generic-array",
+ "pkcs8",
+ "subtle",
+ "zeroize",
]
[[package]]
name = "security-framework"
-version = "2.9.1"
+version = "2.9.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "1fc758eb7bffce5b308734e9b0c1468893cae9ff70ebf13e7090be8dcbcc83a8"
+checksum = "05b64fb303737d99b81884b2c63433e9ae28abebe5eb5045dcdd175dc2ecf4de"
dependencies = [
- "bitflags",
+ "bitflags 1.3.2",
"core-foundation",
"core-foundation-sys",
"libc",
@@ -4387,9 +4603,9 @@ dependencies = [
[[package]]
name = "security-framework-sys"
-version = "2.9.0"
+version = "2.9.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "f51d0c0d83bec45f16480d0ce0058397a69e48fcdc52d1dc8855fb68acbd31a7"
+checksum = "e932934257d3b408ed8f30db49d85ea163bfe74961f017f405b025af298f0c7a"
dependencies = [
"core-foundation-sys",
"libc",
@@ -4397,15 +4613,15 @@ dependencies = [
[[package]]
name = "semver"
-version = "1.0.17"
+version = "1.0.20"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "bebd363326d05ec3e2f532ab7660680f3b02130d780c299bca73469d521bc0ed"
+checksum = "836fa6a3e1e547f9a2c4040802ec865b5d85f4014efe00555d7090a3dcaa1090"
[[package]]
name = "sentry"
-version = "0.31.6"
+version = "0.31.8"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "2e95efd0cefa32028cdb9766c96de71d96671072f9fb494dc9fb84c0ef93e52b"
+checksum = "6ce4b57f1b521f674df7a1d200be8ff5d74e3712020ee25b553146657b5377d5"
dependencies = [
"httpdate",
"reqwest",
@@ -4417,14 +4633,14 @@ dependencies = [
"sentry-tracing",
"tokio",
"ureq",
- "webpki-roots 0.25.2",
+ "webpki-roots",
]
[[package]]
name = "sentry-backtrace"
-version = "0.31.6"
+version = "0.31.8"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "6ac2bac6f310c4c4c4bb094d1541d32ae497f8c5c23405e85492cefdfe0971a9"
+checksum = "58cc8d4e04a73de8f718dc703943666d03f25d3e9e4d0fb271ca0b8c76dfa00e"
dependencies = [
"backtrace",
"once_cell",
@@ -4434,9 +4650,9 @@ dependencies = [
[[package]]
name = "sentry-contexts"
-version = "0.31.6"
+version = "0.31.8"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "6c3e17295cecdbacf66c5bd38d6e1147e09e1e9d824d2d5341f76638eda02a3a"
+checksum = "6436c1bad22cdeb02179ea8ef116ffc217797c028927def303bc593d9320c0d1"
dependencies = [
"hostname",
"libc",
@@ -4448,9 +4664,9 @@ dependencies = [
[[package]]
name = "sentry-core"
-version = "0.31.6"
+version = "0.31.8"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "8339474f587f36cb110fa1ed1b64229eea6d47b0b886375579297b7e47aeb055"
+checksum = "901f761681f97db3db836ef9e094acdd8756c40215326c194201941947164ef1"
dependencies = [
"once_cell",
"rand 0.8.5",
@@ -4461,9 +4677,9 @@ dependencies = [
[[package]]
name = "sentry-panic"
-version = "0.31.6"
+version = "0.31.8"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "875b69f506da75bd664029eafb05f8934297d2990192896d17325f066bd665b7"
+checksum = "74fbf1c163f8b6a9d05912e1b272afa27c652e8b47ea60cb9a57ad5e481eea99"
dependencies = [
"sentry-backtrace",
"sentry-core",
@@ -4471,9 +4687,9 @@ dependencies = [
[[package]]
name = "sentry-tracing"
-version = "0.31.6"
+version = "0.31.8"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "89feead9bdd116f8035e89567651340fc382db29240b6c55ef412078b08d1aa3"
+checksum = "82eabcab0a047040befd44599a1da73d3adb228ff53b5ed9795ae04535577704"
dependencies = [
"sentry-backtrace",
"sentry-core",
@@ -4483,26 +4699,26 @@ dependencies = [
[[package]]
name = "sentry-types"
-version = "0.31.6"
+version = "0.31.8"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "99dc599bd6646884fc403d593cdcb9816dd67c50cff3271c01ff123617908dcd"
+checksum = "da956cca56e0101998c8688bc65ce1a96f00673a0e58e663664023d4c7911e82"
dependencies = [
"debugid 0.8.0",
- "getrandom 0.2.9",
"hex",
+ "rand 0.8.5",
"serde",
"serde_json",
"thiserror",
"time",
"url",
- "uuid 1.3.3",
+ "uuid 1.6.1",
]
[[package]]
name = "serde"
-version = "1.0.183"
+version = "1.0.193"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "32ac8da02677876d532745a130fc9d8e6edfa81a269b107c5b00829b91d8eb3c"
+checksum = "25dd9975e68d0cb5aa1120c288333fc98731bd1dd12f561e468ea4728c042b89"
dependencies = [
"serde_derive",
]
@@ -4519,20 +4735,20 @@ dependencies = [
[[package]]
name = "serde_derive"
-version = "1.0.183"
+version = "1.0.193"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "aafe972d60b0b9bee71a91b92fee2d4fb3c9d7e8f6b179aa99f27203d99a4816"
+checksum = "43576ca501357b9b071ac53cdc7da8ef0cbd9493d8df094cd821777ea6e894d3"
dependencies = [
"proc-macro2",
"quote",
- "syn 2.0.28",
+ "syn 2.0.39",
]
[[package]]
name = "serde_json"
-version = "1.0.96"
+version = "1.0.108"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "057d394a50403bcac12672b2b18fb387ab6d289d957dab67dd201875391e52f1"
+checksum = "3d1c7e3eac408d115102c4c24ad393e0821bb3a5df4d506a80f85f7a742a526b"
dependencies = [
"itoa",
"ryu",
@@ -4562,9 +4778,9 @@ dependencies = [
[[package]]
name = "serde_spanned"
-version = "0.6.2"
+version = "0.6.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "93107647184f6027e3b7dcb2e11034cf95ffa1e3a682c67951963ac69c1c007d"
+checksum = "12022b835073e5b11e90a14f86838ceb1c8fb0325b72416845c487ac0fa95e80"
dependencies = [
"serde",
]
@@ -4590,7 +4806,7 @@ dependencies = [
"base64 0.13.1",
"chrono",
"hex",
- "indexmap",
+ "indexmap 1.9.3",
"serde",
"serde_json",
"serde_with_macros",
@@ -4606,14 +4822,14 @@ dependencies = [
"darling",
"proc-macro2",
"quote",
- "syn 2.0.28",
+ "syn 2.0.39",
]
[[package]]
name = "sha1"
-version = "0.10.5"
+version = "0.10.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "f04293dc80c3993519f2d7f6f511707ee7094fe0c6d3406feb330cdb3540eba3"
+checksum = "e3bf829a2d51ab4a5ddf1352d8470c140cadc8301b2ae1789db023f01cedd6ba"
dependencies = [
"cfg-if",
"cpufeatures",
@@ -4622,9 +4838,9 @@ dependencies = [
[[package]]
name = "sha2"
-version = "0.10.6"
+version = "0.10.8"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "82e6b795fe2e3b1e845bafcb27aa35405c4d47cdfc92af5fc8d3002f76cebdc0"
+checksum = "793db75ad2bcafc3ffa7c68b215fee268f537982cd901d132f89c6343f3a3dc8"
dependencies = [
"cfg-if",
"cpufeatures",
@@ -4633,24 +4849,24 @@ dependencies = [
[[package]]
name = "sharded-slab"
-version = "0.1.4"
+version = "0.1.7"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "900fba806f70c630b0a382d0d825e17a0f19fcd059a2ade1ff237bcddf446b31"
+checksum = "f40ca3c46823713e0d4209592e8d6e826aa57e928f09752619fc696c499637f6"
dependencies = [
"lazy_static",
]
[[package]]
name = "shlex"
-version = "1.1.0"
+version = "1.2.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "43b2853a4d09f215c24cc5489c992ce46052d359b5109343cbafbf26bc62f8a3"
+checksum = "a7cee0529a6d40f580e7a5e6c495c8fbfe21b7b52795ed4bb5e62cdf92bc6380"
[[package]]
name = "signal-hook"
-version = "0.3.15"
+version = "0.3.17"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "732768f1176d21d09e076c23a93123d40bba92d50c4058da34d45c8de8e682b9"
+checksum = "8621587d4798caf8eb44879d42e56b9a93ea5dcd315a6487c357130095b62801"
dependencies = [
"libc",
"signal-hook-registry",
@@ -4676,6 +4892,16 @@ dependencies = [
"libc",
]
+[[package]]
+name = "signature"
+version = "1.6.4"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "74233d3b3b2f6d4b006dc19dee745e73e2a6bfb6f93607cd3b02bd5b00797d7c"
+dependencies = [
+ "digest",
+ "rand_core 0.6.4",
+]
+
[[package]]
name = "simple_asn1"
version = "0.6.2"
@@ -4690,30 +4916,39 @@ dependencies = [
[[package]]
name = "siphasher"
-version = "0.3.10"
+version = "0.3.11"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "7bd3e3206899af3f8b12af284fafc038cc1dc2b41d1b89dd17297221c5d225de"
+checksum = "38b58827f4464d87d377d175e90bf58eb00fd8716ff0a62f80356b5e61555d0d"
[[package]]
name = "slab"
-version = "0.4.8"
+version = "0.4.9"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "6528351c9bc8ab22353f9d776db39a20288e8d6c37ef8cfe3317cf875eecfc2d"
+checksum = "8f92a496fb766b417c996b9c5e57daf2f7ad3b0bebe1ccfca4856390e3d3bb67"
dependencies = [
"autocfg",
]
[[package]]
name = "smallvec"
-version = "1.11.0"
+version = "1.11.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "62bb4feee49fdd9f707ef802e22365a35de4b7b299de4763d44bfea899442ff9"
+checksum = "4dccd0940a2dcdf68d092b8cbab7dc0ad8fa938bf95787e1b916b0e3d0e8e970"
+
+[[package]]
+name = "smol_str"
+version = "0.2.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "74212e6bbe9a4352329b2f68ba3130c15a3f26fe88ff22dbdc6cdd58fa85e99c"
+dependencies = [
+ "serde",
+]
[[package]]
name = "socket2"
-version = "0.4.9"
+version = "0.4.10"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "64a4a911eed85daf18834cfaa86a79b7d266ff93ff5ba14005426219480ed662"
+checksum = "9f7916fc008ca5542385b89a3d3ce689953c143e9304a9bf8beec1de48994c0d"
dependencies = [
"libc",
"winapi",
@@ -4721,9 +4956,9 @@ dependencies = [
[[package]]
name = "socket2"
-version = "0.5.3"
+version = "0.5.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "2538b18701741680e0322a2302176d3253a35388e2e62f172f64f4f16605f877"
+checksum = "7b5fac59a5cb5dd637972e5fca70daf0523c9067fcdc4842f053dae04a18f8e9"
dependencies = [
"libc",
"windows-sys 0.48.0",
@@ -4744,6 +4979,16 @@ dependencies = [
"lock_api",
]
+[[package]]
+name = "spki"
+version = "0.6.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "67cf02bbac7a337dc36e4f5a693db6c21e7863f45070f7064577eb4367a3212b"
+dependencies = [
+ "base64ct",
+ "der",
+]
+
[[package]]
name = "stable_deref_trait"
version = "1.2.0"
@@ -4792,10 +5037,11 @@ checksum = "9091b6114800a5f2141aee1d1b9d6ca3592ac062dc5decb3764ec5895a47b4eb"
[[package]]
name = "stringprep"
-version = "0.1.2"
+version = "0.1.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "8ee348cb74b87454fff4b551cbf727025810a004f88aeacae7f85b87f4e9a1c1"
+checksum = "bb41d74e231a107a1b4ee36bd1214b11285b77768d2e3824aedafa988fd36ee6"
dependencies = [
+ "finl_unicode",
"unicode-bidi",
"unicode-normalization",
]
@@ -4873,9 +5119,9 @@ dependencies = [
[[package]]
name = "syn"
-version = "2.0.28"
+version = "2.0.39"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "04361975b3f5e348b2189d8dc55bc942f278b2d482a6a0365de5bdd62d351567"
+checksum = "23e78b90f2fcf45d3e842032ce32e3f2d1545ba6636271dcbf24fa306d87be7a"
dependencies = [
"proc-macro2",
"quote",
@@ -4902,9 +5148,9 @@ dependencies = [
[[package]]
name = "sysinfo"
-version = "0.29.7"
+version = "0.29.11"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "165d6d8539689e3d3bc8b98ac59541e1f21c7de7c85d60dc80e43ae0ed2113db"
+checksum = "cd727fc423c2060f6c92d9534cef765c65a6ed3f428a03d7def74a8c4348e666"
dependencies = [
"cfg-if",
"core-foundation-sys",
@@ -4915,6 +5161,27 @@ dependencies = [
"winapi",
]
+[[package]]
+name = "system-configuration"
+version = "0.5.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "ba3a3adc5c275d719af8cb4272ea1c4a6d668a777f37e115f6d11ddbc1c8e0e7"
+dependencies = [
+ "bitflags 1.3.2",
+ "core-foundation",
+ "system-configuration-sys",
+]
+
+[[package]]
+name = "system-configuration-sys"
+version = "0.5.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "a75fb188eb626b924683e3b95e3a48e63551fcfb51949de2f06a9d91dbee93c9"
+dependencies = [
+ "core-foundation-sys",
+ "libc",
+]
+
[[package]]
name = "tar"
version = "0.4.40"
@@ -4937,15 +5204,15 @@ dependencies = [
[[package]]
name = "tempfile"
-version = "3.5.0"
+version = "3.8.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "b9fbec84f381d5795b08656e4912bec604d162bff9291d6189a78f4c8ab87998"
+checksum = "7ef1adac450ad7f4b3c28589471ade84f25f731a7a0fe30d71dfa9f60fd808e5"
dependencies = [
"cfg-if",
- "fastrand 1.9.0",
- "redox_syscall 0.3.5",
- "rustix 0.37.25",
- "windows-sys 0.45.0",
+ "fastrand 2.0.1",
+ "redox_syscall 0.4.1",
+ "rustix 0.38.26",
+ "windows-sys 0.48.0",
]
[[package]]
@@ -4960,9 +5227,9 @@ dependencies = [
[[package]]
name = "termcolor"
-version = "1.2.0"
+version = "1.4.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "be55cf8942feac5c765c2c993422806843c9a9a45d4d5c407ad6dd2ea95eb9b6"
+checksum = "ff1bc3d3f05aff0403e8ac0d92ced918ec05b666a43f83297ccef5bea8a3d449"
dependencies = [
"winapi-util",
]
@@ -4990,22 +5257,22 @@ dependencies = [
[[package]]
name = "thiserror"
-version = "1.0.40"
+version = "1.0.50"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "978c9a314bd8dc99be594bc3c175faaa9794be04a5a5e153caba6915336cebac"
+checksum = "f9a7210f5c9a7156bb50aa36aed4c95afb51df0df00713949448cf9e97d382d2"
dependencies = [
"thiserror-impl",
]
[[package]]
name = "thiserror-impl"
-version = "1.0.40"
+version = "1.0.50"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "f9456a42c5b0d803c8cd86e73dd7cc9edd429499f37a3550d286d5e86720569f"
+checksum = "266b2e40bc00e5a6c09c3584011e08b06f123c00362c92b975ba9843aaaa14b8"
dependencies = [
"proc-macro2",
"quote",
- "syn 2.0.28",
+ "syn 2.0.39",
]
[[package]]
@@ -5020,14 +5287,16 @@ dependencies = [
[[package]]
name = "time"
-version = "0.3.21"
+version = "0.3.30"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "8f3403384eaacbca9923fa06940178ac13e4edb725486d70e8e15881d0c836cc"
+checksum = "c4a34ab300f2dee6e562c10a046fc05e358b29f9bf92277f30c3c8d82275f6f5"
dependencies = [
+ "deranged",
"itoa",
"js-sys",
"libc",
"num_threads",
+ "powerfmt",
"serde",
"time-core",
"time-macros",
@@ -5035,15 +5304,15 @@ dependencies = [
[[package]]
name = "time-core"
-version = "0.1.1"
+version = "0.1.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "7300fbefb4dadc1af235a9cef3737cea692a9d97e1b9cbcd4ebdae6f8868e6fb"
+checksum = "ef927ca75afb808a4d64dd374f00a2adf8d0fcff8e7b184af886c3c87ec4a3f3"
[[package]]
name = "time-macros"
-version = "0.2.9"
+version = "0.2.15"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "372950940a5f07bf38dbe211d7283c9e6d7327df53794992d293e534c733d09b"
+checksum = "4ad70d68dba9e1f8aceda7aa6711965dfec1cac869f311a51bd08b3a2ccbce20"
dependencies = [
"time-core",
]
@@ -5089,18 +5358,18 @@ dependencies = [
[[package]]
name = "tokio"
-version = "1.28.1"
+version = "1.34.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "0aa32867d44e6f2ce3385e89dceb990188b8bb0fb25b0cf576647a6f98ac5105"
+checksum = "d0c014766411e834f7af5b8f4cf46257aab4036ca95e9d2c144a10f59ad6f5b9"
dependencies = [
- "autocfg",
+ "backtrace",
"bytes",
"libc",
"mio",
"num_cpus",
"pin-project-lite",
"signal-hook-registry",
- "socket2 0.4.9",
+ "socket2 0.5.5",
"tokio-macros",
"windows-sys 0.48.0",
]
@@ -5117,13 +5386,13 @@ dependencies = [
[[package]]
name = "tokio-macros"
-version = "2.1.0"
+version = "2.2.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "630bdcf245f78637c13ec01ffae6187cca34625e8c63150d424b59e55af2675e"
+checksum = "5b8a1e28f2deaa14e508979454cb3a223b10b938b45af148bc0986de36f1923b"
dependencies = [
"proc-macro2",
"quote",
- "syn 2.0.28",
+ "syn 2.0.39",
]
[[package]]
@@ -5154,7 +5423,7 @@ dependencies = [
"pin-project-lite",
"postgres-protocol",
"postgres-types",
- "socket2 0.5.3",
+ "socket2 0.5.5",
"tokio",
"tokio-util",
]
@@ -5166,7 +5435,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "dd5831152cb0d3f79ef5523b357319ba154795d64c7078b2daa95a803b54057f"
dependencies = [
"futures",
- "ring",
+ "ring 0.16.20",
"rustls",
"tokio",
"tokio-postgres",
@@ -5175,9 +5444,9 @@ dependencies = [
[[package]]
name = "tokio-rustls"
-version = "0.24.0"
+version = "0.24.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "e0d409377ff5b1e3ca6437aa86c1eb7d40c134bfec254e44c830defa92669db5"
+checksum = "c28327cf380ac148141087fbfb9de9d7bd4e84ab5d2c28fbc911d753de8a7081"
dependencies = [
"rustls",
"tokio",
@@ -5211,9 +5480,9 @@ dependencies = [
[[package]]
name = "tokio-tungstenite"
-version = "0.20.0"
+version = "0.20.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "2b2dbec703c26b00d74844519606ef15d09a7d6857860f84ad223dec002ddea2"
+checksum = "212d5dcb2a1ce06d81107c3d0ffa3121fe974b73f068c8282cb1c32328113b6c"
dependencies = [
"futures-util",
"log",
@@ -5223,9 +5492,9 @@ dependencies = [
[[package]]
name = "tokio-util"
-version = "0.7.8"
+version = "0.7.10"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "806fe8c2c87eccc8b3267cbae29ed3ab2d0bd37fca70ab622e46aaa9375ddb7d"
+checksum = "5419f34732d9eb6ee4c3578b7989078579b7f039cbbb9ca2c4da015749371e15"
dependencies = [
"bytes",
"futures-core",
@@ -5237,9 +5506,9 @@ dependencies = [
[[package]]
name = "toml"
-version = "0.7.4"
+version = "0.7.8"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "d6135d499e69981f9ff0ef2167955a5333c35e36f6937d382974566b3d5b94ec"
+checksum = "dd79e69d3b627db300ff956027cc6c3798cef26d22526befdfcd12feeb6d2257"
dependencies = [
"serde",
"serde_spanned",
@@ -5249,20 +5518,20 @@ dependencies = [
[[package]]
name = "toml_datetime"
-version = "0.6.2"
+version = "0.6.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "5a76a9312f5ba4c2dec6b9161fdf25d87ad8a09256ccea5a556fef03c706a10f"
+checksum = "3550f4e9685620ac18a50ed434eb3aec30db8ba93b0287467bca5826ea25baf1"
dependencies = [
"serde",
]
[[package]]
name = "toml_edit"
-version = "0.19.10"
+version = "0.19.15"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "2380d56e8670370eee6566b0bfd4265f65b3f432e8c6d85623f728d4fa31f739"
+checksum = "1b5bb770da30e5cbfde35a2d7b9b8a2c4b8ef89548a7a6aeab5c9a576e3e7421"
dependencies = [
- "indexmap",
+ "indexmap 2.1.0",
"serde",
"serde_spanned",
"toml_datetime",
@@ -5310,7 +5579,7 @@ dependencies = [
"async-stream",
"async-trait",
"axum",
- "base64 0.21.1",
+ "base64 0.21.5",
"bytes",
"futures-core",
"futures-util",
@@ -5354,7 +5623,7 @@ checksum = "b8fa9be0de6cf49e536ce1851f987bd21a43b771b09473c3549a6c853db37c1c"
dependencies = [
"futures-core",
"futures-util",
- "indexmap",
+ "indexmap 1.9.3",
"pin-project",
"pin-project-lite",
"rand 0.8.5",
@@ -5391,11 +5660,10 @@ dependencies = [
[[package]]
name = "tracing"
-version = "0.1.37"
+version = "0.1.40"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "8ce8c33a8d48bd45d624a6e523445fd21ec13d3653cd51f681abf67418f54eb8"
+checksum = "c3523ab5a71916ccf420eebdf5521fcef02141234bbc0b8a49f2fdc4544364ef"
dependencies = [
- "cfg-if",
"log",
"pin-project-lite",
"tracing-attributes",
@@ -5404,31 +5672,32 @@ dependencies = [
[[package]]
name = "tracing-appender"
-version = "0.2.2"
+version = "0.2.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "09d48f71a791638519505cefafe162606f706c25592e4bde4d97600c0195312e"
+checksum = "3566e8ce28cc0a3fe42519fc80e6b4c943cc4c8cef275620eb8dac2d3d4e06cf"
dependencies = [
"crossbeam-channel",
+ "thiserror",
"time",
"tracing-subscriber",
]
[[package]]
name = "tracing-attributes"
-version = "0.1.24"
+version = "0.1.27"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "0f57e3ca2a01450b1a921183a9c9cbfda207fd822cef4ccb00a65402cbba7a74"
+checksum = "34704c8d6ebcbc939824180af020566b01a7c01f80641264eba0999f6c2b6be7"
dependencies = [
"proc-macro2",
"quote",
- "syn 2.0.28",
+ "syn 2.0.39",
]
[[package]]
name = "tracing-core"
-version = "0.1.31"
+version = "0.1.32"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "0955b8137a1df6f1a2e9a37d8a6656291ff0297c1a97c24e0d8425fe2312f79a"
+checksum = "c06d3da6113f116aaee68e4d601191614c9053067f9ab7f6edbcb161237daa54"
dependencies = [
"once_cell",
"valuable",
@@ -5456,12 +5725,23 @@ dependencies = [
[[package]]
name = "tracing-log"
-version = "0.1.3"
+version = "0.1.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "78ddad33d2d10b1ed7eb9d1f518a5674713876e97e5bb9b7345a7984fbb4f922"
+checksum = "f751112709b4e791d8ce53e32c4ed2d353565a795ce84da2285393f41557bdf2"
dependencies = [
- "lazy_static",
"log",
+ "once_cell",
+ "tracing-core",
+]
+
+[[package]]
+name = "tracing-log"
+version = "0.2.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "ee855f1f400bd0e5c02d150ae5de3840039a3f54b025156404e34c23c03f47c3"
+dependencies = [
+ "log",
+ "once_cell",
"tracing-core",
]
@@ -5475,7 +5755,7 @@ dependencies = [
"opentelemetry",
"tracing",
"tracing-core",
- "tracing-log",
+ "tracing-log 0.1.4",
"tracing-subscriber",
]
@@ -5491,9 +5771,9 @@ dependencies = [
[[package]]
name = "tracing-subscriber"
-version = "0.3.17"
+version = "0.3.18"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "30a651bc37f915e81f087d86e62a18eec5f79550c7faff886f7090b4ea757c77"
+checksum = "ad0f048c97dbd9faa9b7df56362b8ebcaa52adb06b498c050d2f4e32f90a7a8b"
dependencies = [
"matchers",
"once_cell",
@@ -5505,7 +5785,7 @@ dependencies = [
"thread_local",
"tracing",
"tracing-core",
- "tracing-log",
+ "tracing-log 0.2.0",
"tracing-serde",
]
@@ -5552,9 +5832,9 @@ dependencies = [
[[package]]
name = "typenum"
-version = "1.16.0"
+version = "1.17.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "497961ef93d974e23eb6f433eb5fe1b7930b659f06d12dec6fc44a8f554c0bba"
+checksum = "42ff0bf0c66b8238c6f3b578df37d0b7848e55df8577b3f74f92a69acceeb825"
[[package]]
name = "tz-rs"
@@ -5576,9 +5856,9 @@ dependencies = [
[[package]]
name = "unicase"
-version = "2.6.0"
+version = "2.7.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "50f37be617794602aabbeee0be4f259dc1778fabe05e2d67ee8f79326d5cb4f6"
+checksum = "f7d2d4dafb69621809a81864c9c1b864479e1235c0dd4e199924b9742439ed89"
dependencies = [
"version_check",
]
@@ -5591,9 +5871,9 @@ checksum = "92888ba5573ff080736b3648696b70cafad7d250551175acbaa4e0385b3e1460"
[[package]]
name = "unicode-ident"
-version = "1.0.9"
+version = "1.0.12"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "b15811caf2415fb889178633e7724bad2509101cde276048e013b9def5e51fa0"
+checksum = "3354b9ac3fae1ff6755cb6db53683adb661634f67557942dea4facebec0fee4b"
[[package]]
name = "unicode-normalization"
@@ -5606,9 +5886,9 @@ dependencies = [
[[package]]
name = "unicode-width"
-version = "0.1.10"
+version = "0.1.11"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "c0edd1e5b14653f783770bce4a4dabb4a5108a5370a5f5d8cfe8710c361f6c8b"
+checksum = "e51733f11c9c4f72aa0c160008246859e340b00807569a0da0e7a1079b27ba85"
[[package]]
name = "unicode-xid"
@@ -5623,25 +5903,31 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a156c684c91ea7d62626509bce3cb4e1d9ed5c4d978f7b4352658f96a4c26b4a"
[[package]]
-name = "ureq"
-version = "2.7.1"
+name = "untrusted"
+version = "0.9.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "0b11c96ac7ee530603dcdf68ed1557050f374ce55a5a07193ebf8cbc9f8927e9"
+checksum = "8ecb6da28b8a351d773b68d5825ac39017e680750f980f3a1a85cd8dd28a47c1"
+
+[[package]]
+name = "ureq"
+version = "2.9.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "f8cdd25c339e200129fe4de81451814e5228c9b771d57378817d6117cc2b3f97"
dependencies = [
- "base64 0.21.1",
+ "base64 0.21.5",
"log",
"once_cell",
"rustls",
- "rustls-webpki 0.100.2",
+ "rustls-webpki",
"url",
- "webpki-roots 0.23.1",
+ "webpki-roots",
]
[[package]]
name = "url"
-version = "2.3.1"
+version = "2.5.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "0d68c799ae75762b8c3fe375feb6600ef5602c883c5d21eb51c09f22b83c4643"
+checksum = "31e6302e3bb753d46e83516cae55ae196fc0c309407cf11ab35cc51a4c2a4633"
dependencies = [
"form_urlencoded",
"idna",
@@ -5651,9 +5937,9 @@ dependencies = [
[[package]]
name = "urlencoding"
-version = "2.1.2"
+version = "2.1.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "e8db7427f936968176eaa7cdf81b7f98b980b18495ec28f1b5791ac3bfe3eea9"
+checksum = "daf8dba3b7eb870caf1ddeed7bc9d2a049f3cfdfae7cb521b087cc33ae4c49da"
[[package]]
name = "utf-8"
@@ -5689,7 +5975,7 @@ dependencies = [
"hyper",
"jsonwebtoken",
"metrics",
- "nix 0.26.2",
+ "nix 0.26.4",
"once_cell",
"pin-project-lite",
"postgres_connection",
@@ -5713,7 +5999,7 @@ dependencies = [
"tracing-error",
"tracing-subscriber",
"url",
- "uuid 1.3.3",
+ "uuid 1.6.1",
"workspace_hack",
]
@@ -5725,11 +6011,11 @@ checksum = "bc5cf98d8186244414c848017f0e2676b3fcb46807f6668a97dfe67359a3c4b7"
[[package]]
name = "uuid"
-version = "1.3.3"
+version = "1.6.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "345444e32442451b267fc254ae85a209c64be56d2890e601a0c37ff0c3c5ecd2"
+checksum = "5e395fcf16a7a3d8127ec99782007af141946b4795001f876d54fb0d55978560"
dependencies = [
- "getrandom 0.2.9",
+ "getrandom 0.2.11",
"serde",
]
@@ -5803,9 +6089,9 @@ dependencies = [
[[package]]
name = "walkdir"
-version = "2.3.3"
+version = "2.4.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "36df944cda56c7d8d8b7496af378e6b16de9284591917d307c9b4d313c44e698"
+checksum = "d71d857dc86794ca4c280d616f7da00d2dbfd8cd788846559a6813e6aa4b54ee"
dependencies = [
"same-file",
"winapi-util",
@@ -5824,11 +6110,10 @@ dependencies = [
[[package]]
name = "want"
-version = "0.3.0"
+version = "0.3.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "1ce8a968cb1cd110d136ff8b819a556d6fb6d919363c61534f6860c7eb172ba0"
+checksum = "bfa7760aed19e106de2c7c0b581b509f2f25d3dacaf737cb82ac61bc6d760b0e"
dependencies = [
- "log",
"try-lock",
]
@@ -5846,9 +6131,9 @@ checksum = "9c8d87e72b64a3b4db28d11ce29237c246188f4f51057d65a7eab63b7987e423"
[[package]]
name = "wasm-bindgen"
-version = "0.2.86"
+version = "0.2.89"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "5bba0e8cb82ba49ff4e229459ff22a191bbe9a1cb3a341610c9c33efc27ddf73"
+checksum = "0ed0d4f68a3015cc185aff4db9506a015f4b96f95303897bfa23f846db54064e"
dependencies = [
"cfg-if",
"wasm-bindgen-macro",
@@ -5856,24 +6141,24 @@ dependencies = [
[[package]]
name = "wasm-bindgen-backend"
-version = "0.2.86"
+version = "0.2.89"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "19b04bc93f9d6bdee709f6bd2118f57dd6679cf1176a1af464fca3ab0d66d8fb"
+checksum = "1b56f625e64f3a1084ded111c4d5f477df9f8c92df113852fa5a374dbda78826"
dependencies = [
"bumpalo",
"log",
"once_cell",
"proc-macro2",
"quote",
- "syn 2.0.28",
+ "syn 2.0.39",
"wasm-bindgen-shared",
]
[[package]]
name = "wasm-bindgen-futures"
-version = "0.4.36"
+version = "0.4.39"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "2d1985d03709c53167ce907ff394f5316aa22cb4e12761295c5dc57dacb6297e"
+checksum = "ac36a15a220124ac510204aec1c3e5db8a22ab06fd6706d881dc6149f8ed9a12"
dependencies = [
"cfg-if",
"js-sys",
@@ -5883,9 +6168,9 @@ dependencies = [
[[package]]
name = "wasm-bindgen-macro"
-version = "0.2.86"
+version = "0.2.89"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "14d6b024f1a526bb0234f52840389927257beb670610081360e5a03c5df9c258"
+checksum = "0162dbf37223cd2afce98f3d0785506dcb8d266223983e4b5b525859e6e182b2"
dependencies = [
"quote",
"wasm-bindgen-macro-support",
@@ -5893,22 +6178,22 @@ dependencies = [
[[package]]
name = "wasm-bindgen-macro-support"
-version = "0.2.86"
+version = "0.2.89"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "e128beba882dd1eb6200e1dc92ae6c5dbaa4311aa7bb211ca035779e5efc39f8"
+checksum = "f0eb82fcb7930ae6219a7ecfd55b217f5f0893484b7a13022ebb2b2bf20b5283"
dependencies = [
"proc-macro2",
"quote",
- "syn 2.0.28",
+ "syn 2.0.39",
"wasm-bindgen-backend",
"wasm-bindgen-shared",
]
[[package]]
name = "wasm-bindgen-shared"
-version = "0.2.86"
+version = "0.2.89"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "ed9d5b4305409d1fc9482fee2d7f9bcbf24b3972bf59817ef757e23982242a93"
+checksum = "7ab9b36309365056cd639da3134bf87fa8f3d86008abf99e612384a6eecd459f"
[[package]]
name = "wasm-streams"
@@ -5940,9 +6225,9 @@ dependencies = [
[[package]]
name = "web-sys"
-version = "0.3.63"
+version = "0.3.66"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "3bdd9ef4e984da1187bf8110c5cf5b845fbc87a23602cdf912386a76fcd3a7c2"
+checksum = "50c24a44ec86bb68fbecd1b3efed7e85ea5621b39b35ef2766b66cd984f8010f"
dependencies = [
"js-sys",
"wasm-bindgen",
@@ -5950,28 +6235,20 @@ dependencies = [
[[package]]
name = "webpki-roots"
-version = "0.23.1"
+version = "0.25.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "b03058f88386e5ff5310d9111d53f48b17d732b401aeb83a8d5190f2ac459338"
-dependencies = [
- "rustls-webpki 0.100.2",
-]
-
-[[package]]
-name = "webpki-roots"
-version = "0.25.2"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "14247bb57be4f377dfb94c72830b8ce8fc6beac03cf4bf7b9732eadd414123fc"
+checksum = "1778a42e8b3b90bff8d0f5032bf22250792889a5cdc752aa0020c84abe3aaf10"
[[package]]
name = "which"
-version = "4.4.0"
+version = "4.4.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "2441c784c52b289a054b7201fc93253e288f094e2f4be9058343127c4226a269"
+checksum = "87ba24419a2078cd2b0f2ede2691b6c66d8e47836da3b6db8265ebad47afbfc7"
dependencies = [
"either",
- "libc",
+ "home",
"once_cell",
+ "rustix 0.38.26",
]
[[package]]
@@ -5992,9 +6269,9 @@ checksum = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6"
[[package]]
name = "winapi-util"
-version = "0.1.5"
+version = "0.1.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "70ec6ce85bb158151cae5e5c87f95a8e97d2c0c4b001223f33a334e3ce5de178"
+checksum = "f29e6f9198ba0d26b4c9f07dbe6f9ed633e1f3d5b8b414090084349e46a52596"
dependencies = [
"winapi",
]
@@ -6006,27 +6283,12 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f"
[[package]]
-name = "windows"
-version = "0.48.0"
+name = "windows-core"
+version = "0.51.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "e686886bc078bc1b0b600cac0147aadb815089b6e4da64016cbd754b6342700f"
+checksum = "f1f8cf84f35d2db49a46868f947758c7a1138116f7fac3bc844f43ade1292e64"
dependencies = [
- "windows-targets 0.48.0",
-]
-
-[[package]]
-name = "windows-sys"
-version = "0.42.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "5a3e1820f08b8513f676f7ab6c1f99ff312fb97b553d30ff4dd86f9f15728aa7"
-dependencies = [
- "windows_aarch64_gnullvm 0.42.2",
- "windows_aarch64_msvc 0.42.2",
- "windows_i686_gnu 0.42.2",
- "windows_i686_msvc 0.42.2",
- "windows_x86_64_gnu 0.42.2",
- "windows_x86_64_gnullvm 0.42.2",
- "windows_x86_64_msvc 0.42.2",
+ "windows-targets 0.48.5",
]
[[package]]
@@ -6044,7 +6306,16 @@ version = "0.48.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "677d2418bec65e3338edb076e806bc1ec15693c5d0104683f2efe857f61056a9"
dependencies = [
- "windows-targets 0.48.0",
+ "windows-targets 0.48.5",
+]
+
+[[package]]
+name = "windows-sys"
+version = "0.52.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "282be5f36a8ce781fad8c8ae18fa3f9beff57ec1b52cb3de0789201425d9a33d"
+dependencies = [
+ "windows-targets 0.52.0",
]
[[package]]
@@ -6064,17 +6335,32 @@ dependencies = [
[[package]]
name = "windows-targets"
-version = "0.48.0"
+version = "0.48.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "7b1eb6f0cd7c80c79759c929114ef071b87354ce476d9d94271031c0497adfd5"
+checksum = "9a2fa6e2155d7247be68c096456083145c183cbbbc2764150dda45a87197940c"
dependencies = [
- "windows_aarch64_gnullvm 0.48.0",
- "windows_aarch64_msvc 0.48.0",
- "windows_i686_gnu 0.48.0",
- "windows_i686_msvc 0.48.0",
- "windows_x86_64_gnu 0.48.0",
- "windows_x86_64_gnullvm 0.48.0",
- "windows_x86_64_msvc 0.48.0",
+ "windows_aarch64_gnullvm 0.48.5",
+ "windows_aarch64_msvc 0.48.5",
+ "windows_i686_gnu 0.48.5",
+ "windows_i686_msvc 0.48.5",
+ "windows_x86_64_gnu 0.48.5",
+ "windows_x86_64_gnullvm 0.48.5",
+ "windows_x86_64_msvc 0.48.5",
+]
+
+[[package]]
+name = "windows-targets"
+version = "0.52.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "8a18201040b24831fbb9e4eb208f8892e1f50a37feb53cc7ff887feb8f50e7cd"
+dependencies = [
+ "windows_aarch64_gnullvm 0.52.0",
+ "windows_aarch64_msvc 0.52.0",
+ "windows_i686_gnu 0.52.0",
+ "windows_i686_msvc 0.52.0",
+ "windows_x86_64_gnu 0.52.0",
+ "windows_x86_64_gnullvm 0.52.0",
+ "windows_x86_64_msvc 0.52.0",
]
[[package]]
@@ -6085,9 +6371,15 @@ checksum = "597a5118570b68bc08d8d59125332c54f1ba9d9adeedeef5b99b02ba2b0698f8"
[[package]]
name = "windows_aarch64_gnullvm"
-version = "0.48.0"
+version = "0.48.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "91ae572e1b79dba883e0d315474df7305d12f569b400fcf90581b06062f7e1bc"
+checksum = "2b38e32f0abccf9987a4e3079dfb67dcd799fb61361e53e2882c3cbaf0d905d8"
+
+[[package]]
+name = "windows_aarch64_gnullvm"
+version = "0.52.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "cb7764e35d4db8a7921e09562a0304bf2f93e0a51bfccee0bd0bb0b666b015ea"
[[package]]
name = "windows_aarch64_msvc"
@@ -6097,9 +6389,15 @@ checksum = "e08e8864a60f06ef0d0ff4ba04124db8b0fb3be5776a5cd47641e942e58c4d43"
[[package]]
name = "windows_aarch64_msvc"
-version = "0.48.0"
+version = "0.48.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "b2ef27e0d7bdfcfc7b868b317c1d32c641a6fe4629c171b8928c7b08d98d7cf3"
+checksum = "dc35310971f3b2dbbf3f0690a219f40e2d9afcf64f9ab7cc1be722937c26b4bc"
+
+[[package]]
+name = "windows_aarch64_msvc"
+version = "0.52.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "bbaa0368d4f1d2aaefc55b6fcfee13f41544ddf36801e793edbbfd7d7df075ef"
[[package]]
name = "windows_i686_gnu"
@@ -6109,9 +6407,15 @@ checksum = "c61d927d8da41da96a81f029489353e68739737d3beca43145c8afec9a31a84f"
[[package]]
name = "windows_i686_gnu"
-version = "0.48.0"
+version = "0.48.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "622a1962a7db830d6fd0a69683c80a18fda201879f0f447f065a3b7467daa241"
+checksum = "a75915e7def60c94dcef72200b9a8e58e5091744960da64ec734a6c6e9b3743e"
+
+[[package]]
+name = "windows_i686_gnu"
+version = "0.52.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "a28637cb1fa3560a16915793afb20081aba2c92ee8af57b4d5f28e4b3e7df313"
[[package]]
name = "windows_i686_msvc"
@@ -6121,9 +6425,15 @@ checksum = "44d840b6ec649f480a41c8d80f9c65108b92d89345dd94027bfe06ac444d1060"
[[package]]
name = "windows_i686_msvc"
-version = "0.48.0"
+version = "0.48.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "4542c6e364ce21bf45d69fdd2a8e455fa38d316158cfd43b3ac1c5b1b19f8e00"
+checksum = "8f55c233f70c4b27f66c523580f78f1004e8b5a8b659e05a4eb49d4166cca406"
+
+[[package]]
+name = "windows_i686_msvc"
+version = "0.52.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "ffe5e8e31046ce6230cc7215707b816e339ff4d4d67c65dffa206fd0f7aa7b9a"
[[package]]
name = "windows_x86_64_gnu"
@@ -6133,9 +6443,15 @@ checksum = "8de912b8b8feb55c064867cf047dda097f92d51efad5b491dfb98f6bbb70cb36"
[[package]]
name = "windows_x86_64_gnu"
-version = "0.48.0"
+version = "0.48.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "ca2b8a661f7628cbd23440e50b05d705db3686f894fc9580820623656af974b1"
+checksum = "53d40abd2583d23e4718fddf1ebec84dbff8381c07cae67ff7768bbf19c6718e"
+
+[[package]]
+name = "windows_x86_64_gnu"
+version = "0.52.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "3d6fa32db2bc4a2f5abeacf2b69f7992cd09dca97498da74a151a3132c26befd"
[[package]]
name = "windows_x86_64_gnullvm"
@@ -6145,9 +6461,15 @@ checksum = "26d41b46a36d453748aedef1486d5c7a85db22e56aff34643984ea85514e94a3"
[[package]]
name = "windows_x86_64_gnullvm"
-version = "0.48.0"
+version = "0.48.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "7896dbc1f41e08872e9d5e8f8baa8fdd2677f29468c4e156210174edc7f7b953"
+checksum = "0b7b52767868a23d5bab768e390dc5f5c55825b6d30b86c844ff2dc7414044cc"
+
+[[package]]
+name = "windows_x86_64_gnullvm"
+version = "0.52.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "1a657e1e9d3f514745a572a6846d3c7aa7dbe1658c056ed9c3344c4109a6949e"
[[package]]
name = "windows_x86_64_msvc"
@@ -6157,15 +6479,21 @@ checksum = "9aec5da331524158c6d1a4ac0ab1541149c0b9505fde06423b02f5ef0106b9f0"
[[package]]
name = "windows_x86_64_msvc"
-version = "0.48.0"
+version = "0.48.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "1a515f5799fe4961cb532f983ce2b23082366b898e52ffbce459c86f67c8378a"
+checksum = "ed94fce61571a4006852b7389a063ab983c02eb1bb37b47f8272ce92d06d9538"
+
+[[package]]
+name = "windows_x86_64_msvc"
+version = "0.52.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "dff9641d1cd4be8d1a070daf9e3773c5f67e78b4d9d42263020c057706765c04"
[[package]]
name = "winnow"
-version = "0.4.6"
+version = "0.5.19"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "61de7bac303dc551fe038e2b3cef0f571087a47571ea6e79a87692ac99b99699"
+checksum = "829846f3e3db426d4cee4510841b71a8e58aa2a76b1132579487ae430ccd9c7b"
dependencies = [
"memchr",
]
@@ -6188,9 +6516,13 @@ dependencies = [
"aws-config",
"aws-runtime",
"aws-sigv4",
+ "aws-smithy-async",
"aws-smithy-http",
+ "aws-smithy-runtime-api",
+ "aws-smithy-types",
"axum",
- "base64 0.21.1",
+ "base64 0.21.5",
+ "base64ct",
"bytes",
"cc",
"chrono",
@@ -6208,6 +6540,7 @@ dependencies = [
"futures-sink",
"futures-util",
"hex",
+ "hmac",
"hyper",
"itertools",
"libc",
@@ -6220,16 +6553,17 @@ dependencies = [
"prost",
"rand 0.8.5",
"regex",
- "regex-syntax 0.7.2",
+ "regex-syntax 0.7.5",
"reqwest",
- "ring",
+ "ring 0.16.20",
"rustls",
"scopeguard",
"serde",
"serde_json",
"smallvec",
+ "subtle",
"syn 1.0.109",
- "syn 2.0.28",
+ "syn 2.0.39",
"time",
"time-macros",
"tokio",
@@ -6242,17 +6576,17 @@ dependencies = [
"tracing-core",
"tungstenite",
"url",
- "uuid 1.3.3",
- "zstd",
- "zstd-safe",
+ "uuid 1.6.1",
+ "zstd 0.12.4",
+ "zstd-safe 6.0.6",
"zstd-sys",
]
[[package]]
name = "x509-parser"
-version = "0.15.0"
+version = "0.15.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "bab0c2f54ae1d92f4fcb99c0b7ccf0b1e3451cbd395e5f115ccbdbcb18d4f634"
+checksum = "7069fba5b66b9193bd2c5d3d4ff12b839118f6bcbef5328efafafb5395cf63da"
dependencies = [
"asn1-rs",
"data-encoding",
@@ -6267,18 +6601,18 @@ dependencies = [
[[package]]
name = "xattr"
-version = "1.0.0"
+version = "1.0.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "ea263437ca03c1522846a4ddafbca2542d0ad5ed9b784909d4b27b76f62bc34a"
+checksum = "f4686009f71ff3e5c4dbcf1a282d0a44db3f021ba69350cd42086b3e5f1c6985"
dependencies = [
"libc",
]
[[package]]
name = "xmlparser"
-version = "0.13.5"
+version = "0.13.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "4d25c75bf9ea12c4040a97f829154768bbbce366287e2dc044af160cd79a13fd"
+checksum = "66fee0b777b0f5ac1c69bb06d361268faafa61cd4682ae064a171c16c433e9e4"
[[package]]
name = "yasna"
@@ -6291,29 +6625,29 @@ dependencies = [
[[package]]
name = "zerocopy"
-version = "0.7.3"
+version = "0.7.28"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "7a7af71d8643341260a65f89fa60c0eeaa907f34544d8f6d9b0df72f069b5e74"
+checksum = "7d6f15f7ade05d2a4935e34a457b936c23dc70a05cc1d97133dc99e7a3fe0f0e"
dependencies = [
"zerocopy-derive",
]
[[package]]
name = "zerocopy-derive"
-version = "0.7.3"
+version = "0.7.28"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "9731702e2f0617ad526794ae28fbc6f6ca8849b5ba729666c2a5bc4b6ddee2cd"
+checksum = "dbbad221e3f78500350ecbd7dfa4e63ef945c05f4c61cb7f4d3f84cd0bba649b"
dependencies = [
"proc-macro2",
"quote",
- "syn 2.0.28",
+ "syn 2.0.39",
]
[[package]]
name = "zeroize"
-version = "1.6.0"
+version = "1.7.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "2a0956f1ba7c7909bfb66c2e9e4124ab6f6482560f6628b5aaeba39207c9aad9"
+checksum = "525b4ec142c6b68a2d10f01f7bbf6755599ca3f81ea53b8431b7dd348f5fdb2d"
[[package]]
name = "zstd"
@@ -6321,7 +6655,16 @@ version = "0.12.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1a27595e173641171fc74a1232b7b1c7a7cb6e18222c11e9dfb9888fa424c53c"
dependencies = [
- "zstd-safe",
+ "zstd-safe 6.0.6",
+]
+
+[[package]]
+name = "zstd"
+version = "0.13.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "bffb3309596d527cfcba7dfc6ed6052f1d39dfbd7c867aa2e865e4a449c10110"
+dependencies = [
+ "zstd-safe 7.0.0",
]
[[package]]
@@ -6335,12 +6678,20 @@ dependencies = [
]
[[package]]
-name = "zstd-sys"
-version = "2.0.8+zstd.1.5.5"
+name = "zstd-safe"
+version = "7.0.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "5556e6ee25d32df2586c098bbfa278803692a20d0ab9565e049480d52707ec8c"
+checksum = "43747c7422e2924c11144d5229878b98180ef8b06cca4ab5af37afc8a8d8ea3e"
+dependencies = [
+ "zstd-sys",
+]
+
+[[package]]
+name = "zstd-sys"
+version = "2.0.9+zstd.1.5.5"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "9e16efa8a874a0481a574084d34cc26fdb3b99627480f785888deb6386506656"
dependencies = [
"cc",
- "libc",
"pkg-config",
]
diff --git a/Cargo.toml b/Cargo.toml
index c50fb7be42..ba8b49c0e0 100644
--- a/Cargo.toml
+++ b/Cargo.toml
@@ -45,12 +45,11 @@ azure_storage_blobs = "0.16"
flate2 = "1.0.26"
async-stream = "0.3"
async-trait = "0.1"
-aws-config = { version = "0.56", default-features = false, features=["rustls"] }
-aws-sdk-s3 = "0.29"
-aws-smithy-http = "0.56"
-aws-smithy-async = { version = "0.56", default-features = false, features=["rt-tokio"] }
-aws-credential-types = "0.56"
-aws-types = "0.56"
+aws-config = { version = "1.0", default-features = false, features=["rustls"] }
+aws-sdk-s3 = "1.0"
+aws-smithy-async = { version = "1.0", default-features = false, features=["rt-tokio"] }
+aws-smithy-types = "1.0"
+aws-credential-types = "1.0"
axum = { version = "0.6.20", features = ["ws"] }
base64 = "0.13.0"
bincode = "1.3"
@@ -89,6 +88,7 @@ humantime-serde = "1.1.1"
hyper = "0.14"
hyper-tungstenite = "0.11"
inotify = "0.10.2"
+ipnet = "2.9.0"
itertools = "0.10"
jsonwebtoken = "8"
libc = "0.2"
@@ -122,14 +122,17 @@ rustls-pemfile = "1"
rustls-split = "0.3"
scopeguard = "1.1"
sysinfo = "0.29.2"
+sd-notify = "0.4.1"
sentry = { version = "0.31", default-features = false, features = ["backtrace", "contexts", "panic", "rustls", "reqwest" ] }
serde = { version = "1.0", features = ["derive"] }
serde_json = "1"
+serde_path_to_error = "0.1"
serde_with = "2.0"
serde_assert = "0.5.0"
sha2 = "0.10.2"
signal-hook = "0.3"
smallvec = "1.11"
+smol_str = { version = "0.2.0", features = ["serde"] }
socket2 = "0.5"
strum = "0.24"
strum_macros = "0.24"
diff --git a/Dockerfile.compute-node b/Dockerfile.compute-node
index 8109091e76..425f163e8b 100644
--- a/Dockerfile.compute-node
+++ b/Dockerfile.compute-node
@@ -387,18 +387,10 @@ COPY --from=pg-build /usr/local/pgsql/ /usr/local/pgsql/
ARG PG_VERSION
ENV PATH "/usr/local/pgsql/bin:$PATH"
-RUN case "${PG_VERSION}" in \
- "v14" | "v15") \
- export TIMESCALEDB_VERSION=2.10.1 \
- export TIMESCALEDB_CHECKSUM=6fca72a6ed0f6d32d2b3523951ede73dc5f9b0077b38450a029a5f411fdb8c73 \
- ;; \
- *) \
- echo "TimescaleDB not supported on this PostgreSQL version. See https://github.com/timescale/timescaledb/issues/5752" && exit 0;; \
- esac && \
- apt-get update && \
+RUN apt-get update && \
apt-get install -y cmake && \
- wget https://github.com/timescale/timescaledb/archive/refs/tags/${TIMESCALEDB_VERSION}.tar.gz -O timescaledb.tar.gz && \
- echo "${TIMESCALEDB_CHECKSUM} timescaledb.tar.gz" | sha256sum --check && \
+ wget https://github.com/timescale/timescaledb/archive/refs/tags/2.13.0.tar.gz -O timescaledb.tar.gz && \
+ echo "584a351c7775f0e067eaa0e7277ea88cab9077cc4c455cbbf09a5d9723dce95d timescaledb.tar.gz" | sha256sum --check && \
mkdir timescaledb-src && cd timescaledb-src && tar xvzf ../timescaledb.tar.gz --strip-components=1 -C . && \
./bootstrap -DSEND_TELEMETRY_DEFAULT:BOOL=OFF -DUSE_TELEMETRY:BOOL=OFF -DAPACHE_ONLY:BOOL=ON -DCMAKE_BUILD_TYPE=Release && \
cd build && \
diff --git a/README.md b/README.md
index 75fad605c5..3e3123f5ee 100644
--- a/README.md
+++ b/README.md
@@ -149,6 +149,9 @@ tenant 9ef87a5bf0d92544f6fafeeb3239695c successfully created on the pageserver
Created an initial timeline 'de200bd42b49cc1814412c7e592dd6e9' at Lsn 0/16B5A50 for tenant: 9ef87a5bf0d92544f6fafeeb3239695c
Setting tenant 9ef87a5bf0d92544f6fafeeb3239695c as a default one
+# create postgres compute node
+> cargo neon endpoint create main
+
# start postgres compute node
> cargo neon endpoint start main
Starting new endpoint main (PostgreSQL v14) on timeline de200bd42b49cc1814412c7e592dd6e9 ...
@@ -185,8 +188,11 @@ Created timeline 'b3b863fa45fa9e57e615f9f2d944e601' at Lsn 0/16F9A00 for tenant:
(L) main [de200bd42b49cc1814412c7e592dd6e9]
(L) ┗━ @0/16F9A00: migration_check [b3b863fa45fa9e57e615f9f2d944e601]
+# create postgres on that branch
+> cargo neon endpoint create migration_check --branch-name migration_check
+
# start postgres on that branch
-> cargo neon endpoint start migration_check --branch-name migration_check
+> cargo neon endpoint start migration_check
Starting new endpoint migration_check (PostgreSQL v14) on timeline b3b863fa45fa9e57e615f9f2d944e601 ...
Starting postgres at 'postgresql://cloud_admin@127.0.0.1:55434/postgres'
diff --git a/control_plane/src/bin/attachment_service.rs b/control_plane/src/bin/attachment_service.rs
index 16577e27d6..be7cff352c 100644
--- a/control_plane/src/bin/attachment_service.rs
+++ b/control_plane/src/bin/attachment_service.rs
@@ -9,6 +9,7 @@ use clap::Parser;
use hex::FromHex;
use hyper::StatusCode;
use hyper::{Body, Request, Response};
+use pageserver_api::shard::TenantShardId;
use serde::{Deserialize, Serialize};
use std::path::{Path, PathBuf};
use std::{collections::HashMap, sync::Arc};
@@ -173,7 +174,8 @@ async fn handle_re_attach(mut req: Request
) -> Result, ApiE
if state.pageserver == Some(reattach_req.node_id) {
state.generation += 1;
response.tenants.push(ReAttachResponseTenant {
- id: *t,
+ // TODO(sharding): make this shard-aware
+ id: TenantShardId::unsharded(*t),
gen: state.generation,
});
}
@@ -196,7 +198,8 @@ async fn handle_validate(mut req: Request) -> Result, ApiEr
};
for req_tenant in validate_req.tenants {
- if let Some(tenant_state) = locked.tenants.get(&req_tenant.id) {
+ // TODO(sharding): make this shard-aware
+ if let Some(tenant_state) = locked.tenants.get(&req_tenant.id.tenant_id) {
let valid = tenant_state.generation == req_tenant.gen;
response.tenants.push(ValidateResponseTenant {
id: req_tenant.id,
diff --git a/control_plane/src/bin/neon_local.rs b/control_plane/src/bin/neon_local.rs
index 3053122f6a..8d53a6a658 100644
--- a/control_plane/src/bin/neon_local.rs
+++ b/control_plane/src/bin/neon_local.rs
@@ -415,6 +415,7 @@ fn handle_tenant(tenant_match: &ArgMatches, env: &mut local_env::LocalEnv) -> an
None,
None,
Some(pg_version),
+ None,
)?;
let new_timeline_id = timeline_info.timeline_id;
let last_record_lsn = timeline_info.last_record_lsn;
@@ -495,6 +496,7 @@ fn handle_timeline(timeline_match: &ArgMatches, env: &mut local_env::LocalEnv) -
None,
None,
Some(pg_version),
+ None,
)?;
let new_timeline_id = timeline_info.timeline_id;
@@ -582,6 +584,7 @@ fn handle_timeline(timeline_match: &ArgMatches, env: &mut local_env::LocalEnv) -
start_lsn,
Some(ancestor_timeline_id),
None,
+ None,
)?;
let new_timeline_id = timeline_info.timeline_id;
@@ -608,11 +611,9 @@ fn handle_endpoint(ep_match: &ArgMatches, env: &local_env::LocalEnv) -> Result<(
};
let mut cplane = ComputeControlPlane::load(env.clone())?;
- // All subcommands take an optional --tenant-id option
- let tenant_id = get_tenant_id(sub_args, env)?;
-
match sub_name {
"list" => {
+ let tenant_id = get_tenant_id(sub_args, env)?;
let timeline_infos = get_timeline_infos(env, &tenant_id).unwrap_or_else(|e| {
eprintln!("Failed to load timeline info: {}", e);
HashMap::new()
@@ -672,6 +673,7 @@ fn handle_endpoint(ep_match: &ArgMatches, env: &local_env::LocalEnv) -> Result<(
println!("{table}");
}
"create" => {
+ let tenant_id = get_tenant_id(sub_args, env)?;
let branch_name = sub_args
.get_one::("branch-name")
.map(|s| s.as_str())
@@ -716,6 +718,18 @@ fn handle_endpoint(ep_match: &ArgMatches, env: &local_env::LocalEnv) -> Result<(
(Some(_), true) => anyhow::bail!("cannot specify both lsn and hot-standby"),
};
+ match (mode, hot_standby) {
+ (ComputeMode::Static(_), true) => {
+ bail!("Cannot start a node in hot standby mode when it is already configured as a static replica")
+ }
+ (ComputeMode::Primary, true) => {
+ bail!("Cannot start a node as a hot standby replica, it is already configured as primary node")
+ }
+ _ => {}
+ }
+
+ cplane.check_conflicting_endpoints(mode, tenant_id, timeline_id)?;
+
cplane.new_endpoint(
&endpoint_id,
tenant_id,
@@ -728,8 +742,6 @@ fn handle_endpoint(ep_match: &ArgMatches, env: &local_env::LocalEnv) -> Result<(
)?;
}
"start" => {
- let pg_port: Option = sub_args.get_one::("pg-port").copied();
- let http_port: Option = sub_args.get_one::("http-port").copied();
let endpoint_id = sub_args
.get_one::("endpoint_id")
.ok_or_else(|| anyhow!("No endpoint ID was provided to start"))?;
@@ -758,80 +770,28 @@ fn handle_endpoint(ep_match: &ArgMatches, env: &local_env::LocalEnv) -> Result<(
env.safekeepers.iter().map(|sk| sk.id).collect()
};
- let endpoint = cplane.endpoints.get(endpoint_id.as_str());
+ let endpoint = cplane
+ .endpoints
+ .get(endpoint_id.as_str())
+ .ok_or_else(|| anyhow::anyhow!("endpoint {endpoint_id} not found"))?;
+
+ cplane.check_conflicting_endpoints(
+ endpoint.mode,
+ endpoint.tenant_id,
+ endpoint.timeline_id,
+ )?;
let ps_conf = env.get_pageserver_conf(pageserver_id)?;
let auth_token = if matches!(ps_conf.pg_auth_type, AuthType::NeonJWT) {
- let claims = Claims::new(Some(tenant_id), Scope::Tenant);
+ let claims = Claims::new(Some(endpoint.tenant_id), Scope::Tenant);
Some(env.generate_auth_token(&claims)?)
} else {
None
};
- let hot_standby = sub_args
- .get_one::("hot-standby")
- .copied()
- .unwrap_or(false);
-
- if let Some(endpoint) = endpoint {
- match (&endpoint.mode, hot_standby) {
- (ComputeMode::Static(_), true) => {
- bail!("Cannot start a node in hot standby mode when it is already configured as a static replica")
- }
- (ComputeMode::Primary, true) => {
- bail!("Cannot start a node as a hot standby replica, it is already configured as primary node")
- }
- _ => {}
- }
- println!("Starting existing endpoint {endpoint_id}...");
- endpoint.start(&auth_token, safekeepers, remote_ext_config)?;
- } else {
- let branch_name = sub_args
- .get_one::("branch-name")
- .map(|s| s.as_str())
- .unwrap_or(DEFAULT_BRANCH_NAME);
- let timeline_id = env
- .get_branch_timeline_id(branch_name, tenant_id)
- .ok_or_else(|| {
- anyhow!("Found no timeline id for branch name '{branch_name}'")
- })?;
- let lsn = sub_args
- .get_one::("lsn")
- .map(|lsn_str| Lsn::from_str(lsn_str))
- .transpose()
- .context("Failed to parse Lsn from the request")?;
- let pg_version = sub_args
- .get_one::("pg-version")
- .copied()
- .context("Failed to `pg-version` from the argument string")?;
-
- let mode = match (lsn, hot_standby) {
- (Some(lsn), false) => ComputeMode::Static(lsn),
- (None, true) => ComputeMode::Replica,
- (None, false) => ComputeMode::Primary,
- (Some(_), true) => anyhow::bail!("cannot specify both lsn and hot-standby"),
- };
-
- // when used with custom port this results in non obvious behaviour
- // port is remembered from first start command, i e
- // start --port X
- // stop
- // start <-- will also use port X even without explicit port argument
- println!("Starting new endpoint {endpoint_id} (PostgreSQL v{pg_version}) on timeline {timeline_id} ...");
-
- let ep = cplane.new_endpoint(
- endpoint_id,
- tenant_id,
- timeline_id,
- pg_port,
- http_port,
- pg_version,
- mode,
- pageserver_id,
- )?;
- ep.start(&auth_token, safekeepers, remote_ext_config)?;
- }
+ println!("Starting existing endpoint {endpoint_id}...");
+ endpoint.start(&auth_token, safekeepers, remote_ext_config)?;
}
"reconfigure" => {
let endpoint_id = sub_args
@@ -1437,15 +1397,7 @@ fn cli() -> Command {
.subcommand(Command::new("start")
.about("Start postgres.\n If the endpoint doesn't exist yet, it is created.")
.arg(endpoint_id_arg.clone())
- .arg(tenant_id_arg.clone())
- .arg(branch_name_arg.clone())
- .arg(timeline_id_arg.clone())
- .arg(lsn_arg)
- .arg(pg_port_arg)
- .arg(http_port_arg)
.arg(endpoint_pageserver_id_arg.clone())
- .arg(pg_version_arg)
- .arg(hot_standby_arg)
.arg(safekeepers_arg)
.arg(remote_ext_config_args)
)
@@ -1458,7 +1410,6 @@ fn cli() -> Command {
.subcommand(
Command::new("stop")
.arg(endpoint_id_arg)
- .arg(tenant_id_arg.clone())
.arg(
Arg::new("destroy")
.help("Also delete data directory (now optional, should be default in future)")
diff --git a/control_plane/src/endpoint.rs b/control_plane/src/endpoint.rs
index ae45746925..12b1250764 100644
--- a/control_plane/src/endpoint.rs
+++ b/control_plane/src/endpoint.rs
@@ -125,6 +125,7 @@ impl ComputeControlPlane {
let http_port = http_port.unwrap_or_else(|| self.get_port() + 1);
let pageserver =
PageServerNode::from_env(&self.env, self.env.get_pageserver_conf(pageserver_id)?);
+
let ep = Arc::new(Endpoint {
endpoint_id: endpoint_id.to_owned(),
pg_address: SocketAddr::new("127.0.0.1".parse().unwrap(), pg_port),
@@ -169,6 +170,30 @@ impl ComputeControlPlane {
Ok(ep)
}
+
+ pub fn check_conflicting_endpoints(
+ &self,
+ mode: ComputeMode,
+ tenant_id: TenantId,
+ timeline_id: TimelineId,
+ ) -> Result<()> {
+ if matches!(mode, ComputeMode::Primary) {
+ // this check is not complete, as you could have a concurrent attempt at
+ // creating another primary, both reading the state before checking it here,
+ // but it's better than nothing.
+ let mut duplicates = self.endpoints.iter().filter(|(_k, v)| {
+ v.tenant_id == tenant_id
+ && v.timeline_id == timeline_id
+ && v.mode == mode
+ && v.status() != "stopped"
+ });
+
+ if let Some((key, _)) = duplicates.next() {
+ bail!("attempting to create a duplicate primary endpoint on tenant {tenant_id}, timeline {timeline_id}: endpoint {key:?} exists already. please don't do this, it is not supported.");
+ }
+ }
+ Ok(())
+ }
}
///////////////////////////////////////////////////////////////////////////////
diff --git a/control_plane/src/pageserver.rs b/control_plane/src/pageserver.rs
index 237df48543..96a41874fd 100644
--- a/control_plane/src/pageserver.rs
+++ b/control_plane/src/pageserver.rs
@@ -11,6 +11,7 @@ use std::io::{BufReader, Write};
use std::num::NonZeroU64;
use std::path::PathBuf;
use std::process::{Child, Command};
+use std::time::Duration;
use std::{io, result};
use anyhow::{bail, Context};
@@ -522,19 +523,24 @@ impl PageServerNode {
&self,
tenant_id: TenantId,
config: LocationConfig,
+ flush_ms: Option,
) -> anyhow::Result<()> {
let req_body = TenantLocationConfigRequest { tenant_id, config };
- self.http_request(
- Method::PUT,
- format!(
- "{}/tenant/{}/location_config",
- self.http_base_url, tenant_id
- ),
- )?
- .json(&req_body)
- .send()?
- .error_from_body()?;
+ let path = format!(
+ "{}/tenant/{}/location_config",
+ self.http_base_url, tenant_id
+ );
+ let path = if let Some(flush_ms) = flush_ms {
+ format!("{}?flush_ms={}", path, flush_ms.as_millis())
+ } else {
+ path
+ };
+
+ self.http_request(Method::PUT, path)?
+ .json(&req_body)
+ .send()?
+ .error_from_body()?;
Ok(())
}
@@ -559,6 +565,7 @@ impl PageServerNode {
ancestor_start_lsn: Option,
ancestor_timeline_id: Option,
pg_version: Option,
+ existing_initdb_timeline_id: Option,
) -> anyhow::Result {
// If timeline ID was not specified, generate one
let new_timeline_id = new_timeline_id.unwrap_or(TimelineId::generate());
@@ -572,6 +579,7 @@ impl PageServerNode {
ancestor_start_lsn,
ancestor_timeline_id,
pg_version,
+ existing_initdb_timeline_id,
})
.send()?
.error_from_body()?
diff --git a/control_plane/src/tenant_migration.rs b/control_plane/src/tenant_migration.rs
index 42780db85c..c0c44e279f 100644
--- a/control_plane/src/tenant_migration.rs
+++ b/control_plane/src/tenant_migration.rs
@@ -117,7 +117,7 @@ pub fn migrate_tenant(
println!("🔁 Already attached to {origin_ps_id}, freshening...");
let gen = attachment_service.attach_hook(tenant_id, dest_ps.conf.id)?;
let dest_conf = build_location_config(LocationConfigMode::AttachedSingle, gen, None);
- dest_ps.location_config(tenant_id, dest_conf)?;
+ dest_ps.location_config(tenant_id, dest_conf, None)?;
println!("✅ Migration complete");
return Ok(());
}
@@ -126,7 +126,7 @@ pub fn migrate_tenant(
let stale_conf =
build_location_config(LocationConfigMode::AttachedStale, Some(*generation), None);
- origin_ps.location_config(tenant_id, stale_conf)?;
+ origin_ps.location_config(tenant_id, stale_conf, Some(Duration::from_secs(10)))?;
baseline_lsns = Some(get_lsns(tenant_id, &origin_ps)?);
}
@@ -135,7 +135,7 @@ pub fn migrate_tenant(
let dest_conf = build_location_config(LocationConfigMode::AttachedMulti, gen, None);
println!("🔁 Attaching to pageserver {}", dest_ps.conf.id);
- dest_ps.location_config(tenant_id, dest_conf)?;
+ dest_ps.location_config(tenant_id, dest_conf, None)?;
if let Some(baseline) = baseline_lsns {
println!("🕑 Waiting for LSN to catch up...");
@@ -181,7 +181,7 @@ pub fn migrate_tenant(
"💤 Switching to secondary mode on pageserver {}",
other_ps.conf.id
);
- other_ps.location_config(tenant_id, secondary_conf)?;
+ other_ps.location_config(tenant_id, secondary_conf, None)?;
}
println!(
@@ -189,7 +189,7 @@ pub fn migrate_tenant(
dest_ps.conf.id
);
let dest_conf = build_location_config(LocationConfigMode::AttachedSingle, gen, None);
- dest_ps.location_config(tenant_id, dest_conf)?;
+ dest_ps.location_config(tenant_id, dest_conf, None)?;
println!("✅ Migration complete");
diff --git a/docs/rfcs/029-pageserver-wal-disaster-recovery.md b/docs/rfcs/029-pageserver-wal-disaster-recovery.md
new file mode 100644
index 0000000000..15ebd72bfe
--- /dev/null
+++ b/docs/rfcs/029-pageserver-wal-disaster-recovery.md
@@ -0,0 +1,205 @@
+# Name
+
+Created on: 2023-09-08
+Author: Arpad Müller
+
+## Summary
+
+Enable the pageserver to recover from data corruption events by implementing
+a feature to re-apply historic WAL records in parallel to the already occurring
+WAL replay.
+
+The feature is outside of the user-visible backup and history story, and only
+serves as a second-level backup for the case that there is a bug in the
+pageservers that corrupted the served pages.
+
+The RFC proposes the addition of two new features:
+* recover a broken branch from WAL (downtime is allowed)
+* a test recovery system to recover random branches to make sure recovery works
+
+## Motivation
+
+The historic WAL is currently stored in S3 even after it has been replayed by
+the pageserver and thus been integrated into the pageserver's storage system.
+This is done to defend from data corruption failures inside the pageservers.
+
+However, application of this WAL in the disaster recovery setting is currently
+very manual and we want to automate this to make it easier.
+
+### Use cases
+
+There are various use cases for this feature, like:
+
+* The main motivation is replaying in the instance of pageservers corrupting
+ data.
+* We might want to, beyond the user-visible history features, through our
+ support channels and upon customer request, in select instances, recover
+ historic versions beyond the range of history that we officially support.
+* Running the recovery process in the background for random tenant timelines
+ to figure out if there was a corruption of data (we would compare with what
+ the pageserver stores for the "official" timeline).
+* Using the WAL to arrive at historic pages we can then back up to S3 so that
+ WAL itself can be discarded, or at least not used for future replays.
+ Again, this sounds a lot like what the pageserver is already doing, but the
+ point is to provide a fallback to the service provided by the pageserver.
+
+## Design
+
+### Design constraints
+
+The main design constraint is that the feature needs to be *simple* enough that
+the number of bugs are as low, and reliability as high as possible: the main
+goal of this endeavour is to achieve higher correctness than the pageserver.
+
+For the background process, we cannot afford a downtime of the timeline that is
+being cloned, as we don't want to restrict ourselves to offline tenants only.
+In the scenario where we want to recover from disasters or roll back to a
+historic lsn through support staff, downtimes are more affordable, and
+inevitable if the original had been subject to the corruption. Ideally, the
+two code paths would share code, so the solution would be designed for not
+requiring downtimes.
+
+### API endpoint changes
+
+This RFC proposes two API endpoint changes in the safekeeper and the
+pageserver.
+
+Remember, the pageserver timeline API creation endpoint is to this URL:
+
+```
+/v1/tenant/{tenant_id}/timeline/
+```
+
+Where `{tenant_id}` is the ID of the tenant the timeline is created for,
+and specified as part of the URL. The timeline ID is passed via the POST
+request body as the only required parameter `new_timeline_id`.
+
+This proposal adds one optional parameter called
+`existing_initdb_timeline_id` to the request's json body. If the parameter
+is not specified, behaviour should be as existing, so the pageserver runs
+initdb.
+If the parameter is specified, it is expected to point to a timeline ID.
+In fact that ID might match `new_timeline_id`, what's important is that
+S3 storage contains a matching initdb under the URL matching the given
+tenant and timeline.
+
+Having both `ancestor_timeline_id` and `existing_initdb_timeline_id`
+specified is illegal and will yield in an HTTP error. This feature is
+only meant for the "main" branch that doesn't have any ancestors
+of its own, as only here initdb is relevant.
+
+For the safekeeper, we propose the addition of the following copy endpoint:
+
+```
+/v1/tenant/{tenant_id}/timeline/{source_timeline_id}/copy
+```
+it is meant for POST requests with json, and the two URL parameters
+`tenant_id` and `source_timeline_id`. The json request body contains
+the two required parameters `target_timeline_id` and `until_lsn`.
+
+After invoking, the copy endpoint starts a copy process of the WAL from
+the source ID to the target ID. The lsn is updated according to the
+progress of the API call.
+
+### Higher level features
+
+We want the API changes to support the following higher level features:
+
+* recovery-after-corruption DR of the main timeline of a tenant. This
+ feature allows for downtime.
+* test DR of the main timeline into a special copy timeline. this feature
+ is meant to run against selected production tenants in the background,
+ without the user noticing, so it does not allow for downtime.
+
+The recovery-after-corruption DR only needs the pageserver changes.
+It works as follows:
+
+* delete the timeline from the pageservers via timeline deletion API
+* re-create it via timeline creation API (same ID as before) and set
+ `existing_initdb_timeline_id` to the same timeline ID
+
+The test DR requires also the copy primitive and works as follows:
+
+* copy the WAL of the timeline to a new place
+* create a new timeline for the tenant
+
+## Non Goals
+
+At the danger of being repetitive, the main goal of this feature is to be a
+backup method, so reliability is very important. This implies that other
+aspects like performance or space reduction are less important.
+
+### Corrupt WAL
+
+The process suggested by this RFC assumes that the WAL is free of corruption.
+In some instances, corruption can make it into WAL, like for example when
+higher level components like postgres or the application first read corrupt
+data, and then execute a write with data derived from that earlier read. That
+written data might then contain the corruption.
+
+Common use cases can hit this quite easily. For example, an application reads
+some counter, increments it, and then writes the new counter value to the
+database.
+On a lower level, the compute might put FPIs (Full Page Images) into the WAL,
+which have corrupt data for rows unrelated to the write operation at hand.
+
+Separating corrupt writes from non-corrupt ones is a hard problem in general,
+and if the application was involved in making the corrupt write, a recovery
+would also involve the application. Therefore, corruption that has made it into
+the WAL is outside of the scope of this feature. However, the WAL replay can be
+issued to right before the point in time where the corruption occured. Then the
+data loss is isolated to post-corruption writes only.
+
+## Impacted components (e.g. pageserver, safekeeper, console, etc)
+
+Most changes would happen to the pageservers.
+For the higher level features, maybe other components like the console would
+be involved.
+
+We need to make sure that the shadow timelines are not subject to the usual
+limits and billing we apply to existing timelines.
+
+## Proposed implementation
+
+The first problem to keep in mind is the reproducability of `initdb`.
+So an initial step would be to upload `initdb` snapshots to S3.
+
+After that, we'd have the endpoint spawn a background process which
+performs the replay of the WAL to that new timeline. This process should
+follow the existing workflows as closely as possible, just using the
+WAL records of a different timeline.
+
+The timeline created will be in a special state that solely looks for WAL
+entries of the timeline it is trying to copy. Once the target LSN is reached,
+it turns into a normal timeline that also accepts writes to its own
+timeline ID.
+
+### Scalability
+
+For now we want to run this entire process on a single node, and as
+it is by nature linear, it's hard to parallelize. However, for the
+verification workloads, we can easily start the WAL replay in parallel
+for different points in time. This is valuable especially for tenants
+with large WAL records.
+
+Compare this with the tricks to make addition circuits execute with
+lower latency by making them perform the addition for both possible
+values of the carry bit, and then, in a second step, taking the
+result for the carry bit that was actually obtained.
+
+The other scalability dimension to consider is the WAL length, which
+is a growing question as tenants accumulate changes. There are
+possible approaches to this, including creating snapshots of the
+page files and uploading them to S3, but if we do this for every single
+branch, we lose the cheap branching property.
+
+### Implementation by component
+
+The proposed changes for the various components of the neon architecture
+are written up in this notion page:
+
+https://www.notion.so/neondatabase/Pageserver-disaster-recovery-one-pager-4ecfb5df16ce4f6bbfc3817ed1a6cbb2
+
+### Unresolved questions
+
+none known (outside of the mentioned ones).
diff --git a/libs/pageserver_api/src/control_api.rs b/libs/pageserver_api/src/control_api.rs
index 8232e81b98..0acc3a7bb0 100644
--- a/libs/pageserver_api/src/control_api.rs
+++ b/libs/pageserver_api/src/control_api.rs
@@ -4,7 +4,9 @@
//! See docs/rfcs/025-generation-numbers.md
use serde::{Deserialize, Serialize};
-use utils::id::{NodeId, TenantId};
+use utils::id::NodeId;
+
+use crate::shard::TenantShardId;
#[derive(Serialize, Deserialize)]
pub struct ReAttachRequest {
@@ -13,7 +15,7 @@ pub struct ReAttachRequest {
#[derive(Serialize, Deserialize)]
pub struct ReAttachResponseTenant {
- pub id: TenantId,
+ pub id: TenantShardId,
pub gen: u32,
}
@@ -24,7 +26,7 @@ pub struct ReAttachResponse {
#[derive(Serialize, Deserialize)]
pub struct ValidateRequestTenant {
- pub id: TenantId,
+ pub id: TenantShardId,
pub gen: u32,
}
@@ -40,6 +42,6 @@ pub struct ValidateResponse {
#[derive(Serialize, Deserialize)]
pub struct ValidateResponseTenant {
- pub id: TenantId,
+ pub id: TenantShardId,
pub valid: bool,
}
diff --git a/libs/pageserver_api/src/models.rs b/libs/pageserver_api/src/models.rs
index c792a5eff7..2234a06501 100644
--- a/libs/pageserver_api/src/models.rs
+++ b/libs/pageserver_api/src/models.rs
@@ -179,6 +179,8 @@ pub struct TimelineCreateRequest {
#[serde(default)]
pub ancestor_timeline_id: Option,
#[serde(default)]
+ pub existing_initdb_timeline_id: Option,
+ #[serde(default)]
pub ancestor_start_lsn: Option,
pub pg_version: Option,
}
@@ -314,25 +316,7 @@ impl std::ops::Deref for TenantConfigRequest {
impl TenantConfigRequest {
pub fn new(tenant_id: TenantId) -> TenantConfigRequest {
- let config = TenantConfig {
- checkpoint_distance: None,
- checkpoint_timeout: None,
- compaction_target_size: None,
- compaction_period: None,
- compaction_threshold: None,
- gc_horizon: None,
- gc_period: None,
- image_creation_threshold: None,
- pitr_interval: None,
- walreceiver_connect_timeout: None,
- lagging_wal_timeout: None,
- max_lsn_wal_lag: None,
- trace_read_requests: None,
- eviction_policy: None,
- min_resident_size_override: None,
- evictions_low_residence_duration_metric_threshold: None,
- gc_feedback: None,
- };
+ let config = TenantConfig::default();
TenantConfigRequest { tenant_id, config }
}
}
@@ -400,7 +384,9 @@ pub struct TimelineInfo {
/// The LSN that we are advertizing to safekeepers
pub remote_consistent_lsn_visible: Lsn,
- pub current_logical_size: Option, // is None when timeline is Unloaded
+ pub current_logical_size: u64,
+ pub current_logical_size_is_accurate: bool,
+
/// Sum of the size of all layer files.
/// If a layer is present in both local FS and S3, it counts only once.
pub current_physical_size: Option, // is None when timeline is Unloaded
diff --git a/libs/pageserver_api/src/shard.rs b/libs/pageserver_api/src/shard.rs
index 688b911425..3510b4dbca 100644
--- a/libs/pageserver_api/src/shard.rs
+++ b/libs/pageserver_api/src/shard.rs
@@ -5,10 +5,10 @@ use serde::{Deserialize, Serialize};
use thiserror;
use utils::id::TenantId;
-#[derive(Ord, PartialOrd, Eq, PartialEq, Clone, Copy, Serialize, Deserialize, Debug)]
+#[derive(Ord, PartialOrd, Eq, PartialEq, Clone, Copy, Serialize, Deserialize, Debug, Hash)]
pub struct ShardNumber(pub u8);
-#[derive(Ord, PartialOrd, Eq, PartialEq, Clone, Copy, Serialize, Deserialize, Debug)]
+#[derive(Ord, PartialOrd, Eq, PartialEq, Clone, Copy, Serialize, Deserialize, Debug, Hash)]
pub struct ShardCount(pub u8);
impl ShardCount {
@@ -39,7 +39,7 @@ impl ShardNumber {
/// Note that the binary encoding is _not_ backward compatible, because
/// at the time sharding is introduced, there are no existing binary structures
/// containing TenantId that we need to handle.
-#[derive(Eq, PartialEq, PartialOrd, Ord, Clone, Copy)]
+#[derive(Eq, PartialEq, PartialOrd, Ord, Clone, Copy, Hash)]
pub struct TenantShardId {
pub tenant_id: TenantId,
pub shard_number: ShardNumber,
diff --git a/libs/remote_storage/Cargo.toml b/libs/remote_storage/Cargo.toml
index d7bcce28cb..e8bfc005d3 100644
--- a/libs/remote_storage/Cargo.toml
+++ b/libs/remote_storage/Cargo.toml
@@ -9,8 +9,7 @@ anyhow.workspace = true
async-trait.workspace = true
once_cell.workspace = true
aws-smithy-async.workspace = true
-aws-smithy-http.workspace = true
-aws-types.workspace = true
+aws-smithy-types.workspace = true
aws-config.workspace = true
aws-sdk-s3.workspace = true
aws-credential-types.workspace = true
diff --git a/libs/remote_storage/src/s3_bucket.rs b/libs/remote_storage/src/s3_bucket.rs
index ab3fd3fe62..0cb73f73b7 100644
--- a/libs/remote_storage/src/s3_bucket.rs
+++ b/libs/remote_storage/src/s3_bucket.rs
@@ -14,18 +14,20 @@ use aws_config::{
provider_config::ProviderConfig,
retry::{RetryConfigBuilder, RetryMode},
web_identity_token::WebIdentityTokenCredentialsProvider,
+ BehaviorVersion,
};
-use aws_credential_types::cache::CredentialsCache;
+use aws_credential_types::provider::SharedCredentialsProvider;
use aws_sdk_s3::{
- config::{AsyncSleep, Config, Region, SharedAsyncSleep},
+ config::{AsyncSleep, Builder, IdentityCache, Region, SharedAsyncSleep},
error::SdkError,
operation::get_object::GetObjectError,
- primitives::ByteStream,
types::{Delete, ObjectIdentifier},
Client,
};
use aws_smithy_async::rt::sleep::TokioSleep;
-use aws_smithy_http::body::SdkBody;
+
+use aws_smithy_types::body::SdkBody;
+use aws_smithy_types::byte_stream::ByteStream;
use hyper::Body;
use scopeguard::ScopeGuard;
use tokio::io::{self, AsyncRead};
@@ -78,7 +80,6 @@ impl S3Bucket {
// needed to access remote extensions bucket
.or_else("token", {
let provider_conf = ProviderConfig::without_region().with_region(region.clone());
-
WebIdentityTokenCredentialsProvider::builder()
.configure(&provider_conf)
.build()
@@ -98,18 +99,20 @@ impl S3Bucket {
.set_max_attempts(Some(1))
.set_mode(Some(RetryMode::Adaptive));
- let mut config_builder = Config::builder()
+ let mut config_builder = Builder::default()
+ .behavior_version(BehaviorVersion::v2023_11_09())
.region(region)
- .credentials_cache(CredentialsCache::lazy())
- .credentials_provider(credentials_provider)
- .sleep_impl(SharedAsyncSleep::from(sleep_impl))
- .retry_config(retry_config.build());
+ .identity_cache(IdentityCache::lazy().build())
+ .credentials_provider(SharedCredentialsProvider::new(credentials_provider))
+ .retry_config(retry_config.build())
+ .sleep_impl(SharedAsyncSleep::from(sleep_impl));
if let Some(custom_endpoint) = aws_config.endpoint.clone() {
config_builder = config_builder
.endpoint_url(custom_endpoint)
.force_path_style(true);
}
+
let client = Client::from_conf(config_builder.build());
let prefix_in_bucket = aws_config.prefix_in_bucket.as_deref().map(|prefix| {
@@ -371,7 +374,7 @@ impl RemoteStorage for S3Bucket {
let response = response?;
- let keys = response.contents().unwrap_or_default();
+ let keys = response.contents();
let empty = Vec::new();
let prefixes = response.common_prefixes.as_ref().unwrap_or(&empty);
@@ -411,7 +414,7 @@ impl RemoteStorage for S3Bucket {
let started_at = start_measuring_requests(kind);
let body = Body::wrap_stream(ReaderStream::new(from));
- let bytes_stream = ByteStream::new(SdkBody::from(body));
+ let bytes_stream = ByteStream::new(SdkBody::from_body_0_4(body));
let res = self
.client
@@ -474,7 +477,7 @@ impl RemoteStorage for S3Bucket {
for path in paths {
let obj_id = ObjectIdentifier::builder()
.set_key(Some(self.relative_path_to_s3_object(path)))
- .build();
+ .build()?;
delete_objects.push(obj_id);
}
@@ -485,7 +488,11 @@ impl RemoteStorage for S3Bucket {
.client
.delete_objects()
.bucket(self.bucket_name.clone())
- .delete(Delete::builder().set_objects(Some(chunk.to_vec())).build())
+ .delete(
+ Delete::builder()
+ .set_objects(Some(chunk.to_vec()))
+ .build()?,
+ )
.send()
.await;
diff --git a/pageserver/Cargo.toml b/pageserver/Cargo.toml
index ab6783f918..571626b2b6 100644
--- a/pageserver/Cargo.toml
+++ b/pageserver/Cargo.toml
@@ -52,6 +52,7 @@ regex.workspace = true
scopeguard.workspace = true
serde.workspace = true
serde_json = { workspace = true, features = ["raw_value"] }
+serde_path_to_error.workspace = true
serde_with.workspace = true
signal-hook.workspace = true
smallvec = { workspace = true, features = ["write"] }
diff --git a/pageserver/benches/bench_layer_map.rs b/pageserver/benches/bench_layer_map.rs
index 735f358d8b..5d05af0c00 100644
--- a/pageserver/benches/bench_layer_map.rs
+++ b/pageserver/benches/bench_layer_map.rs
@@ -3,6 +3,7 @@ use pageserver::repository::Key;
use pageserver::tenant::layer_map::LayerMap;
use pageserver::tenant::storage_layer::LayerFileName;
use pageserver::tenant::storage_layer::PersistentLayerDesc;
+use pageserver_api::shard::TenantShardId;
use rand::prelude::{SeedableRng, SliceRandom, StdRng};
use std::cmp::{max, min};
use std::fs::File;
@@ -211,7 +212,7 @@ fn bench_sequential(c: &mut Criterion) {
let i32 = (i as u32) % 100;
let zero = Key::from_hex("000000000000000000000000000000000000").unwrap();
let layer = PersistentLayerDesc::new_img(
- TenantId::generate(),
+ TenantShardId::unsharded(TenantId::generate()),
TimelineId::generate(),
zero.add(10 * i32)..zero.add(10 * i32 + 1),
Lsn(i),
diff --git a/pageserver/ctl/src/layers.rs b/pageserver/ctl/src/layers.rs
index 22ebe70b16..ebf4a4bec3 100644
--- a/pageserver/ctl/src/layers.rs
+++ b/pageserver/ctl/src/layers.rs
@@ -1,13 +1,15 @@
use std::path::{Path, PathBuf};
use anyhow::Result;
-use camino::Utf8Path;
+use camino::{Utf8Path, Utf8PathBuf};
use clap::Subcommand;
use pageserver::context::{DownloadBehavior, RequestContext};
use pageserver::task_mgr::TaskKind;
use pageserver::tenant::block_io::BlockCursor;
use pageserver::tenant::disk_btree::DiskBtreeReader;
use pageserver::tenant::storage_layer::delta_layer::{BlobRef, Summary};
+use pageserver::tenant::storage_layer::{delta_layer, image_layer};
+use pageserver::tenant::storage_layer::{DeltaLayer, ImageLayer};
use pageserver::tenant::{TENANTS_SEGMENT_NAME, TIMELINES_SEGMENT_NAME};
use pageserver::{page_cache, virtual_file};
use pageserver::{
@@ -20,6 +22,7 @@ use pageserver::{
};
use std::fs;
use utils::bin_ser::BeSer;
+use utils::id::{TenantId, TimelineId};
use crate::layer_map_analyzer::parse_filename;
@@ -45,6 +48,13 @@ pub(crate) enum LayerCmd {
/// The id from list-layer command
id: usize,
},
+ RewriteSummary {
+ layer_file_path: Utf8PathBuf,
+ #[clap(long)]
+ new_tenant_id: Option,
+ #[clap(long)]
+ new_timeline_id: Option,
+ },
}
async fn read_delta_file(path: impl AsRef, ctx: &RequestContext) -> Result<()> {
@@ -100,6 +110,7 @@ pub(crate) async fn main(cmd: &LayerCmd) -> Result<()> {
println!("- timeline {}", timeline.file_name().to_string_lossy());
}
}
+ Ok(())
}
LayerCmd::ListLayer {
path,
@@ -128,6 +139,7 @@ pub(crate) async fn main(cmd: &LayerCmd) -> Result<()> {
idx += 1;
}
}
+ Ok(())
}
LayerCmd::DumpLayer {
path,
@@ -168,7 +180,63 @@ pub(crate) async fn main(cmd: &LayerCmd) -> Result<()> {
idx += 1;
}
}
+ Ok(())
+ }
+ LayerCmd::RewriteSummary {
+ layer_file_path,
+ new_tenant_id,
+ new_timeline_id,
+ } => {
+ pageserver::virtual_file::init(10);
+ pageserver::page_cache::init(100);
+
+ let ctx = RequestContext::new(TaskKind::DebugTool, DownloadBehavior::Error);
+
+ macro_rules! rewrite_closure {
+ ($($summary_ty:tt)*) => {{
+ |summary| $($summary_ty)* {
+ tenant_id: new_tenant_id.unwrap_or(summary.tenant_id),
+ timeline_id: new_timeline_id.unwrap_or(summary.timeline_id),
+ ..summary
+ }
+ }};
+ }
+
+ let res = ImageLayer::rewrite_summary(
+ layer_file_path,
+ rewrite_closure!(image_layer::Summary),
+ &ctx,
+ )
+ .await;
+ match res {
+ Ok(()) => {
+ println!("Successfully rewrote summary of image layer {layer_file_path}");
+ return Ok(());
+ }
+ Err(image_layer::RewriteSummaryError::MagicMismatch) => (), // fallthrough
+ Err(image_layer::RewriteSummaryError::Other(e)) => {
+ return Err(e);
+ }
+ }
+
+ let res = DeltaLayer::rewrite_summary(
+ layer_file_path,
+ rewrite_closure!(delta_layer::Summary),
+ &ctx,
+ )
+ .await;
+ match res {
+ Ok(()) => {
+ println!("Successfully rewrote summary of delta layer {layer_file_path}");
+ return Ok(());
+ }
+ Err(delta_layer::RewriteSummaryError::MagicMismatch) => (), // fallthrough
+ Err(delta_layer::RewriteSummaryError::Other(e)) => {
+ return Err(e);
+ }
+ }
+
+ anyhow::bail!("not an image or delta layer: {layer_file_path}");
}
}
- Ok(())
}
diff --git a/pageserver/src/config.rs b/pageserver/src/config.rs
index 87d9cc522e..13d1fc775b 100644
--- a/pageserver/src/config.rs
+++ b/pageserver/src/config.rs
@@ -5,6 +5,7 @@
//! See also `settings.md` for better description on every parameter.
use anyhow::{anyhow, bail, ensure, Context, Result};
+use pageserver_api::shard::TenantShardId;
use remote_storage::{RemotePath, RemoteStorageConfig};
use serde::de::IntoDeserializer;
use std::env;
@@ -25,7 +26,7 @@ use toml_edit::{Document, Item};
use camino::{Utf8Path, Utf8PathBuf};
use postgres_backend::AuthType;
use utils::{
- id::{NodeId, TenantId, TimelineId},
+ id::{NodeId, TimelineId},
logging::LogFormat,
};
@@ -628,12 +629,13 @@ impl PageServerConf {
self.deletion_prefix().join(format!("header-{VERSION:02x}"))
}
- pub fn tenant_path(&self, tenant_id: &TenantId) -> Utf8PathBuf {
- self.tenants_path().join(tenant_id.to_string())
+ pub fn tenant_path(&self, tenant_shard_id: &TenantShardId) -> Utf8PathBuf {
+ self.tenants_path().join(tenant_shard_id.to_string())
}
- pub fn tenant_ignore_mark_file_path(&self, tenant_id: &TenantId) -> Utf8PathBuf {
- self.tenant_path(tenant_id).join(IGNORED_TENANT_FILE_NAME)
+ pub fn tenant_ignore_mark_file_path(&self, tenant_shard_id: &TenantShardId) -> Utf8PathBuf {
+ self.tenant_path(tenant_shard_id)
+ .join(IGNORED_TENANT_FILE_NAME)
}
/// Points to a place in pageserver's local directory,
@@ -641,47 +643,53 @@ impl PageServerConf {
///
/// Legacy: superseded by tenant_location_config_path. Eventually
/// remove this function.
- pub fn tenant_config_path(&self, tenant_id: &TenantId) -> Utf8PathBuf {
- self.tenant_path(tenant_id).join(TENANT_CONFIG_NAME)
+ pub fn tenant_config_path(&self, tenant_shard_id: &TenantShardId) -> Utf8PathBuf {
+ self.tenant_path(tenant_shard_id).join(TENANT_CONFIG_NAME)
}
- pub fn tenant_location_config_path(&self, tenant_id: &TenantId) -> Utf8PathBuf {
- self.tenant_path(tenant_id)
+ pub fn tenant_location_config_path(&self, tenant_shard_id: &TenantShardId) -> Utf8PathBuf {
+ self.tenant_path(tenant_shard_id)
.join(TENANT_LOCATION_CONFIG_NAME)
}
- pub fn timelines_path(&self, tenant_id: &TenantId) -> Utf8PathBuf {
- self.tenant_path(tenant_id).join(TIMELINES_SEGMENT_NAME)
+ pub fn timelines_path(&self, tenant_shard_id: &TenantShardId) -> Utf8PathBuf {
+ self.tenant_path(tenant_shard_id)
+ .join(TIMELINES_SEGMENT_NAME)
}
- pub fn timeline_path(&self, tenant_id: &TenantId, timeline_id: &TimelineId) -> Utf8PathBuf {
- self.timelines_path(tenant_id).join(timeline_id.to_string())
+ pub fn timeline_path(
+ &self,
+ tenant_shard_id: &TenantShardId,
+ timeline_id: &TimelineId,
+ ) -> Utf8PathBuf {
+ self.timelines_path(tenant_shard_id)
+ .join(timeline_id.to_string())
}
pub fn timeline_uninit_mark_file_path(
&self,
- tenant_id: TenantId,
+ tenant_shard_id: TenantShardId,
timeline_id: TimelineId,
) -> Utf8PathBuf {
path_with_suffix_extension(
- self.timeline_path(&tenant_id, &timeline_id),
+ self.timeline_path(&tenant_shard_id, &timeline_id),
TIMELINE_UNINIT_MARK_SUFFIX,
)
}
pub fn timeline_delete_mark_file_path(
&self,
- tenant_id: TenantId,
+ tenant_shard_id: TenantShardId,
timeline_id: TimelineId,
) -> Utf8PathBuf {
path_with_suffix_extension(
- self.timeline_path(&tenant_id, &timeline_id),
+ self.timeline_path(&tenant_shard_id, &timeline_id),
TIMELINE_DELETE_MARK_SUFFIX,
)
}
- pub fn tenant_deleted_mark_file_path(&self, tenant_id: &TenantId) -> Utf8PathBuf {
- self.tenant_path(tenant_id)
+ pub fn tenant_deleted_mark_file_path(&self, tenant_shard_id: &TenantShardId) -> Utf8PathBuf {
+ self.tenant_path(tenant_shard_id)
.join(TENANT_DELETED_MARKER_FILE_NAME)
}
@@ -691,20 +699,24 @@ impl PageServerConf {
pub fn trace_path(
&self,
- tenant_id: &TenantId,
+ tenant_shard_id: &TenantShardId,
timeline_id: &TimelineId,
connection_id: &ConnectionId,
) -> Utf8PathBuf {
self.traces_path()
- .join(tenant_id.to_string())
+ .join(tenant_shard_id.to_string())
.join(timeline_id.to_string())
.join(connection_id.to_string())
}
/// Points to a place in pageserver's local directory,
/// where certain timeline's metadata file should be located.
- pub fn metadata_path(&self, tenant_id: &TenantId, timeline_id: &TimelineId) -> Utf8PathBuf {
- self.timeline_path(tenant_id, timeline_id)
+ pub fn metadata_path(
+ &self,
+ tenant_shard_id: &TenantShardId,
+ timeline_id: &TimelineId,
+ ) -> Utf8PathBuf {
+ self.timeline_path(tenant_shard_id, timeline_id)
.join(METADATA_FILE_NAME)
}
@@ -767,7 +779,7 @@ impl PageServerConf {
builder.remote_storage_config(RemoteStorageConfig::from_toml(item)?)
}
"tenant_config" => {
- t_conf = Self::parse_toml_tenant_conf(item)?;
+ t_conf = TenantConfOpt::try_from(item.to_owned()).context(format!("failed to parse: '{key}'"))?;
}
"id" => builder.id(NodeId(parse_toml_u64(key, item)?)),
"broker_endpoint" => builder.broker_endpoint(parse_toml_string(key, item)?.parse().context("failed to parse broker endpoint")?),
@@ -841,114 +853,10 @@ impl PageServerConf {
Ok(conf)
}
- // subroutine of parse_and_validate to parse `[tenant_conf]` section
-
- pub fn parse_toml_tenant_conf(item: &toml_edit::Item) -> Result {
- let mut t_conf: TenantConfOpt = Default::default();
- if let Some(checkpoint_distance) = item.get("checkpoint_distance") {
- t_conf.checkpoint_distance =
- Some(parse_toml_u64("checkpoint_distance", checkpoint_distance)?);
- }
-
- if let Some(checkpoint_timeout) = item.get("checkpoint_timeout") {
- t_conf.checkpoint_timeout = Some(parse_toml_duration(
- "checkpoint_timeout",
- checkpoint_timeout,
- )?);
- }
-
- if let Some(compaction_target_size) = item.get("compaction_target_size") {
- t_conf.compaction_target_size = Some(parse_toml_u64(
- "compaction_target_size",
- compaction_target_size,
- )?);
- }
-
- if let Some(compaction_period) = item.get("compaction_period") {
- t_conf.compaction_period =
- Some(parse_toml_duration("compaction_period", compaction_period)?);
- }
-
- if let Some(compaction_threshold) = item.get("compaction_threshold") {
- t_conf.compaction_threshold =
- Some(parse_toml_u64("compaction_threshold", compaction_threshold)?.try_into()?);
- }
-
- if let Some(image_creation_threshold) = item.get("image_creation_threshold") {
- t_conf.image_creation_threshold = Some(
- parse_toml_u64("image_creation_threshold", image_creation_threshold)?.try_into()?,
- );
- }
-
- if let Some(gc_horizon) = item.get("gc_horizon") {
- t_conf.gc_horizon = Some(parse_toml_u64("gc_horizon", gc_horizon)?);
- }
-
- if let Some(gc_period) = item.get("gc_period") {
- t_conf.gc_period = Some(parse_toml_duration("gc_period", gc_period)?);
- }
-
- if let Some(pitr_interval) = item.get("pitr_interval") {
- t_conf.pitr_interval = Some(parse_toml_duration("pitr_interval", pitr_interval)?);
- }
- if let Some(walreceiver_connect_timeout) = item.get("walreceiver_connect_timeout") {
- t_conf.walreceiver_connect_timeout = Some(parse_toml_duration(
- "walreceiver_connect_timeout",
- walreceiver_connect_timeout,
- )?);
- }
- if let Some(lagging_wal_timeout) = item.get("lagging_wal_timeout") {
- t_conf.lagging_wal_timeout = Some(parse_toml_duration(
- "lagging_wal_timeout",
- lagging_wal_timeout,
- )?);
- }
- if let Some(max_lsn_wal_lag) = item.get("max_lsn_wal_lag") {
- t_conf.max_lsn_wal_lag =
- Some(deserialize_from_item("max_lsn_wal_lag", max_lsn_wal_lag)?);
- }
- if let Some(trace_read_requests) = item.get("trace_read_requests") {
- t_conf.trace_read_requests =
- Some(trace_read_requests.as_bool().with_context(|| {
- "configure option trace_read_requests is not a bool".to_string()
- })?);
- }
-
- if let Some(eviction_policy) = item.get("eviction_policy") {
- t_conf.eviction_policy = Some(
- deserialize_from_item("eviction_policy", eviction_policy)
- .context("parse eviction_policy")?,
- );
- }
-
- if let Some(item) = item.get("min_resident_size_override") {
- t_conf.min_resident_size_override = Some(
- deserialize_from_item("min_resident_size_override", item)
- .context("parse min_resident_size_override")?,
- );
- }
-
- if let Some(item) = item.get("evictions_low_residence_duration_metric_threshold") {
- t_conf.evictions_low_residence_duration_metric_threshold = Some(parse_toml_duration(
- "evictions_low_residence_duration_metric_threshold",
- item,
- )?);
- }
-
- if let Some(gc_feedback) = item.get("gc_feedback") {
- t_conf.gc_feedback = Some(
- gc_feedback
- .as_bool()
- .with_context(|| "configure option gc_feedback is not a bool".to_string())?,
- );
- }
-
- Ok(t_conf)
- }
-
#[cfg(test)]
pub fn test_repo_dir(test_name: &str) -> Utf8PathBuf {
- Utf8PathBuf::from(format!("../tmp_check/test_{test_name}"))
+ let test_output_dir = std::env::var("TEST_OUTPUT").unwrap_or("../tmp_check".into());
+ Utf8PathBuf::from(format!("{test_output_dir}/test_{test_name}"))
}
pub fn dummy_conf(repo_dir: Utf8PathBuf) -> Self {
@@ -1417,6 +1325,37 @@ trace_read_requests = {trace_read_requests}"#,
Ok(())
}
+ #[test]
+ fn parse_incorrect_tenant_config() -> anyhow::Result<()> {
+ let config_string = r#"
+ [tenant_config]
+ checkpoint_distance = -1 # supposed to be an u64
+ "#
+ .to_string();
+
+ let toml: Document = config_string.parse()?;
+ let item = toml.get("tenant_config").unwrap();
+ let error = TenantConfOpt::try_from(item.to_owned()).unwrap_err();
+
+ let expected_error_str = "checkpoint_distance: invalid value: integer `-1`, expected u64";
+ assert_eq!(error.to_string(), expected_error_str);
+
+ Ok(())
+ }
+
+ #[test]
+ fn parse_override_tenant_config() -> anyhow::Result<()> {
+ let config_string = r#"tenant_config={ min_resident_size_override = 400 }"#.to_string();
+
+ let toml: Document = config_string.parse()?;
+ let item = toml.get("tenant_config").unwrap();
+ let conf = TenantConfOpt::try_from(item.to_owned()).unwrap();
+
+ assert_eq!(conf.min_resident_size_override, Some(400));
+
+ Ok(())
+ }
+
#[test]
fn eviction_pageserver_config_parse() -> anyhow::Result<()> {
let tempdir = tempdir()?;
diff --git a/pageserver/src/consumption_metrics/metrics.rs b/pageserver/src/consumption_metrics/metrics.rs
index 2989e15e8e..c6ff91e560 100644
--- a/pageserver/src/consumption_metrics/metrics.rs
+++ b/pageserver/src/consumption_metrics/metrics.rs
@@ -1,5 +1,4 @@
-use crate::context::RequestContext;
-use anyhow::Context;
+use crate::{context::RequestContext, tenant::timeline::logical_size::CurrentLogicalSize};
use chrono::{DateTime, Utc};
use consumption_metrics::EventType;
use futures::stream::StreamExt;
@@ -351,14 +350,12 @@ impl TimelineSnapshot {
let last_record_lsn = t.get_last_record_lsn();
let current_exact_logical_size = {
- let span = tracing::info_span!("collect_metrics_iteration", tenant_id = %t.tenant_id, timeline_id = %t.timeline_id);
- let res = span
- .in_scope(|| t.get_current_logical_size(ctx))
- .context("get_current_logical_size");
- match res? {
+ let span = tracing::info_span!("collect_metrics_iteration", tenant_id = %t.tenant_shard_id.tenant_id, timeline_id = %t.timeline_id);
+ let size = span.in_scope(|| t.get_current_logical_size(ctx));
+ match size {
// Only send timeline logical size when it is fully calculated.
- (size, is_exact) if is_exact => Some(size),
- (_, _) => None,
+ CurrentLogicalSize::Exact(ref size) => Some(size.into()),
+ CurrentLogicalSize::Approximate(_) => None,
}
};
diff --git a/pageserver/src/control_plane_client.rs b/pageserver/src/control_plane_client.rs
index f50c19a629..25ae3d1b01 100644
--- a/pageserver/src/control_plane_client.rs
+++ b/pageserver/src/control_plane_client.rs
@@ -1,16 +1,15 @@
use std::collections::HashMap;
-use pageserver_api::control_api::{
- ReAttachRequest, ReAttachResponse, ValidateRequest, ValidateRequestTenant, ValidateResponse,
+use pageserver_api::{
+ control_api::{
+ ReAttachRequest, ReAttachResponse, ValidateRequest, ValidateRequestTenant, ValidateResponse,
+ },
+ shard::TenantShardId,
};
use serde::{de::DeserializeOwned, Serialize};
use tokio_util::sync::CancellationToken;
use url::Url;
-use utils::{
- backoff,
- generation::Generation,
- id::{NodeId, TenantId},
-};
+use utils::{backoff, generation::Generation, id::NodeId};
use crate::config::PageServerConf;
@@ -31,11 +30,11 @@ pub enum RetryForeverError {
#[async_trait::async_trait]
pub trait ControlPlaneGenerationsApi {
- async fn re_attach(&self) -> Result, RetryForeverError>;
+ async fn re_attach(&self) -> Result, RetryForeverError>;
async fn validate(
&self,
- tenants: Vec<(TenantId, Generation)>,
- ) -> Result, RetryForeverError>;
+ tenants: Vec<(TenantShardId, Generation)>,
+ ) -> Result, RetryForeverError>;
}
impl ControlPlaneClient {
@@ -127,7 +126,7 @@ impl ControlPlaneClient {
#[async_trait::async_trait]
impl ControlPlaneGenerationsApi for ControlPlaneClient {
/// Block until we get a successful response, or error out if we are shut down
- async fn re_attach(&self) -> Result, RetryForeverError> {
+ async fn re_attach(&self) -> Result, RetryForeverError> {
let re_attach_path = self
.base_url
.join("re-attach")
@@ -154,8 +153,8 @@ impl ControlPlaneGenerationsApi for ControlPlaneClient {
/// Block until we get a successful response, or error out if we are shut down
async fn validate(
&self,
- tenants: Vec<(TenantId, Generation)>,
- ) -> Result, RetryForeverError> {
+ tenants: Vec<(TenantShardId, Generation)>,
+ ) -> Result, RetryForeverError> {
let re_attach_path = self
.base_url
.join("validate")
diff --git a/pageserver/src/deletion_queue.rs b/pageserver/src/deletion_queue.rs
index ad95254a65..7b05745483 100644
--- a/pageserver/src/deletion_queue.rs
+++ b/pageserver/src/deletion_queue.rs
@@ -15,7 +15,7 @@ use crate::virtual_file::MaybeFatalIo;
use crate::virtual_file::VirtualFile;
use anyhow::Context;
use camino::Utf8PathBuf;
-use hex::FromHex;
+use pageserver_api::shard::TenantShardId;
use remote_storage::{GenericRemoteStorage, RemotePath};
use serde::Deserialize;
use serde::Serialize;
@@ -26,7 +26,7 @@ use tracing::Instrument;
use tracing::{self, debug, error};
use utils::crashsafe::path_with_suffix_extension;
use utils::generation::Generation;
-use utils::id::{TenantId, TimelineId};
+use utils::id::TimelineId;
use utils::lsn::AtomicLsn;
use utils::lsn::Lsn;
@@ -160,11 +160,10 @@ pub struct DeletionQueueClient {
lsn_table: Arc>,
}
-#[derive(Debug, Serialize, Deserialize)]
+#[derive(Debug, Serialize, Deserialize, PartialEq, Eq)]
struct TenantDeletionList {
/// For each Timeline, a list of key fragments to append to the timeline remote path
/// when reconstructing a full key
- #[serde(serialize_with = "to_hex_map", deserialize_with = "from_hex_map")]
timelines: HashMap>,
/// The generation in which this deletion was emitted: note that this may not be the
@@ -179,43 +178,11 @@ impl TenantDeletionList {
}
}
-/// For HashMaps using a `hex` compatible key, where we would like to encode the key as a string
-fn to_hex_map(input: &HashMap, serializer: S) -> Result
-where
- S: serde::Serializer,
- V: Serialize,
- I: AsRef<[u8]>,
-{
- let transformed = input.iter().map(|(k, v)| (hex::encode(k), v));
-
- transformed
- .collect::>()
- .serialize(serializer)
-}
-
-/// For HashMaps using a FromHex key, where we would like to decode the key
-fn from_hex_map<'de, D, V, I>(deserializer: D) -> Result, D::Error>
-where
- D: serde::de::Deserializer<'de>,
- V: Deserialize<'de>,
- I: FromHex + std::hash::Hash + Eq,
-{
- let hex_map = HashMap::::deserialize(deserializer)?;
- hex_map
- .into_iter()
- .map(|(k, v)| {
- I::from_hex(k)
- .map(|k| (k, v))
- .map_err(|_| serde::de::Error::custom("Invalid hex ID"))
- })
- .collect()
-}
-
/// Files ending with this suffix will be ignored and erased
/// during recovery as startup.
const TEMP_SUFFIX: &str = "tmp";
-#[derive(Debug, Serialize, Deserialize)]
+#[derive(Debug, Serialize, Deserialize, PartialEq, Eq)]
struct DeletionList {
/// Serialization version, for future use
version: u8,
@@ -227,8 +194,7 @@ struct DeletionList {
/// nested HashMaps by TenantTimelineID. Each Tenant only appears once
/// with one unique generation ID: if someone tries to push a second generation
/// ID for the same tenant, we will start a new DeletionList.
- #[serde(serialize_with = "to_hex_map", deserialize_with = "from_hex_map")]
- tenants: HashMap,
+ tenants: HashMap,
/// Avoid having to walk `tenants` to calculate the number of keys in
/// the nested deletion lists
@@ -300,7 +266,7 @@ impl DeletionList {
/// deletion list.
fn push(
&mut self,
- tenant: &TenantId,
+ tenant: &TenantShardId,
timeline: &TimelineId,
generation: Generation,
objects: &mut Vec,
@@ -392,7 +358,7 @@ struct TenantLsnState {
#[derive(Default)]
struct VisibleLsnUpdates {
- tenants: HashMap,
+ tenants: HashMap,
}
impl VisibleLsnUpdates {
@@ -449,7 +415,7 @@ impl DeletionQueueClient {
pub(crate) fn recover(
&self,
- attached_tenants: HashMap,
+ attached_tenants: HashMap,
) -> Result<(), DeletionQueueError> {
self.do_push(
&self.tx,
@@ -466,7 +432,7 @@ impl DeletionQueueClient {
/// backend will later wake up and notice that the tenant's generation requires validation.
pub(crate) async fn update_remote_consistent_lsn(
&self,
- tenant_id: TenantId,
+ tenant_shard_id: TenantShardId,
timeline_id: TimelineId,
current_generation: Generation,
lsn: Lsn,
@@ -477,10 +443,13 @@ impl DeletionQueueClient {
.write()
.expect("Lock should never be poisoned");
- let tenant_entry = locked.tenants.entry(tenant_id).or_insert(TenantLsnState {
- timelines: HashMap::new(),
- generation: current_generation,
- });
+ let tenant_entry = locked
+ .tenants
+ .entry(tenant_shard_id)
+ .or_insert(TenantLsnState {
+ timelines: HashMap::new(),
+ generation: current_generation,
+ });
if tenant_entry.generation != current_generation {
// Generation might have changed if we were detached and then re-attached: in this case,
@@ -507,7 +476,7 @@ impl DeletionQueueClient {
/// generations in `layers` are the generations in which those layers were written.
pub(crate) async fn push_layers(
&self,
- tenant_id: TenantId,
+ tenant_shard_id: TenantShardId,
timeline_id: TimelineId,
current_generation: Generation,
layers: Vec<(LayerFileName, LayerFileMetadata)>,
@@ -518,7 +487,7 @@ impl DeletionQueueClient {
let mut layer_paths = Vec::new();
for (layer, meta) in layers {
layer_paths.push(remote_layer_path(
- &tenant_id,
+ &tenant_shard_id.tenant_id,
&timeline_id,
meta.shard,
&layer,
@@ -529,7 +498,7 @@ impl DeletionQueueClient {
return self.flush_immediate().await;
}
- self.push_layers_sync(tenant_id, timeline_id, current_generation, layers)
+ self.push_layers_sync(tenant_shard_id, timeline_id, current_generation, layers)
}
/// When a Tenant has a generation, push_layers is always synchronous because
@@ -539,7 +508,7 @@ impl DeletionQueueClient {
/// support (``)
pub(crate) fn push_layers_sync(
&self,
- tenant_id: TenantId,
+ tenant_shard_id: TenantShardId,
timeline_id: TimelineId,
current_generation: Generation,
layers: Vec<(LayerFileName, LayerFileMetadata)>,
@@ -550,7 +519,7 @@ impl DeletionQueueClient {
self.do_push(
&self.tx,
ListWriterQueueMessage::Delete(DeletionOp {
- tenant_id,
+ tenant_shard_id,
timeline_id,
layers,
generation: current_generation,
@@ -818,12 +787,12 @@ mod test {
}
fn set_latest_generation(&self, gen: Generation) {
- let tenant_id = self.harness.tenant_id;
+ let tenant_shard_id = self.harness.tenant_shard_id;
self.mock_control_plane
.latest_generation
.lock()
.unwrap()
- .insert(tenant_id, gen);
+ .insert(tenant_shard_id, gen);
}
/// Returns remote layer file name, suitable for use in assert_remote_files
@@ -832,8 +801,8 @@ mod test {
file_name: LayerFileName,
gen: Generation,
) -> anyhow::Result {
- let tenant_id = self.harness.tenant_id;
- let relative_remote_path = remote_timeline_path(&tenant_id, &TIMELINE_ID);
+ let tenant_shard_id = self.harness.tenant_shard_id;
+ let relative_remote_path = remote_timeline_path(&tenant_shard_id, &TIMELINE_ID);
let remote_timeline_path = self.remote_fs_dir.join(relative_remote_path.get_path());
std::fs::create_dir_all(&remote_timeline_path)?;
let remote_layer_file_name = format!("{}{}", file_name, gen.get_suffix());
@@ -851,7 +820,7 @@ mod test {
#[derive(Debug, Clone)]
struct MockControlPlane {
- pub latest_generation: std::sync::Arc>>,
+ pub latest_generation: std::sync::Arc>>,
}
impl MockControlPlane {
@@ -865,20 +834,20 @@ mod test {
#[async_trait::async_trait]
impl ControlPlaneGenerationsApi for MockControlPlane {
#[allow(clippy::diverging_sub_expression)] // False positive via async_trait
- async fn re_attach(&self) -> Result, RetryForeverError> {
+ async fn re_attach(&self) -> Result, RetryForeverError> {
unimplemented!()
}
async fn validate(
&self,
- tenants: Vec<(TenantId, Generation)>,
- ) -> Result, RetryForeverError> {
+ tenants: Vec<(TenantShardId, Generation)>,
+ ) -> Result, RetryForeverError> {
let mut result = HashMap::new();
let latest_generation = self.latest_generation.lock().unwrap();
- for (tenant_id, generation) in tenants {
- if let Some(latest) = latest_generation.get(&tenant_id) {
- result.insert(tenant_id, *latest == generation);
+ for (tenant_shard_id, generation) in tenants {
+ if let Some(latest) = latest_generation.get(&tenant_shard_id) {
+ result.insert(tenant_shard_id, *latest == generation);
}
}
@@ -982,10 +951,10 @@ mod test {
client.recover(HashMap::new())?;
let layer_file_name_1: LayerFileName = "000000000000000000000000000000000000-FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF__00000000016B59D8-00000000016B5A51".parse().unwrap();
- let tenant_id = ctx.harness.tenant_id;
+ let tenant_shard_id = ctx.harness.tenant_shard_id;
let content: Vec = "victim1 contents".into();
- let relative_remote_path = remote_timeline_path(&tenant_id, &TIMELINE_ID);
+ let relative_remote_path = remote_timeline_path(&tenant_shard_id, &TIMELINE_ID);
let remote_timeline_path = ctx.remote_fs_dir.join(relative_remote_path.get_path());
let deletion_prefix = ctx.harness.conf.deletion_prefix();
@@ -1015,7 +984,7 @@ mod test {
info!("Pushing");
client
.push_layers(
- tenant_id,
+ tenant_shard_id,
TIMELINE_ID,
now_generation,
[(layer_file_name_1.clone(), layer_metadata)].to_vec(),
@@ -1062,8 +1031,8 @@ mod test {
ctx.set_latest_generation(latest_generation);
- let tenant_id = ctx.harness.tenant_id;
- let relative_remote_path = remote_timeline_path(&tenant_id, &TIMELINE_ID);
+ let tenant_shard_id = ctx.harness.tenant_shard_id;
+ let relative_remote_path = remote_timeline_path(&tenant_shard_id, &TIMELINE_ID);
let remote_timeline_path = ctx.remote_fs_dir.join(relative_remote_path.get_path());
// Initial state: a remote layer exists
@@ -1073,7 +1042,7 @@ mod test {
tracing::debug!("Pushing...");
client
.push_layers(
- tenant_id,
+ tenant_shard_id,
TIMELINE_ID,
stale_generation,
[(EXAMPLE_LAYER_NAME.clone(), layer_metadata.clone())].to_vec(),
@@ -1088,7 +1057,7 @@ mod test {
tracing::debug!("Pushing...");
client
.push_layers(
- tenant_id,
+ tenant_shard_id,
TIMELINE_ID,
latest_generation,
[(EXAMPLE_LAYER_NAME.clone(), layer_metadata.clone())].to_vec(),
@@ -1110,9 +1079,9 @@ mod test {
let client = ctx.deletion_queue.new_client();
client.recover(HashMap::new())?;
- let tenant_id = ctx.harness.tenant_id;
+ let tenant_shard_id = ctx.harness.tenant_shard_id;
- let relative_remote_path = remote_timeline_path(&tenant_id, &TIMELINE_ID);
+ let relative_remote_path = remote_timeline_path(&tenant_shard_id, &TIMELINE_ID);
let remote_timeline_path = ctx.remote_fs_dir.join(relative_remote_path.get_path());
let deletion_prefix = ctx.harness.conf.deletion_prefix();
@@ -1128,7 +1097,7 @@ mod test {
ctx.write_remote_layer(EXAMPLE_LAYER_NAME, layer_generation)?;
client
.push_layers(
- tenant_id,
+ tenant_shard_id,
TIMELINE_ID,
now_generation.previous(),
[(EXAMPLE_LAYER_NAME.clone(), layer_metadata.clone())].to_vec(),
@@ -1142,7 +1111,7 @@ mod test {
ctx.write_remote_layer(EXAMPLE_LAYER_NAME_ALT, layer_generation)?;
client
.push_layers(
- tenant_id,
+ tenant_shard_id,
TIMELINE_ID,
now_generation,
[(EXAMPLE_LAYER_NAME_ALT.clone(), layer_metadata.clone())].to_vec(),
@@ -1173,7 +1142,7 @@ mod test {
drop(client);
ctx.restart().await;
let client = ctx.deletion_queue.new_client();
- client.recover(HashMap::from([(tenant_id, now_generation)]))?;
+ client.recover(HashMap::from([(tenant_shard_id, now_generation)]))?;
info!("Flush-executing");
client.flush_execute().await?;
@@ -1237,7 +1206,7 @@ pub(crate) mod mock {
let mut objects = op.objects;
for (layer, meta) in op.layers {
objects.push(remote_layer_path(
- &op.tenant_id,
+ &op.tenant_shard_id.tenant_id,
&op.timeline_id,
meta.shard,
&layer,
@@ -1321,4 +1290,34 @@ pub(crate) mod mock {
}
}
}
+
+ /// Test round-trip serialization/deserialization, and test stability of the format
+ /// vs. a static expected string for the serialized version.
+ #[test]
+ fn deletion_list_serialization() -> anyhow::Result<()> {
+ let tenant_id = "ad6c1a56f5680419d3a16ff55d97ec3c"
+ .to_string()
+ .parse::()?;
+ let timeline_id = "be322c834ed9e709e63b5c9698691910"
+ .to_string()
+ .parse::()?;
+ let generation = Generation::new(123);
+
+ let object =
+ RemotePath::from_string(&format!("tenants/{tenant_id}/timelines/{timeline_id}/foo"))?;
+ let mut objects = [object].to_vec();
+
+ let mut example = DeletionList::new(1);
+ example.push(&tenant_id, &timeline_id, generation, &mut objects);
+
+ let encoded = serde_json::to_string(&example)?;
+
+ let expected = "{\"version\":1,\"sequence\":1,\"tenants\":{\"ad6c1a56f5680419d3a16ff55d97ec3c\":{\"timelines\":{\"be322c834ed9e709e63b5c9698691910\":[\"foo\"]},\"generation\":123}},\"size\":1}".to_string();
+ assert_eq!(encoded, expected);
+
+ let decoded = serde_json::from_str::(&encoded)?;
+ assert_eq!(example, decoded);
+
+ Ok(())
+ }
}
diff --git a/pageserver/src/deletion_queue/list_writer.rs b/pageserver/src/deletion_queue/list_writer.rs
index 5d52b680e4..7ff27ceb44 100644
--- a/pageserver/src/deletion_queue/list_writer.rs
+++ b/pageserver/src/deletion_queue/list_writer.rs
@@ -19,6 +19,7 @@ use std::collections::HashMap;
use std::fs::create_dir_all;
use std::time::Duration;
+use pageserver_api::shard::TenantShardId;
use regex::Regex;
use remote_storage::RemotePath;
use tokio_util::sync::CancellationToken;
@@ -26,7 +27,6 @@ use tracing::debug;
use tracing::info;
use tracing::warn;
use utils::generation::Generation;
-use utils::id::TenantId;
use utils::id::TimelineId;
use crate::config::PageServerConf;
@@ -54,7 +54,7 @@ const FRONTEND_FLUSHING_TIMEOUT: Duration = Duration::from_millis(100);
#[derive(Debug)]
pub(super) struct DeletionOp {
- pub(super) tenant_id: TenantId,
+ pub(super) tenant_shard_id: TenantShardId,
pub(super) timeline_id: TimelineId,
// `layers` and `objects` are both just lists of objects. `layers` is used if you do not
// have a config object handy to project it to a remote key, and need the consuming worker
@@ -62,14 +62,14 @@ pub(super) struct DeletionOp {
pub(super) layers: Vec<(LayerFileName, LayerFileMetadata)>,
pub(super) objects: Vec,
- /// The _current_ generation of the Tenant attachment in which we are enqueuing
+ /// The _current_ generation of the Tenant shard attachment in which we are enqueuing
/// this deletion.
pub(super) generation: Generation,
}
#[derive(Debug)]
pub(super) struct RecoverOp {
- pub(super) attached_tenants: HashMap,
+ pub(super) attached_tenants: HashMap,
}
#[derive(Debug)]
@@ -206,7 +206,7 @@ impl ListWriter {
async fn recover(
&mut self,
- attached_tenants: HashMap,
+ attached_tenants: HashMap,
) -> Result<(), anyhow::Error> {
debug!(
"recovering with {} attached tenants",
@@ -309,8 +309,8 @@ impl ListWriter {
// generation was issued to another node in the interval while we restarted,
// then we may treat deletion lists from the previous generation as if they
// belong to our currently attached generation, and proceed to validate & execute.
- for (tenant_id, tenant_list) in &mut deletion_list.tenants {
- if let Some(attached_gen) = attached_tenants.get(tenant_id) {
+ for (tenant_shard_id, tenant_list) in &mut deletion_list.tenants {
+ if let Some(attached_gen) = attached_tenants.get(tenant_shard_id) {
if attached_gen.previous() == tenant_list.generation {
tenant_list.generation = *attached_gen;
}
@@ -390,7 +390,7 @@ impl ListWriter {
let mut layer_paths = Vec::new();
for (layer, meta) in op.layers {
layer_paths.push(remote_layer_path(
- &op.tenant_id,
+ &op.tenant_shard_id.tenant_id,
&op.timeline_id,
meta.shard,
&layer,
@@ -400,14 +400,14 @@ impl ListWriter {
layer_paths.extend(op.objects);
if !self.pending.push(
- &op.tenant_id,
+ &op.tenant_shard_id,
&op.timeline_id,
op.generation,
&mut layer_paths,
) {
self.flush().await;
let retry_succeeded = self.pending.push(
- &op.tenant_id,
+ &op.tenant_shard_id,
&op.timeline_id,
op.generation,
&mut layer_paths,
diff --git a/pageserver/src/disk_usage_eviction_task.rs b/pageserver/src/disk_usage_eviction_task.rs
index 642cafad28..f01cd1cf8c 100644
--- a/pageserver/src/disk_usage_eviction_task.rs
+++ b/pageserver/src/disk_usage_eviction_task.rs
@@ -310,7 +310,7 @@ pub async fn disk_usage_eviction_task_iteration_impl(
.unwrap()
.as_micros(),
partition,
- desc.tenant_id,
+ desc.tenant_shard_id,
desc.timeline_id,
candidate.layer,
);
@@ -380,7 +380,7 @@ pub async fn disk_usage_eviction_task_iteration_impl(
let limit = Arc::new(tokio::sync::Semaphore::new(1000.max(max_batch_size)));
for (timeline, batch) in batched {
- let tenant_id = timeline.tenant_id;
+ let tenant_shard_id = timeline.tenant_shard_id;
let timeline_id = timeline.timeline_id;
let batch_size =
u32::try_from(batch.len()).expect("batch size limited to u32::MAX during partitioning");
@@ -431,7 +431,7 @@ pub async fn disk_usage_eviction_task_iteration_impl(
(evicted_bytes, evictions_failed)
}
}
- .instrument(tracing::info_span!("evict_batch", %tenant_id, %timeline_id, batch_size));
+ .instrument(tracing::info_span!("evict_batch", tenant_id=%tenant_shard_id.tenant_id, shard_id=%tenant_shard_id.shard_slug(), %timeline_id, batch_size));
js.spawn(evict);
@@ -572,7 +572,7 @@ async fn collect_eviction_candidates(
continue;
}
let info = tl.get_local_layers_for_disk_usage_eviction().await;
- debug!(tenant_id=%tl.tenant_id, timeline_id=%tl.timeline_id, "timeline resident layers count: {}", info.resident_layers.len());
+ debug!(tenant_id=%tl.tenant_shard_id.tenant_id, shard_id=%tl.tenant_shard_id.shard_slug(), timeline_id=%tl.timeline_id, "timeline resident layers count: {}", info.resident_layers.len());
tenant_candidates.extend(
info.resident_layers
.into_iter()
diff --git a/pageserver/src/http/openapi_spec.yml b/pageserver/src/http/openapi_spec.yml
index 4d455243f0..237109abfe 100644
--- a/pageserver/src/http/openapi_spec.yml
+++ b/pageserver/src/http/openapi_spec.yml
@@ -624,6 +624,99 @@ paths:
$ref: "#/components/schemas/ServiceUnavailableError"
+ /v1/tenant/{tenant_id}/location_config:
+ parameters:
+ - name: tenant_id
+ in: path
+ required: true
+ schema:
+ type: string
+ format: hex
+ - name: flush_ms
+ in: query
+ required: false
+ schema:
+ type: integer
+ put:
+ description: |
+ Configures a _tenant location_, that is how a particular pageserver handles
+ a particular tenant. This includes _attached_ tenants, i.e. those ingesting WAL
+ and page service requests, and _secondary_ tenants, i.e. those which are just keeping
+ a warm cache in anticipation of transitioning to attached state in the future.
+
+ This is a declarative, idempotent API: there are not separate endpoints
+ for different tenant location configurations. Rather, this single endpoint accepts
+ a description of the desired location configuration, and makes whatever changes
+ are required to reach that state.
+
+ In imperative terms, this API is used to attach and detach tenants, and
+ to transition tenants to and from secondary mode.
+
+ This is a synchronous API: there is no 202 response. State transitions should always
+ be fast (milliseconds), with the exception of requests setting `flush_ms`, in which case
+ the caller controls the runtime of the request.
+
+ In some state transitions, it makes sense to flush dirty data to remote storage: this includes transitions
+ to AttachedStale and Detached. Flushing is never necessary for correctness, but is an
+ important optimization when doing migrations. The `flush_ms` parameter controls whether
+ flushing should be attempted, and how much time is allowed for flushing. If the time limit expires,
+ the requested transition will continue without waiting for any outstanding data to flush. Callers
+ should use a duration which is substantially less than their HTTP client's request
+ timeout. It is safe to supply flush_ms irrespective of the request body: in state transitions
+ where flushing doesn't make sense, the server will ignore it.
+
+ It is safe to retry requests, but if one receives a 409 or 503 response, it is not
+ useful to retry aggressively: there is probably an existing request still ongoing.
+ requestBody:
+ required: false
+ content:
+ application/json:
+ schema:
+ $ref: "#/components/schemas/TenantLocationConfigRequest"
+ responses:
+ "200":
+ description: Tenant is now in requested state
+ "503":
+ description: Tenant's state cannot be changed right now. Wait a few seconds and retry.
+ content:
+ application/json:
+ schema:
+ $ref: "#/components/schemas/Error"
+ "401":
+ description: Unauthorized Error
+ content:
+ application/json:
+ schema:
+ $ref: "#/components/schemas/UnauthorizedError"
+ "403":
+ description: Forbidden Error
+ content:
+ application/json:
+ schema:
+ $ref: "#/components/schemas/ForbiddenError"
+ "409":
+ description: |
+ The tenant is already known to Pageserver in some way,
+ and hence this `/attach` call has been rejected.
+
+ Some examples of how this can happen:
+ - tenant was created on this pageserver
+ - tenant attachment was started by an earlier call to `/attach`.
+
+ Callers should poll the tenant status's `attachment_status` field,
+ like for status 202. See the longer description for `POST /attach`
+ for details.
+ content:
+ application/json:
+ schema:
+ $ref: "#/components/schemas/ConflictError"
+ "500":
+ description: Generic operation error
+ content:
+ application/json:
+ schema:
+ $ref: "#/components/schemas/Error"
+
/v1/tenant/{tenant_id}/detach:
parameters:
- name: tenant_id
@@ -935,6 +1028,9 @@ paths:
format: hex
pg_version:
type: integer
+ existing_initdb_timeline_id:
+ type: string
+ format: hex
responses:
"201":
description: TimelineInfo
@@ -1274,6 +1370,31 @@ components:
tenant_id:
type: string
format: hex
+ TenantLocationConfigRequest:
+ type: object
+ required:
+ - tenant_id
+ properties:
+ tenant_id:
+ type: string
+ format: hex
+ mode:
+ type: string
+ enum: ["AttachedSingle", "AttachedMulti", "AttachedStale", "Secondary", "Detached"]
+ description: Mode of functionality that this pageserver will run in for this tenant.
+ generation:
+ type: integer
+ description: Attachment generation number, mandatory when `mode` is an attached state
+ secondary_conf:
+ $ref: '#/components/schemas/SecondaryConfig'
+ tenant_conf:
+ $ref: '#/components/schemas/TenantConfig'
+ SecondaryConfig:
+ type: object
+ properties:
+ warm:
+ type: boolean
+ description: Whether to poll remote storage for layers to download. If false, secondary locations don't download anything.
TenantConfig:
type: object
properties:
diff --git a/pageserver/src/http/routes.rs b/pageserver/src/http/routes.rs
index 5ce09500ee..29a1ff52e8 100644
--- a/pageserver/src/http/routes.rs
+++ b/pageserver/src/http/routes.rs
@@ -4,6 +4,7 @@
use std::collections::HashMap;
use std::str::FromStr;
use std::sync::Arc;
+use std::time::Duration;
use anyhow::{anyhow, Context, Result};
use enumset::EnumSet;
@@ -337,13 +338,7 @@ async fn build_timeline_info_common(
Lsn(0) => None,
lsn @ Lsn(_) => Some(lsn),
};
- let current_logical_size = match timeline.get_current_logical_size(ctx) {
- Ok((size, _)) => Some(size),
- Err(err) => {
- error!("Timeline info creation failed to get current logical size: {err:?}");
- None
- }
- };
+ let current_logical_size = timeline.get_current_logical_size(ctx);
let current_physical_size = Some(timeline.layer_size_sum().await);
let state = timeline.current_state();
let remote_consistent_lsn_projected = timeline
@@ -356,7 +351,8 @@ async fn build_timeline_info_common(
let walreceiver_status = timeline.walreceiver_status();
let info = TimelineInfo {
- tenant_id: timeline.tenant_id,
+ // TODO(sharding): add a shard_id field, or make tenant_id into a tenant_shard_id
+ tenant_id: timeline.tenant_shard_id.tenant_id,
timeline_id: timeline.timeline_id,
ancestor_timeline_id,
ancestor_lsn,
@@ -366,7 +362,11 @@ async fn build_timeline_info_common(
last_record_lsn,
prev_record_lsn: Some(timeline.get_prev_record_lsn()),
latest_gc_cutoff_lsn: *timeline.get_latest_gc_cutoff_lsn(),
- current_logical_size,
+ current_logical_size: current_logical_size.size_dont_care_about_accuracy(),
+ current_logical_size_is_accurate: match current_logical_size.accuracy() {
+ tenant::timeline::logical_size::Accuracy::Approximate => false,
+ tenant::timeline::logical_size::Accuracy::Exact => true,
+ },
current_physical_size,
current_logical_size_non_incremental: None,
timeline_dir_layer_file_size_sum: None,
@@ -439,6 +439,7 @@ async fn timeline_create_handler(
request_data.ancestor_timeline_id.map(TimelineId::from),
request_data.ancestor_start_lsn,
request_data.pg_version.unwrap_or(crate::DEFAULT_PG_VERSION),
+ request_data.existing_initdb_timeline_id,
state.broker_client.clone(),
&ctx,
)
@@ -1157,6 +1158,7 @@ async fn put_tenant_location_config_handler(
let tenant_shard_id: TenantShardId = parse_request_param(&request, "tenant_shard_id")?;
let request_data: TenantLocationConfigRequest = json_request(&mut request).await?;
+ let flush = parse_query_param(&request, "flush_ms")?.map(Duration::from_millis);
check_permission(&request, Some(tenant_shard_id.tenant_id))?;
let ctx = RequestContext::new(TaskKind::MgmtRequest, DownloadBehavior::Warn);
@@ -1189,7 +1191,7 @@ async fn put_tenant_location_config_handler(
state
.tenant_manager
- .upsert_location(tenant_shard_id, location_conf, &ctx)
+ .upsert_location(tenant_shard_id, location_conf, flush, &ctx)
.await
// TODO: badrequest assumes the caller was asking for something unreasonable, but in
// principle we might have hit something like concurrent API calls to the same tenant,
diff --git a/pageserver/src/import_datadir.rs b/pageserver/src/import_datadir.rs
index 770458e02e..452cd73f76 100644
--- a/pageserver/src/import_datadir.rs
+++ b/pageserver/src/import_datadir.rs
@@ -7,12 +7,13 @@ use std::pin::Pin;
use std::task::{self, Poll};
use anyhow::{bail, ensure, Context, Result};
+use async_compression::tokio::bufread::ZstdDecoder;
use async_compression::{tokio::write::ZstdEncoder, zstd::CParameter, Level};
use bytes::Bytes;
use camino::Utf8Path;
use futures::StreamExt;
use nix::NixPath;
-use tokio::io::{AsyncRead, AsyncReadExt, AsyncWrite, AsyncWriteExt};
+use tokio::io::{AsyncBufRead, AsyncRead, AsyncReadExt, AsyncWrite, AsyncWriteExt};
use tokio_tar::Archive;
use tokio_tar::Builder;
use tokio_tar::HeaderMode;
@@ -732,3 +733,13 @@ pub async fn create_tar_zst(pgdata_path: &Utf8Path) -> Result> {
}
Ok(compressed.buf)
}
+
+pub async fn extract_tar_zst(
+ pgdata_path: &Utf8Path,
+ tar_zst: impl AsyncBufRead + Unpin,
+) -> Result<()> {
+ let tar = Box::pin(ZstdDecoder::new(tar_zst));
+ let mut archive = Archive::new(tar);
+ archive.unpack(pgdata_path).await?;
+ Ok(())
+}
diff --git a/pageserver/src/metrics.rs b/pageserver/src/metrics.rs
index d5915f4c98..6aee40b579 100644
--- a/pageserver/src/metrics.rs
+++ b/pageserver/src/metrics.rs
@@ -7,6 +7,7 @@ use metrics::{
HistogramVec, IntCounter, IntCounterVec, IntGauge, IntGaugeVec, UIntGauge, UIntGaugeVec,
};
use once_cell::sync::Lazy;
+use pageserver_api::shard::TenantShardId;
use strum::{EnumCount, IntoEnumIterator, VariantNames};
use strum_macros::{EnumVariantNames, IntoStaticStr};
use utils::id::{TenantId, TimelineId};
@@ -402,6 +403,134 @@ static CURRENT_LOGICAL_SIZE: Lazy = Lazy::new(|| {
.expect("failed to define current logical size metric")
});
+pub(crate) mod initial_logical_size {
+ use metrics::{register_int_counter, register_int_counter_vec, IntCounter, IntCounterVec};
+ use once_cell::sync::Lazy;
+
+ use crate::task_mgr::TaskKind;
+
+ pub(crate) struct StartCalculation(IntCounterVec);
+ pub(crate) static START_CALCULATION: Lazy = Lazy::new(|| {
+ StartCalculation(
+ register_int_counter_vec!(
+ "pageserver_initial_logical_size_start_calculation",
+ "Incremented each time we start an initial logical size calculation attempt. \
+ The `task_kind` label is for the task kind that caused this attempt.",
+ &["attempt", "task_kind"]
+ )
+ .unwrap(),
+ )
+ });
+
+ struct DropCalculation {
+ first: IntCounter,
+ retry: IntCounter,
+ }
+
+ static DROP_CALCULATION: Lazy = Lazy::new(|| {
+ let vec = register_int_counter_vec!(
+ "pageserver_initial_logical_size_drop_calculation",
+ "Incremented each time we abort a started size calculation attmpt.",
+ &["attempt"]
+ )
+ .unwrap();
+ DropCalculation {
+ first: vec.with_label_values(&["first"]),
+ retry: vec.with_label_values(&["retry"]),
+ }
+ });
+
+ pub(crate) struct Calculated {
+ pub(crate) births: IntCounter,
+ pub(crate) deaths: IntCounter,
+ }
+
+ pub(crate) static CALCULATED: Lazy = Lazy::new(|| Calculated {
+ births: register_int_counter!(
+ "pageserver_initial_logical_size_finish_calculation",
+ "Incremented every time we finish calculation of initial logical size.\
+ If everything is working well, this should happen at most once per Timeline object."
+ )
+ .unwrap(),
+ deaths: register_int_counter!(
+ "pageserver_initial_logical_size_drop_finished_calculation",
+ "Incremented when we drop a finished initial logical size calculation result.\
+ Mainly useful to turn pageserver_initial_logical_size_finish_calculation into a gauge."
+ )
+ .unwrap(),
+ });
+
+ pub(crate) struct OngoingCalculationGuard {
+ inc_drop_calculation: Option,
+ }
+
+ impl StartCalculation {
+ pub(crate) fn first(&self, causing_task_kind: Option) -> OngoingCalculationGuard {
+ let task_kind_label: &'static str =
+ causing_task_kind.map(|k| k.into()).unwrap_or_default();
+ self.0.with_label_values(&["first", task_kind_label]);
+ OngoingCalculationGuard {
+ inc_drop_calculation: Some(DROP_CALCULATION.first.clone()),
+ }
+ }
+ pub(crate) fn retry(&self, causing_task_kind: Option) -> OngoingCalculationGuard {
+ let task_kind_label: &'static str =
+ causing_task_kind.map(|k| k.into()).unwrap_or_default();
+ self.0.with_label_values(&["retry", task_kind_label]);
+ OngoingCalculationGuard {
+ inc_drop_calculation: Some(DROP_CALCULATION.retry.clone()),
+ }
+ }
+ }
+
+ impl Drop for OngoingCalculationGuard {
+ fn drop(&mut self) {
+ if let Some(counter) = self.inc_drop_calculation.take() {
+ counter.inc();
+ }
+ }
+ }
+
+ impl OngoingCalculationGuard {
+ pub(crate) fn calculation_result_saved(mut self) -> FinishedCalculationGuard {
+ drop(self.inc_drop_calculation.take());
+ CALCULATED.births.inc();
+ FinishedCalculationGuard {
+ inc_on_drop: CALCULATED.deaths.clone(),
+ }
+ }
+ }
+
+ pub(crate) struct FinishedCalculationGuard {
+ inc_on_drop: IntCounter,
+ }
+
+ impl Drop for FinishedCalculationGuard {
+ fn drop(&mut self) {
+ self.inc_on_drop.inc();
+ }
+ }
+
+ pub(crate) struct Calls {
+ pub(crate) approximate: IntCounter,
+ pub(crate) exact: IntCounter,
+ }
+
+ pub(crate) static CALLS: Lazy = Lazy::new(|| {
+ let vec = register_int_counter_vec!(
+ "pageserver_initial_logical_size_calls",
+ "Incremented each time some code asks for incremental logical size.\
+ The label records the accuracy of the result.",
+ &["accuracy"]
+ )
+ .unwrap();
+ Calls {
+ approximate: vec.with_label_values(&["approximate"]),
+ exact: vec.with_label_values(&["exact"]),
+ }
+ });
+}
+
pub(crate) static TENANT_STATE_METRIC: Lazy = Lazy::new(|| {
register_uint_gauge_vec!(
"pageserver_tenant_states_count",
@@ -1252,6 +1381,15 @@ pub(crate) static WAL_REDO_RECORD_COUNTER: Lazy = Lazy::new(|| {
.unwrap()
});
+pub(crate) static WAL_REDO_PROCESS_LAUNCH_DURATION_HISTOGRAM: Lazy = Lazy::new(|| {
+ register_histogram!(
+ "pageserver_wal_redo_process_launch_duration",
+ "Histogram of the duration of successful WalRedoProcess::launch calls",
+ redo_histogram_time_buckets!(),
+ )
+ .expect("failed to define a metric")
+});
+
pub(crate) struct WalRedoProcessCounters {
pub(crate) started: IntCounter,
pub(crate) killed_by_cause: enum_map::EnumMap,
@@ -1571,9 +1709,9 @@ pub struct RemoteTimelineClientMetrics {
}
impl RemoteTimelineClientMetrics {
- pub fn new(tenant_id: &TenantId, timeline_id: &TimelineId) -> Self {
+ pub fn new(tenant_shard_id: &TenantShardId, timeline_id: &TimelineId) -> Self {
RemoteTimelineClientMetrics {
- tenant_id: tenant_id.to_string(),
+ tenant_id: tenant_shard_id.tenant_id.to_string(),
timeline_id: timeline_id.to_string(),
calls_unfinished_gauge: Mutex::new(HashMap::default()),
bytes_started_counter: Mutex::new(HashMap::default()),
@@ -1961,6 +2099,7 @@ pub fn preinitialize_metrics() {
&WAL_REDO_TIME,
&WAL_REDO_RECORDS_HISTOGRAM,
&WAL_REDO_BYTES_HISTOGRAM,
+ &WAL_REDO_PROCESS_LAUNCH_DURATION_HISTOGRAM,
]
.into_iter()
.for_each(|h| {
diff --git a/pageserver/src/page_service.rs b/pageserver/src/page_service.rs
index ee5f1732e4..82c16eb9bd 100644
--- a/pageserver/src/page_service.rs
+++ b/pageserver/src/page_service.rs
@@ -399,6 +399,9 @@ impl PageServerHandler {
{
debug_assert_current_span_has_tenant_and_timeline_id();
+ // TODO(sharding): enumerate local tenant shards for this tenant, and select the one
+ // that should serve this request.
+
// Make request tracer if needed
let tenant = mgr::get_active_tenant_with_timeout(
tenant_id,
@@ -408,9 +411,10 @@ impl PageServerHandler {
.await?;
let mut tracer = if tenant.get_trace_read_requests() {
let connection_id = ConnectionId::generate();
- let path = tenant
- .conf
- .trace_path(&tenant_id, &timeline_id, &connection_id);
+ let path =
+ tenant
+ .conf
+ .trace_path(&tenant.tenant_shard_id(), &timeline_id, &connection_id);
Some(Tracer::new(path))
} else {
None
diff --git a/pageserver/src/tenant.rs b/pageserver/src/tenant.rs
index bc8779b26f..12610b1c89 100644
--- a/pageserver/src/tenant.rs
+++ b/pageserver/src/tenant.rs
@@ -15,12 +15,16 @@ use anyhow::{bail, Context};
use bytes::Bytes;
use camino::{Utf8Path, Utf8PathBuf};
use enumset::EnumSet;
+use futures::stream::FuturesUnordered;
use futures::FutureExt;
+use futures::StreamExt;
use pageserver_api::models::TimelineState;
+use pageserver_api::shard::TenantShardId;
use remote_storage::DownloadError;
use remote_storage::GenericRemoteStorage;
use std::fmt;
use storage_broker::BrokerClientChannel;
+use tokio::io::BufReader;
use tokio::runtime::Handle;
use tokio::sync::watch;
use tokio::task::JoinSet;
@@ -31,6 +35,7 @@ use utils::completion;
use utils::crashsafe::path_with_suffix_extension;
use utils::fs_ext;
use utils::sync::gate::Gate;
+use utils::sync::gate::GateGuard;
use self::config::AttachedLocationConfig;
use self::config::AttachmentMode;
@@ -50,6 +55,7 @@ use self::timeline::TimelineResources;
use crate::config::PageServerConf;
use crate::context::{DownloadBehavior, RequestContext};
use crate::deletion_queue::DeletionQueueClient;
+use crate::deletion_queue::DeletionQueueError;
use crate::import_datadir;
use crate::is_uninit_mark;
use crate::metrics::TENANT_ACTIVATION;
@@ -228,7 +234,7 @@ pub struct Tenant {
// This is necessary to allow global config updates.
tenant_conf: Arc>,
- tenant_id: TenantId,
+ tenant_shard_id: TenantShardId,
/// The remote storage generation, used to protect S3 objects from split-brain.
/// Does not change over the lifetime of the [`Tenant`] object.
@@ -272,7 +278,7 @@ pub struct Tenant {
impl std::fmt::Debug for Tenant {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
- write!(f, "{} ({})", self.tenant_id, self.current_state())
+ write!(f, "{} ({})", self.tenant_shard_id, self.current_state())
}
}
@@ -466,7 +472,7 @@ impl Tenant {
init_order: Option<&InitializationOrder>,
_ctx: &RequestContext,
) -> anyhow::Result<()> {
- let tenant_id = self.tenant_id;
+ let tenant_id = self.tenant_shard_id;
let timeline = self.create_timeline_struct(
timeline_id,
@@ -558,7 +564,7 @@ impl Tenant {
#[allow(clippy::too_many_arguments)]
pub(crate) fn spawn(
conf: &'static PageServerConf,
- tenant_id: TenantId,
+ tenant_shard_id: TenantShardId,
resources: TenantSharedResources,
attached_conf: AttachedTenantConf,
init_order: Option,
@@ -566,8 +572,10 @@ impl Tenant {
mode: SpawnMode,
ctx: &RequestContext,
) -> anyhow::Result> {
+ // TODO(sharding): make WalRedoManager shard-aware
let wal_redo_manager = Arc::new(WalRedoManager::from(PostgresRedoManager::new(
- conf, tenant_id,
+ conf,
+ tenant_shard_id.tenant_id,
)));
let TenantSharedResources {
@@ -581,7 +589,7 @@ impl Tenant {
conf,
attached_conf,
wal_redo_manager,
- tenant_id,
+ tenant_shard_id,
remote_storage.clone(),
deletion_queue_client,
));
@@ -593,7 +601,7 @@ impl Tenant {
task_mgr::spawn(
&tokio::runtime::Handle::current(),
TaskKind::Attach,
- Some(tenant_id),
+ Some(tenant_shard_id.tenant_id),
None,
"attach tenant",
false,
@@ -632,7 +640,7 @@ impl Tenant {
match tenant_clone
.preload(remote_storage, task_mgr::shutdown_token())
.instrument(
- tracing::info_span!(parent: None, "attach_preload", tenant_id=%tenant_id),
+ tracing::info_span!(parent: None, "attach_preload", tenant_id=%tenant_shard_id.tenant_id, shard_id=%tenant_shard_id.shard_slug()),
)
.await {
Ok(p) => p,
@@ -714,7 +722,7 @@ impl Tenant {
Ok(())
}
.instrument({
- let span = tracing::info_span!(parent: None, "attach", tenant_id=%tenant_id);
+ let span = tracing::info_span!(parent: None, "attach", tenant_id=%tenant_shard_id.tenant_id, shard_id=%tenant_shard_id.shard_slug());
span.follows_from(Span::current());
span
}),
@@ -732,7 +740,7 @@ impl Tenant {
info!("listing remote timelines");
let (remote_timeline_ids, other_keys) = remote_timeline_client::list_remote_timelines(
remote_storage,
- self.tenant_id,
+ self.tenant_shard_id,
cancel.clone(),
)
.await?;
@@ -788,20 +796,31 @@ impl Tenant {
let mut timeline_ancestors = HashMap::new();
let mut existent_timelines = HashSet::new();
for (timeline_id, preload) in preload.timelines {
- // In this context a timeline "exists" if it has any content in remote storage: this will
- // be our cue to not delete any corresponding local directory
- existent_timelines.insert(timeline_id);
-
let index_part = match preload.index_part {
Ok(i) => {
debug!("remote index part exists for timeline {timeline_id}");
+ // We found index_part on the remote, this is the standard case.
+ existent_timelines.insert(timeline_id);
i
}
+ Err(DownloadError::NotFound) => {
+ // There is no index_part on the remote. We only get here
+ // if there is some prefix for the timeline in the remote storage.
+ // This can e.g. be the initdb.tar.zst archive, maybe a
+ // remnant from a prior incomplete creation or deletion attempt.
+ // Delete the local directory as the deciding criterion for a
+ // timeline's existence is presence of index_part.
+ info!(%timeline_id, "index_part not found on remote");
+ continue;
+ }
Err(e) => {
- // Timeline creation is not atomic: we might upload a layer but no index_part. We expect
- // that the creation will be retried by the control plane and eventually result in
- // a valid loadable state.
+ // Some (possibly ephemeral) error happened during index_part download.
+ // Pretend the timeline exists to not delete the timeline directory,
+ // as it might be a temporary issue and we don't want to re-download
+ // everything after it resolves.
warn!(%timeline_id, "Failed to load index_part from remote storage, failed creation? ({e})");
+
+ existent_timelines.insert(timeline_id);
continue;
}
};
@@ -844,7 +863,7 @@ impl Tenant {
.with_context(|| {
format!(
"failed to load remote timeline {} for tenant {}",
- timeline_id, self.tenant_id
+ timeline_id, self.tenant_shard_id
)
})?;
}
@@ -884,7 +903,7 @@ impl Tenant {
/// timeline that still exists: this can happen if we crashed during a deletion/creation, or
/// if a timeline was deleted while the tenant was attached to a different pageserver.
fn clean_up_timelines(&self, existent_timelines: &HashSet) -> anyhow::Result<()> {
- let timelines_dir = self.conf.timelines_path(&self.tenant_id);
+ let timelines_dir = self.conf.timelines_path(&self.tenant_shard_id);
let entries = match timelines_dir.read_dir_utf8() {
Ok(d) => d,
@@ -970,7 +989,7 @@ impl Tenant {
span::debug_assert_current_span_has_tenant_id();
info!("downloading index file for timeline {}", timeline_id);
- tokio::fs::create_dir_all(self.conf.timeline_path(&self.tenant_id, &timeline_id))
+ tokio::fs::create_dir_all(self.conf.timeline_path(&self.tenant_shard_id, &timeline_id))
.await
.context("Failed to create new timeline directory")?;
@@ -992,10 +1011,15 @@ impl Tenant {
let init_order = None;
// timeline loading after attach expects to find metadata file for each metadata
- save_metadata(self.conf, &self.tenant_id, &timeline_id, &remote_metadata)
- .await
- .context("save_metadata")
- .map_err(LoadLocalTimelineError::Load)?;
+ save_metadata(
+ self.conf,
+ &self.tenant_shard_id,
+ &timeline_id,
+ &remote_metadata,
+ )
+ .await
+ .context("save_metadata")
+ .map_err(LoadLocalTimelineError::Load)?;
self.timeline_init_and_sync(
timeline_id,
@@ -1012,11 +1036,13 @@ impl Tenant {
/// Create a placeholder Tenant object for a broken tenant
pub fn create_broken_tenant(
conf: &'static PageServerConf,
- tenant_id: TenantId,
+ tenant_shard_id: TenantShardId,
reason: String,
) -> Arc {
+ // TODO(sharding): make WalRedoManager shard-aware
let wal_redo_manager = Arc::new(WalRedoManager::from(PostgresRedoManager::new(
- conf, tenant_id,
+ conf,
+ tenant_shard_id.tenant_id,
)));
Arc::new(Tenant::new(
TenantState::Broken {
@@ -1026,7 +1052,7 @@ impl Tenant {
conf,
AttachedTenantConf::try_from(LocationConf::default()).unwrap(),
wal_redo_manager,
- tenant_id,
+ tenant_shard_id,
None,
DeletionQueueClient::broken(),
))
@@ -1039,7 +1065,7 @@ impl Tenant {
// completed in non topological order (for example because parent has smaller number of layer files in it)
let mut timelines_to_resume_deletion: Vec<(TimelineId, Option)> = vec![];
- let timelines_dir = self.conf.timelines_path(&self.tenant_id);
+ let timelines_dir = self.conf.timelines_path(&self.tenant_shard_id);
for entry in timelines_dir
.read_dir_utf8()
@@ -1070,7 +1096,7 @@ impl Tenant {
"Could not parse timeline id out of the timeline uninit mark name {timeline_uninit_mark_file}",
)
})?;
- let timeline_dir = self.conf.timeline_path(&self.tenant_id, &timeline_id);
+ let timeline_dir = self.conf.timeline_path(&self.tenant_shard_id, &timeline_id);
if let Err(e) =
remove_timeline_and_uninit_mark(&timeline_dir, timeline_uninit_mark_file)
{
@@ -1087,7 +1113,7 @@ impl Tenant {
info!("Found deletion mark for timeline {}", timeline_id);
- match load_metadata(self.conf, &self.tenant_id, &timeline_id) {
+ match load_metadata(self.conf, &self.tenant_shard_id, &timeline_id) {
Ok(metadata) => {
timelines_to_resume_deletion.push((timeline_id, Some(metadata)))
}
@@ -1131,7 +1157,7 @@ impl Tenant {
})?;
let timeline_uninit_mark_file = self
.conf
- .timeline_uninit_mark_file_path(self.tenant_id, timeline_id);
+ .timeline_uninit_mark_file_path(self.tenant_shard_id, timeline_id);
if timeline_uninit_mark_file.exists() {
info!(
%timeline_id,
@@ -1147,7 +1173,7 @@ impl Tenant {
let timeline_delete_mark_file = self
.conf
- .timeline_delete_mark_file_path(self.tenant_id, timeline_id);
+ .timeline_delete_mark_file_path(self.tenant_shard_id, timeline_id);
if timeline_delete_mark_file.exists() {
// Cleanup should be done in `is_delete_mark` branch above
continue;
@@ -1155,7 +1181,7 @@ impl Tenant {
let file_name = entry.file_name();
if let Ok(timeline_id) = file_name.parse::() {
- let metadata = load_metadata(self.conf, &self.tenant_id, &timeline_id)
+ let metadata = load_metadata(self.conf, &self.tenant_shard_id, &timeline_id)
.context("failed to load metadata")?;
timelines_to_load.insert(timeline_id, metadata);
} else {
@@ -1187,7 +1213,7 @@ impl Tenant {
remote_storage.clone(),
self.deletion_queue_client.clone(),
self.conf,
- self.tenant_id,
+ self.tenant_shard_id,
timeline_id,
self.generation,
);
@@ -1393,8 +1419,12 @@ impl Tenant {
.map_err(LoadLocalTimelineError::Load)
}
- pub fn tenant_id(&self) -> TenantId {
- self.tenant_id
+ pub(crate) fn tenant_id(&self) -> TenantId {
+ self.tenant_shard_id.tenant_id
+ }
+
+ pub(crate) fn tenant_shard_id(&self) -> TenantShardId {
+ self.tenant_shard_id
}
/// Get Timeline handle for given Neon timeline ID.
@@ -1408,13 +1438,13 @@ impl Tenant {
let timeline = timelines_accessor
.get(&timeline_id)
.ok_or(GetTimelineError::NotFound {
- tenant_id: self.tenant_id,
+ tenant_id: self.tenant_shard_id.tenant_id,
timeline_id,
})?;
if active_only && !timeline.is_active() {
Err(GetTimelineError::NotActive {
- tenant_id: self.tenant_id,
+ tenant_id: self.tenant_shard_id.tenant_id,
timeline_id,
state: timeline.current_state(),
})
@@ -1540,12 +1570,14 @@ impl Tenant {
///
/// If the caller specified the timeline ID to use (`new_timeline_id`), and timeline with
/// the same timeline ID already exists, returns CreateTimelineError::AlreadyExists.
+ #[allow(clippy::too_many_arguments)]
pub async fn create_timeline(
&self,
new_timeline_id: TimelineId,
ancestor_timeline_id: Option,
mut ancestor_start_lsn: Option,
pg_version: u32,
+ load_existing_initdb: Option,
broker_client: storage_broker::BrokerClientChannel,
ctx: &RequestContext,
) -> Result, CreateTimelineError> {
@@ -1620,7 +1652,7 @@ impl Tenant {
.await?
}
None => {
- self.bootstrap_timeline(new_timeline_id, pg_version, ctx)
+ self.bootstrap_timeline(new_timeline_id, pg_version, load_existing_initdb, ctx)
.await?
}
};
@@ -1772,7 +1804,7 @@ impl Tenant {
*current_state = TenantState::Activating(ActivatingFrom::Attaching);
}
}
- debug!(tenant_id = %self.tenant_id, "Activating tenant");
+ debug!(tenant_id = %self.tenant_shard_id.tenant_id, shard_id = %self.tenant_shard_id.shard_slug(), "Activating tenant");
activating = true;
// Continue outside the closure. We need to grab timelines.lock()
// and we plan to turn it into a tokio::sync::Mutex in a future patch.
@@ -1809,7 +1841,8 @@ impl Tenant {
// times to activate. see https://github.com/neondatabase/neon/issues/4025
info!(
since_creation_millis = elapsed.as_millis(),
- tenant_id = %self.tenant_id,
+ tenant_id = %self.tenant_shard_id.tenant_id,
+ shard_id = %self.tenant_shard_id.shard_slug(),
activated_timelines,
total_timelines,
post_state = <&'static str>::from(&*current_state),
@@ -1906,7 +1939,7 @@ impl Tenant {
//
// this will additionally shutdown and await all timeline tasks.
tracing::debug!("Waiting for tasks...");
- task_mgr::shutdown_tasks(None, Some(self.tenant_id), None).await;
+ task_mgr::shutdown_tasks(None, Some(self.tenant_shard_id.tenant_id), None).await;
// Wait for any in-flight operations to complete
self.gate.close().await;
@@ -2081,7 +2114,7 @@ impl Tenant {
receiver.changed().await.map_err(
|_e: tokio::sync::watch::error::RecvError|
// Tenant existed but was dropped: report it as non-existent
- GetActiveTenantError::NotFound(GetTenantError::NotFound(self.tenant_id))
+ GetActiveTenantError::NotFound(GetTenantError::NotFound(self.tenant_shard_id.tenant_id))
)?;
}
TenantState::Active { .. } => {
@@ -2155,9 +2188,6 @@ where
}
impl Tenant {
- pub fn get_tenant_id(&self) -> TenantId {
- self.tenant_id
- }
pub fn tenant_specific_overrides(&self) -> TenantConfOpt {
self.tenant_conf.read().unwrap().tenant_conf
}
@@ -2307,7 +2337,7 @@ impl Tenant {
new_metadata,
ancestor,
new_timeline_id,
- self.tenant_id,
+ self.tenant_shard_id,
self.generation,
Arc::clone(&self.walredo_mgr),
resources,
@@ -2329,14 +2359,14 @@ impl Tenant {
conf: &'static PageServerConf,
attached_conf: AttachedTenantConf,
walredo_mgr: Arc,
- tenant_id: TenantId,
+ tenant_shard_id: TenantShardId,
remote_storage: Option,
deletion_queue_client: DeletionQueueClient,
) -> Tenant {
let (state, mut rx) = watch::channel(state);
tokio::spawn(async move {
- let tid = tenant_id.to_string();
+ let tid = tenant_shard_id.to_string();
fn inspect_state(state: &TenantState) -> ([&'static str; 1], bool) {
([state.into()], matches!(state, TenantState::Broken { .. }))
@@ -2388,7 +2418,7 @@ impl Tenant {
});
Tenant {
- tenant_id,
+ tenant_shard_id,
generation: attached_conf.location.generation,
conf,
// using now here is good enough approximation to catch tenants with really long
@@ -2406,17 +2436,17 @@ impl Tenant {
eviction_task_tenant_state: tokio::sync::Mutex::new(EvictionTaskTenantState::default()),
delete_progress: Arc::new(tokio::sync::Mutex::new(DeleteTenantFlow::default())),
cancel: CancellationToken::default(),
- gate: Gate::new(format!("Tenant<{tenant_id}>")),
+ gate: Gate::new(format!("Tenant<{tenant_shard_id}>")),
}
}
/// Locate and load config
pub(super) fn load_tenant_config(
conf: &'static PageServerConf,
- tenant_id: &TenantId,
+ tenant_shard_id: &TenantShardId,
) -> anyhow::Result {
- let legacy_config_path = conf.tenant_config_path(tenant_id);
- let config_path = conf.tenant_location_config_path(tenant_id);
+ let legacy_config_path = conf.tenant_config_path(tenant_shard_id);
+ let config_path = conf.tenant_location_config_path(tenant_shard_id);
if config_path.exists() {
// New-style config takes precedence
@@ -2430,9 +2460,7 @@ impl Tenant {
for (key, item) in deserialized.iter() {
match key {
"tenant_config" => {
- tenant_conf = PageServerConf::parse_toml_tenant_conf(item).with_context(|| {
- format!("Failed to parse config from file '{legacy_config_path}' as pageserver config")
- })?;
+ tenant_conf = TenantConfOpt::try_from(item.to_owned()).context(format!("Failed to parse config from file '{legacy_config_path}' as pageserver config"))?;
}
_ => bail!(
"config file {legacy_config_path} has unrecognized pageserver option '{key}'"
@@ -2470,29 +2498,34 @@ impl Tenant {
.with_context(|| format!("Failed to parse config from file '{path}' as toml file"))
}
- #[tracing::instrument(skip_all, fields(%tenant_id))]
+ #[tracing::instrument(skip_all, fields(tenant_id=%tenant_shard_id.tenant_id, shard_id=%tenant_shard_id.shard_slug()))]
pub(super) async fn persist_tenant_config(
conf: &'static PageServerConf,
- tenant_id: &TenantId,
+ tenant_shard_id: &TenantShardId,
location_conf: &LocationConf,
) -> anyhow::Result<()> {
- let legacy_config_path = conf.tenant_config_path(tenant_id);
- let config_path = conf.tenant_location_config_path(tenant_id);
+ let legacy_config_path = conf.tenant_config_path(tenant_shard_id);
+ let config_path = conf.tenant_location_config_path(tenant_shard_id);
- Self::persist_tenant_config_at(tenant_id, &config_path, &legacy_config_path, location_conf)
- .await
+ Self::persist_tenant_config_at(
+ tenant_shard_id,
+ &config_path,
+ &legacy_config_path,
+ location_conf,
+ )
+ .await
}
- #[tracing::instrument(skip_all, fields(%tenant_id))]
+ #[tracing::instrument(skip_all, fields(tenant_id=%tenant_shard_id.tenant_id, shard_id=%tenant_shard_id.shard_slug()))]
pub(super) async fn persist_tenant_config_at(
- tenant_id: &TenantId,
+ tenant_shard_id: &TenantShardId,
config_path: &Utf8Path,
legacy_config_path: &Utf8Path,
location_conf: &LocationConf,
) -> anyhow::Result<()> {
// Forward compat: write out an old-style configuration that old versions can read, in case we roll back
Self::persist_tenant_config_legacy(
- tenant_id,
+ tenant_shard_id,
legacy_config_path,
&location_conf.tenant_conf,
)
@@ -2519,14 +2552,16 @@ impl Tenant {
let temp_path = path_with_suffix_extension(config_path, TEMP_FILE_SUFFIX);
- let tenant_id = *tenant_id;
+ let tenant_shard_id = *tenant_shard_id;
let config_path = config_path.to_owned();
tokio::task::spawn_blocking(move || {
Handle::current().block_on(async move {
let conf_content = conf_content.as_bytes();
VirtualFile::crashsafe_overwrite(&config_path, &temp_path, conf_content)
.await
- .with_context(|| format!("write tenant {tenant_id} config to {config_path}"))
+ .with_context(|| {
+ format!("write tenant {tenant_shard_id} config to {config_path}")
+ })
})
})
.await??;
@@ -2534,9 +2569,9 @@ impl Tenant {
Ok(())
}
- #[tracing::instrument(skip_all, fields(%tenant_id))]
+ #[tracing::instrument(skip_all, fields(tenant_id=%tenant_shard_id.tenant_id, shard_id=%tenant_shard_id.shard_slug()))]
async fn persist_tenant_config_legacy(
- tenant_id: &TenantId,
+ tenant_shard_id: &TenantShardId,
target_config_path: &Utf8Path,
tenant_conf: &TenantConfOpt,
) -> anyhow::Result<()> {
@@ -2554,7 +2589,7 @@ impl Tenant {
let temp_path = path_with_suffix_extension(target_config_path, TEMP_FILE_SUFFIX);
- let tenant_id = *tenant_id;
+ let tenant_shard_id = *tenant_shard_id;
let target_config_path = target_config_path.to_owned();
tokio::task::spawn_blocking(move || {
Handle::current().block_on(async move {
@@ -2562,7 +2597,7 @@ impl Tenant {
VirtualFile::crashsafe_overwrite(&target_config_path, &temp_path, conf_content)
.await
.with_context(|| {
- format!("write tenant {tenant_id} config to {target_config_path}")
+ format!("write tenant {tenant_shard_id} config to {target_config_path}")
})
})
})
@@ -2930,6 +2965,7 @@ impl Tenant {
&self,
timeline_id: TimelineId,
pg_version: u32,
+ load_existing_initdb: Option,
ctx: &RequestContext,
) -> anyhow::Result> {
let timeline_uninit_mark = {
@@ -2940,7 +2976,7 @@ impl Tenant {
// temporary directory for basebackup files for the given timeline.
let pgdata_path = path_with_suffix_extension(
self.conf
- .timelines_path(&self.tenant_id)
+ .timelines_path(&self.tenant_shard_id)
.join(format!("basebackup-{timeline_id}")),
TEMP_FILE_SUFFIX,
);
@@ -2952,8 +2988,6 @@ impl Tenant {
format!("Failed to remove already existing initdb directory: {pgdata_path}")
})?;
}
- // Init temporarily repo to get bootstrap data, this creates a directory in the `initdb_path` path
- run_initdb(self.conf, &pgdata_path, pg_version, &self.cancel).await?;
// this new directory is very temporary, set to remove it immediately after bootstrap, we don't need it
scopeguard::defer! {
if let Err(e) = fs::remove_dir_all(&pgdata_path) {
@@ -2961,31 +2995,58 @@ impl Tenant {
error!("Failed to remove temporary initdb directory '{pgdata_path}': {e}");
}
}
- let pgdata_lsn = import_datadir::get_lsn_from_controlfile(&pgdata_path)?.align();
+ if let Some(existing_initdb_timeline_id) = load_existing_initdb {
+ let Some(storage) = &self.remote_storage else {
+ bail!("no storage configured but load_existing_initdb set to {existing_initdb_timeline_id}");
+ };
+ let (initdb_tar_zst_path, initdb_tar_zst) =
+ self::remote_timeline_client::download_initdb_tar_zst(
+ self.conf,
+ storage,
+ &self.tenant_shard_id,
+ &existing_initdb_timeline_id,
+ )
+ .await
+ .context("download initdb tar")?;
+ let buf_read = Box::pin(BufReader::new(initdb_tar_zst));
+ import_datadir::extract_tar_zst(&pgdata_path, buf_read)
+ .await
+ .context("extract initdb tar")?;
- // Upload the created data dir to S3
- if let Some(storage) = &self.remote_storage {
- let pgdata_zstd = import_datadir::create_tar_zst(&pgdata_path).await?;
- let pgdata_zstd = Bytes::from(pgdata_zstd);
- backoff::retry(
- || async {
- self::remote_timeline_client::upload_initdb_dir(
- storage,
- &self.tenant_id,
- &timeline_id,
- pgdata_zstd.clone(),
- )
+ if initdb_tar_zst_path.exists() {
+ tokio::fs::remove_file(&initdb_tar_zst_path)
.await
- },
- |_| false,
- 3,
- u32::MAX,
- "persist_initdb_tar_zst",
- // TODO: use a cancellation token (https://github.com/neondatabase/neon/issues/5066)
- backoff::Cancel::new(CancellationToken::new(), || unreachable!()),
- )
- .await?;
+ .context("tempfile removal")?;
+ }
+ } else {
+ // Init temporarily repo to get bootstrap data, this creates a directory in the `initdb_path` path
+ run_initdb(self.conf, &pgdata_path, pg_version, &self.cancel).await?;
+
+ // Upload the created data dir to S3
+ if let Some(storage) = &self.remote_storage {
+ let pgdata_zstd = import_datadir::create_tar_zst(&pgdata_path).await?;
+ let pgdata_zstd = Bytes::from(pgdata_zstd);
+ backoff::retry(
+ || async {
+ self::remote_timeline_client::upload_initdb_dir(
+ storage,
+ &self.tenant_shard_id.tenant_id,
+ &timeline_id,
+ pgdata_zstd.clone(),
+ )
+ .await
+ },
+ |_| false,
+ 3,
+ u32::MAX,
+ "persist_initdb_tar_zst",
+ // TODO: use a cancellation token (https://github.com/neondatabase/neon/issues/5066)
+ backoff::Cancel::new(CancellationToken::new(), || unreachable!()),
+ )
+ .await?;
+ }
}
+ let pgdata_lsn = import_datadir::get_lsn_from_controlfile(&pgdata_path)?.align();
// Import the contents of the data directory at the initial checkpoint
// LSN, and any WAL after that.
@@ -3010,7 +3071,7 @@ impl Tenant {
)
.await?;
- let tenant_id = raw_timeline.owning_tenant.tenant_id;
+ let tenant_shard_id = raw_timeline.owning_tenant.tenant_shard_id;
let unfinished_timeline = raw_timeline.raw_timeline()?;
import_datadir::import_timeline_from_postgres_datadir(
@@ -3021,7 +3082,7 @@ impl Tenant {
)
.await
.with_context(|| {
- format!("Failed to import pgdatadir for timeline {tenant_id}/{timeline_id}")
+ format!("Failed to import pgdatadir for timeline {tenant_shard_id}/{timeline_id}")
})?;
// Flush the new layer files to disk, before we make the timeline as available to
@@ -3039,7 +3100,7 @@ impl Tenant {
.await
.with_context(|| {
format!(
- "Failed to flush after pgdatadir import for timeline {tenant_id}/{timeline_id}"
+ "Failed to flush after pgdatadir import for timeline {tenant_shard_id}/{timeline_id}"
)
})?;
@@ -3062,7 +3123,7 @@ impl Tenant {
remote_storage.clone(),
self.deletion_queue_client.clone(),
self.conf,
- self.tenant_id,
+ self.tenant_shard_id,
timeline_id,
self.generation,
);
@@ -3091,7 +3152,7 @@ impl Tenant {
start_lsn: Lsn,
ancestor: Option>,
) -> anyhow::Result {
- let tenant_id = self.tenant_id;
+ let tenant_shard_id = self.tenant_shard_id;
let resources = self.build_timeline_resources(new_timeline_id);
if let Some(remote_client) = &resources.remote_client {
@@ -3115,12 +3176,14 @@ impl Tenant {
.create_timeline_files(&uninit_mark.timeline_path, &new_timeline_id, new_metadata)
.await
{
- error!("Failed to create initial files for timeline {tenant_id}/{new_timeline_id}, cleaning up: {e:?}");
+ error!("Failed to create initial files for timeline {tenant_shard_id}/{new_timeline_id}, cleaning up: {e:?}");
cleanup_timeline_directory(uninit_mark);
return Err(e);
}
- debug!("Successfully created initial files for timeline {tenant_id}/{new_timeline_id}");
+ debug!(
+ "Successfully created initial files for timeline {tenant_shard_id}/{new_timeline_id}"
+ );
Ok(UninitializedTimeline::new(
self,
@@ -3141,9 +3204,14 @@ impl Tenant {
anyhow::bail!("failpoint after-timeline-uninit-mark-creation");
});
- save_metadata(self.conf, &self.tenant_id, new_timeline_id, new_metadata)
- .await
- .context("Failed to create timeline metadata")?;
+ save_metadata(
+ self.conf,
+ &self.tenant_shard_id,
+ new_timeline_id,
+ new_metadata,
+ )
+ .await
+ .context("Failed to create timeline metadata")?;
Ok(())
}
@@ -3156,13 +3224,13 @@ impl Tenant {
timeline_id: TimelineId,
timelines: &MutexGuard>>,
) -> anyhow::Result {
- let tenant_id = self.tenant_id;
+ let tenant_shard_id = self.tenant_shard_id;
anyhow::ensure!(
timelines.get(&timeline_id).is_none(),
- "Timeline {tenant_id}/{timeline_id} already exists in pageserver's memory"
+ "Timeline {tenant_shard_id}/{timeline_id} already exists in pageserver's memory"
);
- let timeline_path = self.conf.timeline_path(&tenant_id, &timeline_id);
+ let timeline_path = self.conf.timeline_path(&tenant_shard_id, &timeline_id);
anyhow::ensure!(
!timeline_path.exists(),
"Timeline {timeline_path} already exists, cannot create its uninit mark file",
@@ -3170,7 +3238,7 @@ impl Tenant {
let uninit_mark_path = self
.conf
- .timeline_uninit_mark_file_path(tenant_id, timeline_id);
+ .timeline_uninit_mark_file_path(tenant_shard_id, timeline_id);
fs::File::create(&uninit_mark_path)
.context("Failed to create uninit mark file")
.and_then(|_| {
@@ -3178,7 +3246,7 @@ impl Tenant {
.context("Failed to fsync uninit mark file")
})
.with_context(|| {
- format!("Failed to crate uninit mark for timeline {tenant_id}/{timeline_id}")
+ format!("Failed to crate uninit mark for timeline {tenant_shard_id}/{timeline_id}")
})?;
let uninit_mark = TimelineUninitMark::new(uninit_mark_path, timeline_path);
@@ -3189,7 +3257,7 @@ impl Tenant {
/// Gathers inputs from all of the timelines to produce a sizing model input.
///
/// Future is cancellation safe. Only one calculation can be running at once per tenant.
- #[instrument(skip_all, fields(tenant_id=%self.tenant_id))]
+ #[instrument(skip_all, fields(tenant_id=%self.tenant_shard_id.tenant_id, shard_id=%self.tenant_shard_id.shard_slug()))]
pub async fn gather_size_inputs(
&self,
// `max_retention_period` overrides the cutoff that is used to calculate the size
@@ -3228,7 +3296,7 @@ impl Tenant {
/// Calculate synthetic tenant size and cache the result.
/// This is periodically called by background worker.
/// result is cached in tenant struct
- #[instrument(skip_all, fields(tenant_id=%self.tenant_id))]
+ #[instrument(skip_all, fields(tenant_id=%self.tenant_shard_id.tenant_id, shard_id=%self.tenant_shard_id.shard_slug()))]
pub async fn calculate_synthetic_size(
&self,
cause: LogicalSizeCalculationCause,
@@ -3250,7 +3318,7 @@ impl Tenant {
.store(size, Ordering::Relaxed);
TENANT_SYNTHETIC_SIZE_METRIC
- .get_metric_with_label_values(&[&self.tenant_id.to_string()])
+ .get_metric_with_label_values(&[&self.tenant_shard_id.tenant_id.to_string()])
.unwrap()
.set(size);
}
@@ -3258,6 +3326,66 @@ impl Tenant {
pub fn cached_synthetic_size(&self) -> u64 {
self.cached_synthetic_tenant_size.load(Ordering::Relaxed)
}
+
+ /// Flush any in-progress layers, schedule uploads, and wait for uploads to complete.
+ ///
+ /// This function can take a long time: callers should wrap it in a timeout if calling
+ /// from an external API handler.
+ ///
+ /// Cancel-safety: cancelling this function may leave I/O running, but such I/O is
+ /// still bounded by tenant/timeline shutdown.
+ #[tracing::instrument(skip_all)]
+ pub(crate) async fn flush_remote(&self) -> anyhow::Result<()> {
+ let timelines = self.timelines.lock().unwrap().clone();
+
+ async fn flush_timeline(_gate: GateGuard, timeline: Arc) -> anyhow::Result<()> {
+ tracing::info!(timeline_id=%timeline.timeline_id, "Flushing...");
+ timeline.freeze_and_flush().await?;
+ tracing::info!(timeline_id=%timeline.timeline_id, "Waiting for uploads...");
+ if let Some(client) = &timeline.remote_client {
+ client.wait_completion().await?;
+ }
+
+ Ok(())
+ }
+
+ // We do not use a JoinSet for these tasks, because we don't want them to be
+ // aborted when this function's future is cancelled: they should stay alive
+ // holding their GateGuard until they complete, to ensure their I/Os complete
+ // before Timeline shutdown completes.
+ let mut results = FuturesUnordered::new();
+
+ for (_timeline_id, timeline) in timelines {
+ // Run each timeline's flush in a task holding the timeline's gate: this
+ // means that if this function's future is cancelled, the Timeline shutdown
+ // will still wait for any I/O in here to complete.
+ let gate = match timeline.gate.enter() {
+ Ok(g) => g,
+ Err(_) => continue,
+ };
+ let jh = tokio::task::spawn(async move { flush_timeline(gate, timeline).await });
+ results.push(jh);
+ }
+
+ while let Some(r) = results.next().await {
+ if let Err(e) = r {
+ if !e.is_cancelled() && !e.is_panic() {
+ tracing::error!("unexpected join error: {e:?}");
+ }
+ }
+ }
+
+ // The flushes we did above were just writes, but the Tenant might have had
+ // pending deletions as well from recent compaction/gc: we want to flush those
+ // as well. This requires flushing the global delete queue. This is cheap
+ // because it's typically a no-op.
+ match self.deletion_queue_client.flush_execute().await {
+ Ok(_) => {}
+ Err(DeletionQueueError::ShuttingDown) => {}
+ }
+
+ Ok(())
+ }
}
fn remove_timeline_and_uninit_mark(
@@ -3286,9 +3414,9 @@ fn remove_timeline_and_uninit_mark(
pub(crate) async fn create_tenant_files(
conf: &'static PageServerConf,
location_conf: &LocationConf,
- tenant_id: &TenantId,
+ tenant_shard_id: &TenantShardId,
) -> anyhow::Result {
- let target_tenant_directory = conf.tenant_path(tenant_id);
+ let target_tenant_directory = conf.tenant_path(tenant_shard_id);
anyhow::ensure!(
!target_tenant_directory
.try_exists()
@@ -3308,14 +3436,16 @@ pub(crate) async fn create_tenant_files(
let creation_result = try_create_target_tenant_dir(
conf,
location_conf,
- tenant_id,
+ tenant_shard_id,
&temporary_tenant_dir,
&target_tenant_directory,
)
.await;
if creation_result.is_err() {
- error!("Failed to create directory structure for tenant {tenant_id}, cleaning tmp data");
+ error!(
+ "Failed to create directory structure for tenant {tenant_shard_id}, cleaning tmp data"
+ );
if let Err(e) = fs::remove_dir_all(&temporary_tenant_dir) {
error!("Failed to remove temporary tenant directory {temporary_tenant_dir:?}: {e}")
} else if let Err(e) = crashsafe::fsync(&temporary_tenant_dir) {
@@ -3333,31 +3463,31 @@ pub(crate) async fn create_tenant_files(
async fn try_create_target_tenant_dir(
conf: &'static PageServerConf,
location_conf: &LocationConf,
- tenant_id: &TenantId,
+ tenant_shard_id: &TenantShardId,
temporary_tenant_dir: &Utf8Path,
target_tenant_directory: &Utf8Path,
) -> Result<(), anyhow::Error> {
let temporary_tenant_timelines_dir = rebase_directory(
- &conf.timelines_path(tenant_id),
+ &conf.timelines_path(tenant_shard_id),
target_tenant_directory,
temporary_tenant_dir,
)
- .with_context(|| format!("resolve tenant {tenant_id} temporary timelines dir"))?;
+ .with_context(|| format!("resolve tenant {tenant_shard_id} temporary timelines dir"))?;
let temporary_legacy_tenant_config_path = rebase_directory(
- &conf.tenant_config_path(tenant_id),
+ &conf.tenant_config_path(tenant_shard_id),
target_tenant_directory,
temporary_tenant_dir,
)
- .with_context(|| format!("resolve tenant {tenant_id} temporary config path"))?;
+ .with_context(|| format!("resolve tenant {tenant_shard_id} temporary config path"))?;
let temporary_tenant_config_path = rebase_directory(
- &conf.tenant_location_config_path(tenant_id),
+ &conf.tenant_location_config_path(tenant_shard_id),
target_tenant_directory,
temporary_tenant_dir,
)
- .with_context(|| format!("resolve tenant {tenant_id} temporary config path"))?;
+ .with_context(|| format!("resolve tenant {tenant_shard_id} temporary config path"))?;
Tenant::persist_tenant_config_at(
- tenant_id,
+ tenant_shard_id,
&temporary_tenant_config_path,
&temporary_legacy_tenant_config_path,
location_conf,
@@ -3367,7 +3497,7 @@ async fn try_create_target_tenant_dir(
crashsafe::create_dir(&temporary_tenant_timelines_dir).with_context(|| {
format!(
"create tenant {} temporary timelines directory {}",
- tenant_id, temporary_tenant_timelines_dir,
+ tenant_shard_id, temporary_tenant_timelines_dir,
)
})?;
fail::fail_point!("tenant-creation-before-tmp-rename", |_| {
@@ -3382,19 +3512,19 @@ async fn try_create_target_tenant_dir(
fs::rename(temporary_tenant_dir, target_tenant_directory).with_context(|| {
format!(
"move tenant {} temporary directory {} into the permanent one {}",
- tenant_id, temporary_tenant_dir, target_tenant_directory
+ tenant_shard_id, temporary_tenant_dir, target_tenant_directory
)
})?;
let target_dir_parent = target_tenant_directory.parent().with_context(|| {
format!(
"get tenant {} dir parent for {}",
- tenant_id, target_tenant_directory,
+ tenant_shard_id, target_tenant_directory,
)
})?;
crashsafe::fsync(target_dir_parent).with_context(|| {
format!(
"fsync renamed directory's parent {} for tenant {}",
- target_dir_parent, tenant_id,
+ target_dir_parent, tenant_shard_id,
)
})?;
@@ -3472,7 +3602,7 @@ async fn run_initdb(
impl Drop for Tenant {
fn drop(&mut self) {
- remove_tenant_metrics(&self.tenant_id);
+ remove_tenant_metrics(&self.tenant_shard_id.tenant_id);
}
}
/// Dump contents of a layer file to stdout.
@@ -3575,7 +3705,9 @@ pub(crate) mod harness {
pub struct TenantHarness {
pub conf: &'static PageServerConf,
pub tenant_conf: TenantConf,
- pub tenant_id: TenantId,
+ // TODO(sharding): remove duplicative `tenant_id` in favor of access to tenant_shard_id
+ pub(crate) tenant_id: TenantId,
+ pub tenant_shard_id: TenantShardId,
pub generation: Generation,
pub shard: ShardIndex,
pub remote_storage: GenericRemoteStorage,
@@ -3620,8 +3752,9 @@ pub(crate) mod harness {
};
let tenant_id = TenantId::generate();
- fs::create_dir_all(conf.tenant_path(&tenant_id))?;
- fs::create_dir_all(conf.timelines_path(&tenant_id))?;
+ let tenant_shard_id = TenantShardId::unsharded(tenant_id);
+ fs::create_dir_all(conf.tenant_path(&tenant_shard_id))?;
+ fs::create_dir_all(conf.timelines_path(&tenant_shard_id))?;
use remote_storage::{RemoteStorageConfig, RemoteStorageKind};
let remote_fs_dir = conf.workdir.join("localfs");
@@ -3636,6 +3769,7 @@ pub(crate) mod harness {
conf,
tenant_conf,
tenant_id,
+ tenant_shard_id,
generation: Generation::new(0xdeadbeef),
shard: ShardIndex::unsharded(),
remote_storage,
@@ -3655,7 +3789,7 @@ pub(crate) mod harness {
}
fn remote_empty(&self) -> bool {
- let tenant_path = self.conf.tenant_path(&self.tenant_id);
+ let tenant_path = self.conf.tenant_path(&self.tenant_shard_id);
let remote_tenant_dir = self
.remote_fs_dir
.join(tenant_path.strip_prefix(&self.conf.workdir).unwrap());
@@ -3695,7 +3829,7 @@ pub(crate) mod harness {
))
.unwrap(),
walredo_mgr,
- self.tenant_id,
+ self.tenant_shard_id,
Some(self.remote_storage.clone()),
self.deletion_queue.new_client(),
));
@@ -3704,17 +3838,17 @@ pub(crate) mod harness {
LoadMode::Local => {
tenant
.load_local(None, ctx)
- .instrument(info_span!("try_load", tenant_id=%self.tenant_id))
+ .instrument(info_span!("try_load", tenant_id=%self.tenant_shard_id.tenant_id, shard_id=%self.tenant_shard_id.shard_slug()))
.await?;
}
LoadMode::Remote => {
let preload = tenant
.preload(&self.remote_storage, CancellationToken::new())
- .instrument(info_span!("try_load_preload", tenant_id=%self.tenant_id))
+ .instrument(info_span!("try_load_preload", tenant_id=%self.tenant_shard_id.tenant_id, shard_id=%self.tenant_shard_id.shard_slug()))
.await?;
tenant
.attach(None, Some(preload), ctx)
- .instrument(info_span!("try_load", tenant_id=%self.tenant_id))
+ .instrument(info_span!("try_load", tenant_id=%self.tenant_shard_id.tenant_id, shard_id=%self.tenant_shard_id.shard_slug()))
.await?;
}
}
@@ -3748,7 +3882,7 @@ pub(crate) mod harness {
}
pub fn timeline_path(&self, timeline_id: &TimelineId) -> Utf8PathBuf {
- self.conf.timeline_path(&self.tenant_id, timeline_id)
+ self.conf.timeline_path(&self.tenant_shard_id, timeline_id)
}
}
@@ -3864,7 +3998,7 @@ mod tests {
e.to_string(),
format!(
"Timeline {}/{} already exists in pageserver's memory",
- tenant.tenant_id, TIMELINE_ID
+ tenant.tenant_shard_id, TIMELINE_ID
)
),
}
@@ -4248,7 +4382,7 @@ mod tests {
// so that all uploads finish & we can call harness.load() below again
tenant
.shutdown(Default::default(), true)
- .instrument(info_span!("test_shutdown", tenant_id=%tenant.tenant_id))
+ .instrument(info_span!("test_shutdown", tenant_id=%tenant.tenant_shard_id))
.await
.ok()
.unwrap();
@@ -4289,7 +4423,7 @@ mod tests {
// so that all uploads finish & we can call harness.load() below again
tenant
.shutdown(Default::default(), true)
- .instrument(info_span!("test_shutdown", tenant_id=%tenant.tenant_id))
+ .instrument(info_span!("test_shutdown", tenant_id=%tenant.tenant_shard_id))
.await
.ok()
.unwrap();
@@ -4351,7 +4485,7 @@ mod tests {
// so that all uploads finish & we can call harness.try_load() below again
tenant
.shutdown(Default::default(), true)
- .instrument(info_span!("test_shutdown", tenant_id=%tenant.tenant_id))
+ .instrument(info_span!("test_shutdown", tenant_id=%tenant.tenant_shard_id))
.await
.ok()
.unwrap();
@@ -4884,7 +5018,7 @@ mod tests {
let raw_tline = tline.raw_timeline().unwrap();
raw_tline
.shutdown()
- .instrument(info_span!("test_shutdown", tenant_id=%raw_tline.tenant_id))
+ .instrument(info_span!("test_shutdown", tenant_id=%raw_tline.tenant_shard_id))
.await;
std::mem::forget(tline);
}
@@ -4896,7 +5030,7 @@ mod tests {
assert_eq!(
e,
GetTimelineError::NotFound {
- tenant_id: tenant.tenant_id,
+ tenant_id: tenant.tenant_shard_id.tenant_id,
timeline_id: TIMELINE_ID,
}
)
@@ -4905,12 +5039,12 @@ mod tests {
assert!(!harness
.conf
- .timeline_path(&tenant.tenant_id, &TIMELINE_ID)
+ .timeline_path(&tenant.tenant_shard_id, &TIMELINE_ID)
.exists());
assert!(!harness
.conf
- .timeline_uninit_mark_file_path(tenant.tenant_id, TIMELINE_ID)
+ .timeline_uninit_mark_file_path(tenant.tenant_shard_id, TIMELINE_ID)
.exists());
Ok(())
diff --git a/pageserver/src/tenant/config.rs b/pageserver/src/tenant/config.rs
index 4ad6a71f67..7a454b53d2 100644
--- a/pageserver/src/tenant/config.rs
+++ b/pageserver/src/tenant/config.rs
@@ -8,10 +8,12 @@
//! We cannot use global or default config instead, because wrong settings
//! may lead to a data loss.
//!
-use anyhow::Context;
+use anyhow::bail;
use pageserver_api::models;
use pageserver_api::shard::{ShardCount, ShardIdentity, ShardNumber, ShardStripeSize};
+use serde::de::IntoDeserializer;
use serde::{Deserialize, Serialize};
+use serde_json::Value;
use std::num::NonZeroU64;
use std::time::Duration;
use utils::generation::Generation;
@@ -521,105 +523,49 @@ impl Default for TenantConf {
}
}
-// Helper function to standardize the error messages we produce on bad durations
-//
-// Intended to be used with anyhow's `with_context`, e.g.:
-//
-// let value = result.with_context(bad_duration("name", &value))?;
-//
-fn bad_duration<'a>(field_name: &'static str, value: &'a str) -> impl 'a + Fn() -> String {
- move || format!("Cannot parse `{field_name}` duration {value:?}")
-}
-
impl TryFrom<&'_ models::TenantConfig> for TenantConfOpt {
type Error = anyhow::Error;
fn try_from(request_data: &'_ models::TenantConfig) -> Result {
- let mut tenant_conf = TenantConfOpt::default();
+ // Convert the request_data to a JSON Value
+ let json_value: Value = serde_json::to_value(request_data)?;
- if let Some(gc_period) = &request_data.gc_period {
- tenant_conf.gc_period = Some(
- humantime::parse_duration(gc_period)
- .with_context(bad_duration("gc_period", gc_period))?,
- );
- }
- tenant_conf.gc_horizon = request_data.gc_horizon;
- tenant_conf.image_creation_threshold = request_data.image_creation_threshold;
+ // Create a Deserializer from the JSON Value
+ let deserializer = json_value.into_deserializer();
- if let Some(pitr_interval) = &request_data.pitr_interval {
- tenant_conf.pitr_interval = Some(
- humantime::parse_duration(pitr_interval)
- .with_context(bad_duration("pitr_interval", pitr_interval))?,
- );
- }
-
- if let Some(walreceiver_connect_timeout) = &request_data.walreceiver_connect_timeout {
- tenant_conf.walreceiver_connect_timeout = Some(
- humantime::parse_duration(walreceiver_connect_timeout).with_context(
- bad_duration("walreceiver_connect_timeout", walreceiver_connect_timeout),
- )?,
- );
- }
- if let Some(lagging_wal_timeout) = &request_data.lagging_wal_timeout {
- tenant_conf.lagging_wal_timeout = Some(
- humantime::parse_duration(lagging_wal_timeout)
- .with_context(bad_duration("lagging_wal_timeout", lagging_wal_timeout))?,
- );
- }
- if let Some(max_lsn_wal_lag) = request_data.max_lsn_wal_lag {
- tenant_conf.max_lsn_wal_lag = Some(max_lsn_wal_lag);
- }
- if let Some(trace_read_requests) = request_data.trace_read_requests {
- tenant_conf.trace_read_requests = Some(trace_read_requests);
- }
-
- tenant_conf.checkpoint_distance = request_data.checkpoint_distance;
- if let Some(checkpoint_timeout) = &request_data.checkpoint_timeout {
- tenant_conf.checkpoint_timeout = Some(
- humantime::parse_duration(checkpoint_timeout)
- .with_context(bad_duration("checkpoint_timeout", checkpoint_timeout))?,
- );
- }
-
- tenant_conf.compaction_target_size = request_data.compaction_target_size;
- tenant_conf.compaction_threshold = request_data.compaction_threshold;
-
- if let Some(compaction_period) = &request_data.compaction_period {
- tenant_conf.compaction_period = Some(
- humantime::parse_duration(compaction_period)
- .with_context(bad_duration("compaction_period", compaction_period))?,
- );
- }
-
- if let Some(eviction_policy) = &request_data.eviction_policy {
- tenant_conf.eviction_policy = Some(
- serde::Deserialize::deserialize(eviction_policy)
- .context("parse field `eviction_policy`")?,
- );
- }
-
- tenant_conf.min_resident_size_override = request_data.min_resident_size_override;
-
- if let Some(evictions_low_residence_duration_metric_threshold) =
- &request_data.evictions_low_residence_duration_metric_threshold
- {
- tenant_conf.evictions_low_residence_duration_metric_threshold = Some(
- humantime::parse_duration(evictions_low_residence_duration_metric_threshold)
- .with_context(bad_duration(
- "evictions_low_residence_duration_metric_threshold",
- evictions_low_residence_duration_metric_threshold,
- ))?,
- );
- }
- tenant_conf.gc_feedback = request_data.gc_feedback;
+ // Use serde_path_to_error to deserialize the JSON Value into TenantConfOpt
+ let tenant_conf: TenantConfOpt = serde_path_to_error::deserialize(deserializer)?;
Ok(tenant_conf)
}
}
+impl TryFrom for TenantConfOpt {
+ type Error = anyhow::Error;
+
+ fn try_from(item: toml_edit::Item) -> Result {
+ match item {
+ toml_edit::Item::Value(value) => {
+ let d = value.into_deserializer();
+ return serde_path_to_error::deserialize(d)
+ .map_err(|e| anyhow::anyhow!("{}: {}", e.path(), e.inner().message()));
+ }
+ toml_edit::Item::Table(table) => {
+ let deserializer = toml_edit::de::Deserializer::new(table.into());
+ return serde_path_to_error::deserialize(deserializer)
+ .map_err(|e| anyhow::anyhow!("{}: {}", e.path(), e.inner().message()));
+ }
+ _ => {
+ bail!("expected non-inline table but found {item}")
+ }
+ }
+ }
+}
+
#[cfg(test)]
mod tests {
use super::*;
+ use models::TenantConfig;
#[test]
fn de_serializing_pageserver_config_omits_empty_values() {
@@ -636,4 +582,38 @@ mod tests {
assert_eq!(json_form, "{\"gc_horizon\":42}");
assert_eq!(small_conf, serde_json::from_str(&json_form).unwrap());
}
+
+ #[test]
+ fn test_try_from_models_tenant_config_err() {
+ let tenant_config = models::TenantConfig {
+ lagging_wal_timeout: Some("5a".to_string()),
+ ..TenantConfig::default()
+ };
+
+ let tenant_conf_opt = TenantConfOpt::try_from(&tenant_config);
+
+ assert!(
+ tenant_conf_opt.is_err(),
+ "Suceeded to convert TenantConfig to TenantConfOpt"
+ );
+
+ let expected_error_str =
+ "lagging_wal_timeout: invalid value: string \"5a\", expected a duration";
+ assert_eq!(tenant_conf_opt.unwrap_err().to_string(), expected_error_str);
+ }
+
+ #[test]
+ fn test_try_from_models_tenant_config_success() {
+ let tenant_config = models::TenantConfig {
+ lagging_wal_timeout: Some("5s".to_string()),
+ ..TenantConfig::default()
+ };
+
+ let tenant_conf_opt = TenantConfOpt::try_from(&tenant_config).unwrap();
+
+ assert_eq!(
+ tenant_conf_opt.lagging_wal_timeout,
+ Some(Duration::from_secs(5))
+ );
+ }
}
diff --git a/pageserver/src/tenant/delete.rs b/pageserver/src/tenant/delete.rs
index 066f239ff0..b7b2ef9c79 100644
--- a/pageserver/src/tenant/delete.rs
+++ b/pageserver/src/tenant/delete.rs
@@ -2,21 +2,19 @@ use std::sync::Arc;
use anyhow::Context;
use camino::{Utf8Path, Utf8PathBuf};
-use pageserver_api::models::TenantState;
+use pageserver_api::{models::TenantState, shard::TenantShardId};
use remote_storage::{GenericRemoteStorage, RemotePath};
use tokio::sync::OwnedMutexGuard;
use tokio_util::sync::CancellationToken;
-use tracing::{error, instrument, warn, Instrument, Span};
+use tracing::{error, instrument, Instrument, Span};
-use utils::{
- backoff, completion, crashsafe, fs_ext,
- id::{TenantId, TimelineId},
-};
+use utils::{backoff, completion, crashsafe, fs_ext, id::TimelineId};
use crate::{
config::PageServerConf,
context::RequestContext,
task_mgr::{self, TaskKind},
+ tenant::mgr::{TenantSlot, TenantsMapRemoveResult},
InitializationOrder,
};
@@ -59,10 +57,10 @@ type DeletionGuard = tokio::sync::OwnedMutexGuard;
fn remote_tenant_delete_mark_path(
conf: &PageServerConf,
- tenant_id: &TenantId,
+ tenant_shard_id: &TenantShardId,
) -> anyhow::Result {
let tenant_remote_path = conf
- .tenant_path(tenant_id)
+ .tenant_path(tenant_shard_id)
.strip_prefix(&conf.workdir)
.context("Failed to strip workdir prefix")
.and_then(RemotePath::new)
@@ -73,9 +71,9 @@ fn remote_tenant_delete_mark_path(
async fn create_remote_delete_mark(
conf: &PageServerConf,
remote_storage: &GenericRemoteStorage,
- tenant_id: &TenantId,
+ tenant_shard_id: &TenantShardId,
) -> Result<(), DeleteTenantError> {
- let remote_mark_path = remote_tenant_delete_mark_path(conf, tenant_id)?;
+ let remote_mark_path = remote_tenant_delete_mark_path(conf, tenant_shard_id)?;
let data: &[u8] = &[];
backoff::retry(
@@ -99,9 +97,9 @@ async fn create_remote_delete_mark(
async fn create_local_delete_mark(
conf: &PageServerConf,
- tenant_id: &TenantId,
+ tenant_shard_id: &TenantShardId,
) -> Result<(), DeleteTenantError> {
- let marker_path = conf.tenant_deleted_mark_file_path(tenant_id);
+ let marker_path = conf.tenant_deleted_mark_file_path(tenant_shard_id);
// Note: we're ok to replace existing file.
let _ = std::fs::OpenOptions::new()
@@ -170,10 +168,10 @@ async fn ensure_timelines_dir_empty(timelines_path: &Utf8Path) -> Result<(), Del
async fn remove_tenant_remote_delete_mark(
conf: &PageServerConf,
remote_storage: Option<&GenericRemoteStorage>,
- tenant_id: &TenantId,
+ tenant_shard_id: &TenantShardId,
) -> Result<(), DeleteTenantError> {
if let Some(remote_storage) = remote_storage {
- let path = remote_tenant_delete_mark_path(conf, tenant_id)?;
+ let path = remote_tenant_delete_mark_path(conf, tenant_shard_id)?;
backoff::retry(
|| async { remote_storage.delete(&path).await },
|_e| false,
@@ -192,7 +190,7 @@ async fn remove_tenant_remote_delete_mark(
// Cleanup fs traces: tenant config, timelines dir local delete mark, tenant dir
async fn cleanup_remaining_fs_traces(
conf: &PageServerConf,
- tenant_id: &TenantId,
+ tenant_shard_id: &TenantShardId,
) -> Result<(), DeleteTenantError> {
let rm = |p: Utf8PathBuf, is_dir: bool| async move {
if is_dir {
@@ -204,8 +202,8 @@ async fn cleanup_remaining_fs_traces(
.with_context(|| format!("failed to delete {p}"))
};
- rm(conf.tenant_config_path(tenant_id), false).await?;
- rm(conf.tenant_location_config_path(tenant_id), false).await?;
+ rm(conf.tenant_config_path(tenant_shard_id), false).await?;
+ rm(conf.tenant_location_config_path(tenant_shard_id), false).await?;
fail::fail_point!("tenant-delete-before-remove-timelines-dir", |_| {
Err(anyhow::anyhow!(
@@ -213,7 +211,7 @@ async fn cleanup_remaining_fs_traces(
))?
});
- rm(conf.timelines_path(tenant_id), true).await?;
+ rm(conf.timelines_path(tenant_shard_id), true).await?;
fail::fail_point!("tenant-delete-before-remove-deleted-mark", |_| {
Err(anyhow::anyhow!(
@@ -227,14 +225,14 @@ async fn cleanup_remaining_fs_traces(
// to be reordered later and thus missed if a crash occurs.
// Note that we dont need to sync after mark file is removed
// because we can tolerate the case when mark file reappears on startup.
- let tenant_path = &conf.tenant_path(tenant_id);
+ let tenant_path = &conf.tenant_path(tenant_shard_id);
if tenant_path.exists() {
- crashsafe::fsync_async(&conf.tenant_path(tenant_id))
+ crashsafe::fsync_async(&conf.tenant_path(tenant_shard_id))
.await
.context("fsync_pre_mark_remove")?;
}
- rm(conf.tenant_deleted_mark_file_path(tenant_id), false).await?;
+ rm(conf.tenant_deleted_mark_file_path(tenant_shard_id), false).await?;
fail::fail_point!("tenant-delete-before-remove-tenant-dir", |_| {
Err(anyhow::anyhow!(
@@ -242,7 +240,7 @@ async fn cleanup_remaining_fs_traces(
))?
});
- rm(conf.tenant_path(tenant_id), true).await?;
+ rm(conf.tenant_path(tenant_shard_id), true).await?;
Ok(())
}
@@ -287,6 +285,8 @@ impl DeleteTenantFlow {
) -> Result<(), DeleteTenantError> {
span::debug_assert_current_span_has_tenant_id();
+ pausable_failpoint!("tenant-delete-before-run");
+
let mut guard = Self::prepare(&tenant).await?;
if let Err(e) = Self::run_inner(&mut guard, conf, remote_storage.as_ref(), &tenant).await {
@@ -321,7 +321,7 @@ impl DeleteTenantFlow {
// Though sounds scary, different mark name?
// Detach currently uses remove_dir_all so in case of a crash we can end up in a weird state.
if let Some(remote_storage) = &remote_storage {
- create_remote_delete_mark(conf, remote_storage, &tenant.tenant_id)
+ create_remote_delete_mark(conf, remote_storage, &tenant.tenant_shard_id)
.await
.context("remote_mark")?
}
@@ -332,7 +332,7 @@ impl DeleteTenantFlow {
))?
});
- create_local_delete_mark(conf, &tenant.tenant_id)
+ create_local_delete_mark(conf, &tenant.tenant_shard_id)
.await
.context("local delete mark")?;
@@ -374,9 +374,11 @@ impl DeleteTenantFlow {
return Ok(acquire(tenant));
}
- let tenant_id = tenant.tenant_id;
// Check local mark first, if its there there is no need to go to s3 to check whether remote one exists.
- if conf.tenant_deleted_mark_file_path(&tenant_id).exists() {
+ if conf
+ .tenant_deleted_mark_file_path(&tenant.tenant_shard_id)
+ .exists()
+ {
Ok(acquire(tenant))
} else {
Ok(None)
@@ -459,12 +461,12 @@ impl DeleteTenantFlow {
tenants: &'static std::sync::RwLock,
tenant: Arc,
) {
- let tenant_id = tenant.tenant_id;
+ let tenant_shard_id = tenant.tenant_shard_id;
task_mgr::spawn(
task_mgr::BACKGROUND_RUNTIME.handle(),
TaskKind::TimelineDeletionWorker,
- Some(tenant_id),
+ Some(tenant_shard_id.tenant_id),
None,
"tenant_delete",
false,
@@ -478,7 +480,7 @@ impl DeleteTenantFlow {
Ok(())
}
.instrument({
- let span = tracing::info_span!(parent: None, "delete_tenant", tenant_id=%tenant_id);
+ let span = tracing::info_span!(parent: None, "delete_tenant", tenant_id=%tenant_shard_id.tenant_id, shard_id=%tenant_shard_id.shard_slug());
span.follows_from(Span::current());
span
}),
@@ -516,7 +518,7 @@ impl DeleteTenantFlow {
}
}
- let timelines_path = conf.timelines_path(&tenant.tenant_id);
+ let timelines_path = conf.timelines_path(&tenant.tenant_shard_id);
// May not exist if we fail in cleanup_remaining_fs_traces after removing it
if timelines_path.exists() {
// sanity check to guard against layout changes
@@ -525,7 +527,8 @@ impl DeleteTenantFlow {
.context("timelines dir not empty")?;
}
- remove_tenant_remote_delete_mark(conf, remote_storage.as_ref(), &tenant.tenant_id).await?;
+ remove_tenant_remote_delete_mark(conf, remote_storage.as_ref(), &tenant.tenant_shard_id)
+ .await?;
fail::fail_point!("tenant-delete-before-cleanup-remaining-fs-traces", |_| {
Err(anyhow::anyhow!(
@@ -533,21 +536,73 @@ impl DeleteTenantFlow {
))?
});
- cleanup_remaining_fs_traces(conf, &tenant.tenant_id)
+ cleanup_remaining_fs_traces(conf, &tenant.tenant_shard_id)
.await
.context("cleanup_remaining_fs_traces")?;
{
- let mut locked = tenants.write().unwrap();
- if locked.remove(&tenant.tenant_id).is_none() {
- warn!("Tenant got removed from tenants map during deletion");
- };
+ pausable_failpoint!("tenant-delete-before-map-remove");
- // FIXME: we should not be modifying this from outside of mgr.rs.
- // This will go away when we simplify deletion (https://github.com/neondatabase/neon/issues/5080)
- crate::metrics::TENANT_MANAGER
- .tenant_slots
- .set(locked.len() as u64);
+ // This block is simply removing the TenantSlot for this tenant. It requires a loop because
+ // we might conflict with a TenantSlot::InProgress marker and need to wait for it.
+ //
+ // This complexity will go away when we simplify how deletion works:
+ // https://github.com/neondatabase/neon/issues/5080
+ loop {
+ // Under the TenantMap lock, try to remove the tenant. We usually succeed, but if
+ // we encounter an InProgress marker, yield the barrier it contains and wait on it.
+ let barrier = {
+ let mut locked = tenants.write().unwrap();
+ let removed = locked.remove(&tenant.tenant_shard_id.tenant_id);
+
+ // FIXME: we should not be modifying this from outside of mgr.rs.
+ // This will go away when we simplify deletion (https://github.com/neondatabase/neon/issues/5080)
+ crate::metrics::TENANT_MANAGER
+ .tenant_slots
+ .set(locked.len() as u64);
+
+ match removed {
+ TenantsMapRemoveResult::Occupied(TenantSlot::Attached(tenant)) => {
+ match tenant.current_state() {
+ TenantState::Stopping { .. } | TenantState::Broken { .. } => {
+ // Expected: we put the tenant into stopping state before we start deleting it
+ }
+ state => {
+ // Unexpected state
+ tracing::warn!(
+ "Tenant in unexpected state {state} after deletion"
+ );
+ }
+ }
+ break;
+ }
+ TenantsMapRemoveResult::Occupied(TenantSlot::Secondary) => {
+ // This is unexpected: this secondary tenants should not have been created, and we
+ // are not in a position to shut it down from here.
+ tracing::warn!("Tenant transitioned to secondary mode while deleting!");
+ break;
+ }
+ TenantsMapRemoveResult::Occupied(TenantSlot::InProgress(_)) => {
+ unreachable!("TenantsMap::remove handles InProgress separately, should never return it here");
+ }
+ TenantsMapRemoveResult::Vacant => {
+ tracing::warn!(
+ "Tenant removed from TenantsMap before deletion completed"
+ );
+ break;
+ }
+ TenantsMapRemoveResult::InProgress(barrier) => {
+ // An InProgress entry was found, we must wait on its barrier
+ barrier
+ }
+ }
+ };
+
+ tracing::info!(
+ "Waiting for competing operation to complete before deleting state for tenant"
+ );
+ barrier.wait().await;
+ }
}
*guard = Self::Finished;
diff --git a/pageserver/src/tenant/ephemeral_file.rs b/pageserver/src/tenant/ephemeral_file.rs
index 9a06d9df61..591eacd104 100644
--- a/pageserver/src/tenant/ephemeral_file.rs
+++ b/pageserver/src/tenant/ephemeral_file.rs
@@ -7,18 +7,19 @@ use crate::page_cache::{self, PAGE_SZ};
use crate::tenant::block_io::{BlockCursor, BlockLease, BlockReader};
use crate::virtual_file::VirtualFile;
use camino::Utf8PathBuf;
+use pageserver_api::shard::TenantShardId;
use std::cmp::min;
use std::fs::OpenOptions;
use std::io::{self, ErrorKind};
use std::ops::DerefMut;
use std::sync::atomic::AtomicU64;
use tracing::*;
-use utils::id::{TenantId, TimelineId};
+use utils::id::TimelineId;
pub struct EphemeralFile {
page_cache_file_id: page_cache::FileId,
- _tenant_id: TenantId,
+ _tenant_shard_id: TenantShardId,
_timeline_id: TimelineId,
file: VirtualFile,
len: u64,
@@ -31,7 +32,7 @@ pub struct EphemeralFile {
impl EphemeralFile {
pub async fn create(
conf: &PageServerConf,
- tenant_id: TenantId,
+ tenant_shard_id: TenantShardId,
timeline_id: TimelineId,
) -> Result {
static NEXT_FILENAME: AtomicU64 = AtomicU64::new(1);
@@ -39,7 +40,7 @@ impl EphemeralFile {
NEXT_FILENAME.fetch_add(1, std::sync::atomic::Ordering::Relaxed);
let filename = conf
- .timeline_path(&tenant_id, &timeline_id)
+ .timeline_path(&tenant_shard_id, &timeline_id)
.join(Utf8PathBuf::from(format!(
"ephemeral-{filename_disambiguator}"
)));
@@ -52,7 +53,7 @@ impl EphemeralFile {
Ok(EphemeralFile {
page_cache_file_id: page_cache::next_file_id(),
- _tenant_id: tenant_id,
+ _tenant_shard_id: tenant_shard_id,
_timeline_id: timeline_id,
file,
len: 0,
@@ -282,7 +283,7 @@ mod tests {
) -> Result<
(
&'static PageServerConf,
- TenantId,
+ TenantShardId,
TimelineId,
RequestContext,
),
@@ -295,13 +296,13 @@ mod tests {
// OK in a test.
let conf: &'static PageServerConf = Box::leak(Box::new(conf));
- let tenant_id = TenantId::from_str("11000000000000000000000000000000").unwrap();
+ let tenant_shard_id = TenantShardId::from_str("11000000000000000000000000000000").unwrap();
let timeline_id = TimelineId::from_str("22000000000000000000000000000000").unwrap();
- fs::create_dir_all(conf.timeline_path(&tenant_id, &timeline_id))?;
+ fs::create_dir_all(conf.timeline_path(&tenant_shard_id, &timeline_id))?;
let ctx = RequestContext::new(TaskKind::UnitTest, DownloadBehavior::Error);
- Ok((conf, tenant_id, timeline_id, ctx))
+ Ok((conf, tenant_shard_id, timeline_id, ctx))
}
#[tokio::test]
diff --git a/pageserver/src/tenant/metadata.rs b/pageserver/src/tenant/metadata.rs
index 38fd426746..6fb86c65e2 100644
--- a/pageserver/src/tenant/metadata.rs
+++ b/pageserver/src/tenant/metadata.rs
@@ -11,15 +11,12 @@
use std::io::{self};
use anyhow::{ensure, Context};
+use pageserver_api::shard::TenantShardId;
use serde::{de::Error, Deserialize, Serialize, Serializer};
use thiserror::Error;
use utils::bin_ser::SerializeError;
use utils::crashsafe::path_with_suffix_extension;
-use utils::{
- bin_ser::BeSer,
- id::{TenantId, TimelineId},
- lsn::Lsn,
-};
+use utils::{bin_ser::BeSer, id::TimelineId, lsn::Lsn};
use crate::config::PageServerConf;
use crate::virtual_file::VirtualFile;
@@ -272,14 +269,14 @@ impl Serialize for TimelineMetadata {
}
/// Save timeline metadata to file
-#[tracing::instrument(skip_all, fields(%tenant_id, %timeline_id))]
+#[tracing::instrument(skip_all, fields(%tenant_id=tenant_shard_id.tenant_id, %shard_id=tenant_shard_id.shard_slug(), %timeline_id))]
pub async fn save_metadata(
conf: &'static PageServerConf,
- tenant_id: &TenantId,
+ tenant_shard_id: &TenantShardId,
timeline_id: &TimelineId,
data: &TimelineMetadata,
) -> anyhow::Result<()> {
- let path = conf.metadata_path(tenant_id, timeline_id);
+ let path = conf.metadata_path(tenant_shard_id, timeline_id);
let temp_path = path_with_suffix_extension(&path, TEMP_FILE_SUFFIX);
let metadata_bytes = data.to_bytes().context("serialize metadata")?;
VirtualFile::crashsafe_overwrite(&path, &temp_path, &metadata_bytes)
@@ -299,10 +296,10 @@ pub enum LoadMetadataError {
pub fn load_metadata(
conf: &'static PageServerConf,
- tenant_id: &TenantId,
+ tenant_shard_id: &TenantShardId,
timeline_id: &TimelineId,
) -> Result {
- let metadata_path = conf.metadata_path(tenant_id, timeline_id);
+ let metadata_path = conf.metadata_path(tenant_shard_id, timeline_id);
let metadata_bytes = std::fs::read(metadata_path)?;
Ok(TimelineMetadata::from_bytes(&metadata_bytes)?)
diff --git a/pageserver/src/tenant/mgr.rs b/pageserver/src/tenant/mgr.rs
index 5988dcd45f..f34d62ba53 100644
--- a/pageserver/src/tenant/mgr.rs
+++ b/pageserver/src/tenant/mgr.rs
@@ -29,7 +29,9 @@ use crate::control_plane_client::{
use crate::deletion_queue::DeletionQueueClient;
use crate::metrics::TENANT_MANAGER as METRICS;
use crate::task_mgr::{self, TaskKind};
-use crate::tenant::config::{AttachmentMode, LocationConf, LocationMode, TenantConfOpt};
+use crate::tenant::config::{
+ AttachedLocationConfig, AttachmentMode, LocationConf, LocationMode, TenantConfOpt,
+};
use crate::tenant::delete::DeleteTenantFlow;
use crate::tenant::span::debug_assert_current_span_has_tenant_id;
use crate::tenant::{create_tenant_files, AttachedTenantConf, SpawnMode, Tenant, TenantState};
@@ -122,6 +124,12 @@ fn exactly_one_or_none<'a>(
}
}
+pub(crate) enum TenantsMapRemoveResult {
+ Occupied(TenantSlot),
+ Vacant,
+ InProgress(utils::completion::Barrier),
+}
+
impl TenantsMap {
/// Convenience function for typical usage, where we want to get a `Tenant` object, for
/// working with attached tenants. If the TenantId is in the map but in Secondary state,
@@ -136,12 +144,28 @@ impl TenantsMap {
}
}
- pub(crate) fn remove(&mut self, tenant_id: &TenantId) -> Option {
+ /// Only for use from DeleteTenantFlow. This method directly removes a TenantSlot from the map.
+ ///
+ /// The normal way to remove a tenant is using a SlotGuard, which will gracefully remove the guarded
+ /// slot if the enclosed tenant is shutdown.
+ pub(crate) fn remove(&mut self, tenant_id: &TenantId) -> TenantsMapRemoveResult {
+ use std::collections::btree_map::Entry;
match self {
- TenantsMap::Initializing => None,
+ TenantsMap::Initializing => TenantsMapRemoveResult::Vacant,
TenantsMap::Open(m) | TenantsMap::ShuttingDown(m) => {
let key = exactly_one_or_none(m, tenant_id).map(|(k, _)| *k);
- key.and_then(|key| m.remove(&key))
+ match key {
+ Some(key) => match m.entry(key) {
+ Entry::Occupied(entry) => match entry.get() {
+ TenantSlot::InProgress(barrier) => {
+ TenantsMapRemoveResult::InProgress(barrier.clone())
+ }
+ _ => TenantsMapRemoveResult::Occupied(entry.remove()),
+ },
+ Entry::Vacant(_entry) => TenantsMapRemoveResult::Vacant,
+ },
+ None => TenantsMapRemoveResult::Vacant,
+ }
}
}
}
@@ -250,8 +274,8 @@ pub struct TenantManager {
}
fn emergency_generations(
- tenant_confs: &HashMap>,
-) -> HashMap {
+ tenant_confs: &HashMap>,
+) -> HashMap {
tenant_confs
.iter()
.filter_map(|(tid, lc)| {
@@ -271,10 +295,10 @@ fn emergency_generations(
async fn init_load_generations(
conf: &'static PageServerConf,
- tenant_confs: &HashMap>,
+ tenant_confs: &HashMap>,
resources: &TenantSharedResources,
cancel: &CancellationToken,
-) -> anyhow::Result