Replace lazy_static!
with OnceLock
in collab
crate (#8677)
This PR replaces a `lazy_static!` usage in the `collab` crate with `OnceLock` from the standard library. This allows us to drop the `lazy_static` dependency from this crate. Release Notes: - N/A
This commit is contained in:
parent
9723ca95e3
commit
91d1146d97
5 changed files with 67 additions and 56 deletions
|
@ -33,7 +33,6 @@ envy = "0.4.2"
|
||||||
futures.workspace = true
|
futures.workspace = true
|
||||||
hex.workspace = true
|
hex.workspace = true
|
||||||
hyper = "0.14"
|
hyper = "0.14"
|
||||||
lazy_static.workspace = true
|
|
||||||
live_kit_server.workspace = true
|
live_kit_server.workspace = true
|
||||||
log.workspace = true
|
log.workspace = true
|
||||||
nanoid = "0.4"
|
nanoid = "0.4"
|
||||||
|
|
|
@ -1,11 +1,10 @@
|
||||||
use std::sync::Arc;
|
use std::sync::{Arc, OnceLock};
|
||||||
|
|
||||||
use anyhow::{anyhow, Context};
|
use anyhow::{anyhow, Context};
|
||||||
use axum::{
|
use axum::{
|
||||||
body::Bytes, headers::Header, http::HeaderName, routing::post, Extension, Router, TypedHeader,
|
body::Bytes, headers::Header, http::HeaderName, routing::post, Extension, Router, TypedHeader,
|
||||||
};
|
};
|
||||||
use hyper::StatusCode;
|
use hyper::StatusCode;
|
||||||
use lazy_static::lazy_static;
|
|
||||||
use serde::{Serialize, Serializer};
|
use serde::{Serialize, Serializer};
|
||||||
use sha2::{Digest, Sha256};
|
use sha2::{Digest, Sha256};
|
||||||
use telemetry_events::{
|
use telemetry_events::{
|
||||||
|
@ -19,16 +18,12 @@ pub fn router() -> Router {
|
||||||
Router::new().route("/telemetry/events", post(post_events))
|
Router::new().route("/telemetry/events", post(post_events))
|
||||||
}
|
}
|
||||||
|
|
||||||
lazy_static! {
|
|
||||||
static ref ZED_CHECKSUM_HEADER: HeaderName = HeaderName::from_static("x-zed-checksum");
|
|
||||||
static ref CLOUDFLARE_IP_COUNTRY_HEADER: HeaderName = HeaderName::from_static("cf-ipcountry");
|
|
||||||
}
|
|
||||||
|
|
||||||
pub struct ZedChecksumHeader(Vec<u8>);
|
pub struct ZedChecksumHeader(Vec<u8>);
|
||||||
|
|
||||||
impl Header for ZedChecksumHeader {
|
impl Header for ZedChecksumHeader {
|
||||||
fn name() -> &'static HeaderName {
|
fn name() -> &'static HeaderName {
|
||||||
&ZED_CHECKSUM_HEADER
|
static ZED_CHECKSUM_HEADER: OnceLock<HeaderName> = OnceLock::new();
|
||||||
|
ZED_CHECKSUM_HEADER.get_or_init(|| HeaderName::from_static("x-zed-checksum"))
|
||||||
}
|
}
|
||||||
|
|
||||||
fn decode<'i, I>(values: &mut I) -> Result<Self, axum::headers::Error>
|
fn decode<'i, I>(values: &mut I) -> Result<Self, axum::headers::Error>
|
||||||
|
@ -55,7 +50,8 @@ pub struct CloudflareIpCountryHeader(String);
|
||||||
|
|
||||||
impl Header for CloudflareIpCountryHeader {
|
impl Header for CloudflareIpCountryHeader {
|
||||||
fn name() -> &'static HeaderName {
|
fn name() -> &'static HeaderName {
|
||||||
&CLOUDFLARE_IP_COUNTRY_HEADER
|
static CLOUDFLARE_IP_COUNTRY_HEADER: OnceLock<HeaderName> = OnceLock::new();
|
||||||
|
CLOUDFLARE_IP_COUNTRY_HEADER.get_or_init(|| HeaderName::from_static("cf-ipcountry"))
|
||||||
}
|
}
|
||||||
|
|
||||||
fn decode<'i, I>(values: &mut I) -> Result<Self, axum::headers::Error>
|
fn decode<'i, I>(values: &mut I) -> Result<Self, axum::headers::Error>
|
||||||
|
|
|
@ -8,7 +8,6 @@ use axum::{
|
||||||
middleware::Next,
|
middleware::Next,
|
||||||
response::IntoResponse,
|
response::IntoResponse,
|
||||||
};
|
};
|
||||||
use lazy_static::lazy_static;
|
|
||||||
use prometheus::{exponential_buckets, register_histogram, Histogram};
|
use prometheus::{exponential_buckets, register_histogram, Histogram};
|
||||||
use rand::thread_rng;
|
use rand::thread_rng;
|
||||||
use scrypt::{
|
use scrypt::{
|
||||||
|
@ -16,17 +15,9 @@ use scrypt::{
|
||||||
Scrypt,
|
Scrypt,
|
||||||
};
|
};
|
||||||
use serde::{Deserialize, Serialize};
|
use serde::{Deserialize, Serialize};
|
||||||
|
use std::sync::OnceLock;
|
||||||
use std::{sync::Arc, time::Instant};
|
use std::{sync::Arc, time::Instant};
|
||||||
|
|
||||||
lazy_static! {
|
|
||||||
static ref METRIC_ACCESS_TOKEN_HASHING_TIME: Histogram = register_histogram!(
|
|
||||||
"access_token_hashing_time",
|
|
||||||
"time spent hashing access tokens",
|
|
||||||
exponential_buckets(10.0, 2.0, 10).unwrap(),
|
|
||||||
)
|
|
||||||
.unwrap();
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(Clone, Debug, Default, PartialEq, Eq)]
|
#[derive(Clone, Debug, Default, PartialEq, Eq)]
|
||||||
pub struct Impersonator(pub Option<db::User>);
|
pub struct Impersonator(pub Option<db::User>);
|
||||||
|
|
||||||
|
@ -182,6 +173,16 @@ pub async fn verify_access_token(
|
||||||
user_id: UserId,
|
user_id: UserId,
|
||||||
db: &Arc<Database>,
|
db: &Arc<Database>,
|
||||||
) -> Result<VerifyAccessTokenResult> {
|
) -> Result<VerifyAccessTokenResult> {
|
||||||
|
static METRIC_ACCESS_TOKEN_HASHING_TIME: OnceLock<Histogram> = OnceLock::new();
|
||||||
|
let metric_access_token_hashing_time = METRIC_ACCESS_TOKEN_HASHING_TIME.get_or_init(|| {
|
||||||
|
register_histogram!(
|
||||||
|
"access_token_hashing_time",
|
||||||
|
"time spent hashing access tokens",
|
||||||
|
exponential_buckets(10.0, 2.0, 10).unwrap(),
|
||||||
|
)
|
||||||
|
.unwrap()
|
||||||
|
});
|
||||||
|
|
||||||
let token: AccessTokenJson = serde_json::from_str(&token)?;
|
let token: AccessTokenJson = serde_json::from_str(&token)?;
|
||||||
|
|
||||||
let db_token = db.get_access_token(token.id).await?;
|
let db_token = db.get_access_token(token.id).await?;
|
||||||
|
@ -197,7 +198,7 @@ pub async fn verify_access_token(
|
||||||
.is_ok();
|
.is_ok();
|
||||||
let duration = t0.elapsed();
|
let duration = t0.elapsed();
|
||||||
log::info!("hashed access token in {:?}", duration);
|
log::info!("hashed access token in {:?}", duration);
|
||||||
METRIC_ACCESS_TOKEN_HASHING_TIME.observe(duration.as_millis() as f64);
|
metric_access_token_hashing_time.observe(duration.as_millis() as f64);
|
||||||
Ok(VerifyAccessTokenResult {
|
Ok(VerifyAccessTokenResult {
|
||||||
is_valid,
|
is_valid,
|
||||||
impersonator_id: if db_token.impersonated_user_id.is_some() {
|
impersonator_id: if db_token.impersonated_user_id.is_some() {
|
||||||
|
|
|
@ -35,7 +35,6 @@ use futures::{
|
||||||
stream::FuturesUnordered,
|
stream::FuturesUnordered,
|
||||||
FutureExt, SinkExt, StreamExt, TryStreamExt,
|
FutureExt, SinkExt, StreamExt, TryStreamExt,
|
||||||
};
|
};
|
||||||
use lazy_static::lazy_static;
|
|
||||||
use prometheus::{register_int_gauge, IntGauge};
|
use prometheus::{register_int_gauge, IntGauge};
|
||||||
use rpc::{
|
use rpc::{
|
||||||
proto::{
|
proto::{
|
||||||
|
@ -56,7 +55,7 @@ use std::{
|
||||||
rc::Rc,
|
rc::Rc,
|
||||||
sync::{
|
sync::{
|
||||||
atomic::{AtomicBool, Ordering::SeqCst},
|
atomic::{AtomicBool, Ordering::SeqCst},
|
||||||
Arc,
|
Arc, OnceLock,
|
||||||
},
|
},
|
||||||
time::{Duration, Instant},
|
time::{Duration, Instant},
|
||||||
};
|
};
|
||||||
|
@ -73,16 +72,6 @@ const MESSAGE_COUNT_PER_PAGE: usize = 100;
|
||||||
const MAX_MESSAGE_LEN: usize = 1024;
|
const MAX_MESSAGE_LEN: usize = 1024;
|
||||||
const NOTIFICATION_COUNT_PER_PAGE: usize = 50;
|
const NOTIFICATION_COUNT_PER_PAGE: usize = 50;
|
||||||
|
|
||||||
lazy_static! {
|
|
||||||
static ref METRIC_CONNECTIONS: IntGauge =
|
|
||||||
register_int_gauge!("connections", "number of connections").unwrap();
|
|
||||||
static ref METRIC_SHARED_PROJECTS: IntGauge = register_int_gauge!(
|
|
||||||
"shared_projects",
|
|
||||||
"number of open projects with one or more guests"
|
|
||||||
)
|
|
||||||
.unwrap();
|
|
||||||
}
|
|
||||||
|
|
||||||
type MessageHandler =
|
type MessageHandler =
|
||||||
Box<dyn Send + Sync + Fn(Box<dyn AnyTypedEnvelope>, Session) -> BoxFuture<'static, ()>>;
|
Box<dyn Send + Sync + Fn(Box<dyn AnyTypedEnvelope>, Session) -> BoxFuture<'static, ()>>;
|
||||||
|
|
||||||
|
@ -793,16 +782,12 @@ fn broadcast<F>(
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
lazy_static! {
|
|
||||||
static ref ZED_PROTOCOL_VERSION: HeaderName = HeaderName::from_static("x-zed-protocol-version");
|
|
||||||
static ref ZED_APP_VERSION: HeaderName = HeaderName::from_static("x-zed-app-version");
|
|
||||||
}
|
|
||||||
|
|
||||||
pub struct ProtocolVersion(u32);
|
pub struct ProtocolVersion(u32);
|
||||||
|
|
||||||
impl Header for ProtocolVersion {
|
impl Header for ProtocolVersion {
|
||||||
fn name() -> &'static HeaderName {
|
fn name() -> &'static HeaderName {
|
||||||
&ZED_PROTOCOL_VERSION
|
static ZED_PROTOCOL_VERSION: OnceLock<HeaderName> = OnceLock::new();
|
||||||
|
ZED_PROTOCOL_VERSION.get_or_init(|| HeaderName::from_static("x-zed-protocol-version"))
|
||||||
}
|
}
|
||||||
|
|
||||||
fn decode<'i, I>(values: &mut I) -> Result<Self, axum::headers::Error>
|
fn decode<'i, I>(values: &mut I) -> Result<Self, axum::headers::Error>
|
||||||
|
@ -828,7 +813,8 @@ impl Header for ProtocolVersion {
|
||||||
pub struct AppVersionHeader(SemanticVersion);
|
pub struct AppVersionHeader(SemanticVersion);
|
||||||
impl Header for AppVersionHeader {
|
impl Header for AppVersionHeader {
|
||||||
fn name() -> &'static HeaderName {
|
fn name() -> &'static HeaderName {
|
||||||
&ZED_APP_VERSION
|
static ZED_APP_VERSION: OnceLock<HeaderName> = OnceLock::new();
|
||||||
|
ZED_APP_VERSION.get_or_init(|| HeaderName::from_static("x-zed-app-version"))
|
||||||
}
|
}
|
||||||
|
|
||||||
fn decode<'i, I>(values: &mut I) -> Result<Self, axum::headers::Error>
|
fn decode<'i, I>(values: &mut I) -> Result<Self, axum::headers::Error>
|
||||||
|
@ -922,17 +908,29 @@ pub async fn handle_websocket_request(
|
||||||
}
|
}
|
||||||
|
|
||||||
pub async fn handle_metrics(Extension(server): Extension<Arc<Server>>) -> Result<String> {
|
pub async fn handle_metrics(Extension(server): Extension<Arc<Server>>) -> Result<String> {
|
||||||
|
static CONNECTIONS_METRIC: OnceLock<IntGauge> = OnceLock::new();
|
||||||
|
let connections_metric = CONNECTIONS_METRIC
|
||||||
|
.get_or_init(|| register_int_gauge!("connections", "number of connections").unwrap());
|
||||||
|
|
||||||
let connections = server
|
let connections = server
|
||||||
.connection_pool
|
.connection_pool
|
||||||
.lock()
|
.lock()
|
||||||
.connections()
|
.connections()
|
||||||
.filter(|connection| !connection.admin)
|
.filter(|connection| !connection.admin)
|
||||||
.count();
|
.count();
|
||||||
|
connections_metric.set(connections as _);
|
||||||
|
|
||||||
METRIC_CONNECTIONS.set(connections as _);
|
static SHARED_PROJECTS_METRIC: OnceLock<IntGauge> = OnceLock::new();
|
||||||
|
let shared_projects_metric = SHARED_PROJECTS_METRIC.get_or_init(|| {
|
||||||
|
register_int_gauge!(
|
||||||
|
"shared_projects",
|
||||||
|
"number of open projects with one or more guests"
|
||||||
|
)
|
||||||
|
.unwrap()
|
||||||
|
});
|
||||||
|
|
||||||
let shared_projects = server.app_state.db.project_count_excluding_admins().await?;
|
let shared_projects = server.app_state.db.project_count_excluding_admins().await?;
|
||||||
METRIC_SHARED_PROJECTS.set(shared_projects as _);
|
shared_projects_metric.set(shared_projects as _);
|
||||||
|
|
||||||
let encoder = prometheus::TextEncoder::new();
|
let encoder = prometheus::TextEncoder::new();
|
||||||
let metric_families = prometheus::gather();
|
let metric_families = prometheus::gather();
|
||||||
|
|
|
@ -11,6 +11,7 @@ use rand::prelude::*;
|
||||||
use rpc::RECEIVE_TIMEOUT;
|
use rpc::RECEIVE_TIMEOUT;
|
||||||
use serde::{de::DeserializeOwned, Deserialize, Serialize};
|
use serde::{de::DeserializeOwned, Deserialize, Serialize};
|
||||||
use settings::SettingsStore;
|
use settings::SettingsStore;
|
||||||
|
use std::sync::OnceLock;
|
||||||
use std::{
|
use std::{
|
||||||
env,
|
env,
|
||||||
path::PathBuf,
|
path::PathBuf,
|
||||||
|
@ -21,16 +22,32 @@ use std::{
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
lazy_static::lazy_static! {
|
fn plan_load_path() -> &'static Option<PathBuf> {
|
||||||
static ref PLAN_LOAD_PATH: Option<PathBuf> = path_env_var("LOAD_PLAN");
|
static PLAN_LOAD_PATH: OnceLock<Option<PathBuf>> = OnceLock::new();
|
||||||
static ref PLAN_SAVE_PATH: Option<PathBuf> = path_env_var("SAVE_PLAN");
|
PLAN_LOAD_PATH.get_or_init(|| path_env_var("LOAD_PLAN"))
|
||||||
static ref MAX_PEERS: usize = env::var("MAX_PEERS")
|
}
|
||||||
.map(|i| i.parse().expect("invalid `MAX_PEERS` variable"))
|
|
||||||
.unwrap_or(3);
|
|
||||||
static ref MAX_OPERATIONS: usize = env::var("OPERATIONS")
|
|
||||||
.map(|i| i.parse().expect("invalid `OPERATIONS` variable"))
|
|
||||||
.unwrap_or(10);
|
|
||||||
|
|
||||||
|
fn plan_save_path() -> &'static Option<PathBuf> {
|
||||||
|
static PLAN_SAVE_PATH: OnceLock<Option<PathBuf>> = OnceLock::new();
|
||||||
|
PLAN_SAVE_PATH.get_or_init(|| path_env_var("SAVE_PLAN"))
|
||||||
|
}
|
||||||
|
|
||||||
|
fn max_peers() -> usize {
|
||||||
|
static MAX_PEERS: OnceLock<usize> = OnceLock::new();
|
||||||
|
*MAX_PEERS.get_or_init(|| {
|
||||||
|
env::var("MAX_PEERS")
|
||||||
|
.map(|i| i.parse().expect("invalid `MAX_PEERS` variable"))
|
||||||
|
.unwrap_or(3)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
fn max_operations() -> usize {
|
||||||
|
static MAX_OPERATIONS: OnceLock<usize> = OnceLock::new();
|
||||||
|
*MAX_OPERATIONS.get_or_init(|| {
|
||||||
|
env::var("OPERATIONS")
|
||||||
|
.map(|i| i.parse().expect("invalid `OPERATIONS` variable"))
|
||||||
|
.unwrap_or(10)
|
||||||
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
static LOADED_PLAN_JSON: Mutex<Option<Vec<u8>>> = Mutex::new(None);
|
static LOADED_PLAN_JSON: Mutex<Option<Vec<u8>>> = Mutex::new(None);
|
||||||
|
@ -175,7 +192,7 @@ pub async fn run_randomized_test<T: RandomizedTest>(
|
||||||
}
|
}
|
||||||
executor.run_until_parked();
|
executor.run_until_parked();
|
||||||
|
|
||||||
if let Some(path) = &*PLAN_SAVE_PATH {
|
if let Some(path) = plan_save_path() {
|
||||||
eprintln!("saved test plan to path {:?}", path);
|
eprintln!("saved test plan to path {:?}", path);
|
||||||
std::fs::write(path, plan.lock().serialize()).unwrap();
|
std::fs::write(path, plan.lock().serialize()).unwrap();
|
||||||
}
|
}
|
||||||
|
@ -183,7 +200,7 @@ pub async fn run_randomized_test<T: RandomizedTest>(
|
||||||
|
|
||||||
pub fn save_randomized_test_plan() {
|
pub fn save_randomized_test_plan() {
|
||||||
if let Some(serialize_plan) = LAST_PLAN.lock().take() {
|
if let Some(serialize_plan) = LAST_PLAN.lock().take() {
|
||||||
if let Some(path) = &*PLAN_SAVE_PATH {
|
if let Some(path) = plan_save_path() {
|
||||||
eprintln!("saved test plan to path {:?}", path);
|
eprintln!("saved test plan to path {:?}", path);
|
||||||
std::fs::write(path, serialize_plan()).unwrap();
|
std::fs::write(path, serialize_plan()).unwrap();
|
||||||
}
|
}
|
||||||
|
@ -197,7 +214,7 @@ impl<T: RandomizedTest> TestPlan<T> {
|
||||||
let allow_client_disconnection = rng.gen_bool(0.1);
|
let allow_client_disconnection = rng.gen_bool(0.1);
|
||||||
|
|
||||||
let mut users = Vec::new();
|
let mut users = Vec::new();
|
||||||
for ix in 0..*MAX_PEERS {
|
for ix in 0..max_peers() {
|
||||||
let username = format!("user-{}", ix + 1);
|
let username = format!("user-{}", ix + 1);
|
||||||
let user_id = server
|
let user_id = server
|
||||||
.app_state
|
.app_state
|
||||||
|
@ -234,12 +251,12 @@ impl<T: RandomizedTest> TestPlan<T> {
|
||||||
stored_operations: Vec::new(),
|
stored_operations: Vec::new(),
|
||||||
operation_ix: 0,
|
operation_ix: 0,
|
||||||
next_batch_id: 0,
|
next_batch_id: 0,
|
||||||
max_operations: *MAX_OPERATIONS,
|
max_operations: max_operations(),
|
||||||
users,
|
users,
|
||||||
rng,
|
rng,
|
||||||
}));
|
}));
|
||||||
|
|
||||||
if let Some(path) = &*PLAN_LOAD_PATH {
|
if let Some(path) = plan_load_path() {
|
||||||
let json = LOADED_PLAN_JSON
|
let json = LOADED_PLAN_JSON
|
||||||
.lock()
|
.lock()
|
||||||
.get_or_insert_with(|| {
|
.get_or_insert_with(|| {
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue