From a0c4cd7dec7db574e3a89b496cecdbddcdc5e8df Mon Sep 17 00:00:00 2001 From: slinkydeveloper Date: Tue, 10 Nov 2026 17:25:17 +0100 Subject: [PATCH 1/2] Sessions: large databases' checkpoints in an object store (RESTATE_SQL_OBJECT_STORE) Upgrade restate-sdk-shared-core to 8.5.0, with its object store backends. Set RESTATE_SQL_OBJECT_STORE to `s3://bucket/path`, `gs://bucket/path`, `az://container/path` or `file:///a/directory`, and a database whose packs in Restate pass 4 MiB moves them to the object store in one upload. Credentials come from the provider's variables (`AWS_*`, `GOOGLE_*`, `AZURE_*`); MinIO or R2 is `s3://` with `AWS_ENDPOINT`. Unset, every pack stays in Restate, as before. The store is shared-core's `state::ObjectStoreL1`, made once per process; each namespace gets its own directory. Its requests are reqwest's, which need a tokio runtime, and a session's calls are polled on the asyncio loop's thread: the store's futures alone are polled inside pyo3-async-runtimes' runtime (`InRuntime`). Without it, the first request panics with "there is no reactor running". Crypto: `aws_lc_rs` instead of `rust_crypto`. The object stores' backends are aws-lc; with it, the tunnel's TLS and request identity use aws-lc too, and ring is no longer built. Co-Authored-By: Claude Opus 5.5 --- Cargo.lock | 809 ++++++++++++++++++--------------- Cargo.toml | 12 +- src/sessions.rs | 72 ++- tests/sessions_object_store.py | 126 +++++ 4 files changed, 659 insertions(+), 360 deletions(-) create mode 100644 tests/sessions_object_store.py diff --git a/Cargo.lock b/Cargo.lock index dfad8881..cb9f9040 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -158,10 +158,28 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f2032f911046de80f0a198e0901378627c33f59ea0ac00e363d481118bd70a53" [[package]] -name = "base16ct" -version = "0.2.0" +name = "aws-lc-rs" +version = "1.19.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "048006790404103c488e6c5616b3e7e702a71292aadda08e8f7698a9e0d2eb53" +dependencies = [ + "aws-lc-sys", + "untrusted 0.7.1", + "zeroize", +] + +[[package]] +name = "aws-lc-sys" +version = "0.47.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4c7f02d4ea65f2c1853089ffd8d2787bdbc63de2f0d29dedbcf8ccdfa0ccd4cf" +checksum = "8bfbe32ac36b3c428696ce315464181bc4029d689fd58e3f2a4e58c252242f52" +dependencies = [ + "cc", + "cmake", + "dunce", + "fs_extra", + "pkg-config", +] [[package]] name = "base64" @@ -170,10 +188,10 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "72b3254f16251a8381aa12e40e3c4d2f0199f8c6508fbecb9d91f575e0fbb8c6" [[package]] -name = "base64ct" -version = "1.8.3" +name = "base64" +version = "0.23.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2af50177e190e07a26ab74f8b1efbfe2ef87da2116221318cb1c2e82baf7de06" +checksum = "ac07cdecf99051d9a5238b80f35af32cdeba5b336e55d957b318b50137e18da5" [[package]] name = "bigdecimal" @@ -206,15 +224,6 @@ dependencies = [ "wyz", ] -[[package]] -name = "block-buffer" -version = "0.10.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3078c7629b62d3f0439517fa394996acacc5cbc91c5a20d8c658e77abd503a71" -dependencies = [ - "generic-array", -] - [[package]] name = "block-buffer" version = "0.12.1" @@ -340,6 +349,7 @@ dependencies = [ "iana-time-zone", "js-sys", "num-traits", + "serde", "wasm-bindgen", "windows-link", ] @@ -354,6 +364,15 @@ dependencies = [ "inout", ] +[[package]] +name = "cmake" +version = "0.1.58" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c0f78a02292a74a88ac736019ab962ece0bc380e3f977bf72e376c5d78ff0678" +dependencies = [ + "cc", +] + [[package]] name = "cmsketch" version = "0.2.4" @@ -379,12 +398,6 @@ dependencies = [ "crossbeam-utils", ] -[[package]] -name = "const-oid" -version = "0.9.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c2459377285ad874054d797f3ccebf984978aa39129f6eafde5cdc8315b612f8" - [[package]] name = "const-oid" version = "0.10.2" @@ -446,6 +459,16 @@ dependencies = [ "libc", ] +[[package]] +name = "crc-fast" +version = "1.10.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e75b2483e97a5a7da73ac68a05b629f9c53cff58d8ed1c77866079e18b00dba5" +dependencies = [ + "digest 0.10.7", + "spin", +] + [[package]] name = "crc32c" version = "0.6.9" @@ -485,18 +508,6 @@ version = "0.8.23" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a31eee39dddec8330830986fcd7625edb5a24ec90ea038215273bbc3adb08ac6" -[[package]] -name = "crypto-bigint" -version = "0.5.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0dc92fb57ca44df6db8059111ab3af99a63d5d0f8375d9972e319a379c6bab76" -dependencies = [ - "generic-array", - "rand_core 0.6.4", - "subtle", - "zeroize", -] - [[package]] name = "crypto-common" version = "0.1.7" @@ -526,60 +537,19 @@ dependencies = [ "cipher", ] -[[package]] -name = "curve25519-dalek" -version = "4.1.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "97fb8b7c4503de7d6ae7b42ab72a5a59857b4c937ec27a3d4539dba95b5ab2be" -dependencies = [ - "cfg-if", - "cpufeatures 0.2.17", - "curve25519-dalek-derive", - "digest 0.10.7", - "fiat-crypto", - "rustc_version", - "subtle", - "zeroize", -] - -[[package]] -name = "curve25519-dalek-derive" -version = "0.1.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f46882e17999c6cc590af592290432be3bce0428cb0d5f8b6715e4dc7b383eb3" -dependencies = [ - "proc-macro2", - "quote", - "syn 2.0.119", -] - [[package]] name = "data-encoding" version = "2.11.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "4583a4551df46e2792f82ceeac45e850d2e2d5debba0b91f102385cda5b11f06" -[[package]] -name = "der" -version = "0.7.10" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e7c1832837b905bbfb5101e07cc24c8deddf52f93225eee6ead5f4d63d53ddcb" -dependencies = [ - "const-oid 0.9.6", - "pem-rfc7468", - "zeroize", -] - [[package]] name = "digest" version = "0.10.7" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9ed9a281f7bc9b7576e61468ba615a66a5c8cfdff42420a70aa82701a3b1e292" dependencies = [ - "block-buffer 0.10.4", - "const-oid 0.9.6", "crypto-common 0.1.7", - "subtle", ] [[package]] @@ -588,8 +558,8 @@ version = "0.11.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f1dd6dbb5841937940781866fa1281a1ff7bd3bf827091440879f9994983d5c2" dependencies = [ - "block-buffer 0.12.1", - "const-oid 0.10.2", + "block-buffer", + "const-oid", "crypto-common 0.2.2", ] @@ -605,42 +575,10 @@ dependencies = [ ] [[package]] -name = "ecdsa" -version = "0.16.9" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ee27f32b5c5292967d2d4a9d7f1e0b0aed2c15daded5a60300e4abb9d8020bca" -dependencies = [ - "der", - "digest 0.10.7", - "elliptic-curve", - "rfc6979", - "signature", - "spki", -] - -[[package]] -name = "ed25519" -version = "2.2.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "115531babc129696a58c64a4fef0a8bf9e9698629fb97e9e40767d235cfbcd53" -dependencies = [ - "pkcs8", - "signature", -] - -[[package]] -name = "ed25519-dalek" -version = "2.2.0" +name = "dunce" +version = "1.0.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "70e796c081cee67dc755e1a36a0a172b897fab85fc3f6bc48307991f64e4eca9" -dependencies = [ - "curve25519-dalek", - "ed25519", - "serde", - "sha2 0.10.9", - "subtle", - "zeroize", -] +checksum = "92773504d58c093f6de2459af4af33faa518c13451eb8f2b5698ed3d36e7c813" [[package]] name = "either" @@ -648,27 +586,6 @@ version = "1.19.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0e9c71c2167ca323c882b99918929403426e2373ea17242ff5653e0d5e1058be" -[[package]] -name = "elliptic-curve" -version = "0.13.8" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b5e6043086bf7973472e0c7dff2142ea0b680d30e18d9cc40f267efbf222bd47" -dependencies = [ - "base16ct", - "crypto-bigint", - "digest 0.10.7", - "ff", - "generic-array", - "group", - "hkdf", - "pem-rfc7468", - "pkcs8", - "rand_core 0.6.4", - "sec1", - "subtle", - "zeroize", -] - [[package]] name = "equivalent" version = "1.0.3" @@ -718,22 +635,6 @@ version = "2.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "da7c62ceae207dd37ea5b845da6a0696c799f85e97da1ab5b7910be3c1c80223" -[[package]] -name = "ff" -version = "0.13.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c0b50bfb653653f9ca9095b427bed08ab8d75a137839d9ad64eb11810d5b6393" -dependencies = [ - "rand_core 0.6.4", - "subtle", -] - -[[package]] -name = "fiat-crypto" -version = "0.2.9" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "28dea519a9695b9977216879a3ebfddf92f1c08c05d984f8996aecd6ecdc811d" - [[package]] name = "find-msvc-tools" version = "0.1.15" @@ -882,6 +783,12 @@ dependencies = [ "windows-sys 0.59.0", ] +[[package]] +name = "fs_extra" +version = "1.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "42703706b716c37f96a77aea830392ad231f44c9e9a67872fa5548707e11b11c" + [[package]] name = "funty" version = "2.0.0" @@ -999,7 +906,6 @@ checksum = "85649ca51fd72272d7821adaf274ad91c288277713d9c18820d8499a7ff69e9a" dependencies = [ "typenum", "version_check", - "zeroize", ] [[package]] @@ -1053,17 +959,6 @@ dependencies = [ "polyval", ] -[[package]] -name = "group" -version = "0.13.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f0f9ef7462f7c099f518d754361858f86d8a07af53ba9af0fe635bbccb151a63" -dependencies = [ - "ff", - "rand_core 0.6.4", - "subtle", -] - [[package]] name = "h2" version = "0.4.20" @@ -1188,24 +1083,6 @@ dependencies = [ "tracing", ] -[[package]] -name = "hkdf" -version = "0.12.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7b5f8eb2ad728638ea2c7d47a21db23b7b58a72ed6a38256b8a1849f15fbbdf7" -dependencies = [ - "hmac", -] - -[[package]] -name = "hmac" -version = "0.12.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6c49c37c09c17a53d937dfbb742eb3a961d65a994e6bcdcf37e7399d0cc8ab5e" -dependencies = [ - "digest 0.10.7", -] - [[package]] name = "hostname" version = "0.4.2" @@ -1250,12 +1127,24 @@ dependencies = [ "pin-project-lite", ] +[[package]] +name = "httparse" +version = "1.10.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6dbf3de79e51f3d586ab4cb9d5c3e2c14aa28ed23d180cf89b4df0454a69cc87" + [[package]] name = "httpdate" version = "1.0.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "df3b46402a9d5adb4c86a0cf463f42e19994e3ee891101b1841f30a545cb49a9" +[[package]] +name = "humantime" +version = "2.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "15cdd26707701c53297e2fa6afb323d55fbc1d0810c3aec078ae3ef0424c3c15" + [[package]] name = "hybrid-array" version = "0.4.15" @@ -1278,10 +1167,28 @@ dependencies = [ "h2", "http", "http-body", + "httparse", "httpdate", + "itoa", "pin-project-lite", "smallvec", "tokio", + "want", +] + +[[package]] +name = "hyper-rustls" +version = "0.27.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dfa8e654703247911e29c23fbeaa261834bd9bb74efba2f9acddc37bfb127f53" +dependencies = [ + "http", + "hyper", + "hyper-util", + "rustls", + "tokio", + "tokio-rustls", + "tower-service", ] [[package]] @@ -1290,12 +1197,22 @@ version = "0.1.21" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ddc03d96684f9226b8a787cdb71488417b53ab5ea8fdb1dac946cb9431cc8bff" dependencies = [ + "base64 0.23.1", "bytes", + "futures-channel", + "futures-util", "http", "http-body", + "httparse", "hyper", + "ipnet", + "libc", + "percent-encoding", "pin-project-lite", + "socket2", "tokio", + "tower-service", + "tracing", ] [[package]] @@ -1659,18 +1576,12 @@ version = "10.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "eba32bfb4ffdeaca3e34431072faf01745c9b26d25504aa7a6cf5684334fc4fc" dependencies = [ - "base64", - "ed25519-dalek", + "aws-lc-rs", + "base64 0.22.1", "getrandom 0.2.17", - "hmac", "js-sys", - "p256", - "p384", - "rand 0.8.8", - "rsa", "serde", "serde_json", - "sha2 0.10.9", "signature", "zeroize", ] @@ -1680,9 +1591,6 @@ name = "lazy_static" version = "1.5.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "20870f649af7073d53e38067b2a84312175d56ea15217e1b15bc83506ec50afb" -dependencies = [ - "spin", -] [[package]] name = "libc" @@ -1766,6 +1674,12 @@ dependencies = [ "tracing-subscriber", ] +[[package]] +name = "lru-slab" +version = "0.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4050469837a6ff301cd14c1f8f24f88549e6d548f24f64e2148eb0f72cebc51f" + [[package]] name = "lz4" version = "1.28.1" @@ -1794,6 +1708,16 @@ dependencies = [ "regex-automata", ] +[[package]] +name = "md-5" +version = "0.11.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "69b6441f590336821bb897fb28fc622898ccceb1d6cea3fde5ea86b090c4de98" +dependencies = [ + "cfg-if", + "digest 0.11.3", +] + [[package]] name = "mea" version = "0.6.7" @@ -1885,6 +1809,18 @@ version = "0.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "27b02d87554356db9e9a873add8782d4ea6e3e58ea071a9adb9a2e8ddb884a8b" +[[package]] +name = "nix" +version = "0.31.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cf20d2fde8ff38632c426f1165ed7436270b44f199fc55284c38276f9db47c3d" +dependencies = [ + "bitflags", + "cfg-if", + "cfg_aliases", + "libc", +] + [[package]] name = "nu-ansi-term" version = "0.50.3" @@ -1904,22 +1840,6 @@ dependencies = [ "num-traits", ] -[[package]] -name = "num-bigint-dig" -version = "0.8.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e661dda6640fad38e827a6d4a310ff4763082116fe217f279885c97f511bb0b7" -dependencies = [ - "lazy_static", - "libm", - "num-integer", - "num-iter", - "num-traits", - "rand 0.8.8", - "smallvec", - "zeroize", -] - [[package]] name = "num-integer" version = "0.1.47" @@ -1929,16 +1849,6 @@ dependencies = [ "num-traits", ] -[[package]] -name = "num-iter" -version = "0.1.46" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c92800bd69a1eac91786bcfe9da64a897eb72911b8dc3095decbd07429e8048b" -dependencies = [ - "num-integer", - "num-traits", -] - [[package]] name = "num-traits" version = "0.2.19" @@ -1946,7 +1856,6 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "071dfc062690e90b734c0b2273ce72ad0ffa95f0c74596bc250dcfd960262841" dependencies = [ "autocfg", - "libm", ] [[package]] @@ -1959,6 +1868,49 @@ dependencies = [ "libc", ] +[[package]] +name = "object_store" +version = "0.14.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f1796bc93603f78c5760a69f2d58badc9618d22adade0a95385bb2adbae4eb94" +dependencies = [ + "async-trait", + "aws-lc-rs", + "base64 0.23.1", + "bytes", + "chrono", + "crc-fast", + "form_urlencoded", + "futures-channel", + "futures-core", + "futures-util", + "http", + "http-body-util", + "httparse", + "humantime", + "hyper", + "itertools 0.15.0", + "md-5", + "nix", + "parking_lot", + "percent-encoding", + "quick-xml", + "rand 0.10.3", + "reqwest", + "rustls-pki-types", + "serde", + "serde_json", + "serde_urlencoded", + "thiserror", + "tokio", + "tracing", + "url", + "walkdir", + "wasm-bindgen-futures", + "web-time", + "windows-sys 0.61.2", +] + [[package]] name = "once_cell" version = "1.21.4" @@ -1987,30 +1939,6 @@ version = "3.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c1b04fb49957986fdce4d6ee7a65027d55d4b6d2265e5848bbb507b58ccfdb6f" -[[package]] -name = "p256" -version = "0.13.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c9863ad85fa8f4460f9c48cb909d38a0d689dba1f6f6988a5e3e0d31071bcd4b" -dependencies = [ - "ecdsa", - "elliptic-curve", - "primeorder", - "sha2 0.10.9", -] - -[[package]] -name = "p384" -version = "0.13.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fe42f1670a52a47d448f14b6a5c61dd78fce51856e68edaa38f7ae3a46b8d6b6" -dependencies = [ - "ecdsa", - "elliptic-curve", - "primeorder", - "sha2 0.10.9", -] - [[package]] name = "pack1" version = "1.1.0" @@ -2055,15 +1983,6 @@ version = "0.2.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "2ee67f1008b1ba2321834326597b8e186293b049a023cdef258527550b9935b4" -[[package]] -name = "pem-rfc7468" -version = "0.7.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "88b39c9bfcfc231068454382784bb460aae594343fb030d46e9f50a645418412" -dependencies = [ - "base64ct", -] - [[package]] name = "percent-encoding" version = "2.3.2" @@ -2096,27 +2015,6 @@ version = "0.2.17" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a89322df9ebe1c1578d689c92318e070967d1042b512afbe49518723f4e6d5cd" -[[package]] -name = "pkcs1" -version = "0.7.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c8ffb9f10fa047879315e6625af03c164b16962a5368d724ed16323b68ace47f" -dependencies = [ - "der", - "pkcs8", - "spki", -] - -[[package]] -name = "pkcs8" -version = "0.10.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f950b2377845cebe5cf8b5165cb3cc1a5e0fa5cfa3e1f7f55707d8fd82e0a7b7" -dependencies = [ - "der", - "spki", -] - [[package]] name = "pkg-config" version = "0.3.34" @@ -2186,15 +2084,6 @@ dependencies = [ "num-traits", ] -[[package]] -name = "primeorder" -version = "0.13.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "353e1ca18966c16d9deb1c69278edbc5f194139612772bd9537af60ac231e1e6" -dependencies = [ - "elliptic-curve", -] - [[package]] name = "proc-macro2" version = "1.0.107" @@ -2298,6 +2187,73 @@ dependencies = [ "syn 3.0.9", ] +[[package]] +name = "quick-xml" +version = "0.41.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e660451e55124f798a69a5af3f49ccfbefbd41910eefd25caf2393e1f3473ec1" +dependencies = [ + "memchr", + "serde", +] + +[[package]] +name = "quinn" +version = "0.11.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4051e23e9185c255a7e33ef59cdbca87a22d359052eecd22fc6b901fb37d9d11" +dependencies = [ + "bytes", + "cfg_aliases", + "pin-project-lite", + "quinn-proto", + "quinn-udp", + "rustc-hash", + "rustls", + "socket2", + "thiserror", + "tokio", + "tracing", + "web-time", +] + +[[package]] +name = "quinn-proto" +version = "0.11.19" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0e750cca55fe4f0439a15d0bb529da9651e79993e8e72c61a899a36d462befbe" +dependencies = [ + "aws-lc-rs", + "bytes", + "getrandom 0.4.3", + "lru-slab", + "rand 0.10.3", + "rand_pcg 0.10.2", + "ring", + "rustc-hash", + "rustls", + "rustls-pki-types", + "slab", + "thiserror", + "tinyvec", + "tracing", + "web-time", +] + +[[package]] +name = "quinn-udp" +version = "0.5.16" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "af66907df18639dcf4db56ca65490cabc4b27a97dbadd96f2926cca73298f016" +dependencies = [ + "cfg_aliases", + "libc", + "once_cell", + "socket2", + "tracing", + "windows-sys 0.61.2", +] + [[package]] name = "quote" version = "1.0.47" @@ -2410,6 +2366,15 @@ dependencies = [ "rand_core 0.6.4", ] +[[package]] +name = "rand_pcg" +version = "0.10.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "caa0f4137e1c0a72f4c651489402276c8e8e1cf081f3b0ba156d2cbeef09e86a" +dependencies = [ + "rand_core 0.10.1", +] + [[package]] name = "rapidhash" version = "4.5.1" @@ -2457,6 +2422,45 @@ version = "0.8.11" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d6f6ff9a378485b298a5286656da665ba74413d36db0979633275d2e708145d4" +[[package]] +name = "reqwest" +version = "0.13.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "16a1cfa75cc186dd73d5818e510e042e40927bccc9c236b061cea97e1eb08029" +dependencies = [ + "base64 0.23.1", + "bytes", + "futures-core", + "futures-util", + "h2", + "http", + "http-body", + "http-body-util", + "hyper", + "hyper-rustls", + "hyper-util", + "js-sys", + "log", + "percent-encoding", + "pin-project-lite", + "quinn", + "rustls", + "rustls-pki-types", + "rustls-platform-verifier", + "sync_wrapper", + "tokio", + "tokio-rustls", + "tokio-util", + "tower", + "tower-http", + "tower-service", + "url", + "wasm-bindgen", + "wasm-bindgen-futures", + "wasm-streams", + "web-sys", +] + [[package]] name = "resolv-conf" version = "0.7.6" @@ -2486,11 +2490,11 @@ dependencies = [ [[package]] name = "restate-sdk-shared-core" -version = "8.4.0" +version = "8.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "08cd57336afa55c59eb52b63a9d46608677718332f2a813014c37acad74f9fe4" +checksum = "3a955c21a0cd1d0cebbad2878355c9c954282f43f46a9bf37caf10afd36b1a17" dependencies = [ - "base64", + "base64 0.22.1", "bs58", "bytes", "bytes-utils", @@ -2509,6 +2513,7 @@ dependencies = [ "hyper", "hyper-util", "jsonwebtoken", + "object_store", "parking_lot", "pastey", "prost", @@ -2516,7 +2521,7 @@ dependencies = [ "rustls", "rustls-native-certs", "serde", - "sha2 0.11.1", + "sha2", "socket2", "strum 0.27.2", "thiserror", @@ -2525,20 +2530,11 @@ dependencies = [ "tokio-util", "tracing", "turso_core", + "url", "uuid", "zstd-safe", ] -[[package]] -name = "rfc6979" -version = "0.4.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f8dd2a808d456c4a54e300a23e9f5a67e122c3024119acbfd73e3bf664491cb2" -dependencies = [ - "hmac", - "subtle", -] - [[package]] name = "ring" version = "0.17.14" @@ -2549,7 +2545,7 @@ dependencies = [ "cfg-if", "getrandom 0.2.17", "libc", - "untrusted", + "untrusted 0.9.0", "windows-sys 0.52.0", ] @@ -2563,26 +2559,6 @@ dependencies = [ "byteorder", ] -[[package]] -name = "rsa" -version = "0.9.10" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b8573f03f5883dcaebdfcf4725caa1ecb9c15b2ef50c43a07b816e06799bb12d" -dependencies = [ - "const-oid 0.9.6", - "digest 0.10.7", - "num-bigint-dig", - "num-integer", - "num-traits", - "pkcs1", - "pkcs8", - "rand_core 0.6.4", - "signature", - "spki", - "subtle", - "zeroize", -] - [[package]] name = "rustc-hash" version = "2.1.3" @@ -2627,8 +2603,8 @@ version = "0.23.46" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "48e13bd8c0e9365c43cfa5c9e8f9ad49d3c8444926c9aac819e0e4dc503c8fdf" dependencies = [ + "aws-lc-rs", "once_cell", - "ring", "rustls-pki-types", "rustls-webpki", "subtle", @@ -2653,18 +2629,47 @@ version = "1.15.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "2f4925028c7eb5d1fcdaf196971378ed9d2c1c4efc7dc5d011256f76c99c0a96" dependencies = [ + "web-time", "zeroize", ] +[[package]] +name = "rustls-platform-verifier" +version = "0.7.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1167586491e2b18b8bfbb293e8180ec17c201c4f076d7cb3070ca964e7598f98" +dependencies = [ + "core-foundation 0.10.1", + "core-foundation-sys", + "jni", + "log", + "once_cell", + "rustls", + "rustls-native-certs", + "rustls-platform-verifier-android", + "rustls-webpki", + "security-framework", + "security-framework-sys", + "webpki-root-certs", + "windows-sys 0.61.2", +] + +[[package]] +name = "rustls-platform-verifier-android" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "eec689c0bc40ff2458a5977b6619cb718087084a18e02a131c599b62d05e1a5f" + [[package]] name = "rustls-webpki" version = "0.103.16" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "4443b1b6d39d7c663139942cc4558262562d2c84123bb6282ef177009ca8b281" dependencies = [ + "aws-lc-rs", "ring", "rustls-pki-types", - "untrusted", + "untrusted 0.9.0", ] [[package]] @@ -2709,20 +2714,6 @@ version = "1.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "94143f37725109f92c262ed2cf5e59bce7498c01bcc1502d7b9afe439a4e9f49" -[[package]] -name = "sec1" -version = "0.7.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d3e97a565f76233a6003f9f5c54be1d9c5bdfa3eccfb189469f11ec4901c47dc" -dependencies = [ - "base16ct", - "der", - "generic-array", - "pkcs8", - "subtle", - "zeroize", -] - [[package]] name = "security-framework" version = "3.7.0" @@ -2796,21 +2787,22 @@ dependencies = [ ] [[package]] -name = "sha1_smol" -version = "1.0.1" +name = "serde_urlencoded" +version = "0.7.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bbfa15b3dddfee50a0fff136974b3e1bde555604ba463834a7eb7deb6417705d" +checksum = "d3491c14715ca2294c4d6a88f15e84739788c1d030eed8c110436aafdaa2f3fd" +dependencies = [ + "form_urlencoded", + "itoa", + "ryu", + "serde", +] [[package]] -name = "sha2" -version = "0.10.9" +name = "sha1_smol" +version = "1.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a7507d819769d01a365ab707794a4084392c824f54a7a6a7862f8c3d0892b283" -dependencies = [ - "cfg-if", - "cpufeatures 0.2.17", - "digest 0.10.7", -] +checksum = "bbfa15b3dddfee50a0fff136974b3e1bde555604ba463834a7eb7deb6417705d" [[package]] name = "sha2" @@ -2852,7 +2844,7 @@ dependencies = [ "owo-colors", "rand 0.8.8", "rand_core 0.6.4", - "rand_pcg", + "rand_pcg 0.3.1", "scoped-tls", "smallvec", "tracing", @@ -2864,7 +2856,6 @@ version = "2.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "77549399552de45a898a580c1b41d445bf730df867cc44e6c0233bbc4b8329de" dependencies = [ - "digest 0.10.7", "rand_core 0.6.4", ] @@ -2926,19 +2917,9 @@ checksum = "c4fdfe13e1c42e45f497416afb8dc4e783bf0e25b7be9077c1c77c5fb14cb998" [[package]] name = "spin" -version = "0.9.9" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3763264f6b73151db08c50ff20d7d8a0b8796e021cdea7ceedad07b80155fa0e" - -[[package]] -name = "spki" -version = "0.7.3" +version = "0.10.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d91ed6c858b01f942cd56b37a94b3e0a1798290327d1236e4d9cf4eaca44d29d" -dependencies = [ - "base64ct", - "der", -] +checksum = "023a211cb3138dbc438680b32560ad89f699977624c9f8dbb95a47d5b4c07dd3" [[package]] name = "stable_deref_trait" @@ -3017,6 +2998,15 @@ dependencies = [ "unicode-ident", ] +[[package]] +name = "sync_wrapper" +version = "1.0.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0bf256ce5efdfa370213c1dabab5935a12e49f2c58d15e9eac2870d3b4f27263" +dependencies = [ + "futures-core", +] + [[package]] name = "synstructure" version = "0.14.0" @@ -3188,6 +3178,51 @@ dependencies = [ "tokio", ] +[[package]] +name = "tower" +version = "0.5.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ebe5ef63511595f1344e2d5cfa636d973292adc0eec1f0ad45fae9f0851ab1d4" +dependencies = [ + "futures-core", + "futures-util", + "pin-project-lite", + "sync_wrapper", + "tokio", + "tower-layer", + "tower-service", +] + +[[package]] +name = "tower-http" +version = "0.6.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4cfcf7e2740e6fc6d4d688b4ef00650406bb94adf4731e43c096c3a19fe40840" +dependencies = [ + "bitflags", + "bytes", + "futures-util", + "http", + "http-body", + "pin-project-lite", + "tower", + "tower-layer", + "tower-service", + "url", +] + +[[package]] +name = "tower-layer" +version = "0.3.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "121c2a6cda46980bb0fcd1647ffaf6cd3fc79a013de288782836f6df9c48780e" + +[[package]] +name = "tower-service" +version = "0.3.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8df9b6e13f2d32c91b9bd719c00d1958837bc7dec474d94952798cc8e69eeec3" + [[package]] name = "tracing" version = "0.1.44" @@ -3249,6 +3284,12 @@ dependencies = [ "tracing-log", ] +[[package]] +name = "try-lock" +version = "0.2.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e421abadd41a4225275504ea4d6566923418b7f05506fbc9c0fe86ba7396114b" + [[package]] name = "turso_core" version = "0.8.2" @@ -3403,6 +3444,12 @@ dependencies = [ "subtle", ] +[[package]] +name = "untrusted" +version = "0.7.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a156c684c91ea7d62626509bce3cb4e1d9ed5c4d978f7b4352658f96a4c26b4a" + [[package]] name = "untrusted" version = "0.9.0" @@ -3479,6 +3526,15 @@ dependencies = [ "winapi-util", ] +[[package]] +name = "want" +version = "0.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ec4cdd0dd910afe868b7ef477227d8d538b46b3075031afee8a9f2acb0a2ed0b" +dependencies = [ + "try-lock", +] + [[package]] name = "wasi" version = "0.11.1+wasi-snapshot-preview1" @@ -3506,6 +3562,17 @@ dependencies = [ "wasm-bindgen-shared", ] +[[package]] +name = "wasm-bindgen-futures" +version = "0.4.80" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5e14e0327cb5368ad60ccb22d04a9827a693c95a926d8d125e9fa39e0baec501" +dependencies = [ + "js-sys", + "tokio", + "wasm-bindgen", +] + [[package]] name = "wasm-bindgen-macro" version = "0.2.130" @@ -3538,6 +3605,29 @@ dependencies = [ "unicode-ident", ] +[[package]] +name = "wasm-streams" +version = "0.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9d1ec4f6517c9e11ae630e200b2b65d193279042e28edd4a2cda233e46670bbb" +dependencies = [ + "futures-util", + "js-sys", + "wasm-bindgen", + "wasm-bindgen-futures", + "web-sys", +] + +[[package]] +name = "web-sys" +version = "0.3.107" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d7d179596ff5ec0f6de4db64d54011bde6289cc49603d3a6e4ce3f329207ab88" +dependencies = [ + "js-sys", + "wasm-bindgen", +] + [[package]] name = "web-time" version = "1.1.0" @@ -3548,6 +3638,15 @@ dependencies = [ "wasm-bindgen", ] +[[package]] +name = "webpki-root-certs" +version = "1.0.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e49d0e65abc00c142e8f9428da991da9f1a250c39be97459901eb12b9b49f62a" +dependencies = [ + "rustls-pki-types", +] + [[package]] name = "widestring" version = "1.2.1" diff --git a/Cargo.toml b/Cargo.toml index 3ff17370..1569d04b 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -17,13 +17,19 @@ pyo3-async-runtimes = { version = "0.30", features = ["tokio-runtime"] } tracing = "0.1" tracing-subscriber = { version = "0.3", features = ["fmt", "env-filter"] } # The feature `sql` is the sessions' storage: the SQLite-compatible database kept in an -# object's state, with its page cache (foyer); `tunnel` is Restate Cloud's. -restate-sdk-shared-core = { version = "8.4.0", features = [ +# object's state, with its page cache (foyer); `object_store_*`, the object stores its +# checkpoints may outgrow Restate into (RESTATE_SQL_OBJECT_STORE: S3, GCS, Azure, or a +# directory); `tunnel` is Restate Cloud's. `aws_lc_rs` is the crypto of all of them (the +# tunnel's TLS, request identity's signatures), as the object stores' must be aws-lc. +restate-sdk-shared-core = { version = "8.5.0", features = [ "request_identity", "sha2_random_seed", - "rust_crypto", + "aws_lc_rs", "tunnel", "sql", + "object_store_aws", + "object_store_gcp", + "object_store_azure", ] } # ASGI bridge for the tunnel diff --git a/src/sessions.rs b/src/sessions.rs index f9fc8595..01cd9428 100644 --- a/src/sessions.rs +++ b/src/sessions.rs @@ -38,7 +38,10 @@ //! in the order of the requests, so that a read sees the writes before it. //! //! Every database of the process is kept warm in one page cache -//! ([`page_cache`]). +//! ([`page_cache`]), and keeps the checkpoints it outgrows Restate with in +//! the object store `RESTATE_SQL_OBJECT_STORE` names, if any +//! ([`object_store`]). That store's requests are reqwest's, which need a +//! tokio runtime: they alone are polled inside one ([`InRuntime`]). use crate::PyVM; use bytes::Bytes; use futures::channel::oneshot; @@ -50,12 +53,15 @@ use pyo3::sync::PyOnceLock; use pyo3::types::{PyBool, PyByteArray, PyBytes, PyFloat, PyInt, PyList, PyString, PyTuple}; use pyo3::IntoPyObjectExt; use restate_sdk_shared_core::sql::{self, Numeric, Value}; -use restate_sdk_shared_core::state::{self, KvStore, PageCache, PageCacheConfig}; +use restate_sdk_shared_core::state::{ + self, BlobStore, KvStore, ObjectStoreBlobs, ObjectStoreL1, PageCache, PageCacheConfig, +}; use restate_sdk_shared_core::{Value as VmValue, VM}; use std::borrow::Cow; use std::collections::HashMap; use std::future::Future; use std::io; +use std::ops::Range; use std::pin::Pin; use std::sync::atomic::{AtomicBool, Ordering}; use std::sync::{mpsc, Arc, Mutex, OnceLock}; @@ -594,7 +600,65 @@ fn cache_config() -> io::Result> { })) } +/// The process's object store, the one `RESTATE_SQL_OBJECT_STORE` names +/// ([`ObjectStoreL1::from_env`]: `s3://bucket/path`, `gs://bucket/path`, +/// `az://container/path` or `file:///a/directory`, with the provider's own +/// `AWS_*`, `GOOGLE_*` or `AZURE_*` variables), made once: `None` when it is +/// unset or empty, and every pack stays in Restate. Its databases share it, +/// and its HTTP client. A value that names no store fails every open, with +/// its message, as a page cache size that is not one does. Once a database +/// has moved packs to the store, every process that serves it needs the same +/// value, or its opens fail. +fn object_store() -> io::Result> { + static L1: Mutex>> = Mutex::new(None); + let mut l1 = L1.lock().unwrap_or_else(|poisoned| poisoned.into_inner()); + if let Some(l1) = &*l1 { + return Ok(l1.clone()); + } + Ok(l1.insert(ObjectStoreL1::from_env()?).clone()) +} + +/// A database's packs in the object store, each request polled inside +/// pyo3-async-runtimes' tokio runtime (the tunnel's too). The store's HTTP +/// client, reqwest, takes its connections and timers from the current +/// runtime, and a call is polled on the asyncio loop's thread, outside any +/// ([`SqlTask`]); the runtime's threads drive them, and wake the call as +/// any other thread does ([`TaskWaker`]). Nothing else is polled inside it. +struct InRuntime(ObjectStoreBlobs); + +impl BlobStore for InRuntime { + fn get_range<'a>( + &'a self, + key: &'a str, + range: Range, + ) -> BoxFuture<'a, io::Result>> { + in_runtime(self.0.get_range(key, range)) + } + + fn put<'a>(&'a self, key: &'a str, value: Bytes) -> BoxFuture<'a, io::Result<()>> { + in_runtime(self.0.put(key, value)) + } + + fn delete<'a>(&'a self, keys: &'a [String]) -> BoxFuture<'a, io::Result<()>> { + in_runtime(self.0.delete(keys)) + } + + fn list<'a>(&'a self, prefix: &'a str) -> BoxFuture<'a, io::Result>> { + in_runtime(self.0.list(prefix)) + } +} + +/// `future`, each poll inside the runtime's context. +fn in_runtime<'a, T: 'a>(mut future: BoxFuture<'a, T>) -> BoxFuture<'a, T> { + let runtime = pyo3_async_runtimes::tokio::get_runtime(); + Box::pin(std::future::poll_fn(move |cx| { + let _entered = runtime.enter(); + future.as_mut().poll(cx) + })) +} + /// Open the database of `namespace`, kept warm in the process's page cache, +/// with its packs past L0 in the process's object store, if any ([`object_store`]), /// over the invocation's `vm` if given (with `name`, the key's database /// `name`), or else over the store behind `dispatch` (`lists_keys` if it has /// `keys`): see the module's doc. See [`sql::Open::reader`] for a `reader`. @@ -630,6 +694,10 @@ pub(crate) fn sql_open<'py>( if let Some(cache) = &cache { open = open.cached(cache, &namespace); } + let l1 = object_store().map_err(|e| PyRuntimeError::new_err(e.to_string()))?; + if let Some(l1) = l1 { + open = open.checkpoints(Arc::new(InRuntime(l1.blobs(&namespace)))); + } if reader { open = open.reader(); } diff --git a/tests/sessions_object_store.py b/tests/sessions_object_store.py new file mode 100644 index 00000000..4f136f31 --- /dev/null +++ b/tests/sessions_object_store.py @@ -0,0 +1,126 @@ +# +# Copyright (c) 2023-2026 - Restate Software, Inc., Restate GmbH +# +# This file is part of the Restate SDK for Python, +# which is released under the MIT license. +# +# You can find a copy of the license in file LICENSE in the root +# directory of this repository or package, or at +# https://github.com/restatedev/sdk-typescript/blob/main/LICENSE +# +"""A database past L0 (4 MiB compressed): its checkpoints promote to the object +store ``RESTATE_SQL_OBJECT_STORE`` names, here a directory, and read back from it. + +The variable is read at the process's first open, so the scenario runs in a +process of its own, with the variable set before any; the page cache is off, +so every session reads cold. +""" + +import os +import subprocess +import sys +from pathlib import Path + +SCENARIO = """ +import asyncio, hashlib, os +from pathlib import Path + +from restate.sessions._database import open +from sessions_database import Backend, listing + + +def files(path): + if not path.exists(): + return [] + return [str(f.relative_to(path)) for f in path.rglob("*") if f.is_file()] + + +def store(backend): + request = backend.request() + request.keys = listing(backend) + return request + + +async def main(): + # Its directory: the namespace, escaped to one segment. + namespace = "Ledger/a%20b" + packs = Path(os.environ["PACKS"]) / "_4cedger_2fa_2520b" + backend = Backend() + + written = hashlib.sha256() + db = await open(namespace, store(backend)) + await db.execute("CREATE TABLE blobs (id INTEGER PRIMARY KEY, data BLOB NOT NULL)") + # 12 MiB that does not compress, 256 KiB a commit. + for i in range(48): + data = os.urandom(256 << 10) + written.update(data) + await db.execute("INSERT INTO blobs VALUES (?, ?)", [i, data]) + await db.save() + + promoted = files(packs) + assert promoted, "a pack in the object store" + assert all(f.startswith("l1/") for f in promoted), f"only L1's packs: {promoted}" + # Restate keeps no more than L0's few MiB, and the head, tail and manifests. + in_restate = sum(len(v) for v in backend.stored.values()) + assert in_restate < 8 << 20, f"{in_restate} bytes in Restate" + + # A cold session reads every row, from both tiers. + again = await open(namespace, store(backend)) + read = hashlib.sha256() + for (data,) in await again.values("SELECT data FROM blobs ORDER BY id"): + read.update(data) + assert read.hexdigest() == written.hexdigest() + # So does a reader beside it. + reader = await open(namespace, backend.request(), reader=True) + assert await reader.values("SELECT count(*) FROM blobs") == [[48]] + await reader.close() + + # Rewriting it all promotes again; the packs no checkpoint needs go. + for i in range(48): + await again.execute("UPDATE blobs SET data = ? WHERE id = ?", [os.urandom(256 << 10), i]) + await again.save() + stored = sum((packs / f).stat().st_size for f in files(packs)) + assert stored < 40 << 20, f"{stored} bytes in the object store for a 12 MiB database" + + +asyncio.run(main()) +""" + + +def test_a_database_past_l0_promotes_its_packs_to_the_object_store_and_reads_them_back(tmp_path: Path): + packs = tmp_path / "packs" + tests = Path(__file__).parent + env = { + **os.environ, + "RESTATE_SQL_OBJECT_STORE": f"file://{packs}", + "RESTATE_SQL_CACHE": "off", + "PACKS": str(packs), + "PYTHONPATH": os.pathsep.join(filter(None, [str(tests), os.environ.get("PYTHONPATH")])), + } + ran = subprocess.run([sys.executable, "-c", SCENARIO], env=env, capture_output=True, text=True, check=False) + assert ran.returncode == 0, ran.stdout + ran.stderr + + +def test_an_object_store_the_build_cannot_serve_fails_the_open_with_its_message(): + env = { + **os.environ, + "RESTATE_SQL_OBJECT_STORE": "memory:///", + "PYTHONPATH": os.pathsep.join(filter(None, [str(Path(__file__).parent), os.environ.get("PYTHONPATH")])), + } + scenario = """ +import asyncio +from restate.sessions._database import open +from sessions_database import Backend + +async def main(): + try: + await open("Ledger/a", Backend().request()) + except Exception as error: + assert "RESTATE_SQL_OBJECT_STORE=memory:///" in str(error), error + else: + raise AssertionError("the open succeeded") + +asyncio.run(main()) +""" + ran = subprocess.run([sys.executable, "-c", scenario], env=env, capture_output=True, text=True, check=False) + assert ran.returncode == 0, ran.stdout + ran.stderr From 722c8415da3a5221ffe3477279d004cf36feb7e5 Mon Sep 17 00:00:00 2001 From: slinkydeveloper Date: Tue, 10 Nov 2026 17:37:59 +0100 Subject: [PATCH 2/2] Sessions: the object store's runtime wakes calls too (docs) The module docs and `TaskWaker`'s said the page cache's disk tier is the only other thread that wakes a call; with an object store, the tokio runtime driving its requests does too, through the same `foreign_wakes`. Co-Authored-By: Claude Opus 5.5 --- src/sessions.rs | 16 +++++++++------- 1 file changed, 9 insertions(+), 7 deletions(-) diff --git a/src/sessions.rs b/src/sessions.rs index 01cd9428..efb4884f 100644 --- a/src/sessions.rs +++ b/src/sessions.rs @@ -13,10 +13,12 @@ //! task that polls it. A call that needs nothing it must wait for, such as SQL //! on cached pages or a statement inside a transaction, returns its value at //! once, or raises its error ([`answer`]); one that waits returns an asyncio -//! future, and is polled again on the loop as what it waits for completes. The -//! one other thread is the page cache's disk tier (foyer's runtime): its -//! wake-ups reach the loop through a thread of their own, so that the cache -//! never waits for the GIL. +//! future, and is polled again on the loop as what it waits for completes. +//! Two other kinds of thread wake a call: the page cache's disk tier +//! (foyer's runtime), and, with an object store, the tokio runtime that +//! drives its requests' connections and timers ([`InRuntime`]). Their +//! wake-ups reach the loop through a thread of their own ([`foreign_wakes`]), +//! so that neither ever waits for the GIL. //! //! # The store //! @@ -180,9 +182,9 @@ fn poll(py: Python<'_>, task: &Py) -> PyResult<()> { /// Wakes a [`SqlTask`]: a poll on its loop, scheduled once however often it /// is woken before it runs. Woken on the loop's thread, it schedules it -/// there; woken on another (the page cache's disk tier), it hands the -/// scheduling to [`foreign_wakes`], so that the waking thread never waits -/// for the GIL. +/// there; woken on another (the page cache's disk tier, or the object +/// store's tokio runtime), it hands the scheduling to [`foreign_wakes`], so +/// that the waking thread never waits for the GIL. struct TaskWaker(Py); impl Wake for TaskWaker {