diff --git a/quickwit/CLAUDE.md b/quickwit/CLAUDE.md index 43c2bb18367..fff22d71b84 100644 --- a/quickwit/CLAUDE.md +++ b/quickwit/CLAUDE.md @@ -87,7 +87,7 @@ When the client is unlikely to match on an error, you can rely on the crate leve ### Design Patterns - **Trait-based services**: `SearchService`, `MetastoreService`, etc. — enables mocking and multiple implementations - **Feature gates**: Cloud backends (`azure`, `gcs`), message sources (`kafka`, `kinesis`, `pulsar`, `sqs`, `gcp-pubsub`), `postgres` metastore, `multilang` tokenizers -- **Metrics**: `once_cell::sync::Lazy` statics with `quickwit_common::metrics::*` factories +- **Metrics**: `std::sync::LazyLock` statics with `quickwit_common::metrics::*` factories ### Key Dependencies - **Tantivy**: Search engine library (custom fork) diff --git a/quickwit/Cargo.lock b/quickwit/Cargo.lock index 89eefe2bed7..7831c43059f 100644 --- a/quickwit/Cargo.lock +++ b/quickwit/Cargo.lock @@ -6951,7 +6951,6 @@ dependencies = [ "criterion", "flume 0.12.0", "futures", - "once_cell", "quickwit-common", "rand 0.9.2", "serde", @@ -6994,7 +6993,6 @@ dependencies = [ "indicatif", "itertools 0.14.0", "numfmt", - "once_cell", "openssl-probe 0.1.6", "opentelemetry", "opentelemetry-appender-tracing", @@ -7042,7 +7040,6 @@ dependencies = [ "chitchat", "futures", "itertools 0.14.0", - "once_cell", "pin-project", "quickwit-common", "quickwit-config", @@ -7120,7 +7117,6 @@ dependencies = [ "hyper 1.8.1", "hyper-util", "itertools 0.14.0", - "once_cell", "pin-project", "pnet", "prometheus", @@ -7160,7 +7156,6 @@ dependencies = [ "itertools 0.14.0", "json_comments", "new_string_template", - "once_cell", "quickwit-common", "quickwit-doc-mapper", "quickwit-proto", @@ -7189,7 +7184,6 @@ dependencies = [ "itertools 0.14.0", "lru 0.16.3", "mockall", - "once_cell", "proptest", "quickwit-actors", "quickwit-cluster", @@ -7250,7 +7244,6 @@ dependencies = [ "itertools 0.14.0", "matches", "nom 8.0.0", - "once_cell", "quickwit-common", "quickwit-datetime", "quickwit-macros", @@ -7314,7 +7307,6 @@ dependencies = [ "itertools 0.14.0", "libz-sys", "mockall", - "once_cell", "oneshot", "openssl", "parquet", @@ -7370,7 +7362,6 @@ dependencies = [ "itertools 0.14.0", "mockall", "mrecordlog", - "once_cell", "prost 0.14.3", "quickwit-actors", "quickwit-cluster", @@ -7434,7 +7425,6 @@ version = "0.8.0" dependencies = [ "async-trait", "itertools 0.14.0", - "once_cell", "postcard", "prost 0.14.3", "prost-types 0.14.3", @@ -7470,7 +7460,6 @@ dependencies = [ "futures", "itertools 0.14.0", "mockall", - "once_cell", "quickwit-actors", "quickwit-common", "quickwit-config", @@ -7505,7 +7494,6 @@ dependencies = [ "base64 0.22.1", "bytesize", "md5", - "once_cell", "prost 0.14.3", "quickwit-common", "quickwit-config", @@ -7568,7 +7556,6 @@ dependencies = [ "itertools 0.14.0", "md5", "mockall", - "once_cell", "ouroboros", "quickwit-common", "quickwit-config", @@ -7607,7 +7594,6 @@ dependencies = [ "anyhow", "arrow", "async-trait", - "once_cell", "parquet", "prost 0.14.3", "quickwit-common", @@ -7690,7 +7676,6 @@ dependencies = [ "bitpacking", "criterion", "hex", - "once_cell", "proptest", "quickwit-common", "quickwit-datetime", @@ -7748,7 +7733,6 @@ dependencies = [ "http 1.4.0", "itertools 0.14.0", "mockall", - "once_cell", "pin-project", "postcard", "proptest", @@ -7800,7 +7784,6 @@ dependencies = [ "itertools 0.14.0", "mime_guess", "mockall", - "once_cell", "percent-encoding", "pprof", "prost 0.14.3", @@ -7877,7 +7860,6 @@ dependencies = [ "md5", "mini-moka", "mockall", - "once_cell", "opendal", "pin-project", "proptest", @@ -7909,7 +7891,6 @@ dependencies = [ "encoding_rs", "hostname", "md5", - "once_cell", "quickwit-common", "reqwest", "serde", diff --git a/quickwit/Cargo.toml b/quickwit/Cargo.toml index 9242390d898..7aead176deb 100644 --- a/quickwit/Cargo.toml +++ b/quickwit/Cargo.toml @@ -162,7 +162,6 @@ mrecordlog = { git = "https://github.com/quickwit-oss/mrecordlog", rev = "306c0a new_string_template = "1.5" nom = "8.0" numfmt = "1.2" -once_cell = "1" oneshot = "0.1" openssl = { version = "0.10", default-features = false } openssl-probe = "0.1" diff --git a/quickwit/quickwit-actors/Cargo.toml b/quickwit/quickwit-actors/Cargo.toml index a4bae06f7e9..7832c48e967 100644 --- a/quickwit/quickwit-actors/Cargo.toml +++ b/quickwit/quickwit-actors/Cargo.toml @@ -15,7 +15,6 @@ anyhow = { workspace = true } async-trait = { workspace = true } flume = { workspace = true } futures = { workspace = true } -once_cell = { workspace = true } serde = { workspace = true } serde_json = { workspace = true } sync_wrapper = { workspace = true } diff --git a/quickwit/quickwit-actors/src/lib.rs b/quickwit/quickwit-actors/src/lib.rs index b3414650446..ca2e47e10d2 100644 --- a/quickwit/quickwit-actors/src/lib.rs +++ b/quickwit/quickwit-actors/src/lib.rs @@ -24,8 +24,8 @@ use std::fmt; use std::num::NonZeroU64; +use std::sync::LazyLock; -use once_cell::sync::Lazy; use tokio::time::Duration; mod actor; mod actor_context; @@ -70,7 +70,7 @@ pub use self::supervisor::{Supervisor, SupervisorMetrics, SupervisorState}; /// If an actor does not advertise a progress within an interval of duration `HEARTBEAT`, /// its supervisor will consider it as blocked and will proceed to kill it, as well /// as all of the actors all the actors that share the killswitch. -pub static HEARTBEAT: Lazy = Lazy::new(heartbeat_from_env_or_default); +pub static HEARTBEAT: LazyLock = LazyLock::new(heartbeat_from_env_or_default); /// Returns the actor's heartbeat duration: /// - Derived from `QW_ACTOR_HEARTBEAT_SECS` if set and valid. diff --git a/quickwit/quickwit-actors/src/mailbox.rs b/quickwit/quickwit-actors/src/mailbox.rs index 899e289182a..f222294e4c2 100644 --- a/quickwit/quickwit-actors/src/mailbox.rs +++ b/quickwit/quickwit-actors/src/mailbox.rs @@ -16,7 +16,7 @@ use std::any::Any; use std::convert::Infallible; use std::fmt; use std::sync::atomic::{AtomicUsize, Ordering}; -use std::sync::{Arc, OnceLock, Weak}; +use std::sync::{Arc, LazyLock, Weak}; use std::time::Instant; use quickwit_common::metrics::{GaugeGuard, IntCounter, IntGauge}; @@ -386,8 +386,7 @@ impl Inbox { } fn get_actor_inboxes_count_gauge_guard() -> GaugeGuard<'static> { - static INBOX_GAUGE: std::sync::OnceLock = OnceLock::new(); - let gauge = INBOX_GAUGE.get_or_init(|| { + static INBOX_GAUGE: LazyLock = LazyLock::new(|| { quickwit_common::metrics::new_gauge( "inboxes_count", "overall count of actors", @@ -395,7 +394,7 @@ fn get_actor_inboxes_count_gauge_guard() -> GaugeGuard<'static> { &[], ) }); - let mut gauge_guard = GaugeGuard::from_gauge(gauge); + let mut gauge_guard = GaugeGuard::from_gauge(&INBOX_GAUGE); gauge_guard.add(1); gauge_guard } diff --git a/quickwit/quickwit-cli/Cargo.toml b/quickwit/quickwit-cli/Cargo.toml index b40bf5585d3..65a98bd7108 100644 --- a/quickwit/quickwit-cli/Cargo.toml +++ b/quickwit/quickwit-cli/Cargo.toml @@ -34,7 +34,6 @@ humantime = { workspace = true } indicatif = { workspace = true } itertools = { workspace = true } numfmt = { workspace = true } -once_cell = { workspace = true } openssl-probe = { workspace = true, optional = true } opentelemetry = { workspace = true } opentelemetry-appender-tracing = { workspace = true } diff --git a/quickwit/quickwit-cli/src/lib.rs b/quickwit/quickwit-cli/src/lib.rs index aaeb4da7e9d..45275c3ff5d 100644 --- a/quickwit/quickwit-cli/src/lib.rs +++ b/quickwit/quickwit-cli/src/lib.rs @@ -16,7 +16,7 @@ use std::collections::HashSet; use std::str::FromStr; -use std::sync::OnceLock; +use std::sync::LazyLock; use anyhow::Context; use clap::{Arg, ArgMatches, arg}; @@ -109,13 +109,13 @@ fn client_args() -> Vec { } pub fn install_default_crypto_ring_provider() { - static CALL_ONLY_ONCE: OnceLock> = OnceLock::new(); + static CALL_ONLY_ONCE: LazyLock> = LazyLock::new(|| { + rustls::crypto::ring::default_provider() + .install_default() + .map_err(|_| ()) + }); CALL_ONLY_ONCE - .get_or_init(|| { - rustls::crypto::ring::default_provider() - .install_default() - .map_err(|_| ()) - }) + .as_ref() .expect("rustls crypto ring default provider installation should not fail"); } @@ -348,16 +348,16 @@ fn prompt_confirmation(prompt: &str, default: bool) -> bool { } pub mod busy_detector { + use std::sync::LazyLock; use std::sync::atomic::{AtomicBool, AtomicU64, Ordering}; use std::time::Instant; - use once_cell::sync::Lazy; use tracing::debug; use crate::metrics::CLI_METRICS; // we need that time reference to use an atomic and not a mutex for LAST_UNPARK - static TIME_REF: Lazy = Lazy::new(Instant::now); + static TIME_REF: LazyLock = LazyLock::new(Instant::now); static ENABLED: AtomicBool = AtomicBool::new(false); const ALLOWED_DELAY_MICROS: u64 = 5000; diff --git a/quickwit/quickwit-cli/src/metrics.rs b/quickwit/quickwit-cli/src/metrics.rs index 332b968edf9..c51d010c9ea 100644 --- a/quickwit/quickwit-cli/src/metrics.rs +++ b/quickwit/quickwit-cli/src/metrics.rs @@ -12,7 +12,8 @@ // See the License for the specific language governing permissions and // limitations under the License. -use once_cell::sync::Lazy; +use std::sync::LazyLock; + use quickwit_common::metrics::{HistogramVec, new_histogram_vec}; pub struct CliMetrics { @@ -35,4 +36,4 @@ impl Default for CliMetrics { } /// Serve counters exposes a bunch a set of metrics about the request received to quickwit. -pub static CLI_METRICS: Lazy = Lazy::new(CliMetrics::default); +pub static CLI_METRICS: LazyLock = LazyLock::new(CliMetrics::default); diff --git a/quickwit/quickwit-cluster/Cargo.toml b/quickwit/quickwit-cluster/Cargo.toml index 211ae541078..ab01f587cb9 100644 --- a/quickwit/quickwit-cluster/Cargo.toml +++ b/quickwit/quickwit-cluster/Cargo.toml @@ -17,7 +17,6 @@ bytesize = { workspace = true } chitchat = { workspace = true } futures = { workspace = true } itertools = { workspace = true } -once_cell = { workspace = true } pin-project = { workspace = true } rand = { workspace = true } serde = { workspace = true } diff --git a/quickwit/quickwit-cluster/src/grpc_service.rs b/quickwit/quickwit-cluster/src/grpc_service.rs index 5798a385e27..f7195a4688b 100644 --- a/quickwit/quickwit-cluster/src/grpc_service.rs +++ b/quickwit/quickwit-cluster/src/grpc_service.rs @@ -13,10 +13,10 @@ // limitations under the License. use std::net::SocketAddr; +use std::sync::LazyLock; use bytesize::ByteSize; use itertools::Itertools; -use once_cell::sync::Lazy; use quickwit_common::tower::{ClientGrpcConfig, GrpcMetricsLayer, make_channel}; use quickwit_proto::cluster::cluster_service_grpc_server::ClusterServiceGrpcServer; use quickwit_proto::cluster::{ @@ -30,10 +30,10 @@ use crate::Cluster; const MAX_MESSAGE_SIZE: ByteSize = ByteSize::mib(64); -static CLUSTER_GRPC_CLIENT_METRICS_LAYER: Lazy = - Lazy::new(|| GrpcMetricsLayer::new("cluster", "client")); -static CLUSTER_GRPC_SERVER_METRICS_LAYER: Lazy = - Lazy::new(|| GrpcMetricsLayer::new("cluster", "server")); +static CLUSTER_GRPC_CLIENT_METRICS_LAYER: LazyLock = + LazyLock::new(|| GrpcMetricsLayer::new("cluster", "client")); +static CLUSTER_GRPC_SERVER_METRICS_LAYER: LazyLock = + LazyLock::new(|| GrpcMetricsLayer::new("cluster", "server")); pub(crate) async fn cluster_grpc_client( socket_addr: SocketAddr, diff --git a/quickwit/quickwit-cluster/src/metrics.rs b/quickwit/quickwit-cluster/src/metrics.rs index 56ee57d6442..a5ac5d4a9ef 100644 --- a/quickwit/quickwit-cluster/src/metrics.rs +++ b/quickwit/quickwit-cluster/src/metrics.rs @@ -14,11 +14,10 @@ use std::collections::HashSet; use std::net::SocketAddr; -use std::sync::Weak; +use std::sync::{LazyLock, Weak}; use std::time::Duration; use chitchat::{Chitchat, ChitchatId}; -use once_cell::sync::Lazy; use quickwit_common::metrics::{IntCounter, IntGauge, new_counter, new_gauge}; use tokio::sync::Mutex; @@ -118,7 +117,7 @@ impl Default for ClusterMetrics { } } -pub static CLUSTER_METRICS: Lazy = Lazy::new(ClusterMetrics::default); +pub static CLUSTER_METRICS: LazyLock = LazyLock::new(ClusterMetrics::default); pub(crate) fn spawn_metrics_task( weak_chitchat: Weak>, diff --git a/quickwit/quickwit-common/Cargo.toml b/quickwit/quickwit-common/Cargo.toml index ee5fc303644..14c05e19c5e 100644 --- a/quickwit/quickwit-common/Cargo.toml +++ b/quickwit/quickwit-common/Cargo.toml @@ -28,7 +28,6 @@ http = { workspace = true } hyper = { workspace = true } hyper-util = { workspace = true, optional = true } itertools = { workspace = true } -once_cell = { workspace = true } pin-project = { workspace = true } pnet = { workspace = true } prometheus = { workspace = true } diff --git a/quickwit/quickwit-common/src/cpus.rs b/quickwit/quickwit-common/src/cpus.rs index dba84f326d2..1a7d20be557 100644 --- a/quickwit/quickwit-common/src/cpus.rs +++ b/quickwit/quickwit-common/src/cpus.rs @@ -13,7 +13,7 @@ // limitations under the License. use std::num::NonZero; -use std::sync::OnceLock; +use std::sync::LazyLock; use tracing::{error, info, warn}; @@ -27,8 +27,8 @@ const KUBERNETES_LIMITS_CPU: &str = "KUBERNETES_LIMITS_CPU"; /// - from the operating system /// - default to 2. pub fn num_cpus() -> usize { - static NUM_CPUS: OnceLock = OnceLock::new(); - *NUM_CPUS.get_or_init(num_cpus_aux) + static NUM_CPUS: LazyLock = LazyLock::new(num_cpus_aux); + *NUM_CPUS } fn num_cpus_aux() -> usize { diff --git a/quickwit/quickwit-common/src/io.rs b/quickwit/quickwit-common/src/io.rs index 69c2091c237..e1d9ad796f1 100644 --- a/quickwit/quickwit-common/src/io.rs +++ b/quickwit/quickwit-common/src/io.rs @@ -25,6 +25,7 @@ use std::future::Future; use std::io; use std::io::IoSlice; use std::pin::Pin; +use std::sync::LazyLock; use std::task::{Context, Poll}; use std::time::Duration; @@ -32,7 +33,6 @@ pub use async_speed_limit::Limiter; use async_speed_limit::clock::StandardClock; use async_speed_limit::limiter::Consume; use bytesize::ByteSize; -use once_cell::sync::Lazy; use pin_project::pin_project; use prometheus::IntCounter; use tokio::io::AsyncWrite; @@ -66,7 +66,7 @@ impl Default for IoMetrics { } } -static IO_METRICS: Lazy = Lazy::new(IoMetrics::default); +static IO_METRICS: LazyLock = LazyLock::new(IoMetrics::default); /// Parameter used in `async_speed_limit`. /// diff --git a/quickwit/quickwit-common/src/jemalloc_profiled.rs b/quickwit/quickwit-common/src/jemalloc_profiled.rs index 14fe303f3a1..0e000986bb0 100644 --- a/quickwit/quickwit-common/src/jemalloc_profiled.rs +++ b/quickwit/quickwit-common/src/jemalloc_profiled.rs @@ -14,11 +14,10 @@ use std::alloc::{GlobalAlloc, Layout}; use std::hash::Hasher; -use std::sync::Mutex; use std::sync::atomic::{AtomicBool, AtomicU64, Ordering}; +use std::sync::{LazyLock, Mutex}; use bytesize::ByteSize; -use once_cell::sync::Lazy; use tikv_jemallocator::Jemalloc; use tracing::{error, info, trace}; @@ -54,8 +53,8 @@ static FLAGS: Flags = Flags { _padding: [0; 119], }; -static ALLOCATION_TRACKER: Lazy> = - Lazy::new(|| Mutex::new(Allocations::default())); +static ALLOCATION_TRACKER: LazyLock> = + LazyLock::new(|| Mutex::new(Allocations::default())); /// Starts measuring heap allocations and logs important leaks. /// diff --git a/quickwit/quickwit-common/src/net.rs b/quickwit/quickwit-common/src/net.rs index a06ee9af2e1..93116a1b937 100644 --- a/quickwit/quickwit-common/src/net.rs +++ b/quickwit/quickwit-common/src/net.rs @@ -17,10 +17,10 @@ use std::fmt::Display; use std::io; use std::net::{IpAddr, Ipv4Addr, Ipv6Addr, SocketAddr, TcpListener}; use std::str::FromStr; +use std::sync::LazyLock; use anyhow::{Context, bail}; use itertools::Itertools; -use once_cell::sync::OnceCell; use pnet::datalink::{self, NetworkInterface}; use pnet::ipnetwork::IpNetwork; use serde::{Deserialize, Serialize, Serializer}; @@ -275,44 +275,42 @@ pub async fn get_socket_addr( } fn is_forwardable_ip(ip_addr: &IpAddr) -> bool { - static NON_FORWARDABLE_NETWORKS: OnceCell> = OnceCell::new(); + static NON_FORWARDABLE_NETWORKS: LazyLock> = LazyLock::new(|| { + // Blacklist of non-forwardable IP blocks taken from RFC6890 + [ + "0.0.0.0/8", + "127.0.0.0/8", + "169.254.0.0/16", + "192.0.0.0/24", + "192.0.2.0/24", + "198.51.100.0/24", + "2001:10::/28", + "2001:db8::/32", + "203.0.113.0/24", + "240.0.0.0/4", + "255.255.255.255/32", + "::/128", + "::1/128", + "::ffff:0:0/96", + "fe80::/10", + ] + .iter() + .map(|network| network.parse().expect("IP range should parse")) + .collect() + }); NON_FORWARDABLE_NETWORKS - .get_or_init(|| { - // Blacklist of non-forwardable IP blocks taken from RFC6890 - [ - "0.0.0.0/8", - "127.0.0.0/8", - "169.254.0.0/16", - "192.0.0.0/24", - "192.0.2.0/24", - "198.51.100.0/24", - "2001:10::/28", - "2001:db8::/32", - "203.0.113.0/24", - "240.0.0.0/4", - "255.255.255.255/32", - "::/128", - "::1/128", - "::ffff:0:0/96", - "fe80::/10", - ] - .iter() - .map(|network| network.parse().expect("Failed to parse network range. This should never happen! Please, report on https://github.com/quickwit-oss/quickwit/issues.")) - .collect() - }) .iter() .all(|network| !network.contains(*ip_addr)) } fn is_private_ip(ip_addr: &IpAddr) -> bool { - static PRIVATE_NETWORKS: OnceCell> = OnceCell::new(); + static PRIVATE_NETWORKS: LazyLock> = LazyLock::new(|| { + ["192.168.0.0/16", "172.16.0.0/12", "10.0.0.0/8", "fc00::/7"] + .iter() + .map(|network| network.parse().expect("IP range should parse")) + .collect() + }); PRIVATE_NETWORKS - .get_or_init(|| { - ["192.168.0.0/16", "172.16.0.0/12", "10.0.0.0/8", "fc00::/7"] - .iter() - .map(|network| network.parse().expect("Failed to parse network range. This should never happen! Please, report on https://github.com/quickwit-oss/quickwit/issues.")) - .collect() - }) .iter() .any(|network| network.contains(*ip_addr)) } diff --git a/quickwit/quickwit-common/src/runtimes.rs b/quickwit/quickwit-common/src/runtimes.rs index ee93ab7aba9..79ac2611bd9 100644 --- a/quickwit/quickwit-common/src/runtimes.rs +++ b/quickwit/quickwit-common/src/runtimes.rs @@ -13,17 +13,17 @@ // limitations under the License. use std::collections::HashMap; +use std::sync::OnceLock; use std::sync::atomic::{AtomicUsize, Ordering}; use std::time::Duration; -use once_cell::sync::OnceCell; use prometheus::{Gauge, IntCounter, IntGauge}; use tokio::runtime::Runtime; use tokio_metrics::{RuntimeMetrics, RuntimeMonitor}; use crate::metrics::{new_counter, new_float_gauge, new_gauge}; -static RUNTIMES: OnceCell> = OnceCell::new(); +static RUNTIMES: OnceLock> = OnceLock::new(); /// Describes which runtime an actor should run on. #[derive(Clone, Copy, Debug, Hash, Eq, PartialEq)] diff --git a/quickwit/quickwit-common/src/shared_consts.rs b/quickwit/quickwit-common/src/shared_consts.rs index 611636a5aa9..95b3a531aaf 100644 --- a/quickwit/quickwit-common/src/shared_consts.rs +++ b/quickwit/quickwit-common/src/shared_consts.rs @@ -12,7 +12,7 @@ // See the License for the specific language governing permissions and // limitations under the License. -use std::sync::OnceLock; +use std::sync::LazyLock; use std::time::Duration; use bytesize::ByteSize; @@ -35,8 +35,7 @@ const MAXIMUM_DELETION_GRACE_PERIOD: Duration = Duration::from_secs(2 * 24 * 360 pub fn split_deletion_grace_period() -> Duration { const DEFAULT_DELETION_GRACE_PERIOD: Duration = Duration::from_secs(60 * 32); // 32 min - static SPLIT_DELETION_GRACE_PERIOD_SECS_LOCK: OnceLock = std::sync::OnceLock::new(); - *SPLIT_DELETION_GRACE_PERIOD_SECS_LOCK.get_or_init(|| { + static SPLIT_DELETION_GRACE_PERIOD_SECS_LOCK: LazyLock = LazyLock::new(|| { let deletion_grace_period_secs: u64 = crate::get_from_env( "QW_SPLIT_DELETION_GRACE_PERIOD_SECS", DEFAULT_DELETION_GRACE_PERIOD.as_secs(), @@ -54,7 +53,8 @@ pub fn split_deletion_grace_period() -> Duration { ); } Duration::from_secs(deletion_grace_period_secs_clamped) - }) + }); + *SPLIT_DELETION_GRACE_PERIOD_SECS_LOCK } /// In order to amortized search with scroll, we fetch more documents than are diff --git a/quickwit/quickwit-common/src/stream_utils.rs b/quickwit/quickwit-common/src/stream_utils.rs index e0fc126b465..00b40ee4b43 100644 --- a/quickwit/quickwit-common/src/stream_utils.rs +++ b/quickwit/quickwit-common/src/stream_utils.rs @@ -284,7 +284,7 @@ impl TrackedUnboundedSender { #[cfg(test)] mod tests { - use once_cell::sync::Lazy; + use std::sync::LazyLock; use super::*; use crate::metrics::new_gauge; @@ -300,8 +300,9 @@ mod tests { #[tokio::test] async fn test_tracked_service_stream_bounded() { - static TEST_GAUGE: Lazy = - Lazy::new(|| new_gauge("common", "help", "test_tracked_service_stream_bounded", &[])); + static TEST_GAUGE: LazyLock = LazyLock::new(|| { + new_gauge("common", "help", "test_tracked_service_stream_bounded", &[]) + }); let (service_stream_tx, mut service_stream) = ServiceStream::new_bounded_with_gauge(3, &TEST_GAUGE); @@ -319,7 +320,7 @@ mod tests { #[tokio::test] async fn test_tracked_service_stream_unbounded() { - static TEST_GAUGE: Lazy = Lazy::new(|| { + static TEST_GAUGE: LazyLock = LazyLock::new(|| { new_gauge( "common", "help", diff --git a/quickwit/quickwit-common/src/thread_pool.rs b/quickwit/quickwit-common/src/thread_pool.rs index 18201196cf9..f4b738ef2c0 100644 --- a/quickwit/quickwit-common/src/thread_pool.rs +++ b/quickwit/quickwit-common/src/thread_pool.rs @@ -13,10 +13,9 @@ // limitations under the License. use std::fmt; -use std::sync::Arc; +use std::sync::{Arc, LazyLock}; use futures::{Future, TryFutureExt}; -use once_cell::sync::Lazy; use prometheus::IntGauge; use tokio::sync::oneshot; use tracing::error; @@ -117,13 +116,11 @@ where F: FnOnce() -> R + Send + 'static, R: Send + 'static, { - static SMALL_TASK_EXECUTOR: std::sync::OnceLock = std::sync::OnceLock::new(); - SMALL_TASK_EXECUTOR - .get_or_init(|| { - let num_threads: usize = (crate::num_cpus() / 3).max(2); - ThreadPool::new("small_tasks", Some(num_threads)) - }) - .run_cpu_intensive(cpu_intensive_fn) + static SMALL_TASK_EXECUTOR: std::sync::LazyLock = std::sync::LazyLock::new(|| { + let num_threads: usize = (crate::num_cpus() / 3).max(2); + ThreadPool::new("small_tasks", Some(num_threads)) + }); + SMALL_TASK_EXECUTOR.run_cpu_intensive(cpu_intensive_fn) } #[derive(Clone, Copy, Debug, Eq, PartialEq)] @@ -163,7 +160,7 @@ impl Default for ThreadPoolMetrics { } } -static THREAD_POOL_METRICS: Lazy = Lazy::new(ThreadPoolMetrics::default); +static THREAD_POOL_METRICS: LazyLock = LazyLock::new(ThreadPoolMetrics::default); #[cfg(test)] mod tests { diff --git a/quickwit/quickwit-common/src/uri.rs b/quickwit/quickwit-common/src/uri.rs index a094ae34ee8..ff191fb04cb 100644 --- a/quickwit/quickwit-common/src/uri.rs +++ b/quickwit/quickwit-common/src/uri.rs @@ -18,9 +18,9 @@ use std::fmt::{Debug, Display}; use std::hash::Hash; use std::path::{Component, Path, PathBuf}; use std::str::FromStr; +use std::sync::LazyLock; use anyhow::{Context, bail}; -use once_cell::sync::OnceCell; use regex::Regex; use serde::de::Error; use serde::{Deserialize, Serialize, Serializer}; @@ -141,13 +141,11 @@ impl Uri { /// Strips sensitive information such as credentials from URI. fn as_redacted_str(&self) -> Cow<'_, str> { if self.protocol().is_database() { - static DATABASE_URI_PATTERN: OnceCell = OnceCell::new(); - DATABASE_URI_PATTERN - .get_or_init(|| { - Regex::new("(?P^.*://.*)(?P:.*@)(?P.*)") - .expect("regular expression should compile") - }) - .replace(&self.uri, "$before:***redacted***@$after") + static DATABASE_URI_PATTERN: LazyLock = LazyLock::new(|| { + Regex::new("(?P^.*://.*)(?P:.*@)(?P.*)") + .expect("regular expression should compile") + }); + DATABASE_URI_PATTERN.replace(&self.uri, "$before:***redacted***@$after") } else { Cow::Borrowed(&self.uri) } diff --git a/quickwit/quickwit-config/Cargo.toml b/quickwit/quickwit-config/Cargo.toml index 59e98ad3aa1..93a1fdf8de1 100644 --- a/quickwit/quickwit-config/Cargo.toml +++ b/quickwit/quickwit-config/Cargo.toml @@ -23,7 +23,6 @@ humantime = { workspace = true } itertools = { workspace = true } json_comments = { workspace = true } new_string_template = { workspace = true } -once_cell = { workspace = true } regex = { workspace = true } serde = { workspace = true } serde_json = { workspace = true } diff --git a/quickwit/quickwit-config/src/lib.rs b/quickwit/quickwit-config/src/lib.rs index 22cdb2538b4..2abaaef79f3 100644 --- a/quickwit/quickwit-config/src/lib.rs +++ b/quickwit/quickwit-config/src/lib.rs @@ -16,10 +16,10 @@ use std::hash::Hasher; use std::str::FromStr; +use std::sync::LazyLock; use anyhow::{Context, bail, ensure}; use json_comments::StripComments; -use once_cell::sync::Lazy; use quickwit_common::get_bool_from_env; use quickwit_common::net::is_valid_hostname; use quickwit_common::uri::Uri; @@ -85,15 +85,15 @@ pub use crate::storage_config::{ /// Returns true if the ingest API v2 is enabled. pub fn enable_ingest_v2() -> bool { - static ENABLE_INGEST_V2: Lazy = - Lazy::new(|| get_bool_from_env("QW_ENABLE_INGEST_V2", true)); + static ENABLE_INGEST_V2: LazyLock = + LazyLock::new(|| get_bool_from_env("QW_ENABLE_INGEST_V2", true)); *ENABLE_INGEST_V2 } /// Returns true if the ingest API v1 is disabled. pub fn disable_ingest_v1() -> bool { - static DISABLE_INGEST_V1: Lazy = - Lazy::new(|| get_bool_from_env("QW_DISABLE_INGEST_V1", false)); + static DISABLE_INGEST_V1: LazyLock = + LazyLock::new(|| get_bool_from_env("QW_DISABLE_INGEST_V1", false)); *DISABLE_INGEST_V1 } @@ -136,7 +136,7 @@ pub struct ConfigApiSchemas; /// Checks whether an identifier conforms to Quickwit naming conventions. pub fn validate_identifier(label: &str, value: &str) -> anyhow::Result<()> { - static IDENTIFIER_REGEX: Lazy = Lazy::new(|| { + static IDENTIFIER_REGEX: LazyLock = LazyLock::new(|| { Regex::new(r"^[a-zA-Z][a-zA-Z0-9-_\.]{2,254}$").expect("regular expression should compile") }); ensure!( @@ -151,11 +151,11 @@ pub fn validate_identifier(label: &str, value: &str) -> anyhow::Result<()> { /// Index ID patterns accept the same characters as identifiers AND accept `*` /// chars to allow for glob-like patterns. pub fn validate_index_id_pattern(pattern: &str, allow_negative: bool) -> anyhow::Result<()> { - static IDENTIFIER_REGEX_WITH_GLOB_PATTERN: Lazy = Lazy::new(|| { + static IDENTIFIER_REGEX_WITH_GLOB_PATTERN: LazyLock = LazyLock::new(|| { Regex::new(r"^[a-zA-Z\*][a-zA-Z0-9-_\.\*]{0,254}$") .expect("regular expression should compile") }); - static IDENTIFIER_REGEX_WITH_GLOB_PATTERN_NEGATIVE: Lazy = Lazy::new(|| { + static IDENTIFIER_REGEX_WITH_GLOB_PATTERN_NEGATIVE: LazyLock = LazyLock::new(|| { Regex::new(r"^-?[a-zA-Z\*][a-zA-Z0-9-_\.\*]{0,254}$") .expect("regular expression should compile") }); diff --git a/quickwit/quickwit-config/src/qw_env_vars.rs b/quickwit/quickwit-config/src/qw_env_vars.rs index 7f36fdc2911..75f891d332c 100644 --- a/quickwit/quickwit-config/src/qw_env_vars.rs +++ b/quickwit/quickwit-config/src/qw_env_vars.rs @@ -13,8 +13,7 @@ // limitations under the License. use std::collections::HashMap; - -use once_cell::sync::Lazy; +use std::sync::LazyLock; /// Expands the list of QW environment variables into constants of the form `const : /// usize = ;` and builds the map `QW_EN_VARS` of environment variable index to @@ -31,7 +30,7 @@ macro_rules! qw_env_vars { ($($ident:ident),*) => { qw_env_vars!(@step 0usize, $($ident,)*); - pub(crate) static QW_ENV_VARS: Lazy> = Lazy::new(|| { + pub(crate) static QW_ENV_VARS: LazyLock> = LazyLock::new(|| { let mut env_vars = HashMap::new(); $(env_vars.insert($ident, stringify!($ident));)* env_vars diff --git a/quickwit/quickwit-config/src/templating.rs b/quickwit/quickwit-config/src/templating.rs index 39b093a6581..9d546bfeb2f 100644 --- a/quickwit/quickwit-config/src/templating.rs +++ b/quickwit/quickwit-config/src/templating.rs @@ -14,17 +14,17 @@ use std::collections::HashMap; use std::io::BufRead; +use std::sync::LazyLock; use anyhow::{Context, Result, bail}; use new_string_template::template::Template; -use once_cell::sync::Lazy; use regex::Regex; use tracing::debug; // Matches `${value}` if value is formatted as: // `ENV_VAR` or `ENV_VAR:DEFAULT` // Ignores whitespaces in curly braces -static TEMPLATE_ENV_VAR_CAPTURE: Lazy = Lazy::new(|| { +static TEMPLATE_ENV_VAR_CAPTURE: LazyLock = LazyLock::new(|| { Regex::new(r"\$\{\s*([A-Za-z0-9_]+)\s*(?::\-\s*([^\s\}]+)\s*)?}") .expect("regular expression should compile") }); diff --git a/quickwit/quickwit-control-plane/Cargo.toml b/quickwit/quickwit-control-plane/Cargo.toml index abaf672e908..e7d9d012dd0 100644 --- a/quickwit/quickwit-control-plane/Cargo.toml +++ b/quickwit/quickwit-control-plane/Cargo.toml @@ -19,7 +19,6 @@ futures = { workspace = true } itertools = { workspace = true } lru = { workspace = true } mockall = { workspace = true, optional = true } -once_cell = { workspace = true } rand = { workspace = true } serde = { workspace = true } serde_json = { workspace = true } diff --git a/quickwit/quickwit-control-plane/src/indexing_scheduler/mod.rs b/quickwit/quickwit-control-plane/src/indexing_scheduler/mod.rs index 9f79032d7c5..6fdb5129f5f 100644 --- a/quickwit/quickwit-control-plane/src/indexing_scheduler/mod.rs +++ b/quickwit/quickwit-control-plane/src/indexing_scheduler/mod.rs @@ -18,12 +18,11 @@ mod scheduling; use std::cmp::Ordering; use std::fmt; use std::num::NonZeroU32; -use std::sync::{Arc, OnceLock}; +use std::sync::{Arc, LazyLock}; use std::time::{Duration, Instant}; use fnv::{FnvHashMap, FnvHashSet}; use itertools::Itertools; -use once_cell::sync::OnceCell; use quickwit_common::is_metrics_index; use quickwit_common::pretty::PrettySample; use quickwit_config::{FileSourceParams, SourceParams, indexing_pipeline_params_fingerprint}; @@ -122,8 +121,7 @@ impl fmt::Debug for IndexingScheduler { } fn enable_variable_shard_load() -> bool { - static IS_SHARD_LOAD_CP_ENABLED: OnceCell = OnceCell::new(); - *IS_SHARD_LOAD_CP_ENABLED.get_or_init(|| { + static IS_SHARD_LOAD_CP_ENABLED: LazyLock = LazyLock::new(|| { if let Some(enable_flag) = quickwit_common::get_bool_from_env_opt("QW_ENABLE_VARIABLE_SHARD_LOAD") { @@ -148,7 +146,8 @@ fn enable_variable_shard_load() -> bool { DEFAULT_ENABLE_VARIABLE_SHARD_LOAD ); DEFAULT_ENABLE_VARIABLE_SHARD_LOAD - }) + }); + *IS_SHARD_LOAD_CP_ENABLED } /// Computes the CPU load associated to a single shard of a given index. @@ -183,15 +182,15 @@ fn compute_load_per_shard(shard_entries: &[&ShardEntry]) -> NonZeroU32 { } fn get_default_load_per_shard() -> NonZeroU32 { - static DEFAULT_LOAD_PER_SHARD: OnceLock = OnceLock::new(); - *DEFAULT_LOAD_PER_SHARD.get_or_init(|| { + static DEFAULT_LOAD_PER_SHARD: LazyLock = LazyLock::new(|| { let default_load_per_shard = quickwit_common::get_from_env( "QW_DEFAULT_LOAD_PER_SHARD", PIPELINE_FULL_CAPACITY.cpu_millis() / 4, false, ); NonZeroU32::new(default_load_per_shard).unwrap() - }) + }); + *DEFAULT_LOAD_PER_SHARD } fn get_sources_to_schedule(model: &ControlPlaneModel) -> Vec { diff --git a/quickwit/quickwit-control-plane/src/metrics.rs b/quickwit/quickwit-control-plane/src/metrics.rs index 5e534c4f176..7935f18a1e8 100644 --- a/quickwit/quickwit-control-plane/src/metrics.rs +++ b/quickwit/quickwit-control-plane/src/metrics.rs @@ -12,7 +12,8 @@ // See the License for the specific language governing permissions and // limitations under the License. -use once_cell::sync::Lazy; +use std::sync::LazyLock; + use quickwit_common::metrics::{ IntCounter, IntGauge, IntGaugeVec, new_counter, new_gauge, new_gauge_vec, }; @@ -132,5 +133,5 @@ impl Default for ControlPlaneMetrics { } } -pub static CONTROL_PLANE_METRICS: Lazy = - Lazy::new(ControlPlaneMetrics::default); +pub static CONTROL_PLANE_METRICS: LazyLock = + LazyLock::new(ControlPlaneMetrics::default); diff --git a/quickwit/quickwit-datetime/src/java_date_time_format.rs b/quickwit/quickwit-datetime/src/java_date_time_format.rs index 2ef63f32881..6a8ac7d6da9 100644 --- a/quickwit/quickwit-datetime/src/java_date_time_format.rs +++ b/quickwit/quickwit-datetime/src/java_date_time_format.rs @@ -14,7 +14,7 @@ use std::collections::HashMap; use std::num::NonZeroU8; -use std::sync::OnceLock; +use std::sync::LazyLock; use time::error::{Format, TryFromParsed}; use time::format_description::modifier::{ @@ -257,38 +257,37 @@ fn match_java_date_format_token( // If the java_datetime_format is not an alias, it is expected to be a // java date time format and should be returned as is. fn resolve_java_datetime_format_alias(java_datetime_format: &str) -> &str { - static JAVA_DATE_FORMAT_ALIASES: OnceLock> = - OnceLock::new(); - let java_datetime_format_map = JAVA_DATE_FORMAT_ALIASES.get_or_init(|| { - let mut m = HashMap::new(); - m.insert("date_optional_time", "yyyy-MM-dd['T'HH:mm:ss.SSSZ]"); - m.insert( - "strict_date_optional_time", - "yyyy[-MM[-dd['T'HH[:mm[:ss[.SSS[Z]]]]]]]", - ); - m.insert( - "strict_date_optional_time_nanos", - "yyyy[-MM[-dd['T'HH:mm:ss.SSSSSSZ]]]", - ); - m.insert("basic_date", "yyyyMMdd"); - - m.insert("strict_basic_week_date", "xxxx'W'wwe"); - m.insert("basic_week_date", "xxxx'W'wwe"); - - m.insert("strict_basic_week_date_time", "xxxx'W'wwe'T'HHmmss.SSSZ"); - m.insert("basic_week_date_time", "xxxx'W'wwe'T'HHmmss.SSSZ"); - - m.insert( - "strict_basic_week_date_time_no_millis", - "xxxx'W'wwe'T'HHmmssZ", - ); - m.insert("basic_week_date_time_no_millis", "xxxx'W'wwe'T'HHmmssZ"); - - m.insert("strict_week_date", "xxxx-'W'ww-e"); - m.insert("week_date", "xxxx-'W'w[w]-e"); - m - }); - java_datetime_format_map + static JAVA_DATE_FORMAT_ALIASES: LazyLock> = + LazyLock::new(|| { + let mut m = HashMap::new(); + m.insert("date_optional_time", "yyyy-MM-dd['T'HH:mm:ss.SSSZ]"); + m.insert( + "strict_date_optional_time", + "yyyy[-MM[-dd['T'HH[:mm[:ss[.SSS[Z]]]]]]]", + ); + m.insert( + "strict_date_optional_time_nanos", + "yyyy[-MM[-dd['T'HH:mm:ss.SSSSSSZ]]]", + ); + m.insert("basic_date", "yyyyMMdd"); + + m.insert("strict_basic_week_date", "xxxx'W'wwe"); + m.insert("basic_week_date", "xxxx'W'wwe"); + + m.insert("strict_basic_week_date_time", "xxxx'W'wwe'T'HHmmss.SSSZ"); + m.insert("basic_week_date_time", "xxxx'W'wwe'T'HHmmss.SSSZ"); + + m.insert( + "strict_basic_week_date_time_no_millis", + "xxxx'W'wwe'T'HHmmssZ", + ); + m.insert("basic_week_date_time_no_millis", "xxxx'W'wwe'T'HHmmssZ"); + + m.insert("strict_week_date", "xxxx-'W'ww-e"); + m.insert("week_date", "xxxx-'W'w[w]-e"); + m + }); + JAVA_DATE_FORMAT_ALIASES .get(java_datetime_format) .copied() .unwrap_or(java_datetime_format) diff --git a/quickwit/quickwit-doc-mapper/Cargo.toml b/quickwit/quickwit-doc-mapper/Cargo.toml index 92c977fe4da..3919e3d1405 100644 --- a/quickwit/quickwit-doc-mapper/Cargo.toml +++ b/quickwit/quickwit-doc-mapper/Cargo.toml @@ -18,7 +18,6 @@ hex = { workspace = true } indexmap = { workspace = true } itertools = { workspace = true } nom = { workspace = true } -once_cell = { workspace = true } regex = { workspace = true } serde = { workspace = true } serde_json = { workspace = true } diff --git a/quickwit/quickwit-doc-mapper/src/doc_mapper/field_mapping_entry.rs b/quickwit/quickwit-doc-mapper/src/doc_mapper/field_mapping_entry.rs index e69d337a616..f0043d2817d 100644 --- a/quickwit/quickwit-doc-mapper/src/doc_mapper/field_mapping_entry.rs +++ b/quickwit/quickwit-doc-mapper/src/doc_mapper/field_mapping_entry.rs @@ -14,10 +14,10 @@ use std::borrow::Cow; use std::convert::TryFrom; +use std::sync::LazyLock; use anyhow::bail; use base64::prelude::{BASE64_STANDARD, Engine}; -use once_cell::sync::Lazy; use quickwit_common::true_fn; use regex::Regex; use serde::{Deserialize, Serialize}; @@ -870,8 +870,8 @@ pub const FIELD_MAPPING_NAME_PATTERN: &str = r"^[@$_\-a-zA-Z][@$_/\.\-a-zA-Z0-9] /// `_field_presence`; /// - must not be longer than 255 characters. pub fn validate_field_mapping_name(field_mapping_name: &str) -> anyhow::Result<()> { - static FIELD_MAPPING_NAME_PTN: Lazy = - Lazy::new(|| Regex::new(FIELD_MAPPING_NAME_PATTERN).unwrap()); + static FIELD_MAPPING_NAME_PTN: LazyLock = + LazyLock::new(|| Regex::new(FIELD_MAPPING_NAME_PATTERN).unwrap()); if QW_RESERVED_FIELD_NAMES.contains(&field_mapping_name) { bail!( diff --git a/quickwit/quickwit-index-management/src/garbage_collection.rs b/quickwit/quickwit-index-management/src/garbage_collection.rs index 2ca485026ee..076e978d5a9 100644 --- a/quickwit/quickwit-index-management/src/garbage_collection.rs +++ b/quickwit/quickwit-index-management/src/garbage_collection.rs @@ -14,7 +14,7 @@ use std::collections::{HashMap, HashSet}; use std::path::{Path, PathBuf}; -use std::sync::{Arc, OnceLock}; +use std::sync::{Arc, LazyLock}; use std::time::Duration; use anyhow::Context; @@ -290,17 +290,17 @@ async fn list_splits_metadata( /// In order to avoid hammering the load on the metastore, we can throttle the rate of split /// deletion by setting this environment variable. fn get_maximum_split_deletion_rate_per_sec() -> Option { - static MAX_SPLIT_DELETION_RATE_PER_SEC: OnceLock> = OnceLock::new(); - *MAX_SPLIT_DELETION_RATE_PER_SEC.get_or_init(|| { + static MAX_SPLIT_DELETION_RATE_PER_SEC: LazyLock> = LazyLock::new(|| { quickwit_common::get_from_env_opt::("QW_MAX_SPLIT_DELETION_RATE_PER_SEC", false) - }) + }); + *MAX_SPLIT_DELETION_RATE_PER_SEC } fn get_index_gc_concurrency() -> Option { - static INDEX_GC_CONCURRENCY: OnceLock> = OnceLock::new(); - *INDEX_GC_CONCURRENCY.get_or_init(|| { + static INDEX_GC_CONCURRENCY: LazyLock> = LazyLock::new(|| { quickwit_common::get_from_env_opt::("QW_INDEX_GC_CONCURRENCY", false) - }) + }); + *INDEX_GC_CONCURRENCY } /// Removes any splits marked for deletion which haven't been diff --git a/quickwit/quickwit-indexing/Cargo.toml b/quickwit/quickwit-indexing/Cargo.toml index 677b95e32aa..12bea951ada 100644 --- a/quickwit/quickwit-indexing/Cargo.toml +++ b/quickwit/quickwit-indexing/Cargo.toml @@ -29,7 +29,6 @@ google-cloud-googleapis = { workspace = true, optional = true } google-cloud-pubsub = { workspace = true, optional = true } itertools = { workspace = true } libz-sys = { workspace = true, optional = true } -once_cell = { workspace = true } oneshot = { workspace = true } openssl = { workspace = true, optional = true } percent-encoding = { workspace = true } diff --git a/quickwit/quickwit-indexing/src/actors/cooperative_indexing.rs b/quickwit/quickwit-indexing/src/actors/cooperative_indexing.rs index ed9f94dbb6b..f39f97b39d5 100644 --- a/quickwit/quickwit-indexing/src/actors/cooperative_indexing.rs +++ b/quickwit/quickwit-indexing/src/actors/cooperative_indexing.rs @@ -13,10 +13,9 @@ // limitations under the License. use std::hash::{DefaultHasher, Hash, Hasher}; -use std::sync::Arc; +use std::sync::{Arc, LazyLock}; use std::time::Duration; -use once_cell::sync::Lazy; use quickwit_proto::indexing::{CpuCapacity, PIPELINE_FULL_CAPACITY, PipelineMetrics}; use tokio::sync::{OwnedSemaphorePermit, Semaphore}; use tokio::time::Instant; @@ -26,7 +25,7 @@ use tokio::time::Instant; const NUDGE_TOLERANCE: Duration = Duration::from_secs(5); // Origin of time. It is used to compute the phase of the pipeline. -static ORIGIN_OF_TIME: Lazy = Lazy::new(Instant::now); +static ORIGIN_OF_TIME: LazyLock = LazyLock::new(Instant::now); /// Cooperative indexing is a mechanism to deal with a large amount of pipelines. /// diff --git a/quickwit/quickwit-indexing/src/actors/parquet_uploader.rs b/quickwit/quickwit-indexing/src/actors/parquet_uploader.rs index 2f5ea943749..f989072bf07 100644 --- a/quickwit/quickwit-indexing/src/actors/parquet_uploader.rs +++ b/quickwit/quickwit-indexing/src/actors/parquet_uploader.rs @@ -19,12 +19,11 @@ //! Parquet files to storage. use std::path::Path; -use std::sync::Arc; use std::sync::atomic::Ordering; +use std::sync::{Arc, OnceLock}; use anyhow::Context; use async_trait::async_trait; -use once_cell::sync::OnceCell; use quickwit_actors::{Actor, ActorContext, ActorExitStatus, Handler, QueueCapacity}; use quickwit_common::spawn_named_task; use quickwit_metastore::StageMetricsSplitsRequestExt; @@ -42,7 +41,7 @@ use crate::models::ParquetSplitsUpdate; /// Concurrent upload permits for metrics uploader. /// Uses same permit pool as indexer uploads. -static CONCURRENT_UPLOAD_PERMITS_METRICS: OnceCell = OnceCell::new(); +static CONCURRENT_UPLOAD_PERMITS_METRICS: OnceLock = OnceLock::new(); /// ParquetUploader actor for staging and uploading metrics splits. /// diff --git a/quickwit/quickwit-indexing/src/actors/uploader.rs b/quickwit/quickwit-indexing/src/actors/uploader.rs index 1827af7a153..85d43502421 100644 --- a/quickwit/quickwit-indexing/src/actors/uploader.rs +++ b/quickwit/quickwit-indexing/src/actors/uploader.rs @@ -15,14 +15,13 @@ use std::collections::HashSet; use std::iter::FromIterator; use std::mem; -use std::sync::Arc; use std::sync::atomic::{AtomicU64, Ordering}; +use std::sync::{Arc, OnceLock}; use anyhow::{Context, bail}; use async_trait::async_trait; use fail::fail_point; use itertools::Itertools; -use once_cell::sync::OnceCell; use quickwit_actors::{Actor, ActorContext, ActorExitStatus, Handler, Mailbox, QueueCapacity}; use quickwit_common::pubsub::EventBroker; use quickwit_common::spawn_named_task; @@ -53,8 +52,8 @@ use crate::split_store::IndexingSplitStore; /// This "budget" is actually split into two semaphores: one for the indexing pipeline and the merge /// pipeline. The idea is that the merge pipeline is by nature a bit irregular, and we don't want it /// to stall the indexing pipeline, decreasing its throughput. -static CONCURRENT_UPLOAD_PERMITS_INDEX: OnceCell = OnceCell::new(); -static CONCURRENT_UPLOAD_PERMITS_MERGE: OnceCell = OnceCell::new(); +static CONCURRENT_UPLOAD_PERMITS_INDEX: OnceLock = OnceLock::new(); +static CONCURRENT_UPLOAD_PERMITS_MERGE: OnceLock = OnceLock::new(); #[derive(Clone, Copy, Debug)] pub enum UploaderType { diff --git a/quickwit/quickwit-indexing/src/metrics.rs b/quickwit/quickwit-indexing/src/metrics.rs index d3186616252..98ca19636a2 100644 --- a/quickwit/quickwit-indexing/src/metrics.rs +++ b/quickwit/quickwit-indexing/src/metrics.rs @@ -12,7 +12,8 @@ // See the License for the specific language governing permissions and // limitations under the License. -use once_cell::sync::Lazy; +use std::sync::LazyLock; + use quickwit_common::metrics::{ IntCounter, IntCounterVec, IntGauge, IntGaugeVec, new_counter, new_counter_vec, new_gauge, new_gauge_vec, @@ -30,7 +31,7 @@ pub struct IndexerMetrics { pub pending_merge_bytes: IntGauge, // We use a lazy counter, as most users do not use Kafka. #[cfg_attr(not(feature = "kafka"), allow(dead_code))] - pub kafka_rebalance_total: Lazy, + pub kafka_rebalance_total: LazyLock, } impl Default for IndexerMetrics { @@ -98,7 +99,7 @@ impl Default for IndexerMetrics { "indexing", &[], ), - kafka_rebalance_total: Lazy::new(|| { + kafka_rebalance_total: LazyLock::new(|| { new_counter( "kafka_rebalance_total", "Number of kafka rebalances", @@ -112,4 +113,4 @@ impl Default for IndexerMetrics { /// `INDEXER_METRICS` exposes indexing related metrics through a prometheus /// endpoint. -pub static INDEXER_METRICS: Lazy = Lazy::new(IndexerMetrics::default); +pub static INDEXER_METRICS: LazyLock = LazyLock::new(IndexerMetrics::default); diff --git a/quickwit/quickwit-indexing/src/source/kinesis/helpers.rs b/quickwit/quickwit-indexing/src/source/kinesis/helpers.rs index 15becd1c566..8a5a1118cb8 100644 --- a/quickwit/quickwit-indexing/src/source/kinesis/helpers.rs +++ b/quickwit/quickwit-indexing/src/source/kinesis/helpers.rs @@ -48,13 +48,13 @@ pub async fn get_kinesis_client(region_or_endpoint: RegionOrEndpoint) -> anyhow: #[cfg(all(test, feature = "kinesis-localstack-tests"))] pub(crate) mod tests { use std::collections::HashMap; + use std::sync::LazyLock; use std::time::Duration; use anyhow::bail; use aws_sdk_kinesis::Client as KinesisClient; use aws_sdk_kinesis::primitives::Blob; use aws_sdk_kinesis::types::{PutRecordsRequestEntry, StreamStatus}; - use once_cell::sync::Lazy; use quickwit_common::rand::append_random_suffix; use quickwit_common::retry::RetryParams; use quickwit_config::RegionOrEndpoint; @@ -66,7 +66,7 @@ pub(crate) mod tests { }; use crate::source::kinesis::helpers::get_kinesis_client; - pub static DEFAULT_RETRY_PARAMS: Lazy = Lazy::new(RetryParams::standard); + pub static DEFAULT_RETRY_PARAMS: LazyLock = LazyLock::new(RetryParams::standard); pub async fn get_localstack_client() -> anyhow::Result { let endpoint = RegionOrEndpoint::Endpoint("http://localhost:4566".to_string()); diff --git a/quickwit/quickwit-indexing/src/source/mod.rs b/quickwit/quickwit-indexing/src/source/mod.rs index 86d40e5288f..a43d305a9ea 100644 --- a/quickwit/quickwit-indexing/src/source/mod.rs +++ b/quickwit/quickwit-indexing/src/source/mod.rs @@ -73,6 +73,7 @@ mod void_source; use std::collections::BTreeSet; use std::path::PathBuf; +use std::sync::LazyLock; use std::time::Duration; use async_trait::async_trait; @@ -85,7 +86,6 @@ pub use gcp_pubsub_source::{GcpPubSubSource, GcpPubSubSourceFactory}; pub use kafka_source::{KafkaSource, KafkaSourceFactory}; #[cfg(feature = "kinesis")] pub use kinesis::kinesis_source::{KinesisSource, KinesisSourceFactory}; -use once_cell::sync::{Lazy, OnceCell}; #[cfg(feature = "pulsar")] pub use pulsar_source::{PulsarSource, PulsarSourceFactory}; #[cfg(feature = "sqs")] @@ -140,7 +140,7 @@ pub type ParquetSourceLoader = SourceLoader; /// 5MB seems like a good one size fits all value. const BATCH_NUM_BYTES_LIMIT: u64 = ByteSize::mib(5).as_u64(); -static EMIT_BATCHES_TIMEOUT: Lazy = Lazy::new(|| { +static EMIT_BATCHES_TIMEOUT: LazyLock = LazyLock::new(|| { if cfg!(any(test, feature = "testsuite")) { let timeout = Duration::from_millis(100); assert!(timeout < *quickwit_actors::HEARTBEAT); @@ -412,8 +412,7 @@ impl Handler for SourceActor

{ // TODO: Use `SourceType` instead of `&str``. pub fn quickwit_supported_sources() -> &'static SourceLoader { - static SOURCE_LOADER: OnceCell = OnceCell::new(); - SOURCE_LOADER.get_or_init(|| { + static SOURCE_LOADER: LazyLock = LazyLock::new(|| { let mut source_factory = SourceLoader::default(); source_factory.add_source(SourceType::File, FileSourceFactory); #[cfg(feature = "gcp-pubsub")] @@ -430,7 +429,8 @@ pub fn quickwit_supported_sources() -> &'static SourceLoader { source_factory.add_source(SourceType::Vec, VecSourceFactory); source_factory.add_source(SourceType::Void, VoidSourceFactory); source_factory - }) + }); + &SOURCE_LOADER } /// Returns the source loader for parquet pipelines (ParquetDocProcessor). @@ -438,8 +438,7 @@ pub fn quickwit_supported_sources() -> &'static SourceLoader { /// Metrics pipelines currently only support IngestV2 sources, which is the /// production source type for metrics ingestion. pub fn quickwit_supported_parquet_sources() -> &'static ParquetSourceLoader { - static PARQUET_SOURCE_LOADER: OnceCell = OnceCell::new(); - PARQUET_SOURCE_LOADER.get_or_init(|| { + static PARQUET_SOURCE_LOADER: LazyLock = LazyLock::new(|| { let mut source_factory = ParquetSourceLoader::default(); // Only IngestV2 is currently used for metrics ingestion source_factory.add_source(SourceType::IngestV2, IngestSourceFactory); @@ -448,7 +447,8 @@ pub fn quickwit_supported_parquet_sources() -> &'static ParquetSourceLoader { source_factory.add_source(SourceType::Vec, VecSourceFactory); source_factory.add_source(SourceType::Void, VoidSourceFactory); source_factory - }) + }); + &PARQUET_SOURCE_LOADER } pub async fn check_source_connectivity( diff --git a/quickwit/quickwit-ingest/Cargo.toml b/quickwit/quickwit-ingest/Cargo.toml index 3149f2aaaf3..1bf15d76fd4 100644 --- a/quickwit/quickwit-ingest/Cargo.toml +++ b/quickwit/quickwit-ingest/Cargo.toml @@ -21,7 +21,6 @@ http = { workspace = true } itertools = { workspace = true } mockall = { workspace = true, optional = true } mrecordlog = { workspace = true } -once_cell = { workspace = true } prost = { workspace = true } rand = { workspace = true } serde = { workspace = true } diff --git a/quickwit/quickwit-ingest/src/ingest_v2/doc_mapper.rs b/quickwit/quickwit-ingest/src/ingest_v2/doc_mapper.rs index 0bd397b0796..e3ebfc8bfa7 100644 --- a/quickwit/quickwit-ingest/src/ingest_v2/doc_mapper.rs +++ b/quickwit/quickwit-ingest/src/ingest_v2/doc_mapper.rs @@ -14,9 +14,8 @@ use std::collections::hash_map::Entry; use std::collections::{HashMap, HashSet}; -use std::sync::{Arc, Weak}; +use std::sync::{Arc, LazyLock, Weak}; -use once_cell::sync::OnceCell; use quickwit_common::rate_limited_error; use quickwit_common::thread_pool::run_cpu_intensive; use quickwit_config::{DocMapping, SearchSettings, build_doc_mapper}; @@ -136,10 +135,10 @@ fn validate_doc_batch_impl( } fn is_document_validation_enabled() -> bool { - static IS_DOCUMENT_VALIDATION_ENABLED: OnceCell = OnceCell::new(); - *IS_DOCUMENT_VALIDATION_ENABLED.get_or_init(|| { + static IS_DOCUMENT_VALIDATION_ENABLED: LazyLock = LazyLock::new(|| { !quickwit_common::get_bool_from_env("QW_DISABLE_DOCUMENT_VALIDATION", false) - }) + }); + *IS_DOCUMENT_VALIDATION_ENABLED } /// Parses the JSON documents contained in the batch and applies the doc mapper. Returns the diff --git a/quickwit/quickwit-ingest/src/ingest_v2/ingester.rs b/quickwit/quickwit-ingest/src/ingest_v2/ingester.rs index 5091784b885..c176f3d9313 100644 --- a/quickwit/quickwit-ingest/src/ingest_v2/ingester.rs +++ b/quickwit/quickwit-ingest/src/ingest_v2/ingester.rs @@ -16,7 +16,7 @@ use std::collections::hash_map::Entry; use std::collections::{BTreeMap, HashMap, HashSet}; use std::fmt; use std::path::Path; -use std::sync::Arc; +use std::sync::{Arc, LazyLock}; use std::time::{Duration, Instant}; use async_trait::async_trait; @@ -24,7 +24,6 @@ use bytesize::ByteSize; use futures::StreamExt; use futures::stream::FuturesUnordered; use mrecordlog::error::CreateQueueError; -use once_cell::sync::OnceCell; use quickwit_cluster::Cluster; use quickwit_common::metrics::{GaugeGuard, MEMORY_METRICS}; use quickwit_common::pretty::PrettyDisplay; @@ -87,10 +86,10 @@ pub(super) const PERSIST_REQUEST_TIMEOUT: Duration = if cfg!(any(test, feature = const DEFAULT_BATCH_NUM_BYTES: usize = 1024 * 1024; // 1 MiB fn get_batch_num_bytes() -> usize { - static BATCH_NUM_BYTES_CELL: OnceCell = OnceCell::new(); - *BATCH_NUM_BYTES_CELL.get_or_init(|| { + static BATCH_NUM_BYTES_CELL: LazyLock = LazyLock::new(|| { quickwit_common::get_from_env("QW_INGEST_BATCH_NUM_BYTES", DEFAULT_BATCH_NUM_BYTES, false) - }) + }); + *BATCH_NUM_BYTES_CELL } #[derive(Clone)] diff --git a/quickwit/quickwit-ingest/src/ingest_v2/metrics.rs b/quickwit/quickwit-ingest/src/ingest_v2/metrics.rs index 87975a3c462..5e034f1bd36 100644 --- a/quickwit/quickwit-ingest/src/ingest_v2/metrics.rs +++ b/quickwit/quickwit-ingest/src/ingest_v2/metrics.rs @@ -12,8 +12,9 @@ // See the License for the specific language governing permissions and // limitations under the License. +use std::sync::LazyLock; + use mrecordlog::ResourceUsage; -use once_cell::sync::Lazy; use quickwit_common::metrics::{ Histogram, HistogramVec, IntCounter, IntCounterVec, IntGauge, IntGaugeVec, exponential_buckets, linear_buckets, new_counter_vec, new_gauge, new_gauge_vec, new_histogram, new_histogram_vec, @@ -171,4 +172,5 @@ pub(super) fn report_wal_usage(wal_usage: ResourceUsage) { .set(wal_usage.memory_used_bytes as i64); } -pub(super) static INGEST_V2_METRICS: Lazy = Lazy::new(IngestV2Metrics::default); +pub(super) static INGEST_V2_METRICS: LazyLock = + LazyLock::new(IngestV2Metrics::default); diff --git a/quickwit/quickwit-ingest/src/ingest_v2/router.rs b/quickwit/quickwit-ingest/src/ingest_v2/router.rs index d27c5ebfb77..e249dd1e0fe 100644 --- a/quickwit/quickwit-ingest/src/ingest_v2/router.rs +++ b/quickwit/quickwit-ingest/src/ingest_v2/router.rs @@ -14,7 +14,7 @@ use std::collections::{HashMap, HashSet}; use std::fmt; -use std::sync::{Arc, OnceLock, Weak}; +use std::sync::{Arc, LazyLock, Weak}; use std::time::Duration; use async_trait::async_trait; @@ -59,8 +59,7 @@ fn ingest_request_timeout() -> Duration { } else { Duration::from_secs(35) }; - static TIMEOUT: OnceLock = OnceLock::new(); - *TIMEOUT.get_or_init(|| { + static TIMEOUT: LazyLock = LazyLock::new(|| { let duration_ms = quickwit_common::get_from_env( "QW_INGEST_REQUEST_TIMEOUT_MS", DEFAULT_INGEST_REQUEST_TIMEOUT.as_millis() as u64, @@ -79,7 +78,8 @@ fn ingest_request_timeout() -> Duration { } else { requested_ingest_request_timeout } - }) + }); + *TIMEOUT } const MAX_PERSIST_ATTEMPTS: usize = 5; diff --git a/quickwit/quickwit-ingest/src/lib.rs b/quickwit/quickwit-ingest/src/lib.rs index 408d45ff9b3..f021f4888c1 100644 --- a/quickwit/quickwit-ingest/src/lib.rs +++ b/quickwit/quickwit-ingest/src/lib.rs @@ -30,6 +30,7 @@ mod queue; use std::collections::HashMap; use std::path::{Path, PathBuf}; +use std::sync::LazyLock; use anyhow::{Context, bail}; pub use doc_batch::*; @@ -38,7 +39,6 @@ pub use ingest_api_service::{GetMemoryCapacity, GetPartitionId, IngestApiService pub use ingest_service::*; pub use ingest_v2::*; pub use memory_capacity::MemoryCapacity; -use once_cell::sync::OnceCell; pub use position::Position; pub use queue::Queues; use quickwit_actors::{Mailbox, Universe}; @@ -51,8 +51,8 @@ pub type Result = std::result::Result; type IngestApiServiceMailboxes = HashMap>; -pub static INGEST_API_SERVICE_MAILBOXES: OnceCell> = - OnceCell::new(); +pub static INGEST_API_SERVICE_MAILBOXES: LazyLock> = + LazyLock::new(|| Mutex::new(HashMap::new())); /// Initializes an [`IngestApiService`] consuming the queue located at `queue_path`. pub async fn init_ingest_api( @@ -60,10 +60,7 @@ pub async fn init_ingest_api( queues_dir_path: &Path, config: &IngestApiConfig, ) -> anyhow::Result> { - let mut guard = INGEST_API_SERVICE_MAILBOXES - .get_or_init(|| Mutex::new(HashMap::new())) - .lock() - .await; + let mut guard = INGEST_API_SERVICE_MAILBOXES.lock().await; if let Some(mailbox) = guard.get(queues_dir_path) { return Ok(mailbox.clone()); } @@ -88,10 +85,7 @@ pub async fn init_ingest_api( pub async fn get_ingest_api_service( queues_dir_path: &Path, ) -> anyhow::Result> { - let guard = INGEST_API_SERVICE_MAILBOXES - .get_or_init(|| Mutex::new(HashMap::new())) - .lock() - .await; + let guard = INGEST_API_SERVICE_MAILBOXES.lock().await; if let Some(mailbox) = guard.get(queues_dir_path) { return Ok(mailbox.clone()); } diff --git a/quickwit/quickwit-ingest/src/metrics.rs b/quickwit/quickwit-ingest/src/metrics.rs index 15eb5d661de..7b6888243e5 100644 --- a/quickwit/quickwit-ingest/src/metrics.rs +++ b/quickwit/quickwit-ingest/src/metrics.rs @@ -12,7 +12,8 @@ // See the License for the specific language governing permissions and // limitations under the License. -use once_cell::sync::Lazy; +use std::sync::LazyLock; + use quickwit_common::metrics::{IntCounter, IntGauge, new_counter, new_counter_vec, new_gauge}; pub struct IngestMetrics { @@ -78,4 +79,4 @@ impl Default for IngestMetrics { } } -pub static INGEST_METRICS: Lazy = Lazy::new(IngestMetrics::default); +pub static INGEST_METRICS: LazyLock = LazyLock::new(IngestMetrics::default); diff --git a/quickwit/quickwit-jaeger/Cargo.toml b/quickwit/quickwit-jaeger/Cargo.toml index 99ee9db89bc..1ebebc8dbfb 100644 --- a/quickwit/quickwit-jaeger/Cargo.toml +++ b/quickwit/quickwit-jaeger/Cargo.toml @@ -13,7 +13,6 @@ license.workspace = true [dependencies] async-trait = { workspace = true } itertools = { workspace = true } -once_cell = { workspace = true } postcard = { workspace = true } prost = { workspace = true } prost-types = { workspace = true } diff --git a/quickwit/quickwit-jaeger/src/metrics.rs b/quickwit/quickwit-jaeger/src/metrics.rs index b2a64765e1f..3095b68b59f 100644 --- a/quickwit/quickwit-jaeger/src/metrics.rs +++ b/quickwit/quickwit-jaeger/src/metrics.rs @@ -12,7 +12,8 @@ // See the License for the specific language governing permissions and // limitations under the License. -use once_cell::sync::Lazy; +use std::sync::LazyLock; + use quickwit_common::metrics::{ HistogramVec, IntCounterVec, exponential_buckets, new_counter_vec, new_histogram_vec, }; @@ -76,5 +77,5 @@ impl Default for JaegerServiceMetrics { } } -pub static JAEGER_SERVICE_METRICS: Lazy = - Lazy::new(JaegerServiceMetrics::default); +pub static JAEGER_SERVICE_METRICS: LazyLock = + LazyLock::new(JaegerServiceMetrics::default); diff --git a/quickwit/quickwit-janitor/Cargo.toml b/quickwit/quickwit-janitor/Cargo.toml index 8d4cad3beb9..08a43632a68 100644 --- a/quickwit/quickwit-janitor/Cargo.toml +++ b/quickwit/quickwit-janitor/Cargo.toml @@ -15,7 +15,6 @@ anyhow = { workspace = true } async-trait = { workspace = true } futures = { workspace = true } itertools = { workspace = true } -once_cell = { workspace = true } serde = { workspace = true } serde_json = { workspace = true } tantivy = { workspace = true } diff --git a/quickwit/quickwit-janitor/src/metrics.rs b/quickwit/quickwit-janitor/src/metrics.rs index f503739529a..40fa1e03b16 100644 --- a/quickwit/quickwit-janitor/src/metrics.rs +++ b/quickwit/quickwit-janitor/src/metrics.rs @@ -12,7 +12,8 @@ // See the License for the specific language governing permissions and // limitations under the License. -use once_cell::sync::Lazy; +use std::sync::LazyLock; + use quickwit_common::metrics::{ IntCounter, IntCounterVec, IntGaugeVec, new_counter, new_counter_vec, new_gauge_vec, }; @@ -69,4 +70,4 @@ impl Default for JanitorMetrics { /// `JANITOR_METRICS` exposes a bunch of related metrics through a prometheus /// endpoint. -pub static JANITOR_METRICS: Lazy = Lazy::new(JanitorMetrics::default); +pub static JANITOR_METRICS: LazyLock = LazyLock::new(JanitorMetrics::default); diff --git a/quickwit/quickwit-lambda-client/Cargo.toml b/quickwit/quickwit-lambda-client/Cargo.toml index 257172068b3..9f8318e7c15 100644 --- a/quickwit/quickwit-lambda-client/Cargo.toml +++ b/quickwit/quickwit-lambda-client/Cargo.toml @@ -19,7 +19,6 @@ base64 = { workspace = true } md5 = { workspace = true } prost = { workspace = true } serde_json = { workspace = true } -once_cell = { workspace = true } tokio = { workspace = true } tracing = { workspace = true } diff --git a/quickwit/quickwit-lambda-client/src/deploy.rs b/quickwit/quickwit-lambda-client/src/deploy.rs index aacef0929ea..33db8186c04 100644 --- a/quickwit/quickwit-lambda-client/src/deploy.rs +++ b/quickwit/quickwit-lambda-client/src/deploy.rs @@ -26,7 +26,7 @@ //! - Old versions are garbage collected (keep current + top 5 most recent) use std::collections::HashMap; -use std::sync::OnceLock; +use std::sync::LazyLock; use anyhow::{Context, anyhow}; use aws_sdk_lambda::Client as LambdaClient; @@ -55,16 +55,14 @@ const GC_KEEP_RECENT_VERSIONS: usize = 5; /// Format: "{quickwit_version}-{hash_short}" with dots replaced by underscores. /// Example: "0_8_0-fa752891" fn lambda_qualifier() -> &'static str { - static LAMBDA_QUALIFIER: OnceLock = OnceLock::new(); - LAMBDA_QUALIFIER - .get_or_init(|| { - format!( - "{}_{}", - env!("CARGO_PKG_VERSION").replace('.', "_"), - env!("LAMBDA_BINARY_HASH") - ) - }) - .as_str() + static LAMBDA_QUALIFIER: LazyLock = LazyLock::new(|| { + format!( + "{}_{}", + env!("CARGO_PKG_VERSION").replace('.', "_"), + env!("LAMBDA_BINARY_HASH") + ) + }); + LAMBDA_QUALIFIER.as_str() } /// Returns the version description for our qualifier. diff --git a/quickwit/quickwit-lambda-client/src/metrics.rs b/quickwit/quickwit-lambda-client/src/metrics.rs index 4325c9b3a95..f136e4249c1 100644 --- a/quickwit/quickwit-lambda-client/src/metrics.rs +++ b/quickwit/quickwit-lambda-client/src/metrics.rs @@ -14,7 +14,8 @@ // See https://prometheus.io/docs/practices/naming/ -use once_cell::sync::Lazy; +use std::sync::LazyLock; + use quickwit_common::metrics::{ Histogram, HistogramVec, IntCounterVec, exponential_buckets, new_counter_vec, new_histogram, new_histogram_vec, @@ -71,4 +72,4 @@ impl Default for LambdaMetrics { } } -pub static LAMBDA_METRICS: Lazy = Lazy::new(LambdaMetrics::default); +pub static LAMBDA_METRICS: LazyLock = LazyLock::new(LambdaMetrics::default); diff --git a/quickwit/quickwit-metastore/Cargo.toml b/quickwit/quickwit-metastore/Cargo.toml index 0f362f49ceb..8a8a4755feb 100644 --- a/quickwit/quickwit-metastore/Cargo.toml +++ b/quickwit/quickwit-metastore/Cargo.toml @@ -18,7 +18,6 @@ futures = { workspace = true } http = { workspace = true } itertools = { workspace = true } mockall = { workspace = true, optional = true } -once_cell = { workspace = true } ouroboros = { workspace = true } rand = { workspace = true } regex = { workspace = true } diff --git a/quickwit/quickwit-metastore/src/metastore/file_backed/file_backed_metastore_factory.rs b/quickwit/quickwit-metastore/src/metastore/file_backed/file_backed_metastore_factory.rs index fc5f5b9b575..2c489eb4dd5 100644 --- a/quickwit/quickwit-metastore/src/metastore/file_backed/file_backed_metastore_factory.rs +++ b/quickwit/quickwit-metastore/src/metastore/file_backed/file_backed_metastore_factory.rs @@ -14,11 +14,10 @@ use std::collections::HashMap; use std::str::FromStr; -use std::sync::Arc; +use std::sync::{Arc, LazyLock}; use std::time::Duration; use async_trait::async_trait; -use once_cell::sync::OnceCell; use quickwit_common::uri::Uri; use quickwit_config::{MetastoreBackend, MetastoreConfig}; use quickwit_proto::metastore::{MetastoreError, MetastoreServiceClient}; @@ -45,11 +44,9 @@ pub struct FileBackedMetastoreFactory { } fn extract_polling_interval_from_uri(uri: &str) -> (String, Option) { - static URI_FRAGMENT_PATTERN: OnceCell = OnceCell::new(); - if let Some(captures) = URI_FRAGMENT_PATTERN - .get_or_init(|| Regex::new("(.*)#polling_interval=([1-9][0-9]{0,8})s").unwrap()) - .captures(uri) - { + static URI_FRAGMENT_PATTERN: LazyLock = + LazyLock::new(|| Regex::new("(.*)#polling_interval=([1-9][0-9]{0,8})s").unwrap()); + if let Some(captures) = URI_FRAGMENT_PATTERN.captures(uri) { let uri_without_fragment = captures.get(1).unwrap().as_str().to_string(); let polling_interval_in_secs: u64 = captures.get(2).unwrap().as_str().parse::().unwrap(); diff --git a/quickwit/quickwit-metastore/src/metastore/postgres/metrics.rs b/quickwit/quickwit-metastore/src/metastore/postgres/metrics.rs index 3807fcf6829..59cea1db805 100644 --- a/quickwit/quickwit-metastore/src/metastore/postgres/metrics.rs +++ b/quickwit/quickwit-metastore/src/metastore/postgres/metrics.rs @@ -12,7 +12,8 @@ // See the License for the specific language governing permissions and // limitations under the License. -use once_cell::sync::Lazy; +use std::sync::LazyLock; + use quickwit_common::metrics::{IntGauge, new_gauge}; #[derive(Clone)] @@ -47,4 +48,5 @@ impl Default for PostgresMetrics { } } -pub(super) static POSTGRES_METRICS: Lazy = Lazy::new(PostgresMetrics::default); +pub(super) static POSTGRES_METRICS: LazyLock = + LazyLock::new(PostgresMetrics::default); diff --git a/quickwit/quickwit-metastore/src/metastore_resolver.rs b/quickwit/quickwit-metastore/src/metastore_resolver.rs index 7793fdbbf45..dbf250d6afc 100644 --- a/quickwit/quickwit-metastore/src/metastore_resolver.rs +++ b/quickwit/quickwit-metastore/src/metastore_resolver.rs @@ -14,10 +14,9 @@ use std::collections::HashMap; use std::fmt; -use std::sync::Arc; +use std::sync::{Arc, LazyLock}; use anyhow::ensure; -use once_cell::sync::Lazy; use quickwit_common::uri::{Protocol, Uri}; use quickwit_config::{MetastoreBackend, MetastoreConfig, MetastoreConfigs}; use quickwit_proto::metastore::MetastoreServiceClient; @@ -83,7 +82,7 @@ impl MetastoreResolver { /// to provide the necessary credentials, the default Azure or S3 file-backed metastores /// returned by this resolver will not work. pub fn unconfigured() -> Self { - static METASTORE_RESOLVER: Lazy = Lazy::new(|| { + static METASTORE_RESOLVER: LazyLock = LazyLock::new(|| { MetastoreResolver::configured( StorageResolver::unconfigured(), &MetastoreConfigs::default(), diff --git a/quickwit/quickwit-opentelemetry/Cargo.toml b/quickwit/quickwit-opentelemetry/Cargo.toml index d6e897990a2..1521cb8927c 100644 --- a/quickwit/quickwit-opentelemetry/Cargo.toml +++ b/quickwit/quickwit-opentelemetry/Cargo.toml @@ -14,7 +14,6 @@ license.workspace = true anyhow = { workspace = true } arrow = { workspace = true } async-trait = { workspace = true } -once_cell = { workspace = true } parquet = { workspace = true } prost = { workspace = true } serde = { workspace = true } diff --git a/quickwit/quickwit-opentelemetry/src/otlp/metrics.rs b/quickwit/quickwit-opentelemetry/src/otlp/metrics.rs index 14d85e746b6..614630bfb68 100644 --- a/quickwit/quickwit-opentelemetry/src/otlp/metrics.rs +++ b/quickwit/quickwit-opentelemetry/src/otlp/metrics.rs @@ -12,7 +12,8 @@ // See the License for the specific language governing permissions and // limitations under the License. -use once_cell::sync::Lazy; +use std::sync::LazyLock; + use quickwit_common::metrics::{ HistogramVec, IntCounterVec, exponential_buckets, new_counter_vec, new_histogram_vec, }; @@ -85,4 +86,5 @@ impl Default for OtlpServiceMetrics { } /// `OTLP_SERVICE_METRICS` exposes metrics for each OTLP service. -pub static OTLP_SERVICE_METRICS: Lazy = Lazy::new(OtlpServiceMetrics::default); +pub static OTLP_SERVICE_METRICS: LazyLock = + LazyLock::new(OtlpServiceMetrics::default); diff --git a/quickwit/quickwit-parquet-engine/src/index/config.rs b/quickwit/quickwit-parquet-engine/src/index/config.rs index adf59c992be..82a6561772b 100644 --- a/quickwit/quickwit-parquet-engine/src/index/config.rs +++ b/quickwit/quickwit-parquet-engine/src/index/config.rs @@ -14,7 +14,7 @@ //! Parquet index configuration. -use std::sync::OnceLock; +use std::sync::LazyLock; use crate::storage::ParquetWriterConfig; @@ -26,24 +26,24 @@ const DEFAULT_MAX_BYTES: usize = 128 * 1024 * 1024; /// Get max_rows from environment variable or use default. fn get_max_rows_from_env() -> usize { - static MAX_ROWS: OnceLock = OnceLock::new(); - *MAX_ROWS.get_or_init(|| { + static MAX_ROWS: LazyLock = LazyLock::new(|| { std::env::var("QW_METRICS_MAX_ROWS") .ok() .and_then(|s| s.parse().ok()) .unwrap_or(DEFAULT_MAX_ROWS) - }) + }); + *MAX_ROWS } /// Get max_bytes from environment variable or use default. fn get_max_bytes_from_env() -> usize { - static MAX_BYTES: OnceLock = OnceLock::new(); - *MAX_BYTES.get_or_init(|| { + static MAX_BYTES: LazyLock = LazyLock::new(|| { std::env::var("QW_METRICS_MAX_BYTES") .ok() .and_then(|s| s.parse().ok()) .unwrap_or(DEFAULT_MAX_BYTES) - }) + }); + *MAX_BYTES } /// Configuration for parquet indexing. diff --git a/quickwit/quickwit-query/Cargo.toml b/quickwit/quickwit-query/Cargo.toml index f24d8662715..cfe203d3882 100644 --- a/quickwit/quickwit-query/Cargo.toml +++ b/quickwit/quickwit-query/Cargo.toml @@ -15,7 +15,6 @@ anyhow = { workspace = true } base64 = { workspace = true } bitpacking = { workspace = true } hex = { workspace = true } -once_cell = { workspace = true } regex = { workspace = true } serde = { workspace = true } serde_json = { workspace = true } diff --git a/quickwit/quickwit-query/src/json_literal.rs b/quickwit/quickwit-query/src/json_literal.rs index 7c2f6d3888b..11df13cb167 100644 --- a/quickwit/quickwit-query/src/json_literal.rs +++ b/quickwit/quickwit-query/src/json_literal.rs @@ -14,29 +14,27 @@ use std::net::{IpAddr, Ipv6Addr}; use std::str::FromStr; +use std::sync::LazyLock; use base64::Engine; -use once_cell::sync::OnceCell; use quickwit_datetime::{DateTimeInputFormat, parse_date_time_str, parse_timestamp}; use serde::{Deserialize, Serialize}; use tantivy::schema::IntoIpv6Addr; fn get_default_date_time_format() -> &'static [DateTimeInputFormat] { - static DEFAULT_DATE_TIME_FORMATS: OnceCell> = OnceCell::new(); - DEFAULT_DATE_TIME_FORMATS - .get_or_init(|| { - vec![ - DateTimeInputFormat::Rfc3339, - DateTimeInputFormat::Rfc2822, - DateTimeInputFormat::Timestamp, - DateTimeInputFormat::from_str("%Y-%m-%dT%H:%M:%S").unwrap(), - DateTimeInputFormat::from_str("%Y-%m-%d %H:%M:%S.%f").unwrap(), - DateTimeInputFormat::from_str("%Y-%m-%d %H:%M:%S").unwrap(), - DateTimeInputFormat::from_str("%Y-%m-%d").unwrap(), - DateTimeInputFormat::from_str("%Y/%m/%d").unwrap(), - ] - }) - .as_slice() + static DEFAULT_DATE_TIME_FORMATS: LazyLock> = LazyLock::new(|| { + vec![ + DateTimeInputFormat::Rfc3339, + DateTimeInputFormat::Rfc2822, + DateTimeInputFormat::Timestamp, + DateTimeInputFormat::from_str("%Y-%m-%dT%H:%M:%S").unwrap(), + DateTimeInputFormat::from_str("%Y-%m-%d %H:%M:%S.%f").unwrap(), + DateTimeInputFormat::from_str("%Y-%m-%d %H:%M:%S").unwrap(), + DateTimeInputFormat::from_str("%Y-%m-%d").unwrap(), + DateTimeInputFormat::from_str("%Y/%m/%d").unwrap(), + ] + }); + DEFAULT_DATE_TIME_FORMATS.as_slice() } #[derive(Serialize, Deserialize, Eq, PartialEq, Clone, Debug)] diff --git a/quickwit/quickwit-query/src/query_ast/mod.rs b/quickwit/quickwit-query/src/query_ast/mod.rs index d51e36eb93a..5d228a7b80c 100644 --- a/quickwit/quickwit-query/src/query_ast/mod.rs +++ b/quickwit/quickwit-query/src/query_ast/mod.rs @@ -181,11 +181,11 @@ pub struct BuildTantivyAstContext<'a> { impl<'a> BuildTantivyAstContext<'a> { pub fn for_test(schema: &'a TantivySchema) -> Self { - use once_cell::sync::Lazy; + use std::sync::LazyLock; // we do that to have a TokenizerManager with a long enough lifetime - static DEFAULT_TOKENIZER_MANAGER: Lazy = - Lazy::new(crate::create_default_quickwit_tokenizer_manager); + static DEFAULT_TOKENIZER_MANAGER: LazyLock = + LazyLock::new(crate::create_default_quickwit_tokenizer_manager); BuildTantivyAstContext { schema, diff --git a/quickwit/quickwit-query/src/tokenizers/mod.rs b/quickwit/quickwit-query/src/tokenizers/mod.rs index 5a90715075e..bbdae9f3898 100644 --- a/quickwit/quickwit-query/src/tokenizers/mod.rs +++ b/quickwit/quickwit-query/src/tokenizers/mod.rs @@ -16,7 +16,8 @@ mod chinese_compatible; mod code_tokenizer; mod tokenizer_manager; -use once_cell::sync::Lazy; +use std::sync::LazyLock; + use tantivy::tokenizer::{ AsciiFoldingFilter, LowerCaser, RawTokenizer, RemoveLongFilter, SimpleTokenizer, TextAnalyzer, WhitespaceTokenizer, @@ -97,8 +98,8 @@ fn create_quickwit_fastfield_normalizer_manager() -> TokenizerManager { } pub fn get_quickwit_fastfield_normalizer_manager() -> &'static TokenizerManager { - static QUICKWIT_FAST_FIELD_NORMALIZER_MANAGER: Lazy = - Lazy::new(create_quickwit_fastfield_normalizer_manager); + static QUICKWIT_FAST_FIELD_NORMALIZER_MANAGER: LazyLock = + LazyLock::new(create_quickwit_fastfield_normalizer_manager); &QUICKWIT_FAST_FIELD_NORMALIZER_MANAGER } diff --git a/quickwit/quickwit-search/Cargo.toml b/quickwit/quickwit-search/Cargo.toml index ba3c46169fb..dcf2bd5a774 100644 --- a/quickwit/quickwit-search/Cargo.toml +++ b/quickwit/quickwit-search/Cargo.toml @@ -21,7 +21,6 @@ futures = { workspace = true } http = { workspace = true } itertools = { workspace = true } mockall = { workspace = true } -once_cell = { workspace = true } pin-project = { workspace = true } postcard = { workspace = true } prost = { workspace = true } diff --git a/quickwit/quickwit-search/src/lib.rs b/quickwit/quickwit-search/src/lib.rs index 4330b4a6de5..f7989efc3ab 100644 --- a/quickwit/quickwit-search/src/lib.rs +++ b/quickwit/quickwit-search/src/lib.rs @@ -60,7 +60,7 @@ use tantivy::schema::NamedFieldDocument; pub type Result = std::result::Result; use std::net::{Ipv4Addr, SocketAddr}; -use std::sync::{Arc, OnceLock}; +use std::sync::{Arc, LazyLock}; pub use find_trace_ids_collector::{FindTraceIdsCollector, Span}; use quickwit_config::SearcherConfig; @@ -98,8 +98,9 @@ pub use crate::service::{MockSearchService, SearchService, SearchServiceImpl}; pub type SearcherPool = Pool; fn search_thread_pool() -> &'static ThreadPool { - static SEARCH_THREAD_POOL: OnceLock = OnceLock::new(); - SEARCH_THREAD_POOL.get_or_init(|| ThreadPool::new("search", None)) + static SEARCH_THREAD_POOL: LazyLock = + LazyLock::new(|| ThreadPool::new("search", None)); + &SEARCH_THREAD_POOL } /// GlobalDocAddress serves as a hit address. diff --git a/quickwit/quickwit-search/src/metrics.rs b/quickwit/quickwit-search/src/metrics.rs index 9ed11d7ecbb..3e430d7b24b 100644 --- a/quickwit/quickwit-search/src/metrics.rs +++ b/quickwit/quickwit-search/src/metrics.rs @@ -15,9 +15,9 @@ // See https://prometheus.io/docs/practices/naming/ use std::fmt; +use std::sync::LazyLock; use bytesize::ByteSize; -use once_cell::sync::Lazy; use quickwit_common::metrics::{ Histogram, HistogramVec, IntCounter, IntCounterVec, IntGauge, exponential_buckets, linear_buckets, new_counter, new_counter_vec, new_gauge, new_gauge_vec, new_histogram, @@ -252,4 +252,4 @@ impl Default for SearchMetrics { /// `SEARCH_METRICS` exposes a bunch a set of storage/cache related metrics through a prometheus /// endpoint. -pub static SEARCH_METRICS: Lazy = Lazy::new(SearchMetrics::default); +pub static SEARCH_METRICS: LazyLock = LazyLock::new(SearchMetrics::default); diff --git a/quickwit/quickwit-search/src/root.rs b/quickwit/quickwit-search/src/root.rs index a8ca8a6cffc..74922c15268 100644 --- a/quickwit/quickwit-search/src/root.rs +++ b/quickwit/quickwit-search/src/root.rs @@ -13,7 +13,7 @@ // limitations under the License. use std::collections::{HashMap, HashSet}; -use std::sync::OnceLock; +use std::sync::LazyLock; use std::sync::atomic::{AtomicU64, Ordering}; use std::time::{Duration, Instant}; @@ -61,8 +61,7 @@ use crate::{ /// Maximum accepted scroll TTL. fn max_scroll_ttl() -> Duration { - static MAX_SCROLL_TTL_LOCK: OnceLock = OnceLock::new(); - *MAX_SCROLL_TTL_LOCK.get_or_init(|| { + static MAX_SCROLL_TTL_LOCK: LazyLock = LazyLock::new(|| { let split_deletion_grace_period = shared_consts::split_deletion_grace_period(); assert!( split_deletion_grace_period >= shared_consts::MINIMUM_DELETION_GRACE_PERIOD, @@ -71,7 +70,8 @@ fn max_scroll_ttl() -> Duration { ); // We remove an extra margin of 2minutes from the split deletion grace period. split_deletion_grace_period - Duration::from_secs(60 * 2) - }) + }); + *MAX_SCROLL_TTL_LOCK } const SORT_DOC_FIELD_NAMES: &[&str] = &["_shard_doc", "_doc"]; diff --git a/quickwit/quickwit-serve/Cargo.toml b/quickwit/quickwit-serve/Cargo.toml index 2721aa719f3..ba028ce71d5 100644 --- a/quickwit/quickwit-serve/Cargo.toml +++ b/quickwit/quickwit-serve/Cargo.toml @@ -29,7 +29,6 @@ humantime = { workspace = true } hyper-util = {workspace = true} itertools = { workspace = true } mime_guess = { workspace = true } -once_cell = { workspace = true } percent-encoding = { workspace = true } pprof = { workspace = true, optional = true } prost = { workspace = true } diff --git a/quickwit/quickwit-serve/src/build_info.rs b/quickwit/quickwit-serve/src/build_info.rs index 32ba6b53bec..7336c9091be 100644 --- a/quickwit/quickwit-serve/src/build_info.rs +++ b/quickwit/quickwit-serve/src/build_info.rs @@ -12,7 +12,8 @@ // See the License for the specific language governing permissions and // limitations under the License. -use once_cell::sync::OnceCell; +use std::sync::LazyLock; + use quickwit_common::runtimes::RuntimesConfig; use serde::Serialize; @@ -34,9 +35,7 @@ impl BuildInfo { pub fn get() -> &'static Self { const UNKNOWN: &str = "unknown"; - static INSTANCE: OnceCell = OnceCell::new(); - - INSTANCE.get_or_init(|| { + static INSTANCE: LazyLock = LazyLock::new(|| { let commit_date = option_env!("QW_COMMIT_DATE") .filter(|commit_date| !commit_date.is_empty()) .unwrap_or(UNKNOWN); @@ -63,7 +62,7 @@ impl BuildInfo { .cloned() .unwrap_or_else(|| concat!(env!("CARGO_PKG_VERSION"), "-nightly").to_string()); - Self { + BuildInfo { build_date: env!("BUILD_DATE"), build_profile: env!("BUILD_PROFILE"), build_target: env!("BUILD_TARGET"), @@ -74,7 +73,9 @@ impl BuildInfo { commit_tags, version, } - }) + }); + + &INSTANCE } pub fn get_version_text() -> String { @@ -101,16 +102,16 @@ pub struct RuntimeInfo { impl RuntimeInfo { /// Returns the properties of the node. pub fn get() -> &'static Self { - static INSTANCE: OnceCell = OnceCell::new(); - - INSTANCE.get_or_init(|| { + static INSTANCE: LazyLock = LazyLock::new(|| { let num_cpus = quickwit_common::num_cpus(); let runtimes_config = RuntimesConfig::with_num_cpus(num_cpus); - Self { + RuntimeInfo { num_cpus, num_threads_blocking: runtimes_config.num_threads_blocking, num_threads_non_blocking: runtimes_config.num_threads_non_blocking, } - }) + }); + + &INSTANCE } } diff --git a/quickwit/quickwit-serve/src/decompression.rs b/quickwit/quickwit-serve/src/decompression.rs index d65df7d3bea..9e2ddd28197 100644 --- a/quickwit/quickwit-serve/src/decompression.rs +++ b/quickwit/quickwit-serve/src/decompression.rs @@ -13,7 +13,7 @@ // limitations under the License. use std::io::Read; -use std::sync::OnceLock; +use std::sync::LazyLock; use bytes::Bytes; use flate2::read::{MultiGzDecoder, ZlibDecoder}; @@ -26,8 +26,8 @@ use warp::reject::Reject; use crate::load_shield::{LoadShield, LoadShieldPermit}; fn get_ingest_load_shield() -> &'static LoadShield { - static LOAD_SHIELD: OnceLock = OnceLock::new(); - LOAD_SHIELD.get_or_init(|| LoadShield::new("ingest")) + static LOAD_SHIELD: LazyLock = LazyLock::new(|| LoadShield::new("ingest")); + &LOAD_SHIELD } /// There are two ways to decompress the body: diff --git a/quickwit/quickwit-serve/src/developer_api/pprof.rs b/quickwit/quickwit-serve/src/developer_api/pprof.rs index 582ec066976..6bc79aece08 100644 --- a/quickwit/quickwit-serve/src/developer_api/pprof.rs +++ b/quickwit/quickwit-serve/src/developer_api/pprof.rs @@ -12,16 +12,15 @@ // See the License for the specific language governing permissions and // limitations under the License. -use std::sync::OnceLock; +use std::sync::LazyLock; use regex::Regex; use warp::Filter; fn remove_trailing_numbers(thread_name: &mut String) { - static REMOVE_TRAILING_NUMBER_PTN: OnceLock = OnceLock::new(); - let captures_opt = REMOVE_TRAILING_NUMBER_PTN - .get_or_init(|| Regex::new(r"^(.*?)[-\d]+$").unwrap()) - .captures(thread_name); + static REMOVE_TRAILING_NUMBER_PTN: LazyLock = + LazyLock::new(|| Regex::new(r"^(.*?)[-\d]+$").unwrap()); + let captures_opt = REMOVE_TRAILING_NUMBER_PTN.captures(thread_name); if let Some(captures) = captures_opt { *thread_name = captures[1].to_string(); } diff --git a/quickwit/quickwit-serve/src/lib.rs b/quickwit/quickwit-serve/src/lib.rs index cc261cec7a2..c8e2e2f24e2 100644 --- a/quickwit/quickwit-serve/src/lib.rs +++ b/quickwit/quickwit-serve/src/lib.rs @@ -47,7 +47,7 @@ use std::convert::Infallible; use std::fs; use std::net::SocketAddr; use std::num::NonZeroUsize; -use std::sync::Arc; +use std::sync::{Arc, LazyLock}; use std::time::Duration; use anyhow::{Context, bail}; @@ -56,7 +56,6 @@ pub(crate) use decompression::Body; pub use format::BodyFormat; use futures::StreamExt; use itertools::Itertools; -use once_cell::sync::Lazy; use quickwit_actors::{ActorExitStatus, Mailbox, SpawnContext, Universe}; use quickwit_cluster::{ Cluster, ClusterChange, ClusterChangeStream, ClusterNode, ListenerHandle, start_cluster_service, @@ -155,25 +154,25 @@ fn get_metastore_client_max_concurrency() -> usize { ) } -static CP_GRPC_CLIENT_METRICS_LAYER: Lazy = - Lazy::new(|| GrpcMetricsLayer::new("control_plane", "client")); -static CP_GRPC_SERVER_METRICS_LAYER: Lazy = - Lazy::new(|| GrpcMetricsLayer::new("control_plane", "server")); - -static INDEXING_GRPC_CLIENT_METRICS_LAYER: Lazy = - Lazy::new(|| GrpcMetricsLayer::new("indexing", "client")); -pub(crate) static INDEXING_GRPC_SERVER_METRICS_LAYER: Lazy = - Lazy::new(|| GrpcMetricsLayer::new("indexing", "server")); - -static INGEST_GRPC_CLIENT_METRICS_LAYER: Lazy = - Lazy::new(|| GrpcMetricsLayer::new("ingest", "client")); -static INGEST_GRPC_SERVER_METRICS_LAYER: Lazy = - Lazy::new(|| GrpcMetricsLayer::new("ingest", "server")); - -static METASTORE_GRPC_CLIENT_METRICS_LAYER: Lazy = - Lazy::new(|| GrpcMetricsLayer::new("metastore", "client")); -static METASTORE_GRPC_SERVER_METRICS_LAYER: Lazy = - Lazy::new(|| GrpcMetricsLayer::new("metastore", "server")); +static CP_GRPC_CLIENT_METRICS_LAYER: LazyLock = + LazyLock::new(|| GrpcMetricsLayer::new("control_plane", "client")); +static CP_GRPC_SERVER_METRICS_LAYER: LazyLock = + LazyLock::new(|| GrpcMetricsLayer::new("control_plane", "server")); + +static INDEXING_GRPC_CLIENT_METRICS_LAYER: LazyLock = + LazyLock::new(|| GrpcMetricsLayer::new("indexing", "client")); +pub(crate) static INDEXING_GRPC_SERVER_METRICS_LAYER: LazyLock = + LazyLock::new(|| GrpcMetricsLayer::new("indexing", "server")); + +static INGEST_GRPC_CLIENT_METRICS_LAYER: LazyLock = + LazyLock::new(|| GrpcMetricsLayer::new("ingest", "client")); +static INGEST_GRPC_SERVER_METRICS_LAYER: LazyLock = + LazyLock::new(|| GrpcMetricsLayer::new("ingest", "server")); + +static METASTORE_GRPC_CLIENT_METRICS_LAYER: LazyLock = + LazyLock::new(|| GrpcMetricsLayer::new("metastore", "client")); +static METASTORE_GRPC_SERVER_METRICS_LAYER: LazyLock = + LazyLock::new(|| GrpcMetricsLayer::new("metastore", "server")); static GRPC_INGESTER_SERVICE_TIMEOUT: Duration = Duration::from_secs(30); static GRPC_INDEXING_SERVICE_TIMEOUT: Duration = Duration::from_secs(30); diff --git a/quickwit/quickwit-serve/src/metrics.rs b/quickwit/quickwit-serve/src/metrics.rs index c1e4fa24d93..7d922c7fb36 100644 --- a/quickwit/quickwit-serve/src/metrics.rs +++ b/quickwit/quickwit-serve/src/metrics.rs @@ -12,7 +12,8 @@ // See the License for the specific language governing permissions and // limitations under the License. -use once_cell::sync::Lazy; +use std::sync::LazyLock; + use quickwit_common::metrics::{ HistogramVec, IntCounter, IntCounterVec, IntGaugeVec, new_counter, new_counter_vec, new_gauge_vec, new_histogram_vec, @@ -71,4 +72,4 @@ impl Default for ServeMetrics { } /// Serve counters exposes a bunch a set of metrics about the request received to quickwit. -pub static SERVE_METRICS: Lazy = Lazy::new(ServeMetrics::default); +pub static SERVE_METRICS: LazyLock = LazyLock::new(ServeMetrics::default); diff --git a/quickwit/quickwit-serve/src/ui_handler.rs b/quickwit/quickwit-serve/src/ui_handler.rs index f1a57129726..2cdecec50a6 100644 --- a/quickwit/quickwit-serve/src/ui_handler.rs +++ b/quickwit/quickwit-serve/src/ui_handler.rs @@ -12,7 +12,8 @@ // See the License for the specific language governing permissions and // limitations under the License. -use once_cell::sync::Lazy; +use std::sync::LazyLock; + use quickwit_telemetry::payload::TelemetryEvent; use regex::Regex; use rust_embed::RustEmbed; @@ -46,7 +47,7 @@ async fn serve_file(path: Tail) -> Result { } async fn serve_impl(path: &str) -> Result, Rejection> { - static PATH_PTN: Lazy = Lazy::new(|| Regex::new(PATH_PATTERN).unwrap()); + static PATH_PTN: LazyLock = LazyLock::new(|| Regex::new(PATH_PATTERN).unwrap()); let path_to_file = if PATH_PTN.is_match(path) { path } else { diff --git a/quickwit/quickwit-storage/Cargo.toml b/quickwit/quickwit-storage/Cargo.toml index 59ffcc4fa8d..7ef852b046b 100644 --- a/quickwit/quickwit-storage/Cargo.toml +++ b/quickwit/quickwit-storage/Cargo.toml @@ -24,7 +24,6 @@ lru = { workspace = true } md5 = { workspace = true } mini-moka = { workspace = true } mockall = { workspace = true, optional = true } -once_cell = { workspace = true } pin-project = { workspace = true } quick_cache = { workspace = true } regex = { workspace = true } diff --git a/quickwit/quickwit-storage/src/cache/byte_range_cache.rs b/quickwit/quickwit-storage/src/cache/byte_range_cache.rs index eefb4eab799..27661519fbe 100644 --- a/quickwit/quickwit-storage/src/cache/byte_range_cache.rs +++ b/quickwit/quickwit-storage/src/cache/byte_range_cache.rs @@ -396,8 +396,8 @@ mod tests { use std::collections::HashMap; use std::ops::Range; use std::path::Path; + use std::sync::LazyLock; - use once_cell::sync::Lazy; use proptest::prelude::*; use super::ByteRangeCache; @@ -510,8 +510,8 @@ mod tests { fn test_byte_range_cache_doesnt_merge_unnecessarily() { // we need to get a 'static ref to metrics, and want a dedicated metrics because we assert // on it - static METRICS: Lazy = - Lazy::new(|| CacheMetrics::for_component("byterange_cache_test")); + static METRICS: LazyLock = + LazyLock::new(|| CacheMetrics::for_component("byterange_cache_test")); let cache = ByteRangeCache::with_infinite_capacity(&METRICS); diff --git a/quickwit/quickwit-storage/src/debouncer.rs b/quickwit/quickwit-storage/src/debouncer.rs index 60e9a3cf299..9a024b5e190 100644 --- a/quickwit/quickwit-storage/src/debouncer.rs +++ b/quickwit/quickwit-storage/src/debouncer.rs @@ -201,11 +201,10 @@ mod tests { use std::ops::Range; use std::path::PathBuf; - use std::sync::Arc; use std::sync::atomic::{AtomicU32, Ordering}; + use std::sync::{Arc, LazyLock}; use std::time::Duration; - use once_cell::sync::OnceCell; use tempfile::TempDir; use tokio::fs::{self, File}; use tokio::io::AsyncWriteExt; @@ -369,10 +368,10 @@ mod tests { "blub".to_string() } - pub static GLOBAL_DEBOUNCER: once_cell::sync::OnceCell> = - OnceCell::new(); + pub static GLOBAL_DEBOUNCER: LazyLock> = + LazyLock::new(AsyncDebouncer::default); pub fn get_global_debouncer() -> &'static AsyncDebouncer { - GLOBAL_DEBOUNCER.get_or_init(AsyncDebouncer::default) + &GLOBAL_DEBOUNCER } #[tokio::test] diff --git a/quickwit/quickwit-storage/src/metrics.rs b/quickwit/quickwit-storage/src/metrics.rs index 8b439bfaeaa..888d137cc18 100644 --- a/quickwit/quickwit-storage/src/metrics.rs +++ b/quickwit/quickwit-storage/src/metrics.rs @@ -15,9 +15,8 @@ // See https://prometheus.io/docs/practices/naming/ use std::collections::HashMap; -use std::sync::RwLock; +use std::sync::{LazyLock, RwLock}; -use once_cell::sync::Lazy; use quickwit_common::metrics::{ GaugeGuard, Histogram, IntCounter, IntCounterVec, IntGauge, new_counter, new_counter_vec, new_gauge, new_histogram_vec, @@ -305,11 +304,11 @@ impl CacheMetrics { /// Storage counters exposes a bunch a set of storage/cache related metrics through a prometheus /// endpoint. -pub static STORAGE_METRICS: Lazy = Lazy::new(StorageMetrics::default); +pub static STORAGE_METRICS: LazyLock = LazyLock::new(StorageMetrics::default); #[cfg(test)] -pub static CACHE_METRICS_FOR_TESTS: Lazy = - Lazy::new(|| CacheMetrics::for_component("fortest")); +pub static CACHE_METRICS_FOR_TESTS: LazyLock = + LazyLock::new(|| CacheMetrics::for_component("fortest")); pub fn object_storage_get_slice_in_flight_guards( get_request_size: usize, diff --git a/quickwit/quickwit-storage/src/object_storage/azure_blob_storage.rs b/quickwit/quickwit-storage/src/object_storage/azure_blob_storage.rs index d4c9bd67d84..16072f70fc3 100644 --- a/quickwit/quickwit-storage/src/object_storage/azure_blob_storage.rs +++ b/quickwit/quickwit-storage/src/object_storage/azure_blob_storage.rs @@ -16,7 +16,7 @@ use std::collections::HashMap; use std::num::NonZeroU32; use std::ops::Range; use std::path::{Path, PathBuf}; -use std::sync::Arc; +use std::sync::{Arc, LazyLock}; use std::{fmt, io}; use async_trait::async_trait; @@ -30,7 +30,6 @@ use bytes::Bytes; use futures::io::Error as FutureError; use futures::stream::{StreamExt, TryStreamExt}; use md5::Digest; -use once_cell::sync::OnceCell; use quickwit_common::retry::{RetryParams, Retryable, retry}; use quickwit_common::uri::Uri; use quickwit_common::{chunk_range, ignore_error_kind, into_u64_range}; @@ -545,14 +544,12 @@ async fn extract_range_data_and_hash( pub fn parse_azure_uri(uri: &Uri) -> Option<(String, PathBuf)> { // Ex: azure://container/prefix. - static URI_PTN: OnceCell = OnceCell::new(); + static URI_PTN: LazyLock = LazyLock::new(|| { + Regex::new(r"azure(\+[^:]+)?://(?P[^/]+)(/(?P.+))?") + .expect("The regular expression should compile.") + }); - let captures = URI_PTN - .get_or_init(|| { - Regex::new(r"azure(\+[^:]+)?://(?P[^/]+)(/(?P.+))?") - .expect("The regular expression should compile.") - }) - .captures(uri.as_str())?; + let captures = URI_PTN.captures(uri.as_str())?; let container = captures.name("container")?.as_str().to_string(); let prefix = captures diff --git a/quickwit/quickwit-storage/src/object_storage/s3_compatible_storage.rs b/quickwit/quickwit-storage/src/object_storage/s3_compatible_storage.rs index 5214b2bc37f..1c59e04de14 100644 --- a/quickwit/quickwit-storage/src/object_storage/s3_compatible_storage.rs +++ b/quickwit/quickwit-storage/src/object_storage/s3_compatible_storage.rs @@ -16,6 +16,7 @@ use std::collections::HashMap; use std::ops::Range; use std::path::{Path, PathBuf}; use std::pin::Pin; +use std::sync::LazyLock; use std::task::{Context, Poll}; use std::{fmt, io}; @@ -32,7 +33,6 @@ use aws_sdk_s3::types::builders::ObjectIdentifierBuilder; use aws_sdk_s3::types::{CompletedMultipartUpload, CompletedPart, Delete, ObjectIdentifier}; use base64::prelude::{BASE64_STANDARD, Engine}; use futures::{StreamExt, stream}; -use once_cell::sync::{Lazy, OnceCell}; use quickwit_aws::retry::{AwsRetryable, aws_retry}; use quickwit_aws::{aws_behavior_version, get_aws_config}; use quickwit_common::retry::{Retry, RetryParams}; @@ -54,7 +54,7 @@ use crate::{ /// Semaphore to limit the number of concurrent requests to the object store. Some object stores /// (R2, SeaweedFs...) return errors when too many concurrent requests are emitted. -static REQUEST_SEMAPHORE: Lazy = Lazy::new(|| { +static REQUEST_SEMAPHORE: LazyLock = LazyLock::new(|| { let num_permits: usize = quickwit_common::get_from_env("QW_S3_MAX_CONCURRENCY", 10_000usize, false); Semaphore::new(num_permits) @@ -213,15 +213,13 @@ impl S3CompatibleObjectStorage { } pub fn parse_s3_uri(uri: &Uri) -> Option<(String, PathBuf)> { - static S3_URI_PTN: OnceCell = OnceCell::new(); + static S3_URI_PTN: LazyLock = LazyLock::new(|| { + // s3://bucket/path/to/object + Regex::new(r"s3(\+[^:]+)?://(?P[^/]+)(/(?P.+))?") + .expect("The regular expression should compile.") + }); - let captures = S3_URI_PTN - .get_or_init(|| { - // s3://bucket/path/to/object - Regex::new(r"s3(\+[^:]+)?://(?P[^/]+)(/(?P.+))?") - .expect("The regular expression should compile.") - }) - .captures(uri.as_str())?; + let captures = S3_URI_PTN.captures(uri.as_str())?; let bucket = captures.name("bucket")?.as_str().to_string(); let prefix = captures diff --git a/quickwit/quickwit-storage/src/opendal_storage/google_cloud_storage.rs b/quickwit/quickwit-storage/src/opendal_storage/google_cloud_storage.rs index 9f174f0a744..58971a432b7 100644 --- a/quickwit/quickwit-storage/src/opendal_storage/google_cloud_storage.rs +++ b/quickwit/quickwit-storage/src/opendal_storage/google_cloud_storage.rs @@ -13,10 +13,9 @@ // limitations under the License. use std::path::PathBuf; -use std::sync::Arc; +use std::sync::{Arc, LazyLock}; use async_trait::async_trait; -use once_cell::sync::OnceCell; use quickwit_common::uri::Uri; use quickwit_config::{GoogleCloudStorageConfig, StorageBackend}; use regex::Regex; @@ -97,14 +96,12 @@ fn from_uri( fn parse_google_uri(uri: &Uri) -> Option<(String, PathBuf)> { // Ex: gs://bucket/prefix. - static URI_PTN: OnceCell = OnceCell::new(); - - let captures = URI_PTN - .get_or_init(|| { - Regex::new(r"gs(\+[^:]+)?://(?P[^/]+)(/(?P.*))?$") - .expect("The regular expression should compile.") - }) - .captures(uri.as_str())?; + static URI_PTN: LazyLock = LazyLock::new(|| { + Regex::new(r"gs(\+[^:]+)?://(?P[^/]+)(/(?P.*))?$") + .expect("The regular expression should compile.") + }); + + let captures = URI_PTN.captures(uri.as_str())?; let bucket = captures.name("bucket")?.as_str().to_string(); let prefix = captures diff --git a/quickwit/quickwit-storage/src/storage_resolver.rs b/quickwit/quickwit-storage/src/storage_resolver.rs index 6203d6a8d02..f1bef8cacfd 100644 --- a/quickwit/quickwit-storage/src/storage_resolver.rs +++ b/quickwit/quickwit-storage/src/storage_resolver.rs @@ -14,9 +14,8 @@ use std::collections::HashMap; use std::fmt; -use std::sync::Arc; +use std::sync::{Arc, LazyLock}; -use once_cell::sync::Lazy; use quickwit_common::uri::{Protocol, Uri}; use quickwit_config::{StorageBackend, StorageConfigs}; @@ -77,7 +76,7 @@ impl StorageResolver { /// provide the necessary credentials, the default Azure or S3 storage returned by this /// resolver will not work. pub fn unconfigured() -> Self { - static STORAGE_RESOLVER: Lazy = Lazy::new(|| { + static STORAGE_RESOLVER: LazyLock = LazyLock::new(|| { let storage_configs = StorageConfigs::default(); StorageResolver::configured(&storage_configs) }); diff --git a/quickwit/quickwit-storage/tests/s3_storage.rs b/quickwit/quickwit-storage/tests/s3_storage.rs index 6dc1bfacaab..73e0454af77 100644 --- a/quickwit/quickwit-storage/tests/s3_storage.rs +++ b/quickwit/quickwit-storage/tests/s3_storage.rs @@ -20,9 +20,9 @@ pub mod s3_storage_test_suite { use std::path::PathBuf; use std::str::FromStr; + use std::sync::LazyLock; use anyhow::Context; - use once_cell::sync::OnceCell; use quickwit_common::setup_logging_for_tests; use quickwit_common::uri::Uri; use quickwit_config::S3StorageConfig; @@ -36,14 +36,14 @@ pub mod s3_storage_test_suite { // This object packs a smithy connector which itself includes a // hyper client pool. A hyper client cannot be used from multiple runtimes. fn test_runtime_singleton() -> &'static Runtime { - static RUNTIME_CACHE: OnceCell = OnceCell::new(); - RUNTIME_CACHE.get_or_init(|| { + static RUNTIME_CACHE: LazyLock = LazyLock::new(|| { tokio::runtime::Builder::new_multi_thread() .worker_threads(1) .enable_all() .build() .unwrap() - }) + }); + &RUNTIME_CACHE } async fn run_s3_storage_test_suite(s3_storage_config: S3StorageConfig, bucket_uri: &str) { diff --git a/quickwit/quickwit-telemetry/Cargo.toml b/quickwit/quickwit-telemetry/Cargo.toml index b618941fac5..3027fddf8a6 100644 --- a/quickwit/quickwit-telemetry/Cargo.toml +++ b/quickwit/quickwit-telemetry/Cargo.toml @@ -14,7 +14,6 @@ license.workspace = true async-trait = { workspace = true } hostname = { workspace = true } md5 = { workspace = true } -once_cell = { workspace = true } reqwest = { workspace = true } serde = { workspace = true } tokio = { workspace = true } diff --git a/quickwit/quickwit-telemetry/src/lib.rs b/quickwit/quickwit-telemetry/src/lib.rs index 9bd19a63311..72f821005e4 100644 --- a/quickwit/quickwit-telemetry/src/lib.rs +++ b/quickwit/quickwit-telemetry/src/lib.rs @@ -20,7 +20,8 @@ pub mod payload; mod sender; pub(crate) mod sink; -use once_cell::sync::OnceCell; +use std::sync::OnceLock; + use payload::QuickwitTelemetryInfo; use tracing::info; @@ -28,7 +29,7 @@ use crate::payload::TelemetryEvent; pub use crate::sender::is_telemetry_disabled; use crate::sender::{TelemetryLoopHandle, TelemetrySender}; -static TELEMETRY_SENDER: OnceCell = OnceCell::new(); +static TELEMETRY_SENDER: OnceLock = OnceLock::new(); /// Returns a `TelemetryLoopHandle` if the telemetry loop is not yet started. pub fn start_telemetry_loop(quickwit_info: QuickwitTelemetryInfo) -> Option {