From 4fd0463b701ced561b71de60461b1b15112b31d3 Mon Sep 17 00:00:00 2001 From: Sebastian Bernauer Date: Wed, 15 Oct 2025 14:01:30 +0200 Subject: [PATCH 01/14] feat: Add API to activate/deactivate clusters --- Cargo.lock | 651 +++++++++--------- Cargo.toml | 1 + .../trino-lb/configs/trino-lb-config.yaml | 10 +- deploy/helm/trino-lb/templates/trinos.yaml | 20 +- trino-lb-core/src/config.rs | 17 + trino-lb-core/src/trino_cluster.rs | 7 + trino-lb/Cargo.toml | 1 + trino-lb/src/cluster_group_manager.rs | 3 +- trino-lb/src/http_server/admin/mod.rs | 170 +++++ trino-lb/src/http_server/mod.rs | 10 + trino-lb/src/scaling/mod.rs | 12 +- 11 files changed, 571 insertions(+), 331 deletions(-) create mode 100644 trino-lb/src/http_server/admin/mod.rs diff --git a/Cargo.lock b/Cargo.lock index a19313d..4fbdbd1 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -2,15 +2,6 @@ # It is not intended for manual editing. version = 4 -[[package]] -name = "addr2line" -version = "0.24.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dfbe277e56a376000877090da837660b4427aad530e3028d44e0bffe4f89a1c1" -dependencies = [ - "gimli", -] - [[package]] name = "adler2" version = "2.0.1" @@ -24,7 +15,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "5a15f179cd60c4584b8a8c596927aadc462e27f2ca70c04e0071964a73ba7a75" dependencies = [ "cfg-if", - "getrandom 0.3.3", + "getrandom 0.3.4", "once_cell", "version_check", "zerocopy", @@ -71,9 +62,9 @@ dependencies = [ [[package]] name = "anstream" -version = "0.6.20" +version = "0.6.21" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3ae563653d1938f79b1ab1b5e668c87c76a9930414574a6583a7b7e11a8e6192" +checksum = "43d5b281e737544384e969a5ccad3f1cdd24b48086a0fc1b2a5262a26b8f4f4a" dependencies = [ "anstyle", "anstyle-parse", @@ -86,9 +77,9 @@ dependencies = [ [[package]] name = "anstyle" -version = "1.0.11" +version = "1.0.13" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "862ed96ca487e809f1c8e5a8447f6ee2cf102f846893800b20cebdf541fc6bbd" +checksum = "5192cca8006f1fd4f7237516f40fa183bb07f8fbdfedaa0036de5ea9b0b45e78" [[package]] name = "anstyle-parse" @@ -121,9 +112,9 @@ dependencies = [ [[package]] name = "anyhow" -version = "1.0.99" +version = "1.0.100" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b0674a1ddeecb70197781e945de4b3b8ffb61fa939a5597bcf48503737663100" +checksum = "a23eb6b1614318a8071c9b2521f36b424b2c83db5eb3a0fead4a6c0809af6e61" [[package]] name = "arc-swap" @@ -187,9 +178,9 @@ dependencies = [ [[package]] name = "async-compression" -version = "0.4.30" +version = "0.4.32" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "977eb15ea9efd848bb8a4a1a2500347ed7f0bf794edf0dc3ddcf439f43d36b23" +checksum = "5a89bce6054c720275ac2432fbba080a66a2106a44a1b804553930ca6909f4e0" dependencies = [ "compression-codecs", "compression-core", @@ -281,11 +272,11 @@ dependencies = [ [[package]] name = "axum" -version = "0.8.4" +version = "0.8.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "021e862c184ae977658b36c4500f7feac3221ca5da43e3f25bd04ab6c79a29b5" +checksum = "8a18ed336352031311f4e0b4dd2ff392d4fbb370777c9d18d7fc9d7359f73871" dependencies = [ - "axum-core 0.5.2", + "axum-core 0.5.5", "bytes", "form_urlencoded", "futures-util", @@ -300,8 +291,7 @@ dependencies = [ "mime", "percent-encoding", "pin-project-lite", - "rustversion", - "serde", + "serde_core", "serde_json", "serde_path_to_error", "serde_urlencoded", @@ -335,9 +325,9 @@ dependencies = [ [[package]] name = "axum-core" -version = "0.5.2" +version = "0.5.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "68464cd0412f486726fb3373129ef5d2993f90c34bc2bc1c1e9943b2f4fc7ca6" +checksum = "59446ce19cd142f8833f856eb31f3eb097812d1479ab224f54d72428ca21ea22" dependencies = [ "bytes", "futures-core", @@ -346,13 +336,35 @@ dependencies = [ "http-body-util", "mime", "pin-project-lite", - "rustversion", "sync_wrapper 1.0.2", "tower-layer", "tower-service", "tracing", ] +[[package]] +name = "axum-extra" +version = "0.10.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9963ff19f40c6102c76756ef0a46004c0d58957d87259fc9208ff8441c12ab96" +dependencies = [ + "axum 0.8.6", + "axum-core 0.5.5", + "bytes", + "futures-util", + "headers", + "http 1.3.1", + "http-body 1.0.1", + "http-body-util", + "mime", + "pin-project-lite", + "rustversion", + "serde_core", + "tower-layer", + "tower-service", + "tracing", +] + [[package]] name = "axum-server" version = "0.7.2" @@ -367,11 +379,11 @@ dependencies = [ "hyper 1.7.0", "hyper-util", "pin-project-lite", - "rustls 0.23.31", + "rustls 0.23.32", "rustls-pemfile 2.2.0", "rustls-pki-types", "tokio", - "tokio-rustls 0.26.2", + "tokio-rustls 0.26.4", "tower-service", ] @@ -386,21 +398,6 @@ dependencies = [ "tokio", ] -[[package]] -name = "backtrace" -version = "0.3.75" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6806a6321ec58106fea15becdad98371e28d92ccbc7c8f1b3b6dd724fe8f1002" -dependencies = [ - "addr2line", - "cfg-if", - "libc", - "miniz_oxide", - "object", - "rustc-demangle", - "windows-targets 0.52.6", -] - [[package]] name = "base64" version = "0.21.7" @@ -524,9 +521,9 @@ checksum = "d71b6127be86fdcfddb610f7182ac57211d4b18a3e9c82eb2d17662f2227ad6a" [[package]] name = "cc" -version = "1.2.37" +version = "1.2.41" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "65193589c6404eb80b450d618eaf9a2cafaaafd57ecce47370519ef674a7bd44" +checksum = "ac9fe6cdbb24b6ade63616c0a0688e45bb56732262c158df3c0c4bea4ca47cb7" dependencies = [ "find-msvc-tools", "jobserver", @@ -536,9 +533,9 @@ dependencies = [ [[package]] name = "cfg-if" -version = "1.0.3" +version = "1.0.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2fd1289c04a9ea8cb22300a459a72a385d7c73d3259e2ed7dcb2af674838cfa9" +checksum = "9330f8b2ff13f34540b44e946ef35111825727b38d33286ef986142615121801" [[package]] name = "cfg_aliases" @@ -557,7 +554,7 @@ dependencies = [ "num-traits", "serde", "wasm-bindgen", - "windows-link 0.2.0", + "windows-link 0.2.1", ] [[package]] @@ -584,9 +581,9 @@ dependencies = [ [[package]] name = "clap" -version = "4.5.47" +version = "4.5.49" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7eac00902d9d136acd712710d71823fb8ac8004ca445a89e73a41d45aa712931" +checksum = "f4512b90fa68d3a9932cea5184017c5d200f5921df706d45e853537dea51508f" dependencies = [ "clap_builder", "clap_derive", @@ -594,9 +591,9 @@ dependencies = [ [[package]] name = "clap_builder" -version = "4.5.47" +version = "4.5.49" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2ad9bbf750e73b5884fb8a211a9424a1906c1e156724260fdae972f31d70e1d6" +checksum = "0025e98baa12e766c67ba13ff4695a887a1eba19569aad00a472546795bd6730" dependencies = [ "anstream", "anstyle", @@ -606,9 +603,9 @@ dependencies = [ [[package]] name = "clap_derive" -version = "4.5.47" +version = "4.5.49" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bbfd7eae0b0f1a6e63d4b13c9c478de77c2eb546fba158ad50b4203dc24b9f9c" +checksum = "2a0b5487afeab2deb2ff4e03a807ad1a03ac532ff5a2cee5d86884440c7f7671" dependencies = [ "heck", "proc-macro2", @@ -618,9 +615,9 @@ dependencies = [ [[package]] name = "clap_lex" -version = "0.7.5" +version = "0.7.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b94f61472cee1439c0b966b47e3aca9ae07e45d070759512cd390ea2bebc6675" +checksum = "a1d728cc89cf3aee9ff92b05e62b19ee65a02b5702cff7d5a377e32c6ae29d8d" [[package]] name = "colorchoice" @@ -644,9 +641,9 @@ dependencies = [ [[package]] name = "compression-codecs" -version = "0.4.30" +version = "0.4.31" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "485abf41ac0c8047c07c87c72c8fb3eb5197f6e9d7ded615dfd1a00ae00a0f64" +checksum = "ef8a506ec4b81c460798f572caead636d57d3d7e940f998160f52bd254bf2d23" dependencies = [ "brotli", "compression-core", @@ -681,7 +678,7 @@ dependencies = [ "libc", "once_cell", "unicode-width", - "windows-sys 0.61.0", + "windows-sys 0.61.2", ] [[package]] @@ -828,9 +825,9 @@ dependencies = [ [[package]] name = "deranged" -version = "0.5.3" +version = "0.5.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d630bccd429a5bb5a64b5e94f693bfc48c9f8566418fda4c494cc94f911f87cc" +checksum = "a41953f86f8a05768a6cda24def994fd2f424b04ec5c719cf89989779f199071" dependencies = [ "powerfmt", ] @@ -1020,15 +1017,15 @@ checksum = "37909eebbb50d72f9059c3b6d82c0463f2ff062c9e95845c43a6c9c0355411be" [[package]] name = "find-msvc-tools" -version = "0.1.1" +version = "0.1.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7fd99930f64d146689264c637b5af2f0233a933bef0d8570e2526bf9e083192d" +checksum = "52051878f80a721bb68ebfbc930e07b65ba72f2da88968ea5c06fd6ca3d3a127" [[package]] name = "flate2" -version = "1.1.2" +version = "1.1.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4a3d7db9596fecd151c5f638c0ee5d5bd487b6e0ea232e5dc96d5250f6f94b1d" +checksum = "dc5a4e564e38c699f2880d3fda590bedc2e69f3f84cd48b457bd892ce61d0aa9" dependencies = [ "crc32fast", "miniz_oxide", @@ -1068,9 +1065,9 @@ dependencies = [ [[package]] name = "fs-err" -version = "3.1.1" +version = "3.1.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "88d7be93788013f265201256d58f04936a8079ad5dc898743aa20525f503b683" +checksum = "6ad492b2cf1d89d568a43508ab24f98501fe03f2f31c01e1d0fe7366a71745d2" dependencies = [ "autocfg", "tokio", @@ -1184,9 +1181,9 @@ dependencies = [ [[package]] name = "generic-array" -version = "0.14.7" +version = "0.14.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "85649ca51fd72272d7821adaf274ad91c288277713d9c18820d8499a7ff69e9a" +checksum = "4bb6743198531e02858aeaea5398fcc883e71851fcbcb5a2f773e2fb6cb1edf2" dependencies = [ "typenum", "version_check", @@ -1201,30 +1198,24 @@ dependencies = [ "cfg-if", "js-sys", "libc", - "wasi 0.11.1+wasi-snapshot-preview1", + "wasi", "wasm-bindgen", ] [[package]] name = "getrandom" -version = "0.3.3" +version = "0.3.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "26145e563e54f2cadc477553f1ec5ee650b00862f0a58bcd12cbdc5f0ea2d2f4" +checksum = "899def5c37c4fd7b2664648c28120ecec138e4d395b459e5ca34f9cce2dd77fd" dependencies = [ "cfg-if", "js-sys", "libc", "r-efi", - "wasi 0.14.5+wasi-0.2.4", + "wasip2", "wasm-bindgen", ] -[[package]] -name = "gimli" -version = "0.31.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "07e28edb80900c19c28f1072f2e8aeca7fa06b23cd4169cefe1af5aa3260783f" - [[package]] name = "glob" version = "0.3.3" @@ -1255,7 +1246,7 @@ dependencies = [ "futures-sink", "futures-util", "http 0.2.12", - "indexmap 2.11.1", + "indexmap 2.11.4", "slab", "tokio", "tokio-util", @@ -1274,7 +1265,7 @@ dependencies = [ "futures-core", "futures-sink", "http 1.3.1", - "indexmap 2.11.1", + "indexmap 2.11.4", "slab", "tokio", "tokio-util", @@ -1298,6 +1289,12 @@ dependencies = [ "foldhash", ] +[[package]] +name = "hashbrown" +version = "0.16.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5419bdc4f6a9207fbeba6d11b604d481addf78ecd10c11ad51e76c2f6482748d" + [[package]] name = "hashlink" version = "0.10.0" @@ -1307,6 +1304,30 @@ dependencies = [ "hashbrown 0.15.5", ] +[[package]] +name = "headers" +version = "0.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b3314d5adb5d94bcdf56771f2e50dbbc80bb4bdf88967526706205ac9eff24eb" +dependencies = [ + "base64 0.22.1", + "bytes", + "headers-core", + "http 1.3.1", + "httpdate", + "mime", + "sha1", +] + +[[package]] +name = "headers-core" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "54b4a22553d4242c49fddb9ba998a99962b5cc6f22cb5a3482bec22522403ce4" +dependencies = [ + "http 1.3.1", +] + [[package]] name = "heck" version = "0.5.0" @@ -1528,13 +1549,13 @@ dependencies = [ "hyper 1.7.0", "hyper-util", "log", - "rustls 0.23.31", + "rustls 0.23.32", "rustls-native-certs", "rustls-pki-types", "tokio", - "tokio-rustls 0.26.2", + "tokio-rustls 0.26.4", "tower-service", - "webpki-roots 1.0.2", + "webpki-roots 1.0.3", ] [[package]] @@ -1552,9 +1573,9 @@ dependencies = [ [[package]] name = "hyper-util" -version = "0.1.16" +version = "0.1.17" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8d9b05277c7e8da2c93a568989bb6207bef0112e8d17df7a6eda4a3cf143bc5e" +checksum = "3c6995591a8f1380fcb4ba966a252a4b29188d51d2b89e3a252f5305be65aea8" dependencies = [ "base64 0.22.1", "bytes", @@ -1568,7 +1589,7 @@ dependencies = [ "libc", "percent-encoding", "pin-project-lite", - "socket2 0.6.0", + "socket2 0.6.1", "tokio", "tower-service", "tracing", @@ -1717,12 +1738,12 @@ dependencies = [ [[package]] name = "indexmap" -version = "2.11.1" +version = "2.11.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "206a8042aec68fa4a62e8d3f7aa4ceb508177d9324faf261e1959e495b7a1921" +checksum = "4b0f83760fb341a774ed326568e19f5a863af4a952def8c39f9ab92fd95b88e5" dependencies = [ "equivalent", - "hashbrown 0.15.5", + "hashbrown 0.16.0", ] [[package]] @@ -1744,17 +1765,6 @@ version = "2.0.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f4c7245a08504955605670dbf141fceab975f15ca21570696aebe9d2e71576bd" -[[package]] -name = "io-uring" -version = "0.7.10" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "046fa2d4d00aea763528b4950358d0ead425372445dc8ff86312b3c69ff7727b" -dependencies = [ - "bitflags 2.9.4", - "cfg-if", - "libc", -] - [[package]] name = "ipnet" version = "2.11.0" @@ -1816,15 +1826,15 @@ version = "0.1.34" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9afb3de4395d6b3e67a780b6de64b51c978ecf11cb9a462c66be7d4ca9039d33" dependencies = [ - "getrandom 0.3.3", + "getrandom 0.3.4", "libc", ] [[package]] name = "js-sys" -version = "0.3.78" +version = "0.3.81" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0c0b063578492ceec17683ef2f8c5e89121fbd0b172cbc280635ab7567db2738" +checksum = "ec48937a97411dcb524a265206ccd4c90bb711fca92b2792c407f268825b9305" dependencies = [ "once_cell", "wasm-bindgen", @@ -1832,9 +1842,9 @@ dependencies = [ [[package]] name = "json-patch" -version = "4.0.0" +version = "4.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "159294d661a039f7644cea7e4d844e6b25aaf71c1ffe9d73a96d768c24b0faf4" +checksum = "f300e415e2134745ef75f04562dd0145405c2f7fd92065db029ac4b16b57fe90" dependencies = [ "jsonptr", "serde", @@ -1852,7 +1862,7 @@ dependencies = [ "pest_derive", "regex", "serde_json", - "thiserror 2.0.16", + "thiserror 2.0.17", ] [[package]] @@ -1912,12 +1922,12 @@ dependencies = [ "k8s-openapi", "kube-core", "pem", - "rustls 0.23.31", + "rustls 0.23.32", "secrecy", "serde", "serde_json", "serde_yaml", - "thiserror 2.0.16", + "thiserror 2.0.17", "tokio", "tokio-util", "tower 0.5.2", @@ -1940,7 +1950,7 @@ dependencies = [ "serde", "serde-value", "serde_json", - "thiserror 2.0.16", + "thiserror 2.0.17", ] [[package]] @@ -1964,7 +1974,7 @@ dependencies = [ "pin-project", "serde", "serde_json", - "thiserror 2.0.16", + "thiserror 2.0.17", "tokio", "tokio-util", "tracing", @@ -1981,9 +1991,9 @@ dependencies = [ [[package]] name = "libc" -version = "0.2.175" +version = "0.2.177" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6a82ae493e598baaea5209805c49bbf2ea7de956d50d7da0da1164f9c6d28543" +checksum = "2874a2af47a2325c2001a6e6fad9b16a53b802102b528163885171cf92b15976" [[package]] name = "libm" @@ -2026,11 +2036,10 @@ checksum = "f5e54036fe321fd421e10d732f155734c4e4afd610dd556d9a82833ab3ee0bed" [[package]] name = "lock_api" -version = "0.4.13" +version = "0.4.14" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "96936507f153605bddfcda068dd804796c84324ed2510809e5b2a624c81da765" +checksum = "224399e74b87b5f3557511d98dff8b14089b3dadafcab6bb93eab67d3aace965" dependencies = [ - "autocfg", "scopeguard", ] @@ -2085,9 +2094,9 @@ dependencies = [ [[package]] name = "memchr" -version = "2.7.5" +version = "2.7.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "32a282da65faaf38286cf3be983213fcf1d2e2a58700e808f83f4ea9a4804bc0" +checksum = "f52b00d39961fc5b2736ea853c9cc86238e165017a493d1d5c8eac6bdc4cc273" [[package]] name = "memoffset" @@ -2111,6 +2120,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1fa76a2c86f704bdb222d66965fb3d63269ce38518b83cb0575fca855ebb6316" dependencies = [ "adler2", + "simd-adler32", ] [[package]] @@ -2120,17 +2130,17 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "78bed444cc8a2160f01cbcf811ef18cac863ad68ae8ca62092e8db51d51c761c" dependencies = [ "libc", - "wasi 0.11.1+wasi-snapshot-preview1", + "wasi", "windows-sys 0.59.0", ] [[package]] name = "nu-ansi-term" -version = "0.50.1" +version = "0.50.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d4a28e057d01f97e61255210fcff094d74ed0466038633e95017f5beb68e4399" +checksum = "7957b9740744892f114936ab4a57b3f487491bbeafaf8083688b16841a4240e5" dependencies = [ - "windows-sys 0.52.0", + "windows-sys 0.61.2", ] [[package]] @@ -2212,15 +2222,6 @@ version = "0.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "830b246a0e5f20af87141b25c173cd1b609bd7779a4617d6ec582abaf90870f3" -[[package]] -name = "object" -version = "0.36.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "62948e14d923ea95ea2c7c86c71013138b66525b86bdc08d2dcc262bdb497b87" -dependencies = [ - "memchr", -] - [[package]] name = "once_cell" version = "1.21.3" @@ -2348,9 +2349,9 @@ checksum = "f38d5652c16fde515bb1ecef450ab0f6a219d619a7274976324d5e377f7dceba" [[package]] name = "parking_lot" -version = "0.12.4" +version = "0.12.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "70d58bf43669b5795d1576d0641cfb6fbb2057bf629506267a92807158584a13" +checksum = "93857453250e3077bd71ff98b6a65ea6621a19bb0f559a85248955ac12c45a1a" dependencies = [ "lock_api", "parking_lot_core", @@ -2358,15 +2359,15 @@ dependencies = [ [[package]] name = "parking_lot_core" -version = "0.9.11" +version = "0.9.12" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bc838d2a56b5b1a6c25f55575dfc605fabb63bb2365f6c2353ef9159aa69e4a5" +checksum = "2621685985a2ebf1c516881c026032ac7deafcda1a2c9b7850dc81e3dfcb64c1" dependencies = [ "cfg-if", "libc", "redox_syscall", "smallvec", - "windows-targets 0.52.6", + "windows-link 0.2.1", ] [[package]] @@ -2386,12 +2387,12 @@ checksum = "57c0d7b74b563b49d38dae00a0c37d4d6de9b432382b2892f0574ddcae73fd0a" [[package]] name = "pem" -version = "3.0.5" +version = "3.0.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "38af38e8470ac9dee3ce1bae1af9c1671fffc44ddfd8bd1d0a3445bf349a8ef3" +checksum = "1d30c53c26bc5b31a98cd02d20f25a7c8567146caf63ed593a9d87b2775291be" dependencies = [ "base64 0.22.1", - "serde", + "serde_core", ] [[package]] @@ -2411,20 +2412,19 @@ checksum = "9b4f627cb1b25917193a259e49bdad08f671f8d9708acfd5fe0a8c1455d87220" [[package]] name = "pest" -version = "2.8.2" +version = "2.8.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "21e0a3a33733faeaf8651dfee72dd0f388f0c8e5ad496a3478fa5a922f49cfa8" +checksum = "989e7521a040efde50c3ab6bbadafbe15ab6dc042686926be59ac35d74607df4" dependencies = [ "memchr", - "thiserror 2.0.16", "ucd-trie", ] [[package]] name = "pest_derive" -version = "2.8.2" +version = "2.8.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bc58706f770acb1dbd0973e6530a3cff4746fb721207feb3a8a6064cd0b6c663" +checksum = "187da9a3030dbafabbbfb20cb323b976dc7b7ce91fcd84f2f74d6e31d378e2de" dependencies = [ "pest", "pest_generator", @@ -2432,9 +2432,9 @@ dependencies = [ [[package]] name = "pest_generator" -version = "2.8.2" +version = "2.8.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6d4f36811dfe07f7b8573462465d5cb8965fffc2e71ae377a33aecf14c2c9a2f" +checksum = "49b401d98f5757ebe97a26085998d6c0eecec4995cad6ab7fc30ffdf4b052843" dependencies = [ "pest", "pest_meta", @@ -2445,9 +2445,9 @@ dependencies = [ [[package]] name = "pest_meta" -version = "2.8.2" +version = "2.8.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "42919b05089acbd0a5dcd5405fb304d17d1053847b81163d09c4ad18ce8e8420" +checksum = "72f27a2cfee9f9039c4d86faa5af122a0ac3851441a34865b8a043b46be0065a" dependencies = [ "pest", "sha2", @@ -2582,9 +2582,9 @@ dependencies = [ [[package]] name = "proc-macro-crate" -version = "3.3.0" +version = "3.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "edce586971a4dfaa28950c6f18ed55e0406c1ab88bbce2c6f6293a7aaba73d35" +checksum = "219cb19e96be00ab2e37d6e299658a0cfa83e52429179969b0f0121b4ac46983" dependencies = [ "toml_edit", ] @@ -2768,9 +2768,9 @@ dependencies = [ "quinn-proto", "quinn-udp", "rustc-hash", - "rustls 0.23.31", - "socket2 0.6.0", - "thiserror 2.0.16", + "rustls 0.23.32", + "socket2 0.6.1", + "thiserror 2.0.17", "tokio", "tracing", "web-time", @@ -2783,15 +2783,15 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f1906b49b0c3bc04b5fe5d86a77925ae6524a19b816ae38ce1e426255f1d8a31" dependencies = [ "bytes", - "getrandom 0.3.3", + "getrandom 0.3.4", "lru-slab", "rand 0.9.2", "ring", "rustc-hash", - "rustls 0.23.31", + "rustls 0.23.32", "rustls-pki-types", "slab", - "thiserror 2.0.16", + "thiserror 2.0.17", "tinyvec", "tracing", "web-time", @@ -2806,16 +2806,16 @@ dependencies = [ "cfg_aliases", "libc", "once_cell", - "socket2 0.6.0", + "socket2 0.6.1", "tracing", "windows-sys 0.60.2", ] [[package]] name = "quote" -version = "1.0.40" +version = "1.0.41" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1885c039570dc00dcb4ff087a89e185fd56bae234ddc7f056a945bf36467248d" +checksum = "ce25767e7b499d1b604768e7cde645d14cc8584231ea6b295e9c9eb22c02e1d1" dependencies = [ "proc-macro2", ] @@ -2882,14 +2882,14 @@ version = "0.9.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "99d9a13982dcf210057a8a78572b2217b667c3beacbf3a0d8b454f6f82837d38" dependencies = [ - "getrandom 0.3.3", + "getrandom 0.3.4", ] [[package]] name = "redis" -version = "0.32.5" +version = "0.32.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7cd3650deebc68526b304898b192fa4102a4ef0b9ada24da096559cb60e0eef8" +checksum = "014cc767fefab6a3e798ca45112bccad9c6e0e218fbd49720042716c73cfef44" dependencies = [ "arc-swap", "backon", @@ -2906,31 +2906,31 @@ dependencies = [ "percent-encoding", "pin-project-lite", "rand 0.9.2", - "rustls 0.23.31", + "rustls 0.23.32", "rustls-native-certs", "ryu", "sha1_smol", - "socket2 0.6.0", + "socket2 0.6.1", "tokio", - "tokio-rustls 0.26.2", + "tokio-rustls 0.26.4", "tokio-util", "url", ] [[package]] name = "redox_syscall" -version = "0.5.17" +version = "0.5.18" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5407465600fb0548f1442edf71dd20683c6ed326200ace4b1ef0763521bb3b77" +checksum = "ed2bf2547551a7053d6fdfafda3f938979645c44812fbfcda098faae3f1a362d" dependencies = [ "bitflags 2.9.4", ] [[package]] name = "regex" -version = "1.11.2" +version = "1.12.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "23d7fd106d8c02486a8d64e778353d1cffe08ce79ac2e82f540c86d0facf6912" +checksum = "843bc0191f75f3e22651ae5f1e72939ab2f72a4bc30fa80a066bd66edefc24d4" dependencies = [ "aho-corasick", "memchr", @@ -2940,9 +2940,9 @@ dependencies = [ [[package]] name = "regex-automata" -version = "0.4.10" +version = "0.4.13" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6b9458fa0bfeeac22b5ca447c63aaf45f28439a709ccd244698632f9aa6394d6" +checksum = "5276caf25ac86c8d810222b3dbb938e512c55c6831a10f3e6ed1c93b84041f1c" dependencies = [ "aho-corasick", "memchr", @@ -2951,9 +2951,9 @@ dependencies = [ [[package]] name = "regex-syntax" -version = "0.8.6" +version = "0.8.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "caf4aa5b0f434c91fe5c7f1ecb6a5ece2130b02ad2a590589dda5146df959001" +checksum = "7a2d987857b319362043e95f5353c0535c1f58eec5336fdfcf626430af7def58" [[package]] name = "relative-path" @@ -3004,9 +3004,9 @@ dependencies = [ [[package]] name = "reqwest" -version = "0.12.23" +version = "0.12.24" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d429f34c8092b2d42c7c93cec323bb4adeb7c67698f70839adec842ec10c7ceb" +checksum = "9d0946410b9f7b082a427e4ef5c8ff541a88b357bc6c637c40db3a68ac70a36f" dependencies = [ "async-compression", "base64 0.22.1", @@ -3026,14 +3026,14 @@ dependencies = [ "percent-encoding", "pin-project-lite", "quinn", - "rustls 0.23.31", + "rustls 0.23.32", "rustls-pki-types", "serde", "serde_json", "serde_urlencoded", "sync_wrapper 1.0.2", "tokio", - "tokio-rustls 0.26.2", + "tokio-rustls 0.26.4", "tokio-util", "tower 0.5.2", "tower-http", @@ -3042,7 +3042,7 @@ dependencies = [ "wasm-bindgen", "wasm-bindgen-futures", "web-sys", - "webpki-roots 1.0.2", + "webpki-roots 1.0.3", ] [[package]] @@ -3108,12 +3108,6 @@ dependencies = [ "unicode-ident", ] -[[package]] -name = "rustc-demangle" -version = "0.1.26" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "56f7d92ca342cea22a06f2121d944b4fd82af56988c270852495420f961d4ace" - [[package]] name = "rustc-hash" version = "2.1.1" @@ -3143,24 +3137,24 @@ dependencies = [ [[package]] name = "rustls" -version = "0.23.31" +version = "0.23.32" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c0ebcbd2f03de0fc1122ad9bb24b127a5a6cd51d72604a3f3c50ac459762b6cc" +checksum = "cd3c25631629d034ce7cd9940adc9d45762d46de2b0f57193c4443b92c6d4d40" dependencies = [ "log", "once_cell", "ring", "rustls-pki-types", - "rustls-webpki 0.103.5", + "rustls-webpki 0.103.7", "subtle", "zeroize", ] [[package]] name = "rustls-native-certs" -version = "0.8.1" +version = "0.8.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7fcff2dd52b58a8d98a70243663a0d234c4e2b79235637849d15913394a247d3" +checksum = "9980d917ebb0c0536119ba501e90834767bffc3d60641457fd84a1f3fd337923" dependencies = [ "openssl-probe", "rustls-pki-types", @@ -3208,9 +3202,9 @@ dependencies = [ [[package]] name = "rustls-webpki" -version = "0.103.5" +version = "0.103.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b5a37813727b78798e53c2bec3f5e8fe12a6d6f8389bf9ca7802add4c9905ad8" +checksum = "e10b3f4191e8a80e6b43eebabfac91e5dcecebb27a71f04e820c47ec41d314bf" dependencies = [ "ring", "rustls-pki-types", @@ -3235,7 +3229,7 @@ version = "0.1.28" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "891d81b926048e76efe18581bf793546b4c0eaf8448d72be8de2bbee5fd166e1" dependencies = [ - "windows-sys 0.61.0", + "windows-sys 0.61.2", ] [[package]] @@ -3265,9 +3259,9 @@ dependencies = [ [[package]] name = "security-framework" -version = "3.4.0" +version = "3.5.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "60b369d18893388b345804dc0007963c99b7d665ae71d275812d828c6f089640" +checksum = "b3297343eaf830f66ede390ea39da1d462b6b0c1b000f420d0a83f898bbbe6ef" dependencies = [ "bitflags 2.9.4", "core-foundation 0.10.1", @@ -3294,9 +3288,9 @@ checksum = "d767eb0aabc880b29956c35734170f26ed551a859dbd361d140cdbeca61ab1e2" [[package]] name = "serde" -version = "1.0.223" +version = "1.0.228" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a505d71960adde88e293da5cb5eda57093379f64e61cf77bf0e6a63af07a7bac" +checksum = "9a8e94ea7f378bd32cbbd37198a4a91436180c5bb472411e48b5ec2e2124ae9e" dependencies = [ "serde_core", "serde_derive", @@ -3314,18 +3308,18 @@ dependencies = [ [[package]] name = "serde_core" -version = "1.0.223" +version = "1.0.228" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "20f57cbd357666aa7b3ac84a90b4ea328f1d4ddb6772b430caa5d9e1309bb9e9" +checksum = "41d385c7d4ca58e59fc732af25c3983b67ac852c1a25000afe1175de458b67ad" dependencies = [ "serde_derive", ] [[package]] name = "serde_derive" -version = "1.0.223" +version = "1.0.228" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3d428d07faf17e306e699ec1e91996e5a165ba5d6bce5b5155173e91a8a01a56" +checksum = "d540f220d3187173da220f885ab66608367b6574e925011a9353e4badda91d79" dependencies = [ "proc-macro2", "quote", @@ -3347,9 +3341,9 @@ dependencies = [ [[package]] name = "serde_path_to_error" -version = "0.1.19" +version = "0.1.20" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a30a8abed938137c7183c173848e3c9b3517f5e038226849a4ecc9b21a4b4e2a" +checksum = "10a9ff822e371bb5403e391ecd83e182e0e77ba7f6fe0160b795797109d1b457" dependencies = [ "itoa", "serde", @@ -3374,7 +3368,7 @@ version = "0.9.34+deprecated" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "6a8b1a1a2ebf674015cc02edccce75287f1a0130d394307b36743c2f5d504b47" dependencies = [ - "indexmap 2.11.1", + "indexmap 2.11.4", "itoa", "ryu", "serde", @@ -3443,6 +3437,12 @@ dependencies = [ "rand_core 0.6.4", ] +[[package]] +name = "simd-adler32" +version = "0.3.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d66dc143e6b11c1eddc06d5c423cfc97062865baf299914ab64caa38182078fe" + [[package]] name = "siphasher" version = "1.0.1" @@ -3497,12 +3497,12 @@ dependencies = [ [[package]] name = "socket2" -version = "0.6.0" +version = "0.6.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "233504af464074f9d066d7b5416c5f9b894a5862a6506e306f7b816cdd6f1807" +checksum = "17129e116933cf371d018bb80ae557e889637989d8638274fb25622827b03881" dependencies = [ "libc", - "windows-sys 0.59.0", + "windows-sys 0.60.2", ] [[package]] @@ -3556,17 +3556,17 @@ dependencies = [ "futures-util", "hashbrown 0.15.5", "hashlink", - "indexmap 2.11.1", + "indexmap 2.11.4", "log", "memchr", "once_cell", "percent-encoding", - "rustls 0.23.31", + "rustls 0.23.32", "serde", "serde_json", "sha2", "smallvec", - "thiserror 2.0.16", + "thiserror 2.0.17", "tokio", "tokio-stream", "tracing", @@ -3650,7 +3650,7 @@ dependencies = [ "smallvec", "sqlx-core", "stringprep", - "thiserror 2.0.16", + "thiserror 2.0.17", "tracing", "whoami", ] @@ -3688,7 +3688,7 @@ dependencies = [ "smallvec", "sqlx-core", "stringprep", - "thiserror 2.0.16", + "thiserror 2.0.17", "tracing", "whoami", ] @@ -3713,16 +3713,16 @@ dependencies = [ "serde", "serde_urlencoded", "sqlx-core", - "thiserror 2.0.16", + "thiserror 2.0.17", "tracing", "url", ] [[package]] name = "stable_deref_trait" -version = "1.2.0" +version = "1.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a8f112729512f8e442d81f95a8a7ddf2b7c6b8a1a6f509a95864142b30cab2d3" +checksum = "6ce2be8dc25455e1f91df71bfa12ad37d7af1092ae736f3a6cd0e37bc7810596" [[package]] name = "stringprep" @@ -3866,11 +3866,11 @@ dependencies = [ [[package]] name = "thiserror" -version = "2.0.16" +version = "2.0.17" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3467d614147380f2e4e374161426ff399c91084acd2363eaf549172b3d5e60c0" +checksum = "f63587ca0f12b72a0600bcba1d40081f830876000bb46dd2337a3051618f4fc8" dependencies = [ - "thiserror-impl 2.0.16", + "thiserror-impl 2.0.17", ] [[package]] @@ -3886,9 +3886,9 @@ dependencies = [ [[package]] name = "thiserror-impl" -version = "2.0.16" +version = "2.0.17" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6c5e1be1c48b9172ee610da68fd9cd2770e7a4056cb3fc98710ee6906f0c7960" +checksum = "3ff15c8ecd7de3849db632e14d18d2571fa09dfc5ed93479bc4485c7a517c913" dependencies = [ "proc-macro2", "quote", @@ -3906,11 +3906,12 @@ dependencies = [ [[package]] name = "time" -version = "0.3.43" +version = "0.3.44" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "83bde6f1ec10e72d583d91623c939f623002284ef622b87de38cfd546cbf2031" +checksum = "91e7d9e3bb61134e77bde20dd4825b97c010155709965fedf0f49bb138e52a9d" dependencies = [ "deranged", + "itoa", "num-conv", "powerfmt", "serde", @@ -3961,29 +3962,26 @@ checksum = "1f3ccbac311fea05f86f61904b462b55fb3df8837a366dfc601a0161d0532f20" [[package]] name = "tokio" -version = "1.47.1" +version = "1.48.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "89e49afdadebb872d3145a5638b59eb0691ea23e46ca484037cfab3b76b95038" +checksum = "ff360e02eab121e0bc37a2d3b4d4dc622e6eda3a8e5253d5435ecf5bd4c68408" dependencies = [ - "backtrace", "bytes", - "io-uring", "libc", "mio", "parking_lot", "pin-project-lite", "signal-hook-registry", - "slab", - "socket2 0.6.0", + "socket2 0.6.1", "tokio-macros", - "windows-sys 0.59.0", + "windows-sys 0.61.2", ] [[package]] name = "tokio-macros" -version = "2.5.0" +version = "2.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6e06d43f1345a3bcd39f6a56dbb7dcab2ba47e68e8ac134855e7e2bdbaf8cab8" +checksum = "af407857209536a95c8e56f8231ef2c2e2aff839b22e07a1ffcbc617e9db9fa5" dependencies = [ "proc-macro2", "quote", @@ -4002,11 +4000,11 @@ dependencies = [ [[package]] name = "tokio-rustls" -version = "0.26.2" +version = "0.26.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8e727b36a1a0e8b74c376ac2211e40c2c8af09fb4013c60d910495810f008e9b" +checksum = "1729aa945f29d91ba541258c8df89027d5792d85a8841fb65e8bf0f4ede4ef61" dependencies = [ - "rustls 0.23.31", + "rustls 0.23.32", "tokio", ] @@ -4037,18 +4035,31 @@ dependencies = [ [[package]] name = "toml_datetime" -version = "0.6.11" +version = "0.7.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "22cddaf88f4fbc13c51aebbf5f8eceb5c7c5a9da2ac40a13519eb5b0a0e8f11c" +checksum = "f2cdb639ebbc97961c51720f858597f7f24c4fc295327923af55b74c3c724533" +dependencies = [ + "serde_core", +] [[package]] name = "toml_edit" -version = "0.22.27" +version = "0.23.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "41fe8c660ae4257887cf66394862d21dbca4a6ddd26f04a3560410406a2f819a" +checksum = "6485ef6d0d9b5d0ec17244ff7eb05310113c3f316f2d14200d4de56b3cb98f8d" dependencies = [ - "indexmap 2.11.1", + "indexmap 2.11.4", "toml_datetime", + "toml_parser", + "winnow", +] + +[[package]] +name = "toml_parser" +version = "1.0.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c0cbe268d35bdb4bb5a56a2de88d0ad0eb70af5384a99d648cd4b3d04039800e" +dependencies = [ "winnow", ] @@ -4253,7 +4264,8 @@ name = "trino-lb" version = "0.5.0" dependencies = [ "askama", - "axum 0.8.4", + "axum 0.8.6", + "axum-extra", "axum-server", "chrono", "clap", @@ -4277,7 +4289,7 @@ dependencies = [ "rand 0.9.2", "redis", "regex", - "reqwest 0.12.23", + "reqwest 0.12.24", "rstest", "serde", "serde_json", @@ -4320,7 +4332,7 @@ dependencies = [ "opentelemetry-otlp", "prusto", "rand 0.9.2", - "reqwest 0.12.23", + "reqwest 0.12.24", "rstest", "serde", "serde_json", @@ -4360,9 +4372,9 @@ checksum = "e421abadd41a4225275504ea4d6566923418b7f05506fbc9c0fe86ba7396114b" [[package]] name = "typenum" -version = "1.18.0" +version = "1.19.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1dccffe3ce07af9386bfd29e80c0ab1a8205a2fc34e4bcd40364df902cfa8f3f" +checksum = "562d481066bde0658276a35467c4af00bdc6ee726305698a55b86e61d7ad82bb" [[package]] name = "ucd-trie" @@ -4399,9 +4411,9 @@ checksum = "e70f2a8b45122e719eb623c01822704c4e0907e7e426a05927e1a1cfff5b75d0" [[package]] name = "unicode-width" -version = "0.2.1" +version = "0.2.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4a1a07cc7db3810833284e8d372ccdc6da29741639ecc70c9ec107df0fa6154c" +checksum = "b4ac048d71ede7ee76d585517add45da530660ef4390e49b098733c6e897f254" [[package]] name = "unindent" @@ -4469,7 +4481,7 @@ version = "1.18.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "2f87b8aa10b915a06587d0dec516c282ff295b475d94abf425d62b57710070a2" dependencies = [ - "getrandom 0.3.3", + "getrandom 0.3.4", "js-sys", "serde", "wasm-bindgen", @@ -4514,20 +4526,11 @@ version = "0.11.1+wasi-snapshot-preview1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ccf3ec651a847eb01de73ccad15eb7d99f80485de043efb2f370cd654f4ea44b" -[[package]] -name = "wasi" -version = "0.14.5+wasi-0.2.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a4494f6290a82f5fe584817a676a34b9d6763e8d9d18204009fb31dceca98fd4" -dependencies = [ - "wasip2", -] - [[package]] name = "wasip2" -version = "1.0.0+wasi-0.2.4" +version = "1.0.1+wasi-0.2.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "03fa2761397e5bd52002cd7e73110c71af2109aca4e521a9f40473fe685b0a24" +checksum = "0562428422c63773dad2c345a1882263bbf4d65cf3f42e90921f787ef5ad58e7" dependencies = [ "wit-bindgen", ] @@ -4540,9 +4543,9 @@ checksum = "b8dad83b4f25e74f184f64c43b150b91efe7647395b42289f38e50566d82855b" [[package]] name = "wasm-bindgen" -version = "0.2.101" +version = "0.2.104" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7e14915cadd45b529bb8d1f343c4ed0ac1de926144b746e2710f9cd05df6603b" +checksum = "c1da10c01ae9f1ae40cbfac0bac3b1e724b320abfcf52229f80b547c0d250e2d" dependencies = [ "cfg-if", "once_cell", @@ -4553,9 +4556,9 @@ dependencies = [ [[package]] name = "wasm-bindgen-backend" -version = "0.2.101" +version = "0.2.104" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e28d1ba982ca7923fd01448d5c30c6864d0a14109560296a162f80f305fb93bb" +checksum = "671c9a5a66f49d8a47345ab942e2cb93c7d1d0339065d4f8139c486121b43b19" dependencies = [ "bumpalo", "log", @@ -4567,9 +4570,9 @@ dependencies = [ [[package]] name = "wasm-bindgen-futures" -version = "0.4.51" +version = "0.4.54" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0ca85039a9b469b38336411d6d6ced91f3fc87109a2a27b0c197663f5144dffe" +checksum = "7e038d41e478cc73bae0ff9b36c60cff1c98b8f38f8d7e8061e79ee63608ac5c" dependencies = [ "cfg-if", "js-sys", @@ -4580,9 +4583,9 @@ dependencies = [ [[package]] name = "wasm-bindgen-macro" -version = "0.2.101" +version = "0.2.104" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7c3d463ae3eff775b0c45df9da45d68837702ac35af998361e2c84e7c5ec1b0d" +checksum = "7ca60477e4c59f5f2986c50191cd972e3a50d8a95603bc9434501cf156a9a119" dependencies = [ "quote", "wasm-bindgen-macro-support", @@ -4590,9 +4593,9 @@ dependencies = [ [[package]] name = "wasm-bindgen-macro-support" -version = "0.2.101" +version = "0.2.104" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7bb4ce89b08211f923caf51d527662b75bdc9c9c7aab40f86dcb9fb85ac552aa" +checksum = "9f07d2f20d4da7b26400c9f4a0511e6e0345b040694e8a75bd41d578fa4421d7" dependencies = [ "proc-macro2", "quote", @@ -4603,18 +4606,18 @@ dependencies = [ [[package]] name = "wasm-bindgen-shared" -version = "0.2.101" +version = "0.2.104" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f143854a3b13752c6950862c906306adb27c7e839f7414cec8fea35beab624c1" +checksum = "bad67dc8b2a1a6e5448428adec4c3e84c43e561d8c9ee8a9e5aabeb193ec41d1" dependencies = [ "unicode-ident", ] [[package]] name = "web-sys" -version = "0.3.78" +version = "0.3.81" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "77e4b637749ff0d92b8fad63aa1f7cff3cbe125fd49c175cd6345e7272638b12" +checksum = "9367c417a924a74cae129e6a2ae3b47fabb1f8995595ab474029da749a8be120" dependencies = [ "js-sys", "wasm-bindgen", @@ -4642,14 +4645,14 @@ version = "0.26.11" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "521bc38abb08001b01866da9f51eb7c5d647a19260e00054a8c7fd5f9e57f7a9" dependencies = [ - "webpki-roots 1.0.2", + "webpki-roots 1.0.3", ] [[package]] name = "webpki-roots" -version = "1.0.2" +version = "1.0.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7e8983c3ab33d6fb807cfcdad2491c4ea8cbc8ed839181c7dfd9c67c83e261b2" +checksum = "32b130c0d2d49f8b6889abc456e795e82525204f27c42cf767cf0d7734e089b8" dependencies = [ "rustls-pki-types", ] @@ -4666,22 +4669,22 @@ dependencies = [ [[package]] name = "windows-core" -version = "0.62.0" +version = "0.62.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "57fe7168f7de578d2d8a05b07fd61870d2e73b4020e9f49aa00da8471723497c" +checksum = "b8e83a14d34d0623b51dce9581199302a221863196a1dde71a7663a4c2be9deb" dependencies = [ "windows-implement", "windows-interface", - "windows-link 0.2.0", + "windows-link 0.2.1", "windows-result", "windows-strings", ] [[package]] name = "windows-implement" -version = "0.60.0" +version = "0.60.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a47fddd13af08290e67f4acabf4b459f647552718f683a7b415d290ac744a836" +checksum = "053e2e040ab57b9dc951b72c264860db7eb3b0200ba345b4e4c3b14f67855ddf" dependencies = [ "proc-macro2", "quote", @@ -4690,9 +4693,9 @@ dependencies = [ [[package]] name = "windows-interface" -version = "0.59.1" +version = "0.59.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bd9211b69f8dcdfa817bfd14bf1c97c9188afa36f4750130fcdf3f400eca9fa8" +checksum = "3f316c4a2570ba26bbec722032c4099d8c8bc095efccdc15688708623367e358" dependencies = [ "proc-macro2", "quote", @@ -4707,26 +4710,26 @@ checksum = "5e6ad25900d524eaabdbbb96d20b4311e1e7ae1699af4fb28c17ae66c80d798a" [[package]] name = "windows-link" -version = "0.2.0" +version = "0.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "45e46c0661abb7180e7b9c281db115305d49ca1709ab8242adf09666d2173c65" +checksum = "f0805222e57f7521d6a62e36fa9163bc891acd422f971defe97d64e70d0a4fe5" [[package]] name = "windows-result" -version = "0.4.0" +version = "0.4.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7084dcc306f89883455a206237404d3eaf961e5bd7e0f312f7c91f57eb44167f" +checksum = "7781fa89eaf60850ac3d2da7af8e5242a5ea78d1a11c49bf2910bb5a73853eb5" dependencies = [ - "windows-link 0.2.0", + "windows-link 0.2.1", ] [[package]] name = "windows-strings" -version = "0.5.0" +version = "0.5.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7218c655a553b0bed4426cf54b20d7ba363ef543b52d515b3e48d7fd55318dda" +checksum = "7837d08f69c77cf6b07689544538e017c1bfcf57e34b4c0ff58e6c2cd3b37091" dependencies = [ - "windows-link 0.2.0", + "windows-link 0.2.1", ] [[package]] @@ -4762,16 +4765,16 @@ version = "0.60.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f2f500e4d28234f72040990ec9d39e3a6b950f9f22d3dba18416c35882612bcb" dependencies = [ - "windows-targets 0.53.3", + "windows-targets 0.53.5", ] [[package]] name = "windows-sys" -version = "0.61.0" +version = "0.61.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e201184e40b2ede64bc2ea34968b28e33622acdbbf37104f0e4a33f7abe657aa" +checksum = "ae137229bcbd6cdf0f7b80a31df61766145077ddf49416a728b02cb3921ff3fc" dependencies = [ - "windows-link 0.2.0", + "windows-link 0.2.1", ] [[package]] @@ -4807,19 +4810,19 @@ dependencies = [ [[package]] name = "windows-targets" -version = "0.53.3" +version = "0.53.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d5fe6031c4041849d7c496a8ded650796e7b6ecc19df1a431c1a363342e5dc91" +checksum = "4945f9f551b88e0d65f3db0bc25c33b8acea4d9e41163edf90dcd0b19f9069f3" dependencies = [ - "windows-link 0.1.3", - "windows_aarch64_gnullvm 0.53.0", - "windows_aarch64_msvc 0.53.0", - "windows_i686_gnu 0.53.0", - "windows_i686_gnullvm 0.53.0", - "windows_i686_msvc 0.53.0", - "windows_x86_64_gnu 0.53.0", - "windows_x86_64_gnullvm 0.53.0", - "windows_x86_64_msvc 0.53.0", + "windows-link 0.2.1", + "windows_aarch64_gnullvm 0.53.1", + "windows_aarch64_msvc 0.53.1", + "windows_i686_gnu 0.53.1", + "windows_i686_gnullvm 0.53.1", + "windows_i686_msvc 0.53.1", + "windows_x86_64_gnu 0.53.1", + "windows_x86_64_gnullvm 0.53.1", + "windows_x86_64_msvc 0.53.1", ] [[package]] @@ -4836,9 +4839,9 @@ checksum = "32a4622180e7a0ec044bb555404c800bc9fd9ec262ec147edd5989ccd0c02cd3" [[package]] name = "windows_aarch64_gnullvm" -version = "0.53.0" +version = "0.53.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "86b8d5f90ddd19cb4a147a5fa63ca848db3df085e25fee3cc10b39b6eebae764" +checksum = "a9d8416fa8b42f5c947f8482c43e7d89e73a173cead56d044f6a56104a6d1b53" [[package]] name = "windows_aarch64_msvc" @@ -4854,9 +4857,9 @@ checksum = "09ec2a7bb152e2252b53fa7803150007879548bc709c039df7627cabbd05d469" [[package]] name = "windows_aarch64_msvc" -version = "0.53.0" +version = "0.53.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c7651a1f62a11b8cbd5e0d42526e55f2c99886c77e007179efff86c2b137e66c" +checksum = "b9d782e804c2f632e395708e99a94275910eb9100b2114651e04744e9b125006" [[package]] name = "windows_i686_gnu" @@ -4872,9 +4875,9 @@ checksum = "8e9b5ad5ab802e97eb8e295ac6720e509ee4c243f69d781394014ebfe8bbfa0b" [[package]] name = "windows_i686_gnu" -version = "0.53.0" +version = "0.53.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c1dc67659d35f387f5f6c479dc4e28f1d4bb90ddd1a5d3da2e5d97b42d6272c3" +checksum = "960e6da069d81e09becb0ca57a65220ddff016ff2d6af6a223cf372a506593a3" [[package]] name = "windows_i686_gnullvm" @@ -4884,9 +4887,9 @@ checksum = "0eee52d38c090b3caa76c563b86c3a4bd71ef1a819287c19d586d7334ae8ed66" [[package]] name = "windows_i686_gnullvm" -version = "0.53.0" +version = "0.53.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9ce6ccbdedbf6d6354471319e781c0dfef054c81fbc7cf83f338a4296c0cae11" +checksum = "fa7359d10048f68ab8b09fa71c3daccfb0e9b559aed648a8f95469c27057180c" [[package]] name = "windows_i686_msvc" @@ -4902,9 +4905,9 @@ checksum = "240948bc05c5e7c6dabba28bf89d89ffce3e303022809e73deaefe4f6ec56c66" [[package]] name = "windows_i686_msvc" -version = "0.53.0" +version = "0.53.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "581fee95406bb13382d2f65cd4a908ca7b1e4c2f1917f143ba16efe98a589b5d" +checksum = "1e7ac75179f18232fe9c285163565a57ef8d3c89254a30685b57d83a38d326c2" [[package]] name = "windows_x86_64_gnu" @@ -4920,9 +4923,9 @@ checksum = "147a5c80aabfbf0c7d901cb5895d1de30ef2907eb21fbbab29ca94c5b08b1a78" [[package]] name = "windows_x86_64_gnu" -version = "0.53.0" +version = "0.53.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2e55b5ac9ea33f2fc1716d1742db15574fd6fc8dadc51caab1c16a3d3b4190ba" +checksum = "9c3842cdd74a865a8066ab39c8a7a473c0778a3f29370b5fd6b4b9aa7df4a499" [[package]] name = "windows_x86_64_gnullvm" @@ -4938,9 +4941,9 @@ checksum = "24d5b23dc417412679681396f2b49f3de8c1473deb516bd34410872eff51ed0d" [[package]] name = "windows_x86_64_gnullvm" -version = "0.53.0" +version = "0.53.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0a6e035dd0599267ce1ee132e51c27dd29437f63325753051e71dd9e42406c57" +checksum = "0ffa179e2d07eee8ad8f57493436566c7cc30ac536a3379fdf008f47f6bb7ae1" [[package]] name = "windows_x86_64_msvc" @@ -4956,9 +4959,9 @@ checksum = "589f6da84c646204747d1270a2a5661ea66ed1cced2631d546fdfb155959f9ec" [[package]] name = "windows_x86_64_msvc" -version = "0.53.0" +version = "0.53.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "271414315aff87387382ec3d271b52d7ae78726f5d44ac98b4f4030c91880486" +checksum = "d6bbff5f0aada427a1e5a6da5f1f98158182f26556f345ac9e04d36d0ebed650" [[package]] name = "winnow" @@ -4981,9 +4984,9 @@ dependencies = [ [[package]] name = "wit-bindgen" -version = "0.45.1" +version = "0.46.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5c573471f125075647d03df72e026074b7203790d41351cd6edc96f46bcccd36" +checksum = "f17a85883d4e6d00e8a97c586de764dabcc06133f7f1d55dce5cdc070ad7fe59" [[package]] name = "writeable" @@ -5058,9 +5061,9 @@ dependencies = [ [[package]] name = "zeroize" -version = "1.8.1" +version = "1.8.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ced3678a2879b30306d323f4542626697a464a97c0a07c9aebf7ebca65cd4dde" +checksum = "b97154e67e32c85465826e8bcc1c59429aaaf107c1e4a9e53c8d8ccd5eff88d0" [[package]] name = "zerotrie" diff --git a/Cargo.toml b/Cargo.toml index 94509be..e0aa2f4 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -17,6 +17,7 @@ repository = "https://github.com/stackabletech/trino-lb" [workspace.dependencies] askama = "0.14" axum = { version = "0.8", features = ["tracing"] } +axum-extra = { version = "0.10", features = ["typed-header"] } # If we use the feature "tls-rustls" it will pull in the "aws-lc-rs" crate, which as of 2024-08-16 I did not get to build in the "make run-dev" workflow :/ axum-server = { version = "0.7", features = ["tls-rustls-no-provider"] } bincode = { version = "2.0", features = ["serde"] } diff --git a/deploy/helm/trino-lb/configs/trino-lb-config.yaml b/deploy/helm/trino-lb/configs/trino-lb-config.yaml index ca60e4a..38a1212 100644 --- a/deploy/helm/trino-lb/configs/trino-lb-config.yaml +++ b/deploy/helm/trino-lb/configs/trino-lb-config.yaml @@ -4,6 +4,10 @@ trinoLb: enabled: true certPemFile: /certificates/cert.pem keyPemFile: /certificates/key.pem + adminAuthentication: + basicAuth: + username: admin + password: admin persistence: redis: clusterMode: true @@ -35,7 +39,7 @@ trinoClusterGroups: min: 0 trinoClusters: - name: trino-s-1 - endpoint: https://trino-s-1-coordinator-default.default.svc.cluster.local:8443 + endpoint: https://trino-s-1-coordinator.default.svc.cluster.local:8443 credentials: &common-credentials username: admin password: adminadmin @@ -51,10 +55,10 @@ trinoClusterGroups: min: 1 trinoClusters: - name: trino-m-1 - endpoint: https://trino-m-1-coordinator-default.default.svc.cluster.local:8443 + endpoint: https://trino-m-1-coordinator.default.svc.cluster.local:8443 credentials: *common-credentials - name: trino-m-2 - endpoint: https://trino-m-2-coordinator-default.default.svc.cluster.local:8443 + endpoint: https://trino-m-2-coordinator.default.svc.cluster.local:8443 credentials: *common-credentials # oidc: # maxRunningQueries: 3 diff --git a/deploy/helm/trino-lb/templates/trinos.yaml b/deploy/helm/trino-lb/templates/trinos.yaml index 6282a28..8fde5ad 100644 --- a/deploy/helm/trino-lb/templates/trinos.yaml +++ b/deploy/helm/trino-lb/templates/trinos.yaml @@ -8,7 +8,7 @@ metadata: namespace: default spec: image: - productVersion: "455" + productVersion: "476" clusterConfig: catalogLabelSelector: matchLabels: @@ -18,6 +18,10 @@ spec: coordinators: roleConfig: listenerClass: external-stable + config: + resources: + cpu: + min: 50m configOverrides: &configOverrides config.properties: tracing.enabled: "true" @@ -27,6 +31,10 @@ spec: replicas: 1 workers: configOverrides: *configOverrides + config: + resources: + cpu: + min: 50m roleGroups: default: replicas: 1 @@ -41,7 +49,7 @@ metadata: namespace: default spec: image: - productVersion: "455" + productVersion: "476" clusterConfig: catalogLabelSelector: matchLabels: @@ -51,6 +59,10 @@ spec: coordinators: roleConfig: listenerClass: external-stable + config: + resources: + cpu: + min: 50m configOverrides: &configOverrides config.properties: tracing.enabled: "true" @@ -60,6 +72,10 @@ spec: replicas: 1 workers: configOverrides: *configOverrides + config: + resources: + cpu: + min: 50m roleGroups: default: replicas: 1 diff --git a/trino-lb-core/src/config.rs b/trino-lb-core/src/config.rs index 40ba782..8c2f333 100644 --- a/trino-lb-core/src/config.rs +++ b/trino-lb-core/src/config.rs @@ -53,6 +53,8 @@ pub struct TrinoLbConfig { pub persistence: PersistenceConfig, + pub admin_authentication: Option, + #[serde(default)] pub tls: TrinoLbTlsConfig, @@ -170,6 +172,12 @@ fn default_max_connections() -> u32 { 10 } +#[derive(Clone, Debug, Deserialize)] +#[serde(deny_unknown_fields, rename_all = "camelCase")] +pub enum TrinoLbAdminAuthenticationConfig { + BasicAuth { username: String, password: String }, +} + #[derive(Clone, Debug, Deserialize)] #[serde(deny_unknown_fields, rename_all = "camelCase")] pub struct TrinoClusterGroupConfig { @@ -349,3 +357,12 @@ impl Config { .context(ParseConfigFileSnafu { config_file }) } } + +impl Config { + pub fn cluster_in_config(&self, cluster_name: &TrinoClusterName) -> bool { + self.trino_cluster_groups + .values() + .flat_map(|cluster_group| &cluster_group.trino_clusters) + .any(|cluster| &cluster.name == cluster_name) + } +} diff --git a/trino-lb-core/src/trino_cluster.rs b/trino-lb-core/src/trino_cluster.rs index 7e5f445..224d7ae 100644 --- a/trino-lb-core/src/trino_cluster.rs +++ b/trino-lb-core/src/trino_cluster.rs @@ -53,6 +53,13 @@ impl ClusterState { } } + pub fn turn_ready_if_not_deactivated(&self) -> Self { + match self { + ClusterState::Deactivated => Self::Deactivated, + _ => ClusterState::Ready, + } + } + pub fn can_be_started(&self) -> bool { match self { ClusterState::Stopped | ClusterState::Draining { .. } => true, diff --git a/trino-lb/Cargo.toml b/trino-lb/Cargo.toml index ce02644..c7ef24f 100644 --- a/trino-lb/Cargo.toml +++ b/trino-lb/Cargo.toml @@ -16,6 +16,7 @@ trino-lb-core = { path = "../trino-lb-core" } trino-lb-persistence = { path = "../trino-lb-persistence" } askama.workspace = true +axum-extra.workspace = true axum-server.workspace = true axum.workspace = true chrono.workspace = true diff --git a/trino-lb/src/cluster_group_manager.rs b/trino-lb/src/cluster_group_manager.rs index a1a15f5..0c99f8b 100644 --- a/trino-lb/src/cluster_group_manager.rs +++ b/trino-lb/src/cluster_group_manager.rs @@ -8,6 +8,7 @@ use axum::{Json, body::Body, response::IntoResponse}; use futures::future::try_join_all; use http::{HeaderMap, StatusCode}; use reqwest::Client; +use serde::{Deserialize, Serialize}; use snafu::{OptionExt, ResultExt, Snafu}; use tracing::{Instrument, debug, info_span, instrument}; use tracing_opentelemetry::OpenTelemetrySpanExt; @@ -87,7 +88,7 @@ pub struct TrinoCluster { pub endpoint: Url, } -#[derive(Clone, Debug)] +#[derive(Clone, Debug, Serialize, Deserialize)] pub struct ClusterStats { pub state: ClusterState, pub query_counter: u64, diff --git a/trino-lb/src/http_server/admin/mod.rs b/trino-lb/src/http_server/admin/mod.rs new file mode 100644 index 0000000..2383ce5 --- /dev/null +++ b/trino-lb/src/http_server/admin/mod.rs @@ -0,0 +1,170 @@ +use std::{collections::BTreeMap, sync::Arc}; + +use axum::{ + Json, + extract::{Path, State}, + response::{IntoResponse, Response}, +}; +use axum_extra::{ + TypedHeader, + headers::{Authorization, authorization::Basic}, +}; +use http::StatusCode; +use opentelemetry::KeyValue; +use serde::{Deserialize, Serialize}; +use snafu::{ResultExt, Snafu, ensure}; +use tracing::{info, instrument, warn}; +use trino_lb_core::{ + TrinoClusterName, config::TrinoLbAdminAuthenticationConfig, trino_cluster::ClusterState, +}; +use trino_lb_persistence::Persistence; + +use crate::{ + cluster_group_manager::{self, ClusterStats}, + http_server::AppState, +}; + +#[derive(Snafu, Debug)] +pub enum Error { + #[snafu(display("No admin authentication method defined"))] + NoAdminAuthenticationMethodDefined, + + #[snafu(display("Invalid admin credentials"))] + InvalidAdminCredentials, + + #[snafu(display("Unknown Trino cluster {cluster:?}"))] + UnknownCluster { cluster: TrinoClusterName }, + + #[snafu(display("Failed to set cluster state for cluster {cluster:?} in persistence"))] + SetClusterStateInPersistence { + source: trino_lb_persistence::Error, + cluster: TrinoClusterName, + }, + + #[snafu(display("Failed to get all cluster states"))] + GetAllClusterStates { + source: cluster_group_manager::Error, + }, +} + +impl IntoResponse for Error { + fn into_response(self) -> Response { + warn!(error = ?self, "Error while processing admin request"); + let status_code = match self { + Error::NoAdminAuthenticationMethodDefined => StatusCode::UNAUTHORIZED, + Error::InvalidAdminCredentials => StatusCode::UNAUTHORIZED, + Error::UnknownCluster { .. } => StatusCode::NOT_FOUND, + Error::SetClusterStateInPersistence { .. } => StatusCode::INTERNAL_SERVER_ERROR, + Error::GetAllClusterStates { .. } => StatusCode::INTERNAL_SERVER_ERROR, + }; + (status_code, format!("{self}")).into_response() + } +} + +/// (Re)-Activates a Trino Cluster, so that it receives new queries. +/// +/// This is useful for maintenance actions (in combination with deactivation). +#[instrument(name = "POST /admin/activate-cluster/{cluster_name}", skip(state))] +pub async fn post_activate_cluster( + TypedHeader(Authorization(basic_auth)): TypedHeader>, + State(state): State>, + Path(cluster_name): Path, +) -> Result, Error> { + state + .metrics + .http_counter + .add(1, &[KeyValue::new("resource", "post_activate_cluster")]); + + set_cluster_activation(state, basic_auth, &cluster_name, true).await +} + +/// Deactivate a Trino Cluster, so that it doesn't receive any new queries. +/// +/// This is useful for maintenance actions (in combination with activation). +#[instrument(name = "POST /admin/deactivate-cluster/{cluster_name}", skip(state))] +pub async fn post_deactivate_cluster( + TypedHeader(Authorization(basic_auth)): TypedHeader>, + State(state): State>, + Path(cluster_name): Path, +) -> Result, Error> { + state + .metrics + .http_counter + .add(1, &[KeyValue::new("resource", "post_deactivate_cluster")]); + + set_cluster_activation(state, basic_auth, &cluster_name, false).await +} + +/// Get the status of the Trino clusters +#[instrument(name = "GET /admin/cluster-status", skip(state))] +pub async fn get_cluster_status( + State(state): State>, +) -> Result>, Error> { + state + .metrics + .http_counter + .add(1, &[KeyValue::new("resource", "get_cluster_status")]); + + let cluster_stats = state + .cluster_group_manager + .get_all_cluster_stats() + .await + .context(GetAllClusterStatesSnafu)?; + + Ok(Json( + cluster_stats + .into_iter() + .map(|(cluster, stats)| (cluster.name.clone(), stats)) + .collect(), + )) +} + +#[derive(Debug, Deserialize, Serialize)] +pub struct ClusterActivationResponse { + state: ClusterState, +} + +#[instrument(skip(state))] +async fn set_cluster_activation( + state: Arc, + basic_auth: Basic, + cluster_name: &TrinoClusterName, + activation: bool, +) -> Result, Error> { + match &state.config.trino_lb.admin_authentication { + Some(TrinoLbAdminAuthenticationConfig::BasicAuth { username, password }) => { + ensure!( + basic_auth.username() == username && basic_auth.password() == password, + InvalidAdminCredentialsSnafu {} + ); + } + None => return Err(Error::NoAdminAuthenticationMethodDefined), + } + + ensure!( + state.config.cluster_in_config(cluster_name), + UnknownClusterSnafu { + cluster: cluster_name + } + ); + + let desired_state = if activation { + info!(cluster = cluster_name, "Re-activating Trino cluster"); + ClusterState::Unknown + } else { + info!(cluster = cluster_name, "Deactivating Trino cluster"); + ClusterState::Deactivated + }; + + state + .persistence + .set_cluster_state(cluster_name, desired_state.clone()) + .await + .context(SetClusterStateInPersistenceSnafu { + cluster: cluster_name, + })?; + + Ok(Json(ClusterActivationResponse { + state: desired_state, + })) +} diff --git a/trino-lb/src/http_server/mod.rs b/trino-lb/src/http_server/mod.rs index e548023..a90bb06 100644 --- a/trino-lb/src/http_server/mod.rs +++ b/trino-lb/src/http_server/mod.rs @@ -23,6 +23,7 @@ use crate::{ cluster_group_manager::ClusterGroupManager, config::Config, metrics::Metrics, routing, }; +mod admin; mod metrics; mod ui; mod v1; @@ -121,6 +122,15 @@ pub async fn start_http_server( "/v1/statement/executing/{query_id}/{slug}/{token}", delete(v1::statement::delete_trino_executing_statement), ) + .route( + "/admin/activate-cluster/{cluster_name}", + post(admin::post_activate_cluster), + ) + .route( + "/admin/deactivate-cluster/{cluster_name}", + post(admin::post_deactivate_cluster), + ) + .route("/admin/cluster-status", get(admin::get_cluster_status)) .route("/ui/index.html", get(ui::index::get_ui_index)) .route("/ui/query.html", get(ui::query::get_ui_query)) .layer(TraceLayer::new_for_http()) diff --git a/trino-lb/src/scaling/mod.rs b/trino-lb/src/scaling/mod.rs index d829546..87f89ac 100644 --- a/trino-lb/src/scaling/mod.rs +++ b/trino-lb/src/scaling/mod.rs @@ -611,8 +611,18 @@ impl Scaler { #[instrument(name = "Scaler::set_all_clusters_to_ready", skip(self))] async fn set_all_clusters_to_ready(&self) -> Result<(), Error> { for cluster in self.groups.values().flatten() { + let current_state = self + .persistence + .get_cluster_state(&cluster.name) + .await + .context(ReadCurrentClusterStateFromPersistenceSnafu { + cluster: &cluster.name, + })?; + + let new_state = current_state.turn_ready_if_not_deactivated(); + self.persistence - .set_cluster_state(&cluster.name, ClusterState::Ready) + .set_cluster_state(&cluster.name, new_state) .await .context(SetCurrentClusterStateInPersistenceSnafu { cluster: &cluster.name, From 0ecc4bce61eeab5f229f75b8cf27bbca3ea82585 Mon Sep 17 00:00:00 2001 From: Sebastian Bernauer Date: Thu, 16 Oct 2025 08:10:13 +0200 Subject: [PATCH 02/14] changelog --- CHANGELOG.md | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 636618c..e920687 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -4,6 +4,11 @@ All notable changes to this project will be documented in this file. ## [Unreleased] +### Added + +- Support activating and deactivation Trino clusters via API calls to `/admin/activate-cluster/{cluster_name}` and `/admin/deactivate-cluster/{cluster_name}` respectively. For this to work you need to authenticate yourself at trino-lb via basic auth ([#95]). +- Expose cluster statistics at `/admin/cluster-status` ([#95]). + ### Changed - The Stackable scaler now ensures that a `TrinoCluster` has changed to `ready` more than 5 seconds @@ -22,6 +27,7 @@ All notable changes to this project will be documented in this file. [#85]: https://github.com/stackabletech/trino-lb/pull/85 [#86]: https://github.com/stackabletech/trino-lb/pull/86 [#91]: https://github.com/stackabletech/trino-lb/pull/91 +[#95]: https://github.com/stackabletech/trino-lb/pull/95 ## [0.5.0] - 2025-03-14 From 1f1795c39a267eb4768df26f3d1c39667b72a533 Mon Sep 17 00:00:00 2001 From: Sebastian Bernauer Date: Thu, 16 Oct 2025 09:11:13 +0200 Subject: [PATCH 03/14] Add some docs --- docs/design.md | 25 ++++++++++++++++++++++++- 1 file changed, 24 insertions(+), 1 deletion(-) diff --git a/docs/design.md b/docs/design.md index fa01f55..ade2330 100644 --- a/docs/design.md +++ b/docs/design.md @@ -81,7 +81,30 @@ However, as we can't influence the query ID the query will get running on Trino Queued queries that have not been accessed for longer than 5 minutes are removed from the persistence to avoid cluttering the system with abounded queries. Doing so trino-lb behaves the same way Trino does (the relevant setting in Trino is `query.client.timeout`). -## 5. Autoscaling Trino clusters +## 5. Zero downtime maintenance + +You can activate and deactivate Trino clusters in trino-lb. +A deactivated cluster continues to process running queries, but no new queries will be submitted to it. + +To safely update a running Trino cluster you can + +1. Deactivate the Trino cluster using `POST /admin/deactivate-cluster/{cluster_name}` +2. Wait until all running queries have finished. Tip: You can use `GET /admin/cluster-status` to fetch the current query counter or talk to the Trino cluster directly. +3. Safely do modifications to the Trino cluster without any user impact +4. Once you are done with your changes re-activate the Trino cluster again using `POST /admin/activate-cluster/{cluster_name}` + +Important: To activate/deactivate a Trino cluster you need to authenticate against trino-lb. +Currently only Basic Auth is supported, you can configure the credentials like this: + +```yaml +trinoLb: + adminAuthentication: + basicAuth: + username: trino-lb-admin + password: your-password +``` + +## 6. Autoscaling Trino clusters You can scale the number of Trino clusters within a group based on the queue length and clusters utilization. This allows you to significantly save costs by reducing the number of clusters running. From ed809770312b358c1d620d0c8b884c00d288b998 Mon Sep 17 00:00:00 2001 From: Sebastian Bernauer Date: Thu, 16 Oct 2025 09:29:42 +0200 Subject: [PATCH 04/14] linters --- deploy/helm/trino-lb/configs/trino-lb-config.yaml | 1 + docs/design.md | 1 + 2 files changed, 2 insertions(+) diff --git a/deploy/helm/trino-lb/configs/trino-lb-config.yaml b/deploy/helm/trino-lb/configs/trino-lb-config.yaml index 38a1212..df76a44 100644 --- a/deploy/helm/trino-lb/configs/trino-lb-config.yaml +++ b/deploy/helm/trino-lb/configs/trino-lb-config.yaml @@ -1,3 +1,4 @@ +--- trinoLb: externalAddress: https://5.250.179.64:8443 tls: diff --git a/docs/design.md b/docs/design.md index ade2330..2d353d4 100644 --- a/docs/design.md +++ b/docs/design.md @@ -130,6 +130,7 @@ Also, the cluster `trino-s-1` was started on demand, executed the 60 queries and ![Grafana screenshot](./assets/grafana-screenshot.png) ## Tracing + trino-lb emits [OpenTelemetry Traces](https://opentelemetry.io/docs/concepts/signals/traces/) to [OTLP](https://opentelemetry.io/docs/specs/otel/protocol/) endpoints such as [Jaeger](https://www.jaegertracing.io/). When proxy-ing requests to Trino we take care of [OpenTelemetry Propagation](https://opentelemetry.io/docs/instrumentation/js/propagation/), so that the Trino spans will show up within the trino-lb spans. This enables nice tracing across trino-lb and trino (as seen in the screenshot below) From 6014cbafea78d1ccde1c3286b286865449b6acf7 Mon Sep 17 00:00:00 2001 From: Sebastian Bernauer Date: Fri, 17 Oct 2025 15:35:47 +0200 Subject: [PATCH 05/14] Update trino-lb-core/src/config.rs Co-authored-by: Techassi --- trino-lb-core/src/config.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/trino-lb-core/src/config.rs b/trino-lb-core/src/config.rs index 8c2f333..19c4287 100644 --- a/trino-lb-core/src/config.rs +++ b/trino-lb-core/src/config.rs @@ -359,7 +359,7 @@ impl Config { } impl Config { - pub fn cluster_in_config(&self, cluster_name: &TrinoClusterName) -> bool { + pub fn is_cluster_in_config(&self, cluster_name: &TrinoClusterName) -> bool { self.trino_cluster_groups .values() .flat_map(|cluster_group| &cluster_group.trino_clusters) From 8c2e948b76d59f1ea25d2e71686ac30f830c2cf2 Mon Sep 17 00:00:00 2001 From: Sebastian Bernauer Date: Fri, 17 Oct 2025 15:36:01 +0200 Subject: [PATCH 06/14] Update docs/design.md Co-authored-by: Techassi --- docs/design.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/design.md b/docs/design.md index 2d353d4..8c1a667 100644 --- a/docs/design.md +++ b/docs/design.md @@ -84,7 +84,7 @@ Doing so trino-lb behaves the same way Trino does (the relevant setting in Trino ## 5. Zero downtime maintenance You can activate and deactivate Trino clusters in trino-lb. -A deactivated cluster continues to process running queries, but no new queries will be submitted to it. +A deactivated cluster continues to process already running queries, but no new queries will be submitted to it. To safely update a running Trino cluster you can From 084dee0407781f7fb974496829f150e12066fe77 Mon Sep 17 00:00:00 2001 From: Sebastian Bernauer Date: Fri, 17 Oct 2025 15:39:27 +0200 Subject: [PATCH 07/14] Only derive Serialize --- trino-lb/src/cluster_group_manager.rs | 4 ++-- trino-lb/src/http_server/admin/mod.rs | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/trino-lb/src/cluster_group_manager.rs b/trino-lb/src/cluster_group_manager.rs index 0c99f8b..b98f419 100644 --- a/trino-lb/src/cluster_group_manager.rs +++ b/trino-lb/src/cluster_group_manager.rs @@ -8,7 +8,7 @@ use axum::{Json, body::Body, response::IntoResponse}; use futures::future::try_join_all; use http::{HeaderMap, StatusCode}; use reqwest::Client; -use serde::{Deserialize, Serialize}; +use serde::Serialize; use snafu::{OptionExt, ResultExt, Snafu}; use tracing::{Instrument, debug, info_span, instrument}; use tracing_opentelemetry::OpenTelemetrySpanExt; @@ -88,7 +88,7 @@ pub struct TrinoCluster { pub endpoint: Url, } -#[derive(Clone, Debug, Serialize, Deserialize)] +#[derive(Clone, Debug, Serialize)] pub struct ClusterStats { pub state: ClusterState, pub query_counter: u64, diff --git a/trino-lb/src/http_server/admin/mod.rs b/trino-lb/src/http_server/admin/mod.rs index 2383ce5..a91376f 100644 --- a/trino-lb/src/http_server/admin/mod.rs +++ b/trino-lb/src/http_server/admin/mod.rs @@ -142,7 +142,7 @@ async fn set_cluster_activation( } ensure!( - state.config.cluster_in_config(cluster_name), + state.config.is_cluster_in_config(cluster_name), UnknownClusterSnafu { cluster: cluster_name } From bf71769ac7807c19ebb5e3eaf1dc68434b5dcdb8 Mon Sep 17 00:00:00 2001 From: Sebastian Bernauer Date: Fri, 17 Oct 2025 15:52:25 +0200 Subject: [PATCH 08/14] Use Copy instead of Clone --- trino-lb-core/src/trino_cluster.rs | 2 +- trino-lb/src/http_server/admin/mod.rs | 2 +- trino-lb/src/scaling/mod.rs | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/trino-lb-core/src/trino_cluster.rs b/trino-lb-core/src/trino_cluster.rs index 224d7ae..9c7316e 100644 --- a/trino-lb-core/src/trino_cluster.rs +++ b/trino-lb-core/src/trino_cluster.rs @@ -3,7 +3,7 @@ use std::{fmt::Display, time::SystemTime}; use serde::{Deserialize, Serialize}; use strum::IntoStaticStr; -#[derive(Clone, Debug, Deserialize, Eq, PartialEq, Hash, Serialize, IntoStaticStr)] +#[derive(Copy, Clone, Debug, Deserialize, Eq, PartialEq, Hash, Serialize, IntoStaticStr)] pub enum ClusterState { Unknown, /// Not running at all diff --git a/trino-lb/src/http_server/admin/mod.rs b/trino-lb/src/http_server/admin/mod.rs index a91376f..39f62c7 100644 --- a/trino-lb/src/http_server/admin/mod.rs +++ b/trino-lb/src/http_server/admin/mod.rs @@ -158,7 +158,7 @@ async fn set_cluster_activation( state .persistence - .set_cluster_state(cluster_name, desired_state.clone()) + .set_cluster_state(cluster_name, desired_state) .await .context(SetClusterStateInPersistenceSnafu { cluster: cluster_name, diff --git a/trino-lb/src/scaling/mod.rs b/trino-lb/src/scaling/mod.rs index 87f89ac..cca181c 100644 --- a/trino-lb/src/scaling/mod.rs +++ b/trino-lb/src/scaling/mod.rs @@ -434,7 +434,7 @@ impl Scaler { let me = Arc::clone(&self); let target_state = target_states.get(&cluster.name).unwrap(); join_set.spawn( - me.apply_cluster_target_state(cluster, target_state.clone()) + me.apply_cluster_target_state(cluster, *target_state) .instrument(Span::current()), ); } From 74e4da1df02632269b06588f28dee820d2fdef31 Mon Sep 17 00:00:00 2001 From: Sebastian Bernauer Date: Fri, 17 Oct 2025 15:53:15 +0200 Subject: [PATCH 09/14] Only derive Serialize --- trino-lb/src/http_server/admin/mod.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/trino-lb/src/http_server/admin/mod.rs b/trino-lb/src/http_server/admin/mod.rs index 39f62c7..2ffef1d 100644 --- a/trino-lb/src/http_server/admin/mod.rs +++ b/trino-lb/src/http_server/admin/mod.rs @@ -11,7 +11,7 @@ use axum_extra::{ }; use http::StatusCode; use opentelemetry::KeyValue; -use serde::{Deserialize, Serialize}; +use serde::Serialize; use snafu::{ResultExt, Snafu, ensure}; use tracing::{info, instrument, warn}; use trino_lb_core::{ @@ -119,7 +119,7 @@ pub async fn get_cluster_status( )) } -#[derive(Debug, Deserialize, Serialize)] +#[derive(Debug, Serialize)] pub struct ClusterActivationResponse { state: ClusterState, } From 30da232136da7e321e18fd749352358d99525b0b Mon Sep 17 00:00:00 2001 From: Sebastian Bernauer Date: Mon, 20 Oct 2025 08:11:55 +0200 Subject: [PATCH 10/14] Update trino-lb-core/src/trino_cluster.rs Co-authored-by: Techassi --- trino-lb-core/src/trino_cluster.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/trino-lb-core/src/trino_cluster.rs b/trino-lb-core/src/trino_cluster.rs index 9c7316e..7cb8d24 100644 --- a/trino-lb-core/src/trino_cluster.rs +++ b/trino-lb-core/src/trino_cluster.rs @@ -53,7 +53,7 @@ impl ClusterState { } } - pub fn turn_ready_if_not_deactivated(&self) -> Self { + pub fn mark_ready_if_not_deactivated(&self) -> Self { match self { ClusterState::Deactivated => Self::Deactivated, _ => ClusterState::Ready, From fa828bc81150fa75897b345517d7ab2afaf76962 Mon Sep 17 00:00:00 2001 From: Sebastian Bernauer Date: Mon, 20 Oct 2025 08:15:55 +0200 Subject: [PATCH 11/14] Fix compilation --- trino-lb/src/scaling/mod.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/trino-lb/src/scaling/mod.rs b/trino-lb/src/scaling/mod.rs index cca181c..5520ea6 100644 --- a/trino-lb/src/scaling/mod.rs +++ b/trino-lb/src/scaling/mod.rs @@ -619,7 +619,7 @@ impl Scaler { cluster: &cluster.name, })?; - let new_state = current_state.turn_ready_if_not_deactivated(); + let new_state = current_state.mark_ready_if_not_deactivated(); self.persistence .set_cluster_state(&cluster.name, new_state) From c5270dc3bc03502ff4af3e326176cfa30afb5c72 Mon Sep 17 00:00:00 2001 From: Sebastian Bernauer Date: Mon, 20 Oct 2025 08:23:27 +0200 Subject: [PATCH 12/14] clippy --- trino-lb-persistence/src/redis/mod.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/trino-lb-persistence/src/redis/mod.rs b/trino-lb-persistence/src/redis/mod.rs index 7d5f980..c814230 100644 --- a/trino-lb-persistence/src/redis/mod.rs +++ b/trino-lb-persistence/src/redis/mod.rs @@ -483,8 +483,8 @@ where state: ClusterState, ) -> Result<(), super::Error> { let key = cluster_state_key(cluster_name); - let value = bincode::serde::encode_to_vec(&state, BINCODE_CONFIG) - .context(SerializeToBinarySnafu)?; + let value = + bincode::serde::encode_to_vec(state, BINCODE_CONFIG).context(SerializeToBinarySnafu)?; let _: () = self .connection() From e43e3733aa932af965c6012b8ded195ff00b0e32 Mon Sep 17 00:00:00 2001 From: Sebastian Bernauer Date: Mon, 27 Oct 2025 07:57:08 +0100 Subject: [PATCH 13/14] Add API to get single cluster status --- CHANGELOG.md | 4 +- docs/design.md | 6 +-- trino-lb/src/http_server/admin/mod.rs | 63 ++++++++++++++++++++++++--- trino-lb/src/http_server/mod.rs | 10 +++-- 4 files changed, 70 insertions(+), 13 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index e920687..cae06d0 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -6,8 +6,8 @@ All notable changes to this project will be documented in this file. ### Added -- Support activating and deactivation Trino clusters via API calls to `/admin/activate-cluster/{cluster_name}` and `/admin/deactivate-cluster/{cluster_name}` respectively. For this to work you need to authenticate yourself at trino-lb via basic auth ([#95]). -- Expose cluster statistics at `/admin/cluster-status` ([#95]). +- Support activating and deactivation Trino clusters via API calls to `/admin/clusters/{cluster_name}/activate` and `/admin/clusters/{cluster_name}/deactivate` respectively. For this to work you need to authenticate yourself at trino-lb via basic auth ([#95]). +- Expose cluster statistics at `/admin/clusters/{cluster_name}/status` and `/admin/clusters/status` ([#95]). ### Changed diff --git a/docs/design.md b/docs/design.md index 8c1a667..024cda9 100644 --- a/docs/design.md +++ b/docs/design.md @@ -88,10 +88,10 @@ A deactivated cluster continues to process already running queries, but no new q To safely update a running Trino cluster you can -1. Deactivate the Trino cluster using `POST /admin/deactivate-cluster/{cluster_name}` -2. Wait until all running queries have finished. Tip: You can use `GET /admin/cluster-status` to fetch the current query counter or talk to the Trino cluster directly. +1. Deactivate the Trino cluster using `POST /admin/clusters/{cluster_name}/deactivate` +2. Wait until all running queries have finished. Tip: You can use `GET /admin/clusters/{cluster_name}/status` (or `GET /admin/clusters/status`) to fetch the current query counter or talk to the Trino cluster directly. 3. Safely do modifications to the Trino cluster without any user impact -4. Once you are done with your changes re-activate the Trino cluster again using `POST /admin/activate-cluster/{cluster_name}` +4. Once you are done with your changes re-activate the Trino cluster again using `POST /admin/clusters/{cluster_name}/activate` Important: To activate/deactivate a Trino cluster you need to authenticate against trino-lb. Currently only Basic Auth is supported, you can configure the credentials like this: diff --git a/trino-lb/src/http_server/admin/mod.rs b/trino-lb/src/http_server/admin/mod.rs index 2ffef1d..c29df0a 100644 --- a/trino-lb/src/http_server/admin/mod.rs +++ b/trino-lb/src/http_server/admin/mod.rs @@ -35,12 +35,24 @@ pub enum Error { #[snafu(display("Unknown Trino cluster {cluster:?}"))] UnknownCluster { cluster: TrinoClusterName }, + #[snafu(display("Failed to get cluster state for cluster {cluster:?} from persistence"))] + GetClusterStateFromPersistence { + source: trino_lb_persistence::Error, + cluster: TrinoClusterName, + }, + #[snafu(display("Failed to set cluster state for cluster {cluster:?} in persistence"))] SetClusterStateInPersistence { source: trino_lb_persistence::Error, cluster: TrinoClusterName, }, + #[snafu(display("Failed to get the query counter for cluster {cluster:?} from persistence"))] + GetQueryCounterForGroup { + source: trino_lb_persistence::Error, + cluster: TrinoClusterName, + }, + #[snafu(display("Failed to get all cluster states"))] GetAllClusterStates { source: cluster_group_manager::Error, @@ -54,7 +66,9 @@ impl IntoResponse for Error { Error::NoAdminAuthenticationMethodDefined => StatusCode::UNAUTHORIZED, Error::InvalidAdminCredentials => StatusCode::UNAUTHORIZED, Error::UnknownCluster { .. } => StatusCode::NOT_FOUND, + Error::GetClusterStateFromPersistence { .. } => StatusCode::INTERNAL_SERVER_ERROR, Error::SetClusterStateInPersistence { .. } => StatusCode::INTERNAL_SERVER_ERROR, + Error::GetQueryCounterForGroup { .. } => StatusCode::INTERNAL_SERVER_ERROR, Error::GetAllClusterStates { .. } => StatusCode::INTERNAL_SERVER_ERROR, }; (status_code, format!("{self}")).into_response() @@ -64,7 +78,7 @@ impl IntoResponse for Error { /// (Re)-Activates a Trino Cluster, so that it receives new queries. /// /// This is useful for maintenance actions (in combination with deactivation). -#[instrument(name = "POST /admin/activate-cluster/{cluster_name}", skip(state))] +#[instrument(name = "POST /admin/clusters/{cluster_name}/activate", skip(state))] pub async fn post_activate_cluster( TypedHeader(Authorization(basic_auth)): TypedHeader>, State(state): State>, @@ -81,7 +95,7 @@ pub async fn post_activate_cluster( /// Deactivate a Trino Cluster, so that it doesn't receive any new queries. /// /// This is useful for maintenance actions (in combination with activation). -#[instrument(name = "POST /admin/deactivate-cluster/{cluster_name}", skip(state))] +#[instrument(name = "POST /admin/clusters/{cluster_name}/deactivate", skip(state))] pub async fn post_deactivate_cluster( TypedHeader(Authorization(basic_auth)): TypedHeader>, State(state): State>, @@ -95,16 +109,55 @@ pub async fn post_deactivate_cluster( set_cluster_activation(state, basic_auth, &cluster_name, false).await } -/// Get the status of the Trino clusters -#[instrument(name = "GET /admin/cluster-status", skip(state))] +/// Get the status of a single Trino clusters +#[instrument(name = "/admin/clusters/{cluster_name}/status", skip(state))] pub async fn get_cluster_status( State(state): State>, -) -> Result>, Error> { + Path(cluster_name): Path, +) -> Result, Error> { state .metrics .http_counter .add(1, &[KeyValue::new("resource", "get_cluster_status")]); + ensure!( + state.config.is_cluster_in_config(&cluster_name), + UnknownClusterSnafu { + cluster: cluster_name + } + ); + + let cluster_state = state + .persistence + .get_cluster_state(&cluster_name) + .await + .context(GetClusterStateFromPersistenceSnafu { + cluster: &cluster_name, + })?; + let cluster_query_counter = state + .persistence + .get_cluster_query_count(&cluster_name) + .await + .context(GetQueryCounterForGroupSnafu { + cluster: &cluster_name, + })?; + + Ok(Json(ClusterStats { + state: cluster_state, + query_counter: cluster_query_counter, + })) +} + +/// Get the status of all Trino clusters +#[instrument(name = "/admin/clusters/status", skip(state))] +pub async fn get_all_cluster_status( + State(state): State>, +) -> Result>, Error> { + state + .metrics + .http_counter + .add(1, &[KeyValue::new("resource", "get_all_cluster_status")]); + let cluster_stats = state .cluster_group_manager .get_all_cluster_stats() diff --git a/trino-lb/src/http_server/mod.rs b/trino-lb/src/http_server/mod.rs index a90bb06..47ccfb5 100644 --- a/trino-lb/src/http_server/mod.rs +++ b/trino-lb/src/http_server/mod.rs @@ -123,14 +123,18 @@ pub async fn start_http_server( delete(v1::statement::delete_trino_executing_statement), ) .route( - "/admin/activate-cluster/{cluster_name}", + "/admin/clusters/{cluster_name}/activate", post(admin::post_activate_cluster), ) .route( - "/admin/deactivate-cluster/{cluster_name}", + "/admin/clusters/{cluster_name}/deactivate", post(admin::post_deactivate_cluster), ) - .route("/admin/cluster-status", get(admin::get_cluster_status)) + .route( + "/admin/clusters/{cluster_name}/status", + get(admin::get_cluster_status), + ) + .route("/admin/clusters/status", get(admin::get_all_cluster_status)) .route("/ui/index.html", get(ui::index::get_ui_index)) .route("/ui/query.html", get(ui::query::get_ui_query)) .layer(TraceLayer::new_for_http()) From 8cc8f9703d863f617d4c1bde289aaca2d0116b47 Mon Sep 17 00:00:00 2001 From: Sebastian Bernauer Date: Mon, 27 Oct 2025 10:53:11 +0100 Subject: [PATCH 14/14] Improve snafu error messages --- trino-lb/src/error_formatting.rs | 44 ++++++++++++++++++++++++ trino-lb/src/http_server/admin/mod.rs | 3 +- trino-lb/src/http_server/metrics.rs | 8 +++-- trino-lb/src/http_server/ui/index.rs | 3 +- trino-lb/src/http_server/ui/query.rs | 4 +-- trino-lb/src/http_server/v1/statement.rs | 7 +++- trino-lb/src/main.rs | 1 + 7 files changed, 63 insertions(+), 7 deletions(-) create mode 100644 trino-lb/src/error_formatting.rs diff --git a/trino-lb/src/error_formatting.rs b/trino-lb/src/error_formatting.rs new file mode 100644 index 0000000..be6e042 --- /dev/null +++ b/trino-lb/src/error_formatting.rs @@ -0,0 +1,44 @@ +pub fn snafu_error_to_string(err: &E) -> String { + let mut result = format!("{err}"); + let mut source = err.source(); + while let Some(err) = source { + result.push_str(format!(": {err}").as_str()); + source = err.source(); + } + + result +} + +#[test] +fn test_error_formatting() { + let err = trino_lb_persistence::Error::RedisError { + source: trino_lb_persistence::redis::Error::CreateClient { + source: redis::RedisError::from(std::io::Error::new( + std::io::ErrorKind::ConnectionRefused, + "Connection to Redis was refused", + )), + }, + }; + + assert_eq!(format!("{err}"), "Redis persistence error"); + assert_eq!(format!("{err:#}"), "Redis persistence error"); + assert_eq!( + format!("{err:?}"), + "RedisError { source: CreateClient { source: Connection to Redis was refused } }" + ); + assert_eq!( + snafu_error_to_string(&err), + "Redis persistence error: Failed to create redis client: Connection to Redis was refused: Connection to Redis was refused" + ); + assert_eq!( + format!("{:#}", snafu::Report::from_error(err)), + "Redis persistence error + +Caused by these errors (recent errors listed first): + 1: Failed to create redis client + 2: Connection to Redis was refused + +NOTE: Some redundant information has been removed. Set SNAFU_RAW_ERROR_MESSAGES=1 to disable this behavior. +" + ); +} diff --git a/trino-lb/src/http_server/admin/mod.rs b/trino-lb/src/http_server/admin/mod.rs index c29df0a..4d100f9 100644 --- a/trino-lb/src/http_server/admin/mod.rs +++ b/trino-lb/src/http_server/admin/mod.rs @@ -21,6 +21,7 @@ use trino_lb_persistence::Persistence; use crate::{ cluster_group_manager::{self, ClusterStats}, + error_formatting::snafu_error_to_string, http_server::AppState, }; @@ -71,7 +72,7 @@ impl IntoResponse for Error { Error::GetQueryCounterForGroup { .. } => StatusCode::INTERNAL_SERVER_ERROR, Error::GetAllClusterStates { .. } => StatusCode::INTERNAL_SERVER_ERROR, }; - (status_code, format!("{self}")).into_response() + (status_code, snafu_error_to_string(&self)).into_response() } } diff --git a/trino-lb/src/http_server/metrics.rs b/trino-lb/src/http_server/metrics.rs index 14bea2c..ff5b726 100644 --- a/trino-lb/src/http_server/metrics.rs +++ b/trino-lb/src/http_server/metrics.rs @@ -9,7 +9,7 @@ use prometheus::{Encoder, TextEncoder}; use snafu::{ResultExt, Snafu}; use tracing::{instrument, warn}; -use crate::http_server::AppState; +use crate::{error_formatting::snafu_error_to_string, http_server::AppState}; #[derive(Snafu, Debug)] pub enum Error { @@ -23,7 +23,11 @@ pub enum Error { impl IntoResponse for Error { fn into_response(self) -> Response { warn!(error = ?self, "Error while processing metrics request"); - (StatusCode::INTERNAL_SERVER_ERROR, format!("{self:?}")).into_response() + ( + StatusCode::INTERNAL_SERVER_ERROR, + snafu_error_to_string(&self), + ) + .into_response() } } diff --git a/trino-lb/src/http_server/ui/index.rs b/trino-lb/src/http_server/ui/index.rs index 23378cd..8171bdb 100644 --- a/trino-lb/src/http_server/ui/index.rs +++ b/trino-lb/src/http_server/ui/index.rs @@ -12,6 +12,7 @@ use tracing::{instrument, warn}; use crate::{ cluster_group_manager::{self, ClusterStats}, + error_formatting::snafu_error_to_string, http_server::AppState, }; @@ -33,7 +34,7 @@ impl IntoResponse for Error { Error::GetAllClusterStates { .. } => StatusCode::INTERNAL_SERVER_ERROR, Error::RenderTemplate { .. } => StatusCode::INTERNAL_SERVER_ERROR, }; - (status_code, format!("{self}")).into_response() + (status_code, snafu_error_to_string(&self)).into_response() } } diff --git a/trino-lb/src/http_server/ui/query.rs b/trino-lb/src/http_server/ui/query.rs index bf8f5f9..3f18d1a 100644 --- a/trino-lb/src/http_server/ui/query.rs +++ b/trino-lb/src/http_server/ui/query.rs @@ -11,7 +11,7 @@ use tracing::{instrument, warn}; use trino_lb_core::TrinoLbQueryId; use trino_lb_persistence::Persistence; -use crate::http_server::AppState; +use crate::{error_formatting::snafu_error_to_string, http_server::AppState}; #[derive(Snafu, Debug)] pub enum Error { @@ -36,7 +36,7 @@ impl IntoResponse for Error { Error::QueryIdMissing => StatusCode::BAD_REQUEST, Error::QueryIdNotFound { .. } => StatusCode::NOT_FOUND, }; - (status_code, format!("{self}")).into_response() + (status_code, snafu_error_to_string(&self)).into_response() } } diff --git a/trino-lb/src/http_server/v1/statement.rs b/trino-lb/src/http_server/v1/statement.rs index e7f50e1..be55120 100644 --- a/trino-lb/src/http_server/v1/statement.rs +++ b/trino-lb/src/http_server/v1/statement.rs @@ -28,6 +28,7 @@ use url::Url; use crate::{ cluster_group_manager::{self, SendToTrinoResponse}, + error_formatting::snafu_error_to_string, http_server::AppState, maintenance::leftover_queries::UPDATE_QUEUED_QUERY_LAST_ACCESSED_INTERVAL, }; @@ -131,7 +132,11 @@ pub enum Error { impl IntoResponse for Error { fn into_response(self) -> Response { warn!(error = ?self, "Error while processing request"); - (StatusCode::INTERNAL_SERVER_ERROR, format!("{self:?}")).into_response() + ( + StatusCode::INTERNAL_SERVER_ERROR, + snafu_error_to_string(&self), + ) + .into_response() } } diff --git a/trino-lb/src/main.rs b/trino-lb/src/main.rs index 8231452..7f98326 100644 --- a/trino-lb/src/main.rs +++ b/trino-lb/src/main.rs @@ -23,6 +23,7 @@ use crate::{args::Args, http_server::start_http_server}; mod args; mod cluster_group_manager; +mod error_formatting; mod http_server; mod maintenance; mod metrics;