diff --git a/Cargo.toml b/Cargo.toml index ce057972..78d1626b 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -37,7 +37,6 @@ derivative = "2.2.0" http = "1.0.0" log = "0.4" h2 = ">=0.4.11" -once_cell = "1" lru = "0.14" ahash = ">=0.8.9" diff --git a/docs/user_guide/rate_limiter.md b/docs/user_guide/rate_limiter.md index fe337a19..f3868b8c 100644 --- a/docs/user_guide/rate_limiter.md +++ b/docs/user_guide/rate_limiter.md @@ -7,7 +7,6 @@ Pingora provides a crate `pingora-limits` which provides a simple and easy to us async-trait="0.1" pingora = { version = "0.3", features = [ "lb" ] } pingora-limits = "0.3.0" - once_cell = "1.19.0" ``` 2. Declare a global rate limiter map to store the rate limiter for each client. In this example, we use `appid`. 3. Override the `request_filter` method in the `ProxyHttp` trait to implement rate limiting. @@ -19,7 +18,7 @@ Pingora provides a crate `pingora-limits` which provides a simple and easy to us ## Example ```rust use async_trait::async_trait; -use once_cell::sync::Lazy; +use std::sync::LazyLock; use pingora::http::ResponseHeader; use pingora::prelude::*; use pingora_limits::rate::Rate; @@ -67,7 +66,7 @@ impl LB { } // Rate limiter -static RATE_LIMITER: Lazy = Lazy::new(|| Rate::new(Duration::from_secs(1))); +static RATE_LIMITER: LazyLock = LazyLock::new(|| Rate::new(Duration::from_secs(1))); // max request per second per client static MAX_REQ_PER_SEC: isize = 1; diff --git a/pingora-cache/Cargo.toml b/pingora-cache/Cargo.toml index cd51b638..a85f442c 100644 --- a/pingora-cache/Cargo.toml +++ b/pingora-cache/Cargo.toml @@ -25,7 +25,6 @@ pingora-lru = { version = "0.6.0", path = "../pingora-lru" } pingora-timeout = { version = "0.6.0", path = "../pingora-timeout" } http = { workspace = true } indexmap = "1" -once_cell = { workspace = true } regex = "1" blake2 = "0.10" serde = { version = "1.0", features = ["derive"] } diff --git a/pingora-cache/src/cache_control.rs b/pingora-cache/src/cache_control.rs index 8083298e..07028579 100644 --- a/pingora-cache/src/cache_control.rs +++ b/pingora-cache/src/cache_control.rs @@ -19,12 +19,12 @@ use super::*; use http::header::HeaderName; use http::HeaderValue; use indexmap::IndexMap; -use once_cell::sync::Lazy; use pingora_error::{Error, ErrorType}; use regex::bytes::Regex; use std::num::IntErrorKind; use std::slice; use std::str; +use std::sync::LazyLock; /// The max delta-second per [RFC 9111](https://datatracker.ietf.org/doc/html/rfc9111#section-1.2.2) // "If a cache receives a delta-seconds value @@ -157,13 +157,13 @@ impl<'a> Iterator for ListValueIter<'a> { // note the `token` implementation excludes disallowed ASCII ranges // and disallowed delimiters: https://datatracker.ietf.org/doc/html/rfc9110#section-5.6.2 // though it does not forbid `obs-text`: %x80-FF -static RE_CACHE_DIRECTIVE: Lazy = +static RE_CACHE_DIRECTIVE: LazyLock = // to break our version down further: // `(?-u)`: unicode support disabled, which puts the regex into "ASCII compatible mode" for specifying literal bytes like \x7F: https://docs.rs/regex/1.10.4/regex/bytes/index.html#syntax // `(?:^|(?:\s*[,;]\s*)`: allow either , or ; as a delimiter // `([^\x00-\x20\(\)<>@,;:\\"/\[\]\?=\{\}\x7F]+)`: token (directive name capture group) // `(?:=((?:[^\x00-\x20\(\)<>@,;:\\"/\[\]\?=\{\}\x7F]+|(?:"(?:[^"\\]|\\.)*"))))`: token OR quoted-string (directive value capture-group) - Lazy::new(|| { + LazyLock::new(|| { Regex::new(r#"(?-u)(?:^|(?:\s*[,;]\s*))([^\x00-\x20\(\)<>@,;:\\"/\[\]\?=\{\}\x7F]+)(?:=((?:[^\x00-\x20\(\)<>@,;:\\"/\[\]\?=\{\}\x7F]+|(?:"(?:[^"\\]|\\.)*"))))?"#).unwrap() }); diff --git a/pingora-cache/src/memory.rs b/pingora-cache/src/memory.rs index 786cf453..23900539 100644 --- a/pingora-cache/src/memory.rs +++ b/pingora-cache/src/memory.rs @@ -427,7 +427,7 @@ impl Storage for MemCache { mod test { use super::*; use cf_rustracing::span::Span; - use once_cell::sync::Lazy; + use std::sync::LazyLock; fn gen_meta() -> CacheMeta { let mut header = ResponseHeader::build(200, None).unwrap(); @@ -445,7 +445,7 @@ mod test { #[tokio::test] async fn test_write_then_read() { - static MEM_CACHE: Lazy = Lazy::new(MemCache::new); + static MEM_CACHE: LazyLock = LazyLock::new(MemCache::new); let span = &Span::inactive().handle(); let key1 = CacheKey::new("", "a", "1"); @@ -482,7 +482,7 @@ mod test { #[tokio::test] async fn test_read_range() { - static MEM_CACHE: Lazy = Lazy::new(MemCache::new); + static MEM_CACHE: LazyLock = LazyLock::new(MemCache::new); let span = &Span::inactive().handle(); let key1 = CacheKey::new("", "a", "1"); @@ -527,7 +527,7 @@ mod test { async fn test_write_while_read() { use futures::FutureExt; - static MEM_CACHE: Lazy = Lazy::new(MemCache::new); + static MEM_CACHE: LazyLock = LazyLock::new(MemCache::new); let span = &Span::inactive().handle(); let key1 = CacheKey::new("", "a", "1"); @@ -594,7 +594,7 @@ mod test { #[tokio::test] async fn test_purge_partial() { - static MEM_CACHE: Lazy = Lazy::new(MemCache::new); + static MEM_CACHE: LazyLock = LazyLock::new(MemCache::new); let cache = &MEM_CACHE; let key = CacheKey::new("", "a", "1").to_compact(); @@ -621,7 +621,7 @@ mod test { #[tokio::test] async fn test_purge_complete() { - static MEM_CACHE: Lazy = Lazy::new(MemCache::new); + static MEM_CACHE: LazyLock = LazyLock::new(MemCache::new); let cache = &MEM_CACHE; let key = CacheKey::new("", "a", "1").to_compact(); diff --git a/pingora-cache/src/meta.rs b/pingora-cache/src/meta.rs index 9c6bd6fc..7a66c930 100644 --- a/pingora-cache/src/meta.rs +++ b/pingora-cache/src/meta.rs @@ -16,12 +16,12 @@ pub use http::Extensions; use log::warn; -use once_cell::sync::{Lazy, OnceCell}; use pingora_error::{Error, ErrorType::*, OrErr, Result}; use pingora_header_serde::HeaderSerde; use pingora_http::{HMap, ResponseHeader}; use serde::{Deserialize, Serialize}; use std::borrow::Cow; +use std::sync::{LazyLock, OnceLock}; use std::time::{Duration, SystemTime}; use crate::key::HashBinary; @@ -568,9 +568,9 @@ impl CacheMetaDefaults { /// The dictionary content for header compression. /// /// Used during initialization of [`HEADER_SERDE`]. -static COMPRESSION_DICT_CONTENT: OnceCell> = OnceCell::new(); +static COMPRESSION_DICT_CONTENT: OnceLock> = OnceLock::new(); -static HEADER_SERDE: Lazy = Lazy::new(|| { +static HEADER_SERDE: LazyLock = LazyLock::new(|| { let dict_opt = if let Some(dict_content) = COMPRESSION_DICT_CONTENT.get() { Some(dict_content.to_vec()) } else { diff --git a/pingora-cache/src/put.rs b/pingora-cache/src/put.rs index 4c82a482..c6d4a3fd 100644 --- a/pingora-cache/src/put.rs +++ b/pingora-cache/src/put.rs @@ -215,7 +215,7 @@ impl CachePutCtx { mod test { use super::*; use cf_rustracing::span::Span; - use once_cell::sync::Lazy; + use std::sync::LazyLock; struct TestCachePut(); impl CachePut for TestCachePut { @@ -227,7 +227,7 @@ mod test { } type TestCachePutCtx = CachePutCtx; - static CACHE_BACKEND: Lazy = Lazy::new(MemCache::new); + static CACHE_BACKEND: LazyLock = LazyLock::new(MemCache::new); #[tokio::test] async fn test_cache_put() { diff --git a/pingora-core/Cargo.toml b/pingora-core/Cargo.toml index 7818db81..0fef3945 100644 --- a/pingora-core/Cargo.toml +++ b/pingora-core/Cargo.toml @@ -38,7 +38,6 @@ log = { workspace = true } h2 = { workspace = true } derivative.workspace = true clap = { version = "3.2.25", features = ["derive"] } -once_cell = { workspace = true } serde = { version = "1.0", features = ["derive"] } serde_yaml = "0.8" strum = "0.26.2" diff --git a/pingora-core/src/connectors/offload.rs b/pingora-core/src/connectors/offload.rs index 06fc0895..bf438232 100644 --- a/pingora-core/src/connectors/offload.rs +++ b/pingora-core/src/connectors/offload.rs @@ -13,8 +13,8 @@ // limitations under the License. use log::debug; -use once_cell::sync::OnceCell; use rand::Rng; +use std::sync::OnceLock; use tokio::runtime::{Builder, Handle}; use tokio::sync::oneshot::{channel, Sender}; @@ -25,7 +25,7 @@ pub(crate) struct OffloadRuntime { thread_per_shard: usize, // Lazily init the runtimes so that they are created after pingora // daemonize itself. Otherwise the runtime threads are lost. - pools: OnceCell)]>>, + pools: OnceLock)]>>, } impl OffloadRuntime { @@ -35,7 +35,7 @@ impl OffloadRuntime { OffloadRuntime { shards, thread_per_shard, - pools: OnceCell::new(), + pools: OnceLock::new(), } } diff --git a/pingora-core/src/modules/http/mod.rs b/pingora-core/src/modules/http/mod.rs index d220e6b0..17a898bd 100644 --- a/pingora-core/src/modules/http/mod.rs +++ b/pingora-core/src/modules/http/mod.rs @@ -26,13 +26,13 @@ pub mod grpc_web; use async_trait::async_trait; use bytes::Bytes; use http::HeaderMap; -use once_cell::sync::OnceCell; use pingora_error::Result; use pingora_http::{RequestHeader, ResponseHeader}; use std::any::Any; use std::any::TypeId; use std::collections::HashMap; use std::sync::Arc; +use std::sync::OnceLock; /// The trait an HTTP traffic module needs to implement #[async_trait] @@ -101,7 +101,7 @@ pub type ModuleBuilder = Box; /// The object to hold multiple http modules pub struct HttpModules { modules: Vec, - module_index: OnceCell>>, + module_index: OnceLock>>, } impl HttpModules { @@ -109,7 +109,7 @@ impl HttpModules { pub fn new() -> Self { HttpModules { modules: vec![], - module_index: OnceCell::new(), + module_index: OnceLock::new(), } } diff --git a/pingora-core/src/protocols/digest.rs b/pingora-core/src/protocols/digest.rs index f939bb1f..1858535a 100644 --- a/pingora-core/src/protocols/digest.rs +++ b/pingora-core/src/protocols/digest.rs @@ -17,7 +17,7 @@ use std::sync::Arc; use std::time::{Duration, SystemTime}; -use once_cell::sync::OnceCell; +use std::sync::OnceLock; use super::l4::ext::{get_original_dest, get_recv_buf, get_snd_buf, get_tcp_info, TCP_INFO}; use super::l4::socket::SocketAddr; @@ -67,11 +67,11 @@ pub struct SocketDigest { #[cfg(windows)] raw_sock: std::os::windows::io::RawSocket, /// Remote socket address - pub peer_addr: OnceCell>, + pub peer_addr: OnceLock>, /// Local socket address - pub local_addr: OnceCell>, + pub local_addr: OnceLock>, /// Original destination address - pub original_dst: OnceCell>, + pub original_dst: OnceLock>, } impl SocketDigest { @@ -79,9 +79,9 @@ impl SocketDigest { pub fn from_raw_fd(raw_fd: std::os::unix::io::RawFd) -> SocketDigest { SocketDigest { raw_fd, - peer_addr: OnceCell::new(), - local_addr: OnceCell::new(), - original_dst: OnceCell::new(), + peer_addr: OnceLock::new(), + local_addr: OnceLock::new(), + original_dst: OnceLock::new(), } } @@ -89,9 +89,9 @@ impl SocketDigest { pub fn from_raw_socket(raw_sock: std::os::windows::io::RawSocket) -> SocketDigest { SocketDigest { raw_sock, - peer_addr: OnceCell::new(), - local_addr: OnceCell::new(), - original_dst: OnceCell::new(), + peer_addr: OnceLock::new(), + local_addr: OnceLock::new(), + original_dst: OnceLock::new(), } } diff --git a/pingora-core/src/protocols/http/compression/mod.rs b/pingora-core/src/protocols/http/compression/mod.rs index 2f86efce..406b8a1c 100644 --- a/pingora-core/src/protocols/http/compression/mod.rs +++ b/pingora-core/src/protocols/http/compression/mod.rs @@ -616,12 +616,12 @@ fn test_decide_action() { assert_eq!(decide_action(&header, &[Brotli, Gzip]), Noop); } -use once_cell::sync::Lazy; use regex::Regex; +use std::sync::LazyLock; // Allow text, application, font, a few image/ MIME types and binary/octet-stream // TODO: fine tune this list -static MIME_CHECK: Lazy = Lazy::new(|| { +static MIME_CHECK: LazyLock = LazyLock::new(|| { Regex::new(r"^(?:text/|application/|font/|image/(?:x-icon|svg\+xml|nd\.microsoft\.icon)|binary/octet-stream)") .unwrap() }); diff --git a/pingora-core/src/protocols/http/error_resp.rs b/pingora-core/src/protocols/http/error_resp.rs index f802d4d0..e34a9939 100644 --- a/pingora-core/src/protocols/http/error_resp.rs +++ b/pingora-core/src/protocols/http/error_resp.rs @@ -15,8 +15,8 @@ //! Error response generating utilities. use http::header; -use once_cell::sync::Lazy; use pingora_http::ResponseHeader; +use std::sync::LazyLock; use super::SERVER_NAME; @@ -36,6 +36,6 @@ pub fn gen_error_response(code: u16) -> ResponseHeader { } /// Pre-generated 502 response -pub static HTTP_502_RESPONSE: Lazy = Lazy::new(|| gen_error_response(502)); +pub static HTTP_502_RESPONSE: LazyLock = LazyLock::new(|| gen_error_response(502)); /// Pre-generated 400 response -pub static HTTP_400_RESPONSE: Lazy = Lazy::new(|| gen_error_response(400)); +pub static HTTP_400_RESPONSE: LazyLock = LazyLock::new(|| gen_error_response(400)); diff --git a/pingora-core/src/protocols/http/v1/server.rs b/pingora-core/src/protocols/http/v1/server.rs index 073fee41..813c759e 100644 --- a/pingora-core/src/protocols/http/v1/server.rs +++ b/pingora-core/src/protocols/http/v1/server.rs @@ -20,12 +20,12 @@ use http::header::{CONTENT_LENGTH, TRANSFER_ENCODING}; use http::HeaderValue; use http::{header, header::AsHeaderName, Method, Version}; use log::{debug, warn}; -use once_cell::sync::Lazy; use percent_encoding::{percent_encode, AsciiSet, CONTROLS}; use pingora_error::{Error, ErrorType::*, OrErr, Result}; use pingora_http::{IntoCaseHeaderName, RequestHeader, ResponseHeader}; use pingora_timeout::timeout; use regex::bytes::Regex; +use std::sync::LazyLock; use std::time::Duration; use tokio::io::{AsyncReadExt, AsyncWriteExt}; @@ -1128,8 +1128,8 @@ impl HttpSession { } // Regex to parse request line that has illegal chars in it -static REQUEST_LINE_REGEX: Lazy = - Lazy::new(|| Regex::new(r"^\w+ (?P.+) HTTP/\d(?:\.\d)?").unwrap()); +static REQUEST_LINE_REGEX: LazyLock = + LazyLock::new(|| Regex::new(r"^\w+ (?P.+) HTTP/\d(?:\.\d)?").unwrap()); // the chars httparse considers illegal in URL // Almost https://url.spec.whatwg.org/#query-percent-encode-set + {} diff --git a/pingora-core/tests/utils/mod.rs b/pingora-core/tests/utils/mod.rs index 7062b349..21033519 100644 --- a/pingora-core/tests/utils/mod.rs +++ b/pingora-core/tests/utils/mod.rs @@ -12,7 +12,7 @@ // See the License for the specific language governing permissions and // limitations under the License. -use once_cell::sync::Lazy; +use std::sync::LazyLock; use std::{thread, time}; use clap::Parser; @@ -111,7 +111,7 @@ impl MyServer { } } -pub static TEST_SERVER: Lazy = Lazy::new(MyServer::start); +pub static TEST_SERVER: LazyLock = LazyLock::new(MyServer::start); pub fn init() { let _ = *TEST_SERVER; diff --git a/pingora-memory-cache/Cargo.toml b/pingora-memory-cache/Cargo.toml index bb449610..1f3ff33d 100644 --- a/pingora-memory-cache/Cargo.toml +++ b/pingora-memory-cache/Cargo.toml @@ -27,4 +27,3 @@ parking_lot = "0" pingora-timeout = { version = "0.6.0", path = "../pingora-timeout" } [dev-dependencies] -once_cell = { workspace = true } diff --git a/pingora-memory-cache/src/read_through.rs b/pingora-memory-cache/src/read_through.rs index 140f2362..7cd89c51 100644 --- a/pingora-memory-cache/src/read_through.rs +++ b/pingora-memory-cache/src/read_through.rs @@ -773,10 +773,10 @@ mod tests { #[tokio::test] async fn test_get_stale_while_update() { - use once_cell::sync::Lazy; + use std::sync::LazyLock; let ttl = Some(Duration::from_millis(100)); - static CACHE: Lazy> = - Lazy::new(|| RTCache::new(10, None, None)); + static CACHE: LazyLock> = + LazyLock::new(|| RTCache::new(10, None, None)); let opt = Some(ExtraOpt { error: false, empty: false, diff --git a/pingora-proxy/Cargo.toml b/pingora-proxy/Cargo.toml index aeaa15eb..468ef36b 100644 --- a/pingora-proxy/Cargo.toml +++ b/pingora-proxy/Cargo.toml @@ -29,7 +29,6 @@ bytes = { workspace = true } async-trait = { workspace = true } log = { workspace = true } h2 = { workspace = true } -once_cell = { workspace = true } clap = { version = "3.2.25", features = ["derive"] } regex = "1" rand = "0.8" diff --git a/pingora-proxy/examples/rate_limiter.rs b/pingora-proxy/examples/rate_limiter.rs index d2c8b7ec..87a4b34b 100644 --- a/pingora-proxy/examples/rate_limiter.rs +++ b/pingora-proxy/examples/rate_limiter.rs @@ -1,5 +1,4 @@ use async_trait::async_trait; -use once_cell::sync::Lazy; use pingora_core::prelude::*; use pingora_http::{RequestHeader, ResponseHeader}; use pingora_limits::rate::Rate; @@ -7,6 +6,7 @@ use pingora_load_balancing::prelude::{RoundRobin, TcpHealthCheck}; use pingora_load_balancing::LoadBalancer; use pingora_proxy::{http_proxy_service, ProxyHttp, Session}; use std::sync::Arc; +use std::sync::LazyLock; use std::time::Duration; fn main() { @@ -50,7 +50,7 @@ impl LB { } // Rate limiter -static RATE_LIMITER: Lazy = Lazy::new(|| Rate::new(Duration::from_secs(1))); +static RATE_LIMITER: LazyLock = LazyLock::new(|| Rate::new(Duration::from_secs(1))); // max request per second per client static MAX_REQ_PER_SEC: isize = 1; diff --git a/pingora-proxy/src/lib.rs b/pingora-proxy/src/lib.rs index d0f41f71..6efe09a2 100644 --- a/pingora-proxy/src/lib.rs +++ b/pingora-proxy/src/lib.rs @@ -40,11 +40,11 @@ use bytes::Bytes; use futures::future::FutureExt; use http::{header, version::Version}; use log::{debug, error, trace, warn}; -use once_cell::sync::Lazy; use pingora_http::{RequestHeader, ResponseHeader}; use std::fmt::Debug; use std::str; use std::sync::Arc; +use std::sync::LazyLock; use std::time::Duration; use tokio::sync::{mpsc, Notify}; use tokio::time; @@ -518,7 +518,7 @@ impl DerefMut for Session { } // generic HTTP 502 response sent when proxy_upstream_filter refuses to connect to upstream -static BAD_GATEWAY: Lazy = Lazy::new(|| { +static BAD_GATEWAY: LazyLock = LazyLock::new(|| { let mut resp = ResponseHeader::build(http::StatusCode::BAD_GATEWAY, Some(3)).unwrap(); resp.insert_header(header::SERVER, &SERVER_NAME[..]) .unwrap(); diff --git a/pingora-proxy/src/proxy_cache.rs b/pingora-proxy/src/proxy_cache.rs index e3d1ba52..53e2aac7 100644 --- a/pingora-proxy/src/proxy_cache.rs +++ b/pingora-proxy/src/proxy_cache.rs @@ -932,8 +932,8 @@ pub mod range_filter { use regex::Regex; // Match individual range parts, (e.g. "0-100", "-5", "1-") - static RE_SINGLE_RANGE_PART: Lazy = - Lazy::new(|| Regex::new(r"(?i)^\s*(?P\d*)-(?P\d*)\s*$").unwrap()); + static RE_SINGLE_RANGE_PART: LazyLock = + LazyLock::new(|| Regex::new(r"(?i)^\s*(?P\d*)-(?P\d*)\s*$").unwrap()); // Convert bytes to UTF-8 string let range_str = match str::from_utf8(range) { diff --git a/pingora-proxy/src/proxy_purge.rs b/pingora-proxy/src/proxy_purge.rs index 1464aa15..ccaae5fb 100644 --- a/pingora-proxy/src/proxy_purge.rs +++ b/pingora-proxy/src/proxy_purge.rs @@ -52,12 +52,13 @@ fn gen_purge_response(code: u16) -> ResponseHeader { resp } -static OK: Lazy = Lazy::new(|| gen_purge_response(200)); -static NOT_FOUND: Lazy = Lazy::new(|| gen_purge_response(404)); +static OK: LazyLock = LazyLock::new(|| gen_purge_response(200)); +static NOT_FOUND: LazyLock = LazyLock::new(|| gen_purge_response(404)); // for when purge is sent to uncacheable assets -static NOT_PURGEABLE: Lazy = Lazy::new(|| gen_purge_response(405)); +static NOT_PURGEABLE: LazyLock = LazyLock::new(|| gen_purge_response(405)); // on cache storage or proxy error -static INTERNAL_ERROR: Lazy = Lazy::new(|| error_resp::gen_error_response(500)); +static INTERNAL_ERROR: LazyLock = + LazyLock::new(|| error_resp::gen_error_response(500)); impl HttpProxy { pub(crate) async fn proxy_purge( diff --git a/pingora-proxy/tests/utils/cert.rs b/pingora-proxy/tests/utils/cert.rs index 7594afa4..69a60582 100644 --- a/pingora-proxy/tests/utils/cert.rs +++ b/pingora-proxy/tests/utils/cert.rs @@ -12,7 +12,6 @@ // See the License for the specific language governing permissions and // limitations under the License. -use once_cell::sync::Lazy; #[cfg(feature = "s2n")] use pingora_core::tls::load_pem_file; #[cfg(feature = "rustls")] @@ -23,6 +22,7 @@ use pingora_core::tls::{ x509::X509, }; use std::fs; +use std::sync::LazyLock; #[cfg(feature = "openssl_derived")] mod key_types { @@ -47,17 +47,20 @@ mod key_types { use key_types::*; -pub static INTERMEDIATE_CERT: Lazy = Lazy::new(|| load_cert("keys/intermediate.crt")); -pub static LEAF_CERT: Lazy = Lazy::new(|| load_cert("keys/leaf.crt")); -pub static LEAF2_CERT: Lazy = Lazy::new(|| load_cert("keys/leaf2.crt")); -pub static LEAF_KEY: Lazy = Lazy::new(|| load_key("keys/leaf.key")); -pub static LEAF2_KEY: Lazy = Lazy::new(|| load_key("keys/leaf2.key")); -pub static CURVE_521_TEST_KEY: Lazy = - Lazy::new(|| load_key("keys/curve_test.521.key.pem")); -pub static CURVE_521_TEST_CERT: Lazy = Lazy::new(|| load_cert("keys/curve_test.521.crt")); -pub static CURVE_384_TEST_KEY: Lazy = - Lazy::new(|| load_key("keys/curve_test.384.key.pem")); -pub static CURVE_384_TEST_CERT: Lazy = Lazy::new(|| load_cert("keys/curve_test.384.crt")); +pub static INTERMEDIATE_CERT: LazyLock = + LazyLock::new(|| load_cert("keys/intermediate.crt")); +pub static LEAF_CERT: LazyLock = LazyLock::new(|| load_cert("keys/leaf.crt")); +pub static LEAF2_CERT: LazyLock = LazyLock::new(|| load_cert("keys/leaf2.crt")); +pub static LEAF_KEY: LazyLock = LazyLock::new(|| load_key("keys/leaf.key")); +pub static LEAF2_KEY: LazyLock = LazyLock::new(|| load_key("keys/leaf2.key")); +pub static CURVE_521_TEST_KEY: LazyLock = + LazyLock::new(|| load_key("keys/curve_test.521.key.pem")); +pub static CURVE_521_TEST_CERT: LazyLock = + LazyLock::new(|| load_cert("keys/curve_test.521.crt")); +pub static CURVE_384_TEST_KEY: LazyLock = + LazyLock::new(|| load_key("keys/curve_test.384.key.pem")); +pub static CURVE_384_TEST_CERT: LazyLock = + LazyLock::new(|| load_cert("keys/curve_test.384.crt")); #[cfg(feature = "openssl_derived")] fn load_cert(path: &str) -> X509 { diff --git a/pingora-proxy/tests/utils/mock_origin.rs b/pingora-proxy/tests/utils/mock_origin.rs index f3564dbe..360e9ee4 100644 --- a/pingora-proxy/tests/utils/mock_origin.rs +++ b/pingora-proxy/tests/utils/mock_origin.rs @@ -12,12 +12,12 @@ // See the License for the specific language governing permissions and // limitations under the License. -use once_cell::sync::Lazy; use std::path::Path; use std::process; +use std::sync::LazyLock; use std::{thread, time}; -pub static MOCK_ORIGIN: Lazy = Lazy::new(init); +pub static MOCK_ORIGIN: LazyLock = LazyLock::new(init); fn init() -> bool { #[cfg(feature = "rustls")] diff --git a/pingora-proxy/tests/utils/mod.rs b/pingora-proxy/tests/utils/mod.rs index 7a70ae4f..69538ee6 100644 --- a/pingora-proxy/tests/utils/mod.rs +++ b/pingora-proxy/tests/utils/mod.rs @@ -21,13 +21,13 @@ pub mod mock_origin; pub mod server_utils; pub mod websocket; -use once_cell::sync::Lazy; +use std::sync::LazyLock; use tokio::runtime::{Builder, Runtime}; // for tests with a static connection pool, if we use tokio::test the reactor // will no longer be associated with the backing pool fds since it's dropped per test -pub static GLOBAL_RUNTIME: Lazy = - Lazy::new(|| Builder::new_multi_thread().enable_all().build().unwrap()); +pub static GLOBAL_RUNTIME: LazyLock = + LazyLock::new(|| Builder::new_multi_thread().enable_all().build().unwrap()); pub fn conf_dir() -> String { format!("{}/tests/utils/conf", env!("CARGO_MANIFEST_DIR")) diff --git a/pingora-proxy/tests/utils/server_utils.rs b/pingora-proxy/tests/utils/server_utils.rs index 73629c8d..d6b4a18e 100644 --- a/pingora-proxy/tests/utils/server_utils.rs +++ b/pingora-proxy/tests/utils/server_utils.rs @@ -19,7 +19,6 @@ use clap::Parser; use http::header::{ACCEPT_ENCODING, VARY}; use http::HeaderValue; use log::error; -use once_cell::sync::Lazy; use pingora_cache::cache_control::CacheControl; use pingora_cache::hashtable::ConcurrentHashTable; use pingora_cache::key::HashBinary; @@ -46,6 +45,7 @@ use pingora_http::{RequestHeader, ResponseHeader}; use pingora_proxy::{FailToProxy, ProxyHttp, Session}; use std::collections::{HashMap, HashSet}; use std::sync::Arc; +use std::sync::LazyLock; use std::thread; use std::time::Duration; @@ -363,16 +363,16 @@ impl ProxyHttp for ExampleProxyHttp { } } -static CACHE_BACKEND: Lazy = Lazy::new(MemCache::new); +static CACHE_BACKEND: LazyLock = LazyLock::new(MemCache::new); const CACHE_DEFAULT: CacheMetaDefaults = CacheMetaDefaults::new(|_| Some(Duration::from_secs(1)), 1, 1); -static CACHE_PREDICTOR: Lazy> = Lazy::new(|| Predictor::new(5, None)); -static EVICTION_MANAGER: Lazy = Lazy::new(|| Manager::new(8192)); // 8192 bytes -static CACHE_LOCK: Lazy> = - Lazy::new(|| CacheLock::new_boxed(std::time::Duration::from_secs(2))); +static CACHE_PREDICTOR: LazyLock> = LazyLock::new(|| Predictor::new(5, None)); +static EVICTION_MANAGER: LazyLock = LazyLock::new(|| Manager::new(8192)); // 8192 bytes +static CACHE_LOCK: LazyLock> = + LazyLock::new(|| CacheLock::new_boxed(std::time::Duration::from_secs(2))); // Example of how one might restrict which fields can be varied on. -static CACHE_VARY_ALLOWED_HEADERS: Lazy>> = - Lazy::new(|| Some(vec!["accept", "accept-encoding"].into_iter().collect())); +static CACHE_VARY_ALLOWED_HEADERS: LazyLock>> = + LazyLock::new(|| Some(vec!["accept", "accept-encoding"].into_iter().collect())); // #[allow(clippy::upper_case_acronyms)] pub struct CacheCTX { @@ -852,9 +852,9 @@ impl PskTlsServer { } // FIXME: this still allows multiple servers to spawn across integration tests -pub static TEST_SERVER: Lazy = Lazy::new(Server::start); +pub static TEST_SERVER: LazyLock = LazyLock::new(Server::start); #[cfg(feature = "s2n")] -pub static TEST_PSK_TLS_SERVER: Lazy = Lazy::new(PskTlsServer::start); +pub static TEST_PSK_TLS_SERVER: LazyLock = LazyLock::new(PskTlsServer::start); use super::mock_origin::MOCK_ORIGIN; pub fn init() { diff --git a/pingora-proxy/tests/utils/websocket.rs b/pingora-proxy/tests/utils/websocket.rs index 92b35e95..4b4ac6a8 100644 --- a/pingora-proxy/tests/utils/websocket.rs +++ b/pingora-proxy/tests/utils/websocket.rs @@ -2,13 +2,13 @@ use std::{io::Error, thread, time::Duration}; use futures_util::{SinkExt, StreamExt}; use log::debug; -use once_cell::sync::Lazy; +use std::sync::LazyLock; use tokio::{ net::{TcpListener, TcpStream}, runtime::Builder, }; -pub static WS_ECHO: Lazy = Lazy::new(init); +pub static WS_ECHO: LazyLock = LazyLock::new(init); fn init() -> bool { thread::spawn(move || { diff --git a/pingora-runtime/Cargo.toml b/pingora-runtime/Cargo.toml index de419400..f2e0983b 100644 --- a/pingora-runtime/Cargo.toml +++ b/pingora-runtime/Cargo.toml @@ -19,7 +19,6 @@ path = "src/lib.rs" [dependencies] rand = "0.8" tokio = { workspace = true, features = ["rt-multi-thread", "sync", "time"] } -once_cell = { workspace = true } thread_local = "1" [dev-dependencies] diff --git a/pingora-runtime/src/lib.rs b/pingora-runtime/src/lib.rs index 07883400..f7e4f736 100644 --- a/pingora-runtime/src/lib.rs +++ b/pingora-runtime/src/lib.rs @@ -23,9 +23,8 @@ //! This flavor is as efficient as the single-threaded runtime while allows the async //! program to use multiple cores. -use once_cell::sync::{Lazy, OnceCell}; use rand::Rng; -use std::sync::Arc; +use std::sync::{Arc, LazyLock, OnceLock}; use std::thread::JoinHandle; use std::time::Duration; use thread_local::ThreadLocal; @@ -83,7 +82,7 @@ impl Runtime { } // only NoStealRuntime set the pools in thread threads -static CURRENT_HANDLE: Lazy> = Lazy::new(ThreadLocal::new); +static CURRENT_HANDLE: LazyLock> = LazyLock::new(ThreadLocal::new); /// Return the [Handle] of current runtime. /// If the current thread is under a `Steal` runtime, the current [Handle] is returned. @@ -103,7 +102,7 @@ pub fn current_handle() -> Handle { } type Control = (Sender, JoinHandle<()>); -type Pools = Arc>>; +type Pools = Arc>>; /// Multi-threaded runtime backed by a pool of single threaded tokio runtime pub struct NoStealRuntime { @@ -112,7 +111,7 @@ pub struct NoStealRuntime { // Lazily init the runtimes so that they are created after pingora // daemonize itself. Otherwise the runtime threads are lost. pools: Pools, - controls: OnceCell>, + controls: OnceLock>, } impl NoStealRuntime { @@ -122,8 +121,8 @@ impl NoStealRuntime { NoStealRuntime { threads, name: name.to_string(), - pools: Arc::new(OnceCell::new()), - controls: OnceCell::new(), + pools: Arc::new(OnceLock::new()), + controls: OnceLock::new(), } } @@ -171,14 +170,25 @@ impl NoStealRuntime { // TODO: use a mutex to avoid creating a lot threads only to drop them let (pools, controls) = self.init_pools(); // there could be another thread racing with this one to init the pools - match self.pools.try_insert(pools) { - Ok(p) => { + // TODO: replace with try_insert() once stable (tracking issue: https://github.com/rust-lang/rust/issues/116693) + // Desired code: + // match self.pools.try_insert(pools) { + // Ok(p) => { + // // unwrap to make sure that this is the one that init both pools and controls + // self.controls.set(controls).unwrap(); + // p + // } + // // another thread already set it, just return it + // Err((p, _my_pools)) => p, + // } + match self.pools.set(pools) { + Ok(()) => { // unwrap to make sure that this is the one that init both pools and controls self.controls.set(controls).unwrap(); - p + self.pools.get().unwrap() } // another thread already set it, just return it - Err((p, _my_pools)) => p, + Err(_my_pools) => self.pools.get().unwrap(), } } } diff --git a/pingora-timeout/Cargo.toml b/pingora-timeout/Cargo.toml index ff14283c..7cfefd90 100644 --- a/pingora-timeout/Cargo.toml +++ b/pingora-timeout/Cargo.toml @@ -24,7 +24,6 @@ tokio = { workspace = true, features = [ "sync", ] } pin-project-lite = "0.2" -once_cell = { workspace = true } parking_lot = "0.12" thread_local = "1.0" diff --git a/pingora-timeout/src/fast_timeout.rs b/pingora-timeout/src/fast_timeout.rs index 8fd22908..d839e012 100644 --- a/pingora-timeout/src/fast_timeout.rs +++ b/pingora-timeout/src/fast_timeout.rs @@ -26,10 +26,9 @@ use super::timer::*; use super::*; -use once_cell::sync::Lazy; -use std::sync::Arc; +use std::sync::{Arc, LazyLock}; -static TIMER_MANAGER: Lazy> = Lazy::new(|| { +static TIMER_MANAGER: LazyLock> = LazyLock::new(|| { let tm = Arc::new(TimerManager::new()); check_clock_thread(&tm); tm diff --git a/pingora/Cargo.toml b/pingora/Cargo.toml index 864ae306..5b0cd1bf 100644 --- a/pingora/Cargo.toml +++ b/pingora/Cargo.toml @@ -43,7 +43,6 @@ async-trait = { workspace = true } http = { workspace = true } log = { workspace = true } prometheus = "0.13" -once_cell = { workspace = true } bytes = { workspace = true } regex = "1" diff --git a/pingora/examples/app/echo.rs b/pingora/examples/app/echo.rs index 97e449df..7da93b60 100644 --- a/pingora/examples/app/echo.rs +++ b/pingora/examples/app/echo.rs @@ -16,10 +16,10 @@ use async_trait::async_trait; use bytes::Bytes; use http::{Response, StatusCode}; use log::debug; -use once_cell::sync::Lazy; use pingora_timeout::timeout; use prometheus::{register_int_counter, IntCounter}; use std::sync::Arc; +use std::sync::LazyLock; use std::time::Duration; use tokio::io::{AsyncReadExt, AsyncWriteExt}; @@ -29,8 +29,8 @@ use pingora::protocols::http::ServerSession; use pingora::protocols::Stream; use pingora::server::ShutdownWatch; -static REQ_COUNTER: Lazy = - Lazy::new(|| register_int_counter!("reg_counter", "Number of requests").unwrap()); +static REQ_COUNTER: LazyLock = + LazyLock::new(|| register_int_counter!("reg_counter", "Number of requests").unwrap()); #[derive(Clone)] pub struct EchoApp;