diff --git a/Cargo.lock b/Cargo.lock index e3ca172e..f158091d 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -775,27 +775,27 @@ dependencies = [ [[package]] name = "cranelift-assembler-x64" -version = "0.136.3" +version = "0.136.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f6d504c8c7ba3f3accaf8e98b7096beb98e1a271404357744c7e9e730c6865ff" +checksum = "c9c587da2696fbaa58e7a2fa2e5bfdd365d0928219f36992304ac1f15e5bc254" dependencies = [ "cranelift-assembler-x64-meta", ] [[package]] name = "cranelift-assembler-x64-meta" -version = "0.136.3" +version = "0.136.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c065757905596bc06e82969ebd7b92d691b7fd710a7e9e8181ae0c30dab588d0" +checksum = "f28a60027b7556b680b051651291053ec381edf4ffbc01784997ae51a64269bb" dependencies = [ "cranelift-srcgen", ] [[package]] name = "cranelift-bforest" -version = "0.136.3" +version = "0.136.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5ca7162cd4d4fc5f9f2f88d1459d939882203d93a8c5a19ef2c405b2e82ef13f" +checksum = "62bfdb846acebfd591d601994ea283c98d525ac0bc9a84ca3f2c36bcf5b69ff1" dependencies = [ "cranelift-entity", "wasmtime-internal-core", @@ -803,9 +803,9 @@ dependencies = [ [[package]] name = "cranelift-bitset" -version = "0.136.3" +version = "0.136.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0ec2ba2d4f3d959ec4023a10266c3dcfb28381d1938d507a9a5e1abb78bbcc88" +checksum = "aa9f8cc1080739d5f72b4ee7e00aff7d589f1284beaf0a19472c07878be7f299" dependencies = [ "serde", "serde_derive", @@ -814,9 +814,9 @@ dependencies = [ [[package]] name = "cranelift-codegen" -version = "0.136.3" +version = "0.136.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "51a64cb821d5fed56bdd6053acd36fa928cd82b70bf6b19b8b14b8b27d047b9a" +checksum = "d85417d493ecec833b5134546b4a252c78cc0bd5be11729a35d25dcff9e4e70b" dependencies = [ "bumpalo", "cranelift-assembler-x64", @@ -845,9 +845,9 @@ dependencies = [ [[package]] name = "cranelift-codegen-meta" -version = "0.136.3" +version = "0.136.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "142be1e267a7497ba3c2b5a829eaf5387b92b9bcdba6e0a6020f1ffccae7f2b8" +checksum = "d01c8ed0098360bae69ad6b82952d4247516799ce8050d45ad168d6689f4eae6" dependencies = [ "cranelift-assembler-x64-meta", "cranelift-codegen-shared", @@ -858,24 +858,24 @@ dependencies = [ [[package]] name = "cranelift-codegen-shared" -version = "0.136.3" +version = "0.136.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0e41f75410da6cce8601330137d73718f679db81cb790a33de3871b5c90a0de3" +checksum = "04f9b86d809cec9c4e88b201f1b3ed3b0347674c9ccfbb8c355228669e34be81" [[package]] name = "cranelift-control" -version = "0.136.3" +version = "0.136.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0c2616c6d01c14921ac9289ef65eb7702d9c760dfdc4537a8ee5bf38ea2832c6" +checksum = "ce182038fb10b719841e65fdf5deeee258c684f63439f5be680c2be059274b58" dependencies = [ "arbitrary", ] [[package]] name = "cranelift-entity" -version = "0.136.3" +version = "0.136.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a03e8b44c4877cf2fb21e5788d514af6fd291a066ed9ae37adf114a25fecb4aa" +checksum = "7bca812b03a7b942796391f25bc02aa70a1a007fee3ce2756490c788429e9c39" dependencies = [ "cranelift-bitset", "serde", @@ -885,9 +885,9 @@ dependencies = [ [[package]] name = "cranelift-frontend" -version = "0.136.3" +version = "0.136.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "366ff7cb014bd08752210eba55a650969f8db9b52670d69d2ea0b23e1e9e3edf" +checksum = "a0c30563d2aef95e8d1a00a920199c99117b350339599f0e9487a7a1cf5d59de" dependencies = [ "cranelift-codegen", "hashbrown 0.17.1", @@ -898,15 +898,15 @@ dependencies = [ [[package]] name = "cranelift-isle" -version = "0.136.3" +version = "0.136.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9ea6526ebf9064fff8ce3b1e26afad7027f9e6bb0e45d2b9200e4cbab8343345" +checksum = "9c54184333a275698edb1d3bdff226131a25d47133d792aa716e47e32b8b7f05" [[package]] name = "cranelift-native" -version = "0.136.3" +version = "0.136.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b44d323f3e5108a8a5bc61f3acd227285ece066e19afe9aece211d66b34a64ea" +checksum = "eb67a4c8a3180b5f1d77dffcd6317c05386ced42e5a31c7004523a9d99dc85c1" dependencies = [ "cranelift-codegen", "libc", @@ -915,9 +915,9 @@ dependencies = [ [[package]] name = "cranelift-srcgen" -version = "0.136.3" +version = "0.136.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fc173168f291ff3b95b5d0769d6a05b1eaef5e6d74c2600affab8396b4e7b420" +checksum = "b533db1679b4b728568bd490da6533cf50974c48a4d7534e78f1e0e02bc39769" [[package]] name = "crc32fast" @@ -2379,9 +2379,9 @@ dependencies = [ [[package]] name = "pulley-interpreter" -version = "49.0.3" +version = "49.0.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "def59f28ccaf2cb4f8dfaac83197fd7d56a4470a70e4f2589454c731370101c5" +checksum = "5cd3de43f4f4cff536de8902097edbdf749321b97dda548f36a37918eb85bba3" dependencies = [ "cranelift-bitset", "log", @@ -2391,9 +2391,9 @@ dependencies = [ [[package]] name = "pulley-macros" -version = "49.0.3" +version = "49.0.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3a1834d3b3ef994f266a0c9ed29a8214f2c2faaa9b1c44babfa57566bb05af83" +checksum = "8319a8fa5269b4895957f8795861c42822bd26218e495f70060a963323d94847" dependencies = [ "proc-macro2", "quote", @@ -3670,7 +3670,7 @@ dependencies = [ [[package]] name = "tw-api" -version = "0.78.0" +version = "0.79.0" dependencies = [ "serde", "serde_json", @@ -3681,7 +3681,7 @@ dependencies = [ [[package]] name = "tw-bedrock" -version = "0.78.0" +version = "0.79.0" dependencies = [ "aws-credential-types", "aws-sigv4", @@ -3702,7 +3702,7 @@ dependencies = [ [[package]] name = "tw-breaker" -version = "0.78.0" +version = "0.79.0" dependencies = [ "serde", "serde_json", @@ -3710,7 +3710,7 @@ dependencies = [ [[package]] name = "tw-config" -version = "0.78.0" +version = "0.79.0" dependencies = [ "blake3", "libc", @@ -3736,7 +3736,7 @@ dependencies = [ [[package]] name = "tw-control" -version = "0.78.0" +version = "0.79.0" dependencies = [ "axum", "base64 0.22.1", @@ -3781,7 +3781,7 @@ dependencies = [ [[package]] name = "tw-dialect" -version = "0.78.0" +version = "0.79.0" dependencies = [ "memchr", "serde", @@ -3790,7 +3790,7 @@ dependencies = [ [[package]] name = "tw-engine" -version = "0.78.0" +version = "0.79.0" dependencies = [ "chrono", "serde", @@ -3804,7 +3804,7 @@ dependencies = [ [[package]] name = "tw-gateway" -version = "0.78.0" +version = "0.79.0" dependencies = [ "arc-swap", "async-stream", @@ -3855,7 +3855,7 @@ dependencies = [ [[package]] name = "tw-guard" -version = "0.78.0" +version = "0.79.0" dependencies = [ "aho-corasick", "base64 0.22.1", @@ -3873,7 +3873,7 @@ dependencies = [ [[package]] name = "tw-link" -version = "0.78.0" +version = "0.79.0" dependencies = [ "serde", "serde_json", @@ -3887,7 +3887,7 @@ dependencies = [ [[package]] name = "tw-observe" -version = "0.78.0" +version = "0.79.0" dependencies = [ "tokio", "tracing", @@ -3896,7 +3896,7 @@ dependencies = [ [[package]] name = "tw-pack" -version = "0.78.0" +version = "0.79.0" dependencies = [ "age", "blake3", @@ -3920,7 +3920,7 @@ dependencies = [ [[package]] name = "tw-plugin" -version = "0.78.0" +version = "0.79.0" dependencies = [ "libc", "rand 0.10.2", @@ -3936,7 +3936,7 @@ dependencies = [ [[package]] name = "tw-pricing" -version = "0.78.0" +version = "0.79.0" dependencies = [ "arc-swap", "flate2", @@ -3949,14 +3949,14 @@ dependencies = [ [[package]] name = "tw-secret" -version = "0.78.0" +version = "0.79.0" dependencies = [ "thiserror 2.0.20", ] [[package]] name = "tw-store" -version = "0.78.0" +version = "0.79.0" dependencies = [ "blake3", "bytes", @@ -3976,7 +3976,7 @@ dependencies = [ [[package]] name = "tw-sync" -version = "0.78.0" +version = "0.79.0" dependencies = [ "age", "axum", @@ -4004,7 +4004,7 @@ dependencies = [ [[package]] name = "tw-types" -version = "0.78.0" +version = "0.79.0" dependencies = [ "serde", "serde_json", @@ -4013,7 +4013,7 @@ dependencies = [ [[package]] name = "tw-watch" -version = "0.78.0" +version = "0.79.0" dependencies = [ "libc", "notify", @@ -4024,7 +4024,7 @@ dependencies = [ [[package]] name = "tw-yaml" -version = "0.78.0" +version = "0.79.0" dependencies = [ "saphyr-parser", "serde_yaml_ng", @@ -4034,7 +4034,7 @@ dependencies = [ [[package]] name = "twcore" -version = "0.78.0" +version = "0.79.0" dependencies = [ "anyhow", "axum", @@ -4346,9 +4346,9 @@ dependencies = [ [[package]] name = "wasmtime" -version = "49.0.3" +version = "49.0.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4fbdd39f5c66f63ba6b5b31391b324b7ade7237d29c866cdb561330118ef436e" +checksum = "36abb25de5518707e5ba96b586366b09db168d2d4976cb9dac57265a317497ea" dependencies = [ "addr2line", "async-trait", @@ -4385,9 +4385,9 @@ dependencies = [ [[package]] name = "wasmtime-environ" -version = "49.0.3" +version = "49.0.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e915c27826de4f7b4411b61fd6db32ca448657a5136b8c8e8874a15e90cecbf4" +checksum = "92f16a4d09fb1fbf2dcfeddb9818e1517a258e13b505b3bfdadcf47a19bf31ca" dependencies = [ "anyhow", "cpp_demangle", @@ -4416,15 +4416,15 @@ dependencies = [ [[package]] name = "wasmtime-internal-component-util" -version = "49.0.3" +version = "49.0.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e754a3ff5690c34eb4713bd7c65f60dd607ead4e39042cbf52ac8011de14455b" +checksum = "4006009fc3598af4e895ab18c6c33d2c6b7c657b1bd0a755ca7ee1abef6f0c16" [[package]] name = "wasmtime-internal-core" -version = "49.0.3" +version = "49.0.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ba00c5db77adb0749ee059068e5a417bfac3d8969f5a3479d9bd1ca8c1ba248d" +checksum = "947a732ad659f42c10ec639706fc8cb1f068dd9a55eebde8a1f24dfd06dfa525" dependencies = [ "hashbrown 0.17.1", "libm", @@ -4433,9 +4433,9 @@ dependencies = [ [[package]] name = "wasmtime-internal-cranelift" -version = "49.0.3" +version = "49.0.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "97ceeb4325712a253f463e50a69b5a547fbbecd52e45612360c543eaa25a03ff" +checksum = "fbfb8b455d524939e03df42e3e749f8e26e26ba2acd8b08fa00b3bda55686750" dependencies = [ "cranelift-codegen", "cranelift-control", @@ -4459,9 +4459,9 @@ dependencies = [ [[package]] name = "wasmtime-internal-fiber" -version = "49.0.3" +version = "49.0.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3eb3f21bc32b5382ea95f83ce9a5f2f62b68f1b25a37d0802a41a65236eae5ae" +checksum = "bd8aa8711f68b2cdd94c2b85ba5c8317edaa1ac4ee0a0534b957123680239307" dependencies = [ "cc", "libc", @@ -4473,9 +4473,9 @@ dependencies = [ [[package]] name = "wasmtime-internal-jit-debug" -version = "49.0.3" +version = "49.0.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e786f9925126e0d2e466c5308e572e8b6226f4047596228a3d63d99528a78949" +checksum = "e873e4504faf50aa8ce255d6ea7210d87b39d5f379c2486782e2c5f179c70ca8" dependencies = [ "cc", "wasmtime-internal-versioned-export-macros", @@ -4483,9 +4483,9 @@ dependencies = [ [[package]] name = "wasmtime-internal-jit-icache-coherence" -version = "49.0.3" +version = "49.0.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "92cb1dd5da78f5b21d65e91063bdd8c2eb343c1f077a1dcbc29003d4a794abb0" +checksum = "197ab1fda5da958a5c0b8a97eb241beafc48ac568b82ef4f12f38d6866c74173" dependencies = [ "libc", "wasmtime-internal-core", @@ -4494,9 +4494,9 @@ dependencies = [ [[package]] name = "wasmtime-internal-unwinder" -version = "49.0.3" +version = "49.0.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d0243d244f6dd07ccd114e6bb099e8dd1197b47de5c054576adc9483f80f65d8" +checksum = "5577f3a5a979a7c3b1b23c1e9f13e70a8583acc8828471ec56f282117fc4952b" dependencies = [ "cranelift-codegen", "log", @@ -4506,9 +4506,9 @@ dependencies = [ [[package]] name = "wasmtime-internal-versioned-export-macros" -version = "49.0.3" +version = "49.0.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "20fa5616cd875ec78f5b92020fa47ced7c8bb923079185c8475751098b8c4a69" +checksum = "f6399c9c4050ed431cf66e21c05fadd6f9731db44476f452f8c7142b4597b883" dependencies = [ "proc-macro2", "quote", @@ -4517,9 +4517,9 @@ dependencies = [ [[package]] name = "wasmtime-internal-winch" -version = "49.0.3" +version = "49.0.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e9af52e40494b4ccc9e28e79d74999814c6b62a413a8b4d01971dc01c32ccb65" +checksum = "19f1b2b35e5260f0d0d0cd7f789893515894cd407650b5ab4b1ccbf06c9ecb90" dependencies = [ "cranelift-codegen", "gimli", @@ -4572,9 +4572,9 @@ dependencies = [ [[package]] name = "winch-codegen" -version = "49.0.3" +version = "49.0.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "96b51835167dc181074f20e833e7dbe89915b579c28f6788bd6263da3a28d44c" +checksum = "3b6796e6383dadb97ecfe9a6685bdfe3c48bad1b9d3627420ed874fa0b424787" dependencies = [ "cranelift-assembler-x64", "cranelift-codegen", diff --git a/Cargo.toml b/Cargo.toml index 05cd9195..4cba0f0c 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -59,7 +59,7 @@ categories = ["network-programming", "web-programming::http-server"] # 二进制走 CalVer,crate 走 SemVer —— 两者是两回事,卖给不同的人。 # 这里是 crate 的版本。 -version = "0.78.0" +version = "0.79.0" [workspace.dependencies] # ── 内部 crate ─────────────────────────────────────────── diff --git a/crates/tw-plugin/Cargo.toml b/crates/tw-plugin/Cargo.toml index 38fd3e98..7b228ee6 100644 --- a/crates/tw-plugin/Cargo.toml +++ b/crates/tw-plugin/Cargo.toml @@ -18,7 +18,7 @@ description = "Runs one script plugin's hooks inside a WebAssembly sandbox (Quic # **只有运行时**:没有 Cranelift,没有池分配器。沙箱的机器码在 build.rs 里预编译 # 好、嵌进二进制。版本钉死,并且和下面构建依赖里的是同一个:预编译产物只肯在 # 同一版本的 Wasmtime 里加载 -wasmtime = { version = "=49.0.3", default-features = false, features = ["runtime", "std"] } +wasmtime = { version = "=49.0.4", default-features = false, features = ["runtime", "std"] } serde = { workspace = true } serde_json = { workspace = true } sha2 = { workspace = true } @@ -36,7 +36,7 @@ windows-sys = { workspace = true, features = ["Win32_Foundation", "Win32_System_ [build-dependencies] # 构建时的编译器:Cranelift 把快照编成目标平台的机器码;all-arch 让交叉编译 # (比如在 x64 上编 aarch64 的 Windows)也能编 -wasmtime = { version = "=49.0.3", default-features = false, features = ["runtime", "std", "cranelift", "all-arch", "parallel-compilation"] } +wasmtime = { version = "=49.0.4", default-features = false, features = ["runtime", "std", "cranelift", "all-arch", "parallel-compilation"] } # 改写快照的数据段。和 Wasmtime 49 自己用的是同一版 wasmparser = "0.258" wasm-encoder = "0.258" diff --git a/release-notes/0.79.0.md b/release-notes/0.79.0.md new file mode 100644 index 00000000..8c7b4244 --- /dev/null +++ b/release-notes/0.79.0.md @@ -0,0 +1,31 @@ +This release turns an upstream's 429 into a short wait instead of an error, and adds usage limits to upstreams. + +**Upgrade notes** + +- The control-plane protocol version is now 51. Use the ThinkWatch Lite release that ships with 0.79.0; earlier Lite releases cannot connect. +- The request store's schema is unchanged; nothing is cleared. +- `failover.slot_wait_secs` is replaced by `failover.wait_secs` (default 120 seconds, up to 600). A configuration that still sets `slot_wait_secs` starts in safe mode; the repair removes the key, and its value is not carried over. +- An upstream's 429 no longer counts as a failure: it does not open the breaker and does not lower the upstream's success rate. + +**Rate limits become a wait.** +- When an upstream answers 429, the whole upstream pauses until its `retry-after-ms`, `Retry-After` or the delay in the error body; without one, it backs off 5, 10, 20, 40 and then 60 seconds, and a success resets the count. +- Requests for it wait in the gateway, one queue per upstream, and are sent again once it recovers. When the pause ends, only the first request goes out; the rest follow once it gets a real answer. A request that has another upstream it can use right away goes there instead. +- A conversation that is held on an upstream for its prompt cache waits for that upstream when it can recover in time. +- A lone upstream is waited for as well. +- Every wait of a request (gateway key limits, concurrency slots, rate-limit pauses, upstream usage limits) shares one deadline, `failover.wait_secs`. Streaming clients get their response head and keep-alives while they wait, so they only see a slower first token. +- When the deadline passes, the client gets a 429 with `Retry-After` for the earliest recovery. When every upstream has used up its daily, weekly or monthly limit, `x-should-retry` is `false`. + +**Upstream usage limits.** +- An upstream can carry limits in the same form as gateway key limits: requests, tokens or cost per minute, hour, day, week or month. +- `every` sets the window to several minutes or hours, for example `{ per: minute, every: 5, tokens: 10000000 }`. Gateway key limits accept `every` too. +- A full minute or hour window makes requests switch to another upstream or wait. A used-up day, week or month is skipped until it resets. +- Each request sent to the upstream counts, except one it answered with 429. Tokens and cost come from the answer. Calendar periods are rebuilt from the request records after a restart. + +**New in the control-plane API.** +- Upstreams carry `throttle` (paused, window full or period used up, until when) and `limits` with their live usage. +- New events: `ThrottleChanged`, `RequestQueued` and `RequestDequeued`. +- Attempts can be skipped as `throttled`, `window_full` or `period_used_up`, and carry `pause_ms` when the upstream answered 429. + +**Plugins on Windows.** The plugin CPU limit on Windows used wall time, so time the thread spent waiting for the processor counted against the plugin. It now charges the smaller of the wall time and the thread's CPU time plus one clock tick. + +**Security.** The plugin sandbox's Wasmtime is updated to 49.0.4 for RUSTSEC-2026-0378 and RUSTSEC-2026-0379 (a Cranelift fault on aarch64 that could jump to the wrong target on a large `br_table`).