From f66bacea3628cd8dfd3683e67ff368a7c4c5beac Mon Sep 17 00:00:00 2001 From: sarowar Date: Sat, 6 Jun 2026 16:05:52 +0900 Subject: [PATCH 1/6] edition, msrv and other version up --- Cargo.toml | 24 ++++++++++-- cluster-executor/Cargo.toml | 28 ++++---------- datagen/Cargo.toml | 3 +- lua-helper/Cargo.toml | 5 +-- overload-http/Cargo.toml | 8 ++-- overload/Cargo.toml | 75 +++---------------------------------- response-assert/Cargo.toml | 5 +-- 7 files changed, 42 insertions(+), 106 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index cb0dd89..2920fd6 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -14,13 +14,13 @@ members = [ resolver = "2" [workspace.package] -edition = "2021" -rust-version = "1.70" +edition = "2024" +rust-version = "1.96" authors = ["Md Sarowar Alam "] license = "MIT" [workspace.dependencies.tokio] -version = "1.37.0" +version = "1.52" default-features = false features = ["rt-multi-thread", "macros"] @@ -38,5 +38,23 @@ version = "0.11" [workspace.dependencies.anyhow] version = "1.0" +[workspace.dependencies.mlua] +version = "0.8" +features = ["lua53", "send", "serialize"] + +[workspace.dependencies.url] +version = "2.3" + +[workspace.dependencies.sqlx] +version = "0.8" +default-features = false +features = ["sqlite", "runtime-tokio-native-tls"] + +[workspace.dependencies.hyper] +version = "0.14" + +[workspace.dependencies.http] +version = "0.2" + [profile.release] debug = true diff --git a/cluster-executor/Cargo.toml b/cluster-executor/Cargo.toml index 66edd78..1ebf35b 100644 --- a/cluster-executor/Cargo.toml +++ b/cluster-executor/Cargo.toml @@ -51,7 +51,7 @@ features = ["derive"] version = "1.0" [dependencies.http] -version = "0.2" +workspace = true [dependencies.log] version = "0.4" @@ -66,18 +66,16 @@ version = "0.3" version = "0.3" [dependencies.fastrand] -version = "1.8" +version = "2.4" [dependencies.sqlx] -version = "0.5" -default-features = false -features = ["sqlite", "runtime-tokio-native-tls"] +workspace = true [dependencies.tokio-stream] version = "0.1" [dependencies.hyper] -version = "0.14" +workspace = true [dependencies.tower] version = "0.4" @@ -99,36 +97,26 @@ version = "1.2" features = ["v4"] [dependencies.mlua] -version = "0.8" -features = ["lua53", "send", "serialize"] +workspace = true [dependencies.url] -version = "2.3" +workspace = true [dev-dependencies.tracing-subscriber] version = "0.3" features = ["fmt", "env-filter"] -[dev-dependencies.tracing-core] -version = "0.1" - [dev-dependencies.httpmock] version = "0.6" -[dev-dependencies.url] -version = "2.3" - -[dev-dependencies.tokio-test] -version = "0.4" - [dev-dependencies.more-asserts] version = "0.3" [dev-dependencies.rand] -version = "0.8" +version = "0.10" [dev-dependencies.base64] -version = "0.13" +version = "0.22" [dev-dependencies.env_logger] workspace = true diff --git a/datagen/Cargo.toml b/datagen/Cargo.toml index 22ec636..e5fe625 100644 --- a/datagen/Cargo.toml +++ b/datagen/Cargo.toml @@ -34,8 +34,7 @@ version = "0.6" version = "0.2" [dependencies.anyhow] -version = "1.0" - +workspace = true [dependencies.log] version = "0.4" diff --git a/lua-helper/Cargo.toml b/lua-helper/Cargo.toml index d9de504..f7cc64d 100644 --- a/lua-helper/Cargo.toml +++ b/lua-helper/Cargo.toml @@ -6,14 +6,13 @@ edition.workspace = true # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html [dependencies.mlua] -version = "0.8" -features = ["lua53", "send"] +workspace = true [dependencies.log] version = "0.4" [dev-dependencies.env_logger] -version = "0.10" +version = "0.11" [dev-dependencies.serde_json] workspace = true \ No newline at end of file diff --git a/overload-http/Cargo.toml b/overload-http/Cargo.toml index 2dcdded..d095dca 100644 --- a/overload-http/Cargo.toml +++ b/overload-http/Cargo.toml @@ -41,9 +41,7 @@ version = "0.4" version = "1.4" [dependencies.sqlx] -version = "0.5" -default-features = false -features = ["sqlite", "runtime-tokio-native-tls"] +workspace = true [dependencies.once_cell] version = "1.16" @@ -53,10 +51,10 @@ version = "0.1.18" features = ["serde"] [dependencies.http] -version = "0.2" +workspace = true [dependencies.hyper] -version = "0.14" +workspace = true [dependencies.regex] version = "1.4" diff --git a/overload/Cargo.toml b/overload/Cargo.toml index c1bee3c..26b1d44 100644 --- a/overload/Cargo.toml +++ b/overload/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "overload" -version = "0.8.0" +version = "0.9.0" authors.workspace = true edition.workspace = true license.workspace = true @@ -16,9 +16,6 @@ keywords = ["load-testing", "cluster"] name = "overload" path = "src/overload/lib.rs" -[dependencies.response-assert] -path = "../response-assert" - [dependencies.lua-helper] path = "../lua-helper" @@ -47,15 +44,7 @@ version = "0.3" optional = true [dependencies.bytes] -version = "1.0" - -[dependencies.smallvec] -version = "1.7" -features = ["serde", "union", "const_generics"] - -[dependencies.smol_str] -version = "0.1.18" -features = ["serde"] +version = "1.4" [dependencies.lazy_static] version = "1.4" @@ -69,9 +58,6 @@ version = "0.3" [dependencies.futures-util] version = "0.3" -[dependencies.pin-project] -version = "1.0" - [dependencies.tokio] workspace = true features = ["rt-multi-thread", "macros", "fs", "io-util", "sync", "parking_lot"] @@ -83,26 +69,16 @@ version = "0.1" version = "0.7" features = ["io", "compat"] -[dependencies.native-tls] -version = "0.2" - [dependencies.http] -version = "0.2" +workspace = true [dependencies.url] -version = "2.2" +workspace = true [dependencies.hyper] -version = "0.14" +workspace = true features = ["runtime", "http1", "http2", "client", "stream"] -[dependencies.hyper-tls] -version = "0.5" - -[dependencies.tower] -version = "0.4" -features = ["util"] - [dependencies.warp] version = "0.3" @@ -114,9 +90,7 @@ version = "1.2" features = ["tokio"] [dependencies.sqlx] -version = "0.5" -default-features = false -features = ["sqlite", "runtime-tokio-native-tls"] +workspace = true [dependencies.regex] version = "1.4" @@ -128,32 +102,13 @@ features = ["derive"] [dependencies.serde_json] version = "1.0" -[dependencies.http-serde] -version = "1.0" - [dependencies.uuid] version = "1.1" features = ["v4"] -[dependencies.fastrand] -version = "1.4" - -[dependencies.rand] -version = "0.8" - -[dependencies.regex-syntax] -version = "0.6" - -[dependencies.regex_generate] -git = "https://github.com/eipi1/regex_generate" -branch = "pub-gen-from-hir" - [dependencies.anyhow] version = "1.0" -[dependencies.cfg-if] -version = "1.0" - [dependencies.prometheus] version = "=0.13.2" features = ["process"] @@ -175,30 +130,12 @@ features = ["gzip", "tokio"] workspace = true features = ["rt-multi-thread", "macros", "fs", "io-util", "time", "test-util"] -[dev-dependencies.tokio-test] -version = "0.4" - -[dev-dependencies.more-asserts] -version = "0.3" - -[dev-dependencies.base64] -version = "0.13" - [dev-dependencies.httpmock] version = "0.6" -[dev-dependencies.assert-json-diff] -version = "2.0" - [dev-dependencies.sha2] version = "0.10" -[dev-dependencies.serial_test] -version = "0.9" - -[dev-dependencies.portpicker] -version = "0.1" - [dev-dependencies.test-case] version = "2.2" diff --git a/response-assert/Cargo.toml b/response-assert/Cargo.toml index 1c01058..5d3b44e 100644 --- a/response-assert/Cargo.toml +++ b/response-assert/Cargo.toml @@ -22,7 +22,7 @@ version = "1.0" version = "1.0" [dependencies.http] -version = "0.2" +workspace = true [dependencies.jsonschema] version = "0.16" @@ -37,6 +37,3 @@ version = "0.4" [dependencies.tokio] workspace = true features = ["sync"] - -[dependencies.mlua] -version = "0.8" \ No newline at end of file From 181cc12b4ac82f17bbbf5013365b3ccab08db09a Mon Sep 17 00:00:00 2001 From: sarowar Date: Sat, 6 Jun 2026 17:16:30 +0900 Subject: [PATCH 2/6] fix clippy warnings, fmt --- cluster-executor/src/connection.rs | 10 +- cluster-executor/src/lib.rs | 30 +-- cluster-executor/src/primary.rs | 11 +- cluster-executor/src/request_providers.rs | 57 +++-- cluster-executor/src/secondary.rs | 262 ++++++++++++--------- cluster-executor/src/split_request.rs | 2 +- cluster-executor/src/standalone.rs | 4 +- datagen/src/lib.rs | 156 ++++++------ datagen/src/template.rs | 31 ++- lua-helper/src/lib.rs | 12 +- overload-http/src/lib.rs | 22 +- overload-http/src/rate_spec.rs | 10 +- overload-http/src/request_specs.rs | 4 +- overload/src/filters.rs | 14 +- overload/src/filters_cluster.rs | 31 ++- overload/src/filters_common.rs | 6 +- overload/src/main.rs | 14 +- overload/src/overload/cluster/mod.rs | 6 +- overload/src/overload/cluster/secondary.rs | 6 +- overload/src/overload/file_uploader.rs | 11 +- overload/src/overload/lib.rs | 18 +- overload/src/overload/standalone.rs | 4 +- response-assert/src/lib.rs | 13 +- tests/src/lib.rs | 10 +- 24 files changed, 390 insertions(+), 354 deletions(-) diff --git a/cluster-executor/src/connection.rs b/cluster-executor/src/connection.rs index 546f666..79132c4 100644 --- a/cluster-executor/src/connection.rs +++ b/cluster-executor/src/connection.rs @@ -1,4 +1,4 @@ -use futures_util::{stream::FuturesUnordered, StreamExt}; +use futures_util::{StreamExt, stream::FuturesUnordered}; use hyper::client::conn; use hyper::client::conn::{Connection, SendRequest}; use hyper::{Body, Error}; @@ -7,8 +7,8 @@ use overload_metrics::Metrics; use std::collections::VecDeque; use std::env; use std::str::FromStr; -use std::sync::atomic::{AtomicU32, AtomicUsize, Ordering}; use std::sync::Arc; +use std::sync::atomic::{AtomicU32, AtomicUsize, Ordering}; use std::time::{Duration, Instant, SystemTime, UNIX_EPOCH}; use tokio::net::TcpStream; use tokio::sync::RwLock; @@ -377,9 +377,7 @@ impl QueuePool { */ #[inline] - async fn check_ready<'a>( - mut connection: HttpConnection, - ) -> (HttpConnection, Result<(), Error>) { + async fn check_ready(mut connection: HttpConnection) -> (HttpConnection, Result<(), Error>) { let result = connection.request_handle.ready().await.map(|_| {}); (connection, result) } @@ -457,7 +455,7 @@ fn since_epoch() -> u64 { } fn get_expiry(ttl: u32) -> u64 { - since_epoch().checked_add(ttl as u64).unwrap_or(u64::MAX) + since_epoch().saturating_add(ttl as u64) } /* diff --git a/cluster-executor/src/lib.rs b/cluster-executor/src/lib.rs index 048344a..7282841 100644 --- a/cluster-executor/src/lib.rs +++ b/cluster-executor/src/lib.rs @@ -8,13 +8,13 @@ use std::task::{Context, Poll}; use std::time::{Duration, Instant}; use anyhow::Result as AnyResult; -use futures_core::future::BoxFuture; use futures_core::Stream; +use futures_core::future::BoxFuture; use futures_util::FutureExt; use http::{StatusCode, Uri}; +use hyper::Error; use hyper::body::Bytes; use hyper::client::conn::ResponseFuture; -use hyper::Error; use lazy_static::lazy_static; use log::{error, info, trace}; use once_cell::sync::OnceCell; @@ -291,8 +291,7 @@ impl Future for HttpRequestFuture<'_> { let elapsed = self.timer.unwrap().elapsed().as_millis() as f64; trace!( "HttpRequestFuture [{}] - body - Ready, elapsed={}", - &self.job_id, - &elapsed + &self.job_id, &elapsed ); if let Ok(body) = body { if self.assertion.simple_assertions.is_some() { @@ -329,9 +328,10 @@ impl Future for HttpRequestFuture<'_> { OriginalRequest::PlaceHolder => {} }, Err(e) => { - error!("HttpRequestFuture [{}] - error - body can not convert to string - {}", - &self.job_id, - e.to_string()) + error!( + "HttpRequestFuture [{}] - error - body can not convert to string - {}", + &self.job_id, e + ) } } } @@ -364,9 +364,7 @@ impl Future for HttpRequestFuture<'_> { let elapsed = self.timer.unwrap().elapsed().as_millis() as f64; trace!( "HttpRequestFuture [{}] - status: {:?}, elapsed: {}", - &self.job_id, - &self.status, - &elapsed + &self.job_id, &self.status, &elapsed ); let status_str = status.as_str(); self.metrics.upstream_response_time(status_str, elapsed); @@ -410,8 +408,7 @@ async fn do_lua_assertion( if let Err(e) = result { error!( "do_lua_assertion [{}] - error - failed to send to lua executor - {}", - &job_id, - e.to_string() + &job_id, e ) } @@ -425,16 +422,14 @@ async fn do_lua_assertion( Err(e) => { error!( "do_lua_assertion [{}] - error - receiver error - {}", - &job_id, - e.to_string() + &job_id, e ) } }, Err(e) => { error!( "do_lua_assertion [{}] - error - receiver timeout - {}", - &job_id, - e.to_string() + &job_id, e ) } } @@ -454,8 +449,7 @@ async fn do_lua_assertion( fn do_simple_assertion(self_: &Pin<&mut HttpRequestFuture>, body: &Bytes) { trace!( "[HttpRequestFuture] [{}] - asserting - {:?}", - &self_.job_id, - &self_.assertion + &self_.job_id, &self_.assertion ); let _ = serde_json::from_slice(body.as_ref()) .map_err(|e| { diff --git a/cluster-executor/src/primary.rs b/cluster-executor/src/primary.rs index 4323940..a04f710 100644 --- a/cluster-executor/src/primary.rs +++ b/cluster-executor/src/primary.rs @@ -1,8 +1,8 @@ use crate::split_request::process_and_send_request; use crate::{ + JOB_STATUS, JobStatus, MessageFromPrimary, REMOC_PORT_NAME, RateMessage, RequestGenerator, get_sender_for_host_port, log_error, remoc_port_name, require_reset, send_end_msg, - send_metadata, send_request_to_secondary, JobStatus, MessageFromPrimary, RateMessage, - RequestGenerator, JOB_STATUS, REMOC_PORT_NAME, + send_metadata, send_request_to_secondary, }; use cluster_mode::{Cluster, RestClusterNode}; use log::{debug, error, info}; @@ -44,7 +44,7 @@ pub async fn handle_request(request: Request, cluster: Arc) { let mut sender_dropped = false; let require_reset = require_reset(&request); while let Some((qps, connection_count)) = stream.next().await { - if counter % 5 == 0 { + if counter.is_multiple_of(5) { // check for stop every 5 seconds if matches!( JOB_STATUS.read().await.get(&job_id), @@ -241,7 +241,7 @@ pub(crate) async fn get_sender_for_secondary( mod test { use crate::primary::{get_sender_for_secondary, send_rate_message_to_secondaries}; use crate::test_common::{cluster_node, get_request, init}; - use crate::{send_request_to_secondary, MessageFromPrimary}; + use crate::{MessageFromPrimary, send_request_to_secondary}; use log::{info, trace}; use remoc::rch; use remoc::rch::base::Receiver; @@ -250,7 +250,7 @@ mod test { use std::collections::HashMap; use std::error::Error; use std::net::Ipv4Addr; - use std::sync::mpsc::{channel, Receiver as StdReceiver, Sender as StdSender}; + use std::sync::mpsc::{Receiver as StdReceiver, Sender as StdSender, channel}; use std::time::Duration; use tokio::net::TcpListener; use tokio::time::sleep; @@ -480,6 +480,7 @@ mod test { handle.abort(); } + #[allow(dead_code)] pub struct TestDiscoverService { instances: Vec, } diff --git a/cluster-executor/src/request_providers.rs b/cluster-executor/src/request_providers.rs index e5f56d1..de8c47b 100644 --- a/cluster-executor/src/request_providers.rs +++ b/cluster-executor/src/request_providers.rs @@ -1,4 +1,4 @@ -use anyhow::{anyhow, Result as AnyResult}; +use anyhow::{Result as AnyResult, anyhow}; use datagen::generate_data; use datagen::template::populate_data; use log::{debug, error, trace}; @@ -6,8 +6,8 @@ use overload_http::{ HttpReq, JsonTemplate, RandomDataRequest, RequestFile, RequestList, SplitRequestFile, }; use remoc::rtc::async_trait; -use sqlx::sqlite::SqliteConnectOptions; use sqlx::ConnectOptions; +use sqlx::sqlite::SqliteConnectOptions; use std::cmp::{max, min}; use std::iter::repeat_with; use std::str::FromStr; @@ -148,8 +148,10 @@ impl RequestProvider for SplitRequestFile { if self.range_end_inclusive == 0 { self.range_end_inclusive = self.size; } - trace!("[SplitRequestFile] - init - range_start_inclusive:{}, range_end_inclusive:{}, next_read_cursor:{}", - self.range_start_inclusive, self.range_end_inclusive, self.next_read_cursor) + trace!( + "[SplitRequestFile] - init - range_start_inclusive:{}, range_end_inclusive:{}, next_read_cursor:{}", + self.range_start_inclusive, self.range_end_inclusive, self.next_read_cursor + ) } let mut data_need = n; @@ -208,16 +210,16 @@ impl RequestProvider for RandomDataRequest { for _ in 0..n { let mut body = Option::None; let mut url = self.url.clone(); - if let Some(schema) = &self.uri_param_schema { - if let Some(positions) = &self.url_param_pos { - let data = generate_data(schema); - RandomDataRequest::substitute_param_with_data(&mut url, positions, data) - } + if let Some(schema) = &self.uri_param_schema + && let Some(positions) = &self.url_param_pos + { + let data = generate_data(schema); + RandomDataRequest::substitute_param_with_data(&mut url, positions, data) } - if matches!(self.method, http::Method::POST) { - if let Some(schema) = &self.body_schema { - body = Some(generate_data(schema).to_string()); - } + if matches!(self.method, http::Method::POST) + && let Some(schema) = &self.body_schema + { + body = Some(generate_data(schema).to_string()); } let req = HttpReq { id: "".to_string(), @@ -279,14 +281,14 @@ impl RequestProvider for JsonTemplate { #[cfg(test)] pub(crate) mod test { use super::*; - use crate::rate_spec::RateScheme; use crate::RequestGenerator; + use crate::rate_spec::RateScheme; use datagen::data_schema_from_value; use datagen::template::build_engine; use http::Method; use overload_http::{ConstantRate, Elastic, Linear, Scheme, Steps, Target}; use regex::Regex; - use serde_json::{json, Value}; + use serde_json::{Value, json}; use std::collections::HashMap; use std::ops::Deref; use std::sync::{Arc, Once}; @@ -399,11 +401,13 @@ pub(crate) mod test { "#; let steps = serde_json::from_str::(json_str); assert!(steps.is_err()); - assert!(steps - .err() - .unwrap() - .to_string() - .starts_with("start(9) can not be greater than or equal to end(9)")); + assert!( + steps + .err() + .unwrap() + .to_string() + .starts_with("start(9) can not be greater than or equal to end(9)") + ); } #[tokio::test] @@ -787,8 +791,7 @@ pub(crate) mod test { } async fn create_sqlite_file() -> anyhow::Result<()> { - let sqlite_base64 = - "U1FMaXRlIGZvcm1hdCAzABAAAgIAQCAgAAAAAgAAAAIAAAAAAAAAAAAAAAEAAAAEAAAAAAAAAAAA\ + let sqlite_base64 = "U1FMaXRlIGZvcm1hdCAzABAAAgIAQCAgAAAAAgAAAAIAAAAAAAAAAAAAAAEAAAAEAAAAAAAAAAAA\ AAABAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACAC5PfA0AAAABD0sAD0sAAAAA\ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\ @@ -933,8 +936,14 @@ IjoicmFuZG9tIGRhdGEiLCJzZWNvbmQta2V5IjoibW9yZSBkYXRhIn17IkF1dGhvcml6YXRpb24i\ OiJCZWFyZXIgMTIzIn0oAgVJEwARaHR0cDovL2h0dHBiaW4ub3JnL2FueXRoaW5nLzEzR0VUe30o\ AQVJEwARaHR0cDovL2h0dHBiaW4ub3JnL2FueXRoaW5nLzExR0VUe30="; let mut file = File::create("test-data.sqlite").await?; - file.write_all(base64::decode(sqlite_base64).unwrap().as_slice()) - .await?; + use base64::Engine; + file.write_all( + base64::engine::general_purpose::STANDARD + .decode(sqlite_base64) + .unwrap() + .as_slice(), + ) + .await?; Ok(()) } } diff --git a/cluster-executor/src/secondary.rs b/cluster-executor/src/secondary.rs index d9c5538..46a890f 100644 --- a/cluster-executor/src/secondary.rs +++ b/cluster-executor/src/secondary.rs @@ -3,11 +3,11 @@ use crate::connection::{ConnectionKeepAlive, HttpConnection, QueuePool}; use crate::request_providers::RequestProvider; use crate::{ - data_dir_path, log_error, HttpRequestFuture, HttpRequestState, MessageFromPrimary, Metadata, - OriginalRequest, RateMessage, ReturnableConnection, CYCLE_LENGTH_IN_MILLIS, - CYCLE_LENGTH_IN_MILLIS_V2, + CYCLE_LENGTH_IN_MILLIS, CYCLE_LENGTH_IN_MILLIS_V2, HttpRequestFuture, HttpRequestState, + MessageFromPrimary, Metadata, OriginalRequest, RateMessage, ReturnableConnection, + data_dir_path, log_error, }; -use anyhow::{anyhow, Error as AnyError, Result as AnyResult}; +use anyhow::{Error as AnyError, Result as AnyResult, anyhow}; use cluster_mode::Cluster; use common_env::wait_on_no_connection; use common_types::LoadGenerationMode; @@ -20,14 +20,14 @@ use hyper::body::{Bytes, HttpBody}; use hyper::{Body, Client}; use lazy_static::lazy_static; use log::{debug, error, info, trace, warn}; -use lua_helper::{init_lua, load_lua_func, load_lua_func_with_registry, LuaAssertionResult}; +use lua_helper::{LuaAssertionResult, init_lua, load_lua_func, load_lua_func_with_registry}; use mlua::Value::Function; use once_cell::sync::OnceCell; use overload_http::{ - ConcurrentConnectionRateSpec, HttpReq, Request, RequestSpecEnum, Target, - PATH_REQUEST_DATA_FILE_DOWNLOAD, + ConcurrentConnectionRateSpec, HttpReq, PATH_REQUEST_DATA_FILE_DOWNLOAD, Request, + RequestSpecEnum, Target, }; -use overload_metrics::{Metrics, MetricsFactory, METRICS_FACTORY}; +use overload_metrics::{METRICS_FACTORY, Metrics, MetricsFactory}; use regex::Regex; use remoc::rch; use remoc::rch::base::{Receiver, RecvError}; @@ -45,10 +45,10 @@ use std::{env, io}; use tokio::fs::File; use tokio::io::AsyncWriteExt; use tokio::net::TcpListener; +use tokio::sync::RwLock; use tokio::sync::mpsc::{UnboundedReceiver as TkMpscReceiver, UnboundedSender as TkMpscSender}; use tokio::sync::oneshot::Sender; use tokio::sync::oneshot::{Receiver as TkOneShotReceiver, Sender as TkOneShotSender}; -use tokio::sync::RwLock; use tokio::time::{sleep, timeout}; use tokio_stream::StreamExt; use url::Url; @@ -231,59 +231,66 @@ async fn handle_connection_from_primary( error_exit = true; break; } - Ok(msg) => { - match msg { - None => { - debug!("[handle_connection_from_primary] - None received, exiting loop"); + Ok(msg) => match msg { + None => { + debug!("[handle_connection_from_primary] - None received, exiting loop"); + break; + } + Some(msg) => match msg { + MessageFromPrimary::Metadata(_) => { + error!( + "[handle_connection_from_primary] - [{}] - unexpected MessageFromPrimary::Request", + &job_id + ); + } + MessageFromPrimary::Rates(rate) => { + trace!("[handle_connection_from_primary] - {:?}", &rate); + (prev_connection_count, time_offset) = handle_rate_msg( + rate, + prev_connection_count, + &metrics, + time_offset, + job_id.clone(), + &mut queue_pool, + &mut request_spec, + response_assertion.clone(), + lua_executor_sender.clone(), + ) + .await; + } + MessageFromPrimary::Stop => { + stop = true; break; } - Some(msg) => match msg { - MessageFromPrimary::Metadata(_) => { - error!("[handle_connection_from_primary] - [{}] - unexpected MessageFromPrimary::Request", &job_id); - } - MessageFromPrimary::Rates(rate) => { - trace!("[handle_connection_from_primary] - {:?}", &rate); - (prev_connection_count, time_offset) = handle_rate_msg( - rate, - prev_connection_count, - &metrics, - time_offset, - job_id.clone(), - &mut queue_pool, - &mut request_spec, - response_assertion.clone(), - lua_executor_sender.clone(), - ) - .await; - } - MessageFromPrimary::Stop => { - stop = true; - break; - } - MessageFromPrimary::Finished => { - finish = true; - stop = true; - break; - } - MessageFromPrimary::Reset => { - info!( - "[handle_connection_from_primary] - [{}] - reset received", - &job_id + MessageFromPrimary::Finished => { + finish = true; + stop = true; + break; + } + MessageFromPrimary::Reset => { + info!( + "[handle_connection_from_primary] - [{}] - reset received", + &job_id + ); + reset = true; + } + MessageFromPrimary::Request(mut req) => { + if !reset { + error!( + "[handle_connection_from_primary] - [{}] - unexpected message - {:?}", + &job_id, req ); - reset = true; - } - MessageFromPrimary::Request(mut req) => { - if !reset { - error!("[handle_connection_from_primary] - [{}] - unexpected message - {:?}", &job_id, req); - } - info!("[handle_connection_from_primary] - [{}] - reset - new request - {:?}", &job_id, &req); - prepare(&mut req, metadata.primary_host.clone()).await?; - request_spec = req.req; - reset = false; } - }, - } - } + info!( + "[handle_connection_from_primary] - [{}] - reset - new request - {:?}", + &job_id, &req + ); + prepare(&mut req, metadata.primary_host.clone()).await?; + request_spec = req.req; + reset = false; + } + }, + }, } } // #[cfg(feature = "cluster")] @@ -307,8 +314,10 @@ async fn handle_connection_from_primary( // { // METRICS_FACTORY.remove_metrics(&job_id).await; // } - debug!("[handle_connection_from_primary] - [{}] - exiting with status stop:{}, finish:{}, error_exit:{}", &job_id, - stop, finish, error_exit); + debug!( + "[handle_connection_from_primary] - [{}] - exiting with status stop:{}, finish:{}, error_exit:{}", + &job_id, stop, finish, error_exit + ); Ok(()) } @@ -387,48 +396,55 @@ async fn handle_connection_from_primary_v2( error_exit = true; break; } - Ok(msg) => { - match msg { - None => { - debug!("[handle_connection_from_primary] - None received, exiting loop"); + Ok(msg) => match msg { + None => { + debug!("[handle_connection_from_primary] - None received, exiting loop"); + break; + } + Some(msg) => match msg { + MessageFromPrimary::Metadata(_) => { + error!( + "[handle_connection_from_primary] - [{}] - unexpected MessageFromPrimary::Request", + &job_id + ); + } + MessageFromPrimary::Rates(rate) => { + trace!("[handle_connection_from_primary] - {:?}", &rate); + handle_rate_msg_v2(rate, &mut ctx).await; + } + MessageFromPrimary::Stop => { + stop = true; break; } - Some(msg) => match msg { - MessageFromPrimary::Metadata(_) => { - error!("[handle_connection_from_primary] - [{}] - unexpected MessageFromPrimary::Request", &job_id); - } - MessageFromPrimary::Rates(rate) => { - trace!("[handle_connection_from_primary] - {:?}", &rate); - handle_rate_msg_v2(rate, &mut ctx).await; - } - MessageFromPrimary::Stop => { - stop = true; - break; - } - MessageFromPrimary::Finished => { - finish = true; - stop = true; - break; - } - MessageFromPrimary::Reset => { - info!( - "[handle_connection_from_primary] - [{}] - reset received", - &job_id + MessageFromPrimary::Finished => { + finish = true; + stop = true; + break; + } + MessageFromPrimary::Reset => { + info!( + "[handle_connection_from_primary] - [{}] - reset received", + &job_id + ); + reset = true; + } + MessageFromPrimary::Request(mut req) => { + if !reset { + error!( + "[handle_connection_from_primary] - [{}] - unexpected message - {:?}", + &job_id, req ); - reset = true; - } - MessageFromPrimary::Request(mut req) => { - if !reset { - error!("[handle_connection_from_primary] - [{}] - unexpected message - {:?}", &job_id, req); - } - info!("[handle_connection_from_primary] - [{}] - reset - new request - {:?}", &job_id, &req); - prepare(&mut req, metadata.primary_host.clone()).await?; - ctx.request_spec = req.req; - reset = false; } - }, - } - } + info!( + "[handle_connection_from_primary] - [{}] - reset - new request - {:?}", + &job_id, &req + ); + prepare(&mut req, metadata.primary_host.clone()).await?; + ctx.request_spec = req.req; + reset = false; + } + }, + }, } } { @@ -447,8 +463,9 @@ async fn handle_connection_from_primary_v2( METRICS_FACTORY.remove_metrics(&job_id).await; } } - info!("[handle_connection_from_primary] - [{}] - exiting with status stop:{}, finish:{}, error_exit:{}", - &job_id,stop, finish, error_exit + info!( + "[handle_connection_from_primary] - [{}] - exiting with status stop:{}, finish:{}, error_exit:{}", + &job_id, stop, finish, error_exit ); Ok(()) } @@ -567,7 +584,7 @@ async fn check_for_request_msg(rx: &mut Receiver) -> Result< _ => { return Err(anyhow!( "Expected MessageFromPrimary::Request|Reset, but didn't receive" - )) + )); } } } @@ -635,7 +652,10 @@ async fn send_n_request_in_t_duration( let time_remaining = || CYCLE_LENGTH_IN_MILLIS_V2 - start_of_cycle.elapsed().as_millis() as i64; if time_remaining() < 10 { - error!("[{}] [send_n_request_in_t_duration] - available time is less than 10ms. not sending any request", &ctx.job_id); + error!( + "[{}] [send_n_request_in_t_duration] - available time is less than 10ms. not sending any request", + &ctx.job_id + ); return; } @@ -669,8 +689,15 @@ async fn send_n_request_in_t_duration( .get_connections(requested_connection, &ctx.metrics) .await; let available_connection = connections.len(); - debug!("[{}] - connection requested:{}, available connection: {}, request remaining: {}, remaining duration: {}ms, sleep duration: {}ms", - &job_id, requested_connection, available_connection, total_remaining_qps, remaining_t, sleep_time); + debug!( + "[{}] - connection requested:{}, available connection: {}, request remaining: {}, remaining duration: {}ms, sleep duration: {}ms", + &job_id, + requested_connection, + available_connection, + total_remaining_qps, + remaining_t, + sleep_time + ); if available_connection < 1 { //adjust sleep time @@ -850,8 +877,7 @@ async fn send_multiple_requests( let remaining_time_in_cycle = time_remaining(); trace!( "remaining time in cycle:{}, remaining requests: {}", - remaining_time_in_cycle, - remaining_requests + remaining_time_in_cycle, remaining_requests ); if remaining_time_in_cycle < 1 { warn!( @@ -888,8 +914,15 @@ async fn send_multiple_requests( .get_connections(requested_connection, &metrics) .await; let available_connection = connections.len(); - debug!("[{}] - connection requested:{}, available connection: {}, request remaining: {}, remaining duration: {}, sleep duration: {}", - &job_id, requested_connection, available_connection, total_remaining_qps, remaining_t, sleep_time); + debug!( + "[{}] - connection requested:{}, available connection: {}, request remaining: {}, remaining duration: {}, sleep duration: {}", + &job_id, + requested_connection, + available_connection, + total_remaining_qps, + remaining_t, + sleep_time + ); if available_connection < requested_connection as usize { if available_connection < 1 { //adjust sleep time @@ -1085,7 +1118,7 @@ pub(crate) fn initiator_for_request_from_primary( request: &mut Request, primary_uri: String, ) -> BoxFuture<'static, Result<(), anyhow::Error>> { - return match &mut request.req { + match &mut request.req { RequestSpecEnum::RequestFile(req) => { download_request_file_from_primary(req.file_name.to_string(), primary_uri).boxed() } @@ -1095,7 +1128,7 @@ pub(crate) fn initiator_for_request_from_primary( RequestSpecEnum::RandomDataRequest(_) | RequestSpecEnum::RequestList(_) | RequestSpecEnum::JsonTemplateRequest(_) => noop().boxed(), - }; + } } pub async fn noop() -> Result<(), anyhow::Error> { @@ -1153,8 +1186,7 @@ pub async fn download_file_from_url( tokio_util::compat::FuturesAsyncReadCompatExt::compat(r) } let futures_io_async_read = - TryStreamExt::map_err(resp.body_mut(), |e| io::Error::new(io::ErrorKind::Other, e)) - .into_async_read(); + TryStreamExt::map_err(resp.body_mut(), io::Error::other).into_async_read(); let mut tokio_async_read = to_tokio_async_read(futures_io_async_read); tokio::io::copy(&mut tokio_async_read, data_file_destination).await?; let _ = data_file_destination.flush().await; @@ -1168,14 +1200,14 @@ mod test { #[cfg(feature = "cluster")] use crate::primary::get_sender_for_secondary; use crate::secondary::{ - fill_req_if_less_than_connections, handle_rate_msg, primary_listener, - send_multiple_requests, ExecutionContext, + ExecutionContext, fill_req_if_less_than_connections, handle_rate_msg, primary_listener, + send_multiple_requests, }; use crate::test_common::init; #[cfg(feature = "cluster")] use crate::test_common::{cluster_node, get_request}; use crate::{ - send_metadata_with_primary, send_request_to_secondary, RateMessage, DEFAULT_REMOC_PORT, + DEFAULT_REMOC_PORT, RateMessage, send_metadata_with_primary, send_request_to_secondary, }; use common_types::LoadGenerationMode; use httpmock::{Mock, MockServer}; diff --git a/cluster-executor/src/split_request.rs b/cluster-executor/src/split_request.rs index 27f91ce..a50348c 100644 --- a/cluster-executor/src/split_request.rs +++ b/cluster-executor/src/split_request.rs @@ -1,5 +1,5 @@ use crate::request_providers::RequestProvider; -use crate::{log_error, MessageFromPrimary}; +use crate::{MessageFromPrimary, log_error}; use log::{error, info}; use overload_http::{Request, RequestSpecEnum}; use remoc::rch::base::Sender; diff --git a/cluster-executor/src/standalone.rs b/cluster-executor/src/standalone.rs index c887ec7..9f8de61 100644 --- a/cluster-executor/src/standalone.rs +++ b/cluster-executor/src/standalone.rs @@ -11,9 +11,9 @@ use tokio_stream::StreamExt; use overload_http::Request; use crate::{ + JOB_STATUS, JobStatus, MessageFromPrimary, REMOC_PORT, RateMessage, RequestGenerator, get_sender_for_host_port, log_error, remoc_port, send_end_msg, send_metadata_with_primary, - send_request_to_secondary, JobStatus, MessageFromPrimary, RateMessage, RequestGenerator, - JOB_STATUS, REMOC_PORT, + send_request_to_secondary, }; pub async fn handle_request(request: Request) { diff --git a/datagen/src/lib.rs b/datagen/src/lib.rs index 189edb8..743e590 100644 --- a/datagen/src/lib.rs +++ b/datagen/src/lib.rs @@ -4,14 +4,14 @@ pub mod template; use crate::DataSchema::Empty; -use anyhow::{anyhow, Error as AnyError, Result as AnyResult}; +use anyhow::{Error as AnyError, Result as AnyResult, anyhow}; use log::{error, trace, warn}; use rand::thread_rng; use regex_generate::generate_from_hir; -use regex_syntax::hir::Hir; use regex_syntax::Parser; +use regex_syntax::hir::Hir; use serde::{Deserialize, Serialize, Serializer}; -use serde_json::{json, Map, Value}; +use serde_json::{Map, Value, json}; use std::collections::HashMap; use std::convert::TryFrom; @@ -324,15 +324,14 @@ fn validate_constraints( properties ))); } - if let Some(min) = min { - if let Some(max) = max { - if max.as_i64() < min.as_i64() { - return Err(anyhow!(format!( - "invalid constraints - minimum > maximum - {}", - properties - ))); - } - } + if let Some(min) = min + && let Some(max) = max + && max.as_i64() < min.as_i64() + { + return Err(anyhow!(format!( + "invalid constraints - minimum > maximum - {}", + properties + ))); } // validated length @@ -344,15 +343,14 @@ fn validate_constraints( properties ))); } - if let Some(min) = min { - if let Some(max) = max { - if max.as_i64() < min.as_i64() { - return Err(anyhow!(format!( - "invalid constraints - minLength > maxLength - {}", - properties - ))); - } - } + if let Some(min) = min + && let Some(max) = max + && max.as_i64() < min.as_i64() + { + return Err(anyhow!(format!( + "invalid constraints - minLength > maxLength - {}", + properties + ))); } Ok(()) } @@ -532,28 +530,28 @@ fn generate_string_data(constraints: &HashMap) -> String .unwrap_or("Error: invalid constant constraint") .into(); } - if let Some(constraint) = constraints.get(&Keywords::Pattern) { - if let Some((pattern, hir)) = constraint.as_pattern() { - let mut rng = thread_rng(); - let mut buffer: Vec = vec![]; - return match hir.as_ref() { - Some(hir) => generate_from_hir(&mut buffer, hir, &mut rng, PATTER_MAX_REPEAT) + if let Some(constraint) = constraints.get(&Keywords::Pattern) + && let Some((pattern, hir)) = constraint.as_pattern() + { + let mut rng = thread_rng(); + let mut buffer: Vec = vec![]; + return match hir.as_ref() { + Some(hir) => generate_from_hir(&mut buffer, hir, &mut rng, PATTER_MAX_REPEAT) + .ok() + .and_then(|_| String::from_utf8(buffer).ok()) + .unwrap_or(format!("Couldn't generate string for: {}", pattern)), + None => { + log::warn!("Hir not pre-generated for pattern constraint"); + Parser::new() + .parse(pattern) .ok() + .and_then(|ir| { + generate_from_hir(&mut buffer, &ir, &mut rng, PATTER_MAX_REPEAT).ok() + }) .and_then(|_| String::from_utf8(buffer).ok()) - .unwrap_or(format!("Couldn't generate string for: {}", pattern)), - None => { - log::warn!("Hir not pre-generated for pattern constraint"); - Parser::new() - .parse(pattern) - .ok() - .and_then(|ir| { - generate_from_hir(&mut buffer, &ir, &mut rng, PATTER_MAX_REPEAT).ok() - }) - .and_then(|_| String::from_utf8(buffer).ok()) - .unwrap_or(format!("Couldn't generate string for: {}", pattern)) - } - }; - } + .unwrap_or(format!("Couldn't generate string for: {}", pattern)) + } + }; } let min = constraints .get(&Keywords::MinLength) @@ -572,10 +570,10 @@ fn generate_string_data(constraints: &HashMap) -> String #[cfg(test)] mod test { - use crate::{data_schema_from_value, generate_data, Constraints, DataSchema, Keywords}; + use crate::{Constraints, DataSchema, Keywords, data_schema_from_value, generate_data}; use log::info; use regex::Regex; - use serde_json::{json, Value}; + use serde_json::{Value, json}; use std::str::FromStr; use std::sync::Once; @@ -984,11 +982,13 @@ mod test { "#; let schema = serde_json::from_str::(data); assert!(schema.is_err()); - assert!(schema - .err() - .unwrap() - .to_string() - .contains("minimum > maximum")); + assert!( + schema + .err() + .unwrap() + .to_string() + .contains("minimum > maximum") + ); } #[test] @@ -1021,11 +1021,13 @@ mod test { "#; let schema = serde_json::from_str::(data); assert!(schema.is_err()); - assert!(schema - .err() - .unwrap() - .to_string() - .contains("minLength > maxLength")); + assert!( + schema + .err() + .unwrap() + .to_string() + .contains("minLength > maxLength") + ); } #[test] @@ -1057,11 +1059,13 @@ mod test { "#; let schema = serde_json::from_str::(data); assert!(schema.is_err()); - assert!(schema - .err() - .unwrap() - .to_string() - .contains("requires both minimum & maximum")); + assert!( + schema + .err() + .unwrap() + .to_string() + .contains("requires both minimum & maximum") + ); } #[test] @@ -1093,11 +1097,13 @@ mod test { "#; let schema = serde_json::from_str::(data); assert!(schema.is_err()); - assert!(schema - .err() - .unwrap() - .to_string() - .contains("requires both minimum & maximum")); + assert!( + schema + .err() + .unwrap() + .to_string() + .contains("requires both minimum & maximum") + ); } #[test] @@ -1129,11 +1135,13 @@ mod test { "#; let schema = serde_json::from_str::(data); assert!(schema.is_err()); - assert!(schema - .err() - .unwrap() - .to_string() - .contains("requires both minLength & maxLength")); + assert!( + schema + .err() + .unwrap() + .to_string() + .contains("requires both minLength & maxLength") + ); } #[test] @@ -1165,11 +1173,13 @@ mod test { "#; let schema = serde_json::from_str::(data); assert!(schema.is_err()); - assert!(schema - .err() - .unwrap() - .to_string() - .contains("requires both minLength & maxLength")); + assert!( + schema + .err() + .unwrap() + .to_string() + .contains("requires both minLength & maxLength") + ); } #[test] diff --git a/datagen/src/template.rs b/datagen/src/template.rs index b517580..a08976d 100644 --- a/datagen/src/template.rs +++ b/datagen/src/template.rs @@ -3,8 +3,8 @@ use log::trace; use rand::thread_rng; use regex::Regex; use rhai::packages::{Package, StandardPackage}; -use rhai::{Dynamic, Engine, AST}; -use serde_json::{json, Value}; +use rhai::{AST, Dynamic, Engine}; +use serde_json::{Value, json}; use std::cmp::max; use std::collections::HashMap; @@ -33,8 +33,7 @@ pub fn parse_templates_inner( if let Some(ast) = find_pattern_and_compile(&PATTERN_FUNCTION, str_val, engine) { trace!( "[parse_templates] - input: {}, Rhai AST: {:?}", - str_val, - ast + str_val, ast ); template_map.insert(path.to_string(), ast); } @@ -60,14 +59,14 @@ fn find_pattern_and_compile(regex: &Regex, target: &str, engine: &Engine) -> Opt "[parse_templates] - text: {target}, captures: {:?}", &captures ); - if let Some(captures) = captures { - if captures.len() > 1 { - let expr = captures.get(1).unwrap().as_str(); - let ast = engine - .compile(expr) - .unwrap_or_else(|e| engine.compile(format!("`{}`", e)).unwrap()); - return Some(ast); - } + if let Some(captures) = captures + && captures.len() > 1 + { + let expr = captures.get(1).unwrap().as_str(); + let ast = engine + .compile(expr) + .unwrap_or_else(|e| engine.compile(format!("`{}`", e)).unwrap()); + return Some(ast); } None } @@ -168,14 +167,14 @@ fn register_template_functions(engine: &mut Engine) { #[cfg(test)] mod tests { use crate::template::{ - build_engine, find_pattern_and_compile, parse_templates_inner, populate_data, - PATTERN_FUNCTION, + PATTERN_FUNCTION, build_engine, find_pattern_and_compile, parse_templates_inner, + populate_data, }; use crate::test::init_logger; use log::info; use regex::Regex; - use rhai::{Dynamic, Engine, AST}; - use serde_json::{json, Value}; + use rhai::{AST, Dynamic, Engine}; + use serde_json::{Value, json}; use std::collections::HashMap; #[test] diff --git a/lua-helper/src/lib.rs b/lua-helper/src/lib.rs index 334f8ab..9a1508b 100644 --- a/lua-helper/src/lib.rs +++ b/lua-helper/src/lib.rs @@ -59,18 +59,15 @@ pub fn init_lua() -> Lua { pub fn load_lua_func<'lua>(lua_chunk: &str, lua: &'lua Lua) -> Option> { debug!("loading lua module from"); - let result = lua - .load(lua_chunk) + lua.load(lua_chunk) .eval::() .map_err(|e| error!("Failed to load lua function - {}", e)) - .ok(); - result + .ok() } pub fn load_lua_func_with_registry(lua_chunk: &str, lua: &Lua) -> Option { debug!("loading lua module from"); - let result = lua - .load(lua_chunk) + lua.load(lua_chunk) .eval::() .map_err(|e| error!("Failed to load lua function:{}, error: {}", lua_chunk, e)) .ok() @@ -78,8 +75,7 @@ pub fn load_lua_func_with_registry(lua_chunk: &str, lua: &Lua) -> Option Result<(), String> { diff --git a/overload-http/src/lib.rs b/overload-http/src/lib.rs index b2cf614..b65bfe2 100644 --- a/overload-http/src/lib.rs +++ b/overload-http/src/lib.rs @@ -12,8 +12,8 @@ use once_cell::sync::OnceCell; use response_assert::ResponseAssertion; use serde::{Deserialize, Serialize}; use smallvec::SmallVec; -use sqlx::sqlite::SqliteRow; use sqlx::Row; +use sqlx::sqlite::SqliteRow; use std::collections::HashMap; use std::error::Error as StdError; use std::fmt::{Display, Formatter}; @@ -398,8 +398,8 @@ pub const PATH_REQUEST_DATA_FILE_DOWNLOAD: &str = "/cluster/data-file/"; #[cfg(test)] mod test { use crate::*; - use http::header::HOST; use http::Method; + use http::header::HOST; use std::collections::HashMap; use std::convert::TryInto; @@ -633,10 +633,11 @@ mod test { assert!(matches!(req, RequestSpecEnum::JsonTemplateRequest(_))); if let RequestSpecEnum::JsonTemplateRequest(req) = req { assert_eq!(req.headers.len(), 2); - assert!(req - .headers - .iter() - .any(|(k, v)| HOST.eq(k.as_str()) && v.eq(target_host))); + assert!( + req.headers + .iter() + .any(|(k, v)| HOST.eq(k.as_str()) && v.eq(target_host)) + ); assert!(req.headers.keys().any(|x| { HOST.eq(x.as_str()) })); } @@ -687,10 +688,11 @@ mod test { assert!(matches!(req, RequestSpecEnum::JsonTemplateRequest(_))); if let RequestSpecEnum::JsonTemplateRequest(req) = req { assert_eq!(req.headers.len(), 2); - assert!(req - .headers - .iter() - .any(|(k, v)| HOST.eq(k.as_str()) && v.eq("localhost"))); + assert!( + req.headers + .iter() + .any(|(k, v)| HOST.eq(k.as_str()) && v.eq("localhost")) + ); assert!(req.headers.keys().any(|x| { HOST.eq(x.as_str()) })); } diff --git a/overload-http/src/rate_spec.rs b/overload-http/src/rate_spec.rs index 4587eab..3b32c27 100644 --- a/overload-http/src/rate_spec.rs +++ b/overload-http/src/rate_spec.rs @@ -112,7 +112,7 @@ impl TryFrom for Steps { "Need more than one step. Use ConstantQPS for single step." )); } - value.steps.sort_by(|a, b| a.start.cmp(&b.start)); + value.steps.sort_by_key(|a| a.start); //check continuity of steps let steps = &value.steps; let mut iter = steps.iter(); @@ -127,8 +127,12 @@ impl TryFrom for Steps { let mut prev = first.end; for current in iter { if prev + 1 != current.start { - return Err(anyhow::anyhow!("Steps are not continuous. An step ends at {} but next step should start at {}, but starts at {}", - prev, prev+1, current.start)); + return Err(anyhow::anyhow!( + "Steps are not continuous. An step ends at {} but next step should start at {}, but starts at {}", + prev, + prev + 1, + current.start + )); } else { prev = current.end; } diff --git a/overload-http/src/request_specs.rs b/overload-http/src/request_specs.rs index dddc8fc..48bb84a 100644 --- a/overload-http/src/request_specs.rs +++ b/overload-http/src/request_specs.rs @@ -1,8 +1,8 @@ -use crate::{data_dir_path, HttpReq}; +use crate::{HttpReq, data_dir_path}; use datagen::DataSchema; use http::Method; use regex::Regex; -use rhai::{Engine, AST}; +use rhai::{AST, Engine}; use serde::{Deserialize, Deserializer, Serialize}; use serde_json::Value; use smol_str::SmolStr; diff --git a/overload/src/filters.rs b/overload/src/filters.rs index 6523473..ae76077 100644 --- a/overload/src/filters.rs +++ b/overload/src/filters.rs @@ -10,7 +10,7 @@ use overload::standalone::handle_get_status; use overload_http::{JobStatusQueryParams, MultiRequest, Request}; use std::collections::HashMap; use std::convert::{Infallible, TryFrom}; -use warp::{reply, Filter}; +use warp::{Filter, reply}; pub fn get_routes() -> impl Filter + Clone { let prometheus_metric = filters_common::prometheus_metric(); @@ -39,8 +39,8 @@ pub fn overload_req() -> impl Filter impl Filter + Clone { +pub fn overload_multi_req() +-> impl Filter + Clone { warp::post() .and(warp::path("tests").and(warp::path::end())) .and(warp::body::content_length_limit(1024 * 1024 * 5)) @@ -48,8 +48,8 @@ pub fn overload_multi_req( .and_then(|request: MultiRequest| async move { execute_multiple(request).await }) } -pub fn upload_binary_file( -) -> impl Filter + Clone { +pub fn upload_binary_file() +-> impl Filter + Clone { warp::post() .and( warp::path("test") @@ -74,8 +74,8 @@ pub fn upload_csv_file() -> impl Filter impl Filter + Clone { +pub fn upload_sqlite_file() +-> impl Filter + Clone { let enc = warp::header::(http::header::CONTENT_ENCODING.as_str()) .map(Some) .or_else(|_| async { Ok::<(Option,), std::convert::Infallible>((None,)) }); diff --git a/overload/src/filters_cluster.rs b/overload/src/filters_cluster.rs index a9eb54e..bdf0904 100644 --- a/overload/src/filters_cluster.rs +++ b/overload/src/filters_cluster.rs @@ -4,7 +4,7 @@ use crate::filters_common; use crate::filters_common::prometheus_metric; use bytes::{Buf, Bytes, BytesMut}; use cluster_executor::data_dir_path; -use cluster_mode::{get_cluster_info, Cluster}; +use cluster_mode::{Cluster, get_cluster_info}; use futures_util::future::Either; use futures_util::{FutureExt, Stream, StreamExt}; use http::StatusCode; @@ -23,7 +23,7 @@ use std::task::Poll; use tokio::fs::File; use tokio::io::AsyncSeekExt; use warp::reply::{Json, Response, WithStatus}; -use warp::{reply, Filter}; +use warp::{Filter, reply}; lazy_static! { pub static ref CLUSTER: Arc = Arc::new(Cluster::new()); @@ -336,8 +336,7 @@ async fn cluster_request_vote( ) -> Result { trace!( "req: cluster_request_vote: requester: {}, term: {}", - &requester_node_id, - &term + &requester_node_id, &term ); if !cluster_mode { let err = no_cluster_err(); @@ -359,8 +358,7 @@ async fn cluster_request_vote_response( ) -> Result { trace!( "req: cluster_request_vote_response: term: {}, vote: {}", - &term, - &vote + &term, &vote ); if !cluster_mode { let err = no_cluster_err(); @@ -380,8 +378,7 @@ async fn cluster_heartbeat( ) -> Result { trace!( "req: cluster_heartbeat: leader: {}, term: {}", - &leader_node_id, - &term + &leader_node_id, &term ); if !cluster_mode { let err = no_cluster_err(); @@ -398,8 +395,8 @@ fn no_cluster_err() -> WithStatus { reply::with_status(reply::json(&error_msg), StatusCode::NOT_FOUND) } -pub fn download_req_from_secondaries( -) -> impl Filter + Clone { +pub fn download_req_from_secondaries() +-> impl Filter + Clone { warp::path!("cluster" / "data-file" / String) .and_then(|filename| async move { response_file(filename).await }) } @@ -448,7 +445,7 @@ fn file_stream( let mut f = match result { Ok(f) => f, Err(f) => { - return Either::Left(futures_util::stream::once(futures_util::future::err(f))) + return Either::Left(futures_util::stream::once(futures_util::future::err(f))); } }; @@ -505,11 +502,11 @@ mod cluster_test { use csv_async::AsyncReaderBuilder; use http::Request; use httpmock::Method::POST; - use hyper::body::to_bytes; use hyper::Body; + use hyper::body::to_bytes; use log::info; use overload::file_uploader::csv_reader_to_sqlite; - use overload::{init, JobStatus}; + use overload::{JobStatus, init}; use regex::Regex; use rust_cloud_discovery::DiscoveryService; use rust_cloud_discovery::ServiceInstance; @@ -527,10 +524,10 @@ mod cluster_test { fn start_warp_with_route( route: impl Filter - + Send - + Sync - + Clone - + 'static, + + Send + + Sync + + Clone + + 'static, ) -> (Sender<()>, JoinHandle<()>) { let (tx, rx) = tokio::sync::oneshot::channel::<()>(); let (_addr, server) = diff --git a/overload/src/filters_common.rs b/overload/src/filters_common.rs index 359f5e3..3a2d785 100644 --- a/overload/src/filters_common.rs +++ b/overload/src/filters_common.rs @@ -7,10 +7,10 @@ use overload_http::{GenericError, GenericResponse}; use overload_metrics::METRICS_FACTORY; use prometheus::{Encoder, TextEncoder}; use serde::Serialize; -use warp::{reply, Filter}; +use warp::{Filter, reply}; -pub fn prometheus_metric( -) -> impl Filter + Clone { +pub fn prometheus_metric() +-> impl Filter + Clone { warp::get().and(warp::path("metrics")).map(|| { let encoder = TextEncoder::new(); let metrics = METRICS_FACTORY.registry().gather(); diff --git a/overload/src/main.rs b/overload/src/main.rs index 3337efe..8f8c12b 100644 --- a/overload/src/main.rs +++ b/overload/src/main.rs @@ -1,7 +1,7 @@ // #![allow(deprecated)] #[cfg(feature = "cluster")] use cloud_discovery_kubernetes::KubernetesDiscoverService; -use cluster_executor::{remoc_port, REMOC_PORT}; +use cluster_executor::{REMOC_PORT, remoc_port}; #[cfg(feature = "cluster")] use cluster_mode::ClusterConfig; use log::info; @@ -62,8 +62,14 @@ async fn main() { Ok(k8s) => { let discovery_client = DiscoveryClient::new(k8s); let config = cluster_config(); - info!("cluster configuration - connection_timeout:{}, election_timeout:{}, update_interval: {}, max_node: {}, min_node:{}", - &config.connection_timeout, &config.election_timeout, &config.update_interval,&config.max_node,&config.min_node); + info!( + "cluster configuration - connection_timeout:{}, election_timeout:{}, update_interval: {}, max_node: {}, min_node:{}", + &config.connection_timeout, + &config.election_timeout, + &config.update_interval, + &config.max_node, + &config.min_node + ); tokio::spawn(cluster_mode::start_cluster( filters::CLUSTER.clone(), discovery_client, @@ -72,7 +78,7 @@ async fn main() { } Err(e) => { _cluster_up = false; - info!("error initializing kubernetes: {}", e.to_string()); + info!("error initializing kubernetes: {}", e); } } } diff --git a/overload/src/overload/cluster/mod.rs b/overload/src/overload/cluster/mod.rs index 18bc031..be2f43a 100644 --- a/overload/src/overload/cluster/mod.rs +++ b/overload/src/overload/cluster/mod.rs @@ -1,9 +1,9 @@ use crate::cluster::secondary::{ forward_get_status_request, forward_stop_request_to_primary, forward_test_request, }; -use crate::{job_id, pre_check, Response, PATH_FILE_UPLOAD, PATH_FILE_UPLOAD_SQLITE}; +use crate::{PATH_FILE_UPLOAD, PATH_FILE_UPLOAD_SQLITE, Response, job_id, pre_check}; use bytes::Buf; -use cluster_executor::{get_status_all, get_status_by_job_id, ErrorCode, JobStatus}; +use cluster_executor::{ErrorCode, JobStatus, get_status_all, get_status_by_job_id}; use cluster_mode::{Cluster, RestClusterNode}; use futures_util::Stream; use http::header::CONTENT_LENGTH; @@ -286,7 +286,7 @@ pub(crate) async fn primary_uri( pub(crate) fn convert_stream( data: S, -) -> Box>> + Send> +) -> Box>> + Send> where S: Stream> + Unpin + Send + Sync + 'static, B: Buf + Send + Sync, diff --git a/overload/src/overload/cluster/secondary.rs b/overload/src/overload/cluster/secondary.rs index 0ddde03..0673620 100644 --- a/overload/src/overload/cluster/secondary.rs +++ b/overload/src/overload/cluster/secondary.rs @@ -1,6 +1,6 @@ use crate::cluster::primary_uri; -use crate::cluster::{unknown_error_resp, GenericResult}; -use crate::{Response, PATH_JOB_STATUS, PATH_STOP_JOB}; +use crate::cluster::{GenericResult, unknown_error_resp}; +use crate::{PATH_JOB_STATUS, PATH_STOP_JOB, Response}; use bytes::Buf; use cluster_executor::JobStatus; use cluster_mode::Cluster; @@ -8,8 +8,8 @@ use hyper::client::HttpConnector; use hyper::{Body, Client}; use log::trace; use overload_http::{GenericError, GenericResponse, JobStatusQueryParams}; -use serde::de::DeserializeOwned; use serde::Serialize; +use serde::de::DeserializeOwned; use std::sync::Arc; pub(crate) async fn forward_other_requests_to_primary( diff --git a/overload/src/overload/file_uploader.rs b/overload/src/overload/file_uploader.rs index 1f41bdb..77caae0 100644 --- a/overload/src/overload/file_uploader.rs +++ b/overload/src/overload/file_uploader.rs @@ -4,7 +4,6 @@ use std::error::Error as StdError; use std::fmt; use std::fmt::{Debug, Display}; use std::io::Error as StdIoError; -use std::io::ErrorKind; use std::path::PathBuf; use std::pin::Pin; use std::str::FromStr; @@ -88,7 +87,7 @@ where success += 1; sqlx::query("insert into http_req values(?,?,?,?)") .bind(&req.url) - .bind(&req.method.to_string()) + .bind(req.method.to_string()) .bind(&req.body) .bind(serde_json::to_string(&req.headers)?) .execute(&mut connection) @@ -147,7 +146,7 @@ impl StdError for WarpStdIoError {} #[allow(clippy::from_over_into)] impl Into for WarpStdIoError { fn into(self) -> StdIoError { - std::io::Error::new(ErrorKind::Other, self.inner.to_string()) + std::io::Error::other(self.inner.to_string()) } } @@ -228,10 +227,7 @@ where )) })?; let http_stream = WarpByteStream { inner: http_stream }; - let async_read = TryStreamExt::map_err(http_stream, |e| { - std::io::Error::new(std::io::ErrorKind::Other, e) - }) - .into_async_read(); + let async_read = TryStreamExt::map_err(http_stream, std::io::Error::other).into_async_read(); let mut reader = to_tokio_async_read(async_read); if content_encoding == "gzip" { debug!("extracting gzipped file"); @@ -260,7 +256,6 @@ mod test { use crate::file_uploader::csv_reader_to_sqlite; use crate::log_error; use csv_async::AsyncReaderBuilder; - use log::error; use std::sync::Once; static ONCE: Once = Once::new(); diff --git a/overload/src/overload/lib.rs b/overload/src/overload/lib.rs index 2a81093..6b31699 100644 --- a/overload/src/overload/lib.rs +++ b/overload/src/overload/lib.rs @@ -12,8 +12,8 @@ use overload_metrics::MetricsFactory; use regex::Regex; use serde::{Deserialize, Serialize}; use serde_json::Value; -use sqlx::sqlite::SqliteConnectOptions; use sqlx::ConnectOptions; +use sqlx::sqlite::SqliteConnectOptions; use std::env; use std::path::PathBuf; use std::str::FromStr; @@ -79,15 +79,15 @@ pub(crate) fn pre_check(request: &Request) -> Result<(), ErrorCode> { } } RequestSpecEnum::RandomDataRequest(req) => { - if let Some(schema) = &req.body_schema { - if matches!(generate_data(schema), Value::Null) { - return Err(ErrorCode::BodyGenerationFailure); - } + if let Some(schema) = &req.body_schema + && matches!(generate_data(schema), Value::Null) + { + return Err(ErrorCode::BodyGenerationFailure); } - if let Some(schema) = &req.uri_param_schema { - if matches!(generate_data(schema), Value::Null) { - return Err(ErrorCode::UriParamGenerationFailure); - } + if let Some(schema) = &req.uri_param_schema + && matches!(generate_data(schema), Value::Null) + { + return Err(ErrorCode::UriParamGenerationFailure); } } _ => {} diff --git a/overload/src/overload/standalone.rs b/overload/src/overload/standalone.rs index 65a55c4..41bc063 100644 --- a/overload/src/overload/standalone.rs +++ b/overload/src/overload/standalone.rs @@ -1,5 +1,5 @@ -use crate::{job_id, pre_check, Response}; -use cluster_executor::{get_status_all, get_status_by_job_id, JobStatus}; +use crate::{Response, job_id, pre_check}; +use cluster_executor::{JobStatus, get_status_all, get_status_by_job_id}; use log::error; use overload_http::{GenericError, GenericResponse, JobStatusQueryParams, MultiRequest, Request}; use std::collections::HashMap; diff --git a/response-assert/src/lib.rs b/response-assert/src/lib.rs index dbc772f..74ff2e0 100644 --- a/response-assert/src/lib.rs +++ b/response-assert/src/lib.rs @@ -6,7 +6,7 @@ use anyhow::anyhow; use http::{Method, Uri}; use jsonpath_lib::Compiled; use log::trace; -use lua_helper::{call_lua_func_from_registry, LuaAssertionResult}; +use lua_helper::{LuaAssertionResult, call_lua_func_from_registry}; use serde::{Deserialize, Serialize}; use serde_json::Value; use std::collections::HashMap; @@ -64,6 +64,7 @@ impl TryFrom for JsonSchema { } } +#[allow(dead_code)] #[derive(Deserialize, Serialize)] struct JsonSchemaShadowType { pub(crate) schema: Value, @@ -177,7 +178,7 @@ pub fn simple_assert( .simple_assertions .as_ref() .map_or(0, |v| { v.len() }), - request_url.to_string() + request_url ); let mut errors = vec![]; let mut paths: Option> = None; @@ -326,11 +327,7 @@ pub fn simple_assert( all_matched = false; } } - if all_matched { - Ok(()) - } else { - Err(errors) - } + if all_matched { Ok(()) } else { Err(errors) } } type ResponseBody = String; @@ -395,7 +392,7 @@ pub async fn init_lua_executor(response_assert: &ResponseAssertion) -> Option usize { - if !cfg!(feature = "cluster") { - 1 - } else { - 3 - } + if !cfg!(feature = "cluster") { 1 } else { 3 } } pub fn resource_dir() -> PathBuf { @@ -672,8 +668,8 @@ mod tests { pub fn get_value_for_metrics(metrics: &str) -> i64 { info!("getting value for metrics: {}", metrics.trim()); - return metrics + metrics .rsplit_once(' ') - .map_or(0, |(_, count)| count.parse::().unwrap()); + .map_or(0, |(_, count)| count.parse::().unwrap()) } } From 34f99729b9f2576da1d8da28a3aac758e893a84d Mon Sep 17 00:00:00 2001 From: sarowar Date: Sat, 6 Jun 2026 17:27:21 +0900 Subject: [PATCH 3/6] upgrade mlua version --- Cargo.toml | 2 +- cluster-executor/src/standalone.rs | 2 +- lua-helper/src/lib.rs | 37 ++++++++++++++---------------- 3 files changed, 19 insertions(+), 22 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index 2920fd6..545f997 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -39,7 +39,7 @@ version = "0.11" version = "1.0" [workspace.dependencies.mlua] -version = "0.8" +version = "0.11" features = ["lua53", "send", "serialize"] [workspace.dependencies.url] diff --git a/cluster-executor/src/standalone.rs b/cluster-executor/src/standalone.rs index 9f8de61..5dac5e7 100644 --- a/cluster-executor/src/standalone.rs +++ b/cluster-executor/src/standalone.rs @@ -51,7 +51,7 @@ pub async fn handle_request(request: Request) { let mut counter = 0u8; while let Some((qps, connection_count)) = stream.next().await { counter += 1; - if counter % 5 == 0 { + if counter.is_multiple_of(5) { // check for stop every 5 seconds if matches!( JOB_STATUS.read().await.get(&job_id), diff --git a/lua-helper/src/lib.rs b/lua-helper/src/lib.rs index 9a1508b..de46b0b 100644 --- a/lua-helper/src/lib.rs +++ b/lua-helper/src/lib.rs @@ -20,14 +20,14 @@ impl LuaAssertionResult { } } -impl FromLua<'_> for LuaAssertionResult { +impl FromLua for LuaAssertionResult { fn from_lua(lua_value: Value, _lua: &Lua) -> mlua::Result { match lua_value { Value::Table(table) => { - let id = table.raw_get::<_, i32>("id")?; + let id = table.raw_get::("id")?; let mut result = Ok(()); - if !table.raw_get::<_, bool>("success")? { - result = Err(table.raw_get::<_, String>("error")?); + if !table.raw_get::("success")? { + result = Err(table.raw_get::<_>("error")?); } Ok(Self { assertion_id: id, @@ -36,7 +36,7 @@ impl FromLua<'_> for LuaAssertionResult { } _ => Err(mlua::Error::FromLuaConversionError { from: lua_value.type_name(), - to: "LuaAssertionResult", + to: "LuaAssertionResult".to_string(), message: Some("expected table".to_string()), }), } @@ -57,7 +57,7 @@ pub fn init_lua() -> Lua { lua } -pub fn load_lua_func<'lua>(lua_chunk: &str, lua: &'lua Lua) -> Option> { +pub fn load_lua_func(lua_chunk: &str, lua: &Lua) -> Option { debug!("loading lua module from"); lua.load(lua_chunk) .eval::() @@ -97,7 +97,7 @@ pub fn call_lua_func_from_registry( ) -> Result<(), Vec> { match lua.registry_value::(func_key) { Ok(func) => func - .call::<_, Vec>((method, url, req_body, resp_body)) + .call::>((method, url, req_body, resp_body)) .map_err(|e| { error!("Error calling lua function: {}", &e); vec![LuaAssertionResult::lua_error(e.to_string())] @@ -151,7 +151,7 @@ mod tests { assert_eq!( test_json - .call::<_, String>("{\"hello\":\"world\"}".to_string()) + .call::("{\"hello\":\"world\"}".to_string()) .unwrap(), "world from lua" ); @@ -226,11 +226,11 @@ mod tests { .unwrap(); let json = sample_json(); - let lua_table = test_json.call::<_, Table>(json.to_string()).unwrap(); + let lua_table = test_json.call::(json.to_string()).unwrap(); let v = lua_table - .get::<_, Table>(1) + .get::
(1) .unwrap() - .get::<_, String>("id") + .get::("id") .unwrap(); assert_eq!(v, "0001".to_string()) } @@ -258,15 +258,12 @@ mod tests { .unwrap(); let json = sample_json(); - let lua_table = test_json.call::<_, Table>(json.to_string()).unwrap(); + let lua_table = test_json.call::
(json.to_string()).unwrap(); // let v = - assert_eq!(lua_table.get::<_, String>(1).unwrap(), "0001".to_string()); - assert_eq!(lua_table.get::<_, String>(2).unwrap(), "0002".to_string()); - assert_eq!(lua_table.get::<_, String>(3).unwrap(), "1001".to_string()); - assert_eq!( - lua_table.get::<_, String>(4).unwrap(), - "Chocolate".to_string() - ); + assert_eq!(lua_table.get::(1).unwrap(), "0001".to_string()); + assert_eq!(lua_table.get::(2).unwrap(), "0002".to_string()); + assert_eq!(lua_table.get::(3).unwrap(), "1001".to_string()); + assert_eq!(lua_table.get::(4).unwrap(), "Chocolate".to_string()); } fn sample_json() -> serde_json::Value { @@ -352,7 +349,7 @@ mod tests { "#; let lua = Lua::new(); let lua_twice: Function = lua.load(lua_txt).eval().unwrap(); - assert_eq!(lua_twice.call::<_, u32>(5).unwrap(), 10); + assert_eq!(lua_twice.call::(5).unwrap(), 10); } #[test] From 2a357c7041df0969d15909de3d1e821c7083aefe Mon Sep 17 00:00:00 2001 From: sarowar Date: Sat, 6 Jun 2026 18:31:31 +0900 Subject: [PATCH 4/6] setup rust toolchain --- .github/workflows/rust.yml | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/.github/workflows/rust.yml b/.github/workflows/rust.yml index 6c4110e..63aeeab 100644 --- a/.github/workflows/rust.yml +++ b/.github/workflows/rust.yml @@ -36,6 +36,11 @@ jobs: target/ key: ${{ runner.os }}-cargo-${{ hashFiles('**/Cargo.lock') }} restore-keys: ${{ runner.os }}-cargo- + - name: Set up Rust toolchain + uses: actions-rust-lang/setup-rust-toolchain@v1 + with: + toolchain: stable + components: clippy, rustfmt - name: Lint run: cargo fmt --all -- --check - name: Run cluster tests From aff86a35208612dd019b1513fb958f7dba223ad6 Mon Sep 17 00:00:00 2001 From: sarowar Date: Sat, 6 Jun 2026 19:15:51 +0900 Subject: [PATCH 5/6] fix for standalone --- overload/Cargo.toml | 6 ++++++ overload/src/filters.rs | 24 ++++++++++++++++++------ 2 files changed, 24 insertions(+), 6 deletions(-) diff --git a/overload/Cargo.toml b/overload/Cargo.toml index 26b1d44..e1900d8 100644 --- a/overload/Cargo.toml +++ b/overload/Cargo.toml @@ -130,12 +130,18 @@ features = ["gzip", "tokio"] workspace = true features = ["rt-multi-thread", "macros", "fs", "io-util", "time", "test-util"] +[dev-dependencies.more-asserts] +version = "0.3" + [dev-dependencies.httpmock] version = "0.6" [dev-dependencies.sha2] version = "0.10" +[dev-dependencies.portpicker] +version = "0.1" + [dev-dependencies.test-case] version = "2.2" diff --git a/overload/src/filters.rs b/overload/src/filters.rs index ae76077..3888013 100644 --- a/overload/src/filters.rs +++ b/overload/src/filters.rs @@ -280,7 +280,9 @@ mod standalone_mode_tests { info!("using ports: {}, {}", http_port, remoc_port); //wait a bit for bootstrapping tokio::time::sleep(Duration::from_millis(50)).await; - std::env::set_var(ENV_NAME_REMOC_PORT, remoc_port.to_string()); + unsafe { + std::env::set_var(ENV_NAME_REMOC_PORT, remoc_port.to_string()); + } let (mock_server, url) = ASYNC_ONCE_HTTP_MOCK.get_or_init(init_http_mock).await; @@ -329,7 +331,9 @@ mod standalone_mode_tests { // let (tx, http_port, remoc_port, handle) = init_env().await; // info!("handle status: {}", handle.is_finished()); info!("using ports: {}, {}", http_port, remoc_port); - std::env::set_var(ENV_NAME_REMOC_PORT, remoc_port.to_string()); + unsafe { + std::env::set_var(ENV_NAME_REMOC_PORT, remoc_port.to_string()); + } let (mock_server, url) = ASYNC_ONCE_HTTP_MOCK.get_or_init(init_http_mock).await; @@ -373,7 +377,9 @@ mod standalone_mode_tests { let (tx, http_port, remoc_port) = init_env().await; info!("using ports: {}, {}", http_port, remoc_port); - std::env::set_var(ENV_NAME_REMOC_PORT, remoc_port.to_string()); + unsafe { + std::env::set_var(ENV_NAME_REMOC_PORT, remoc_port.to_string()); + } let (mock_server, url) = ASYNC_ONCE_HTTP_MOCK.get_or_init(init_http_mock).await; @@ -422,7 +428,9 @@ mod standalone_mode_tests { info!("using ports: {}, {}", http_port, remoc_port); //wait a bit for bootstrapping tokio::time::sleep(Duration::from_millis(50)).await; - std::env::set_var(ENV_NAME_REMOC_PORT, remoc_port.to_string()); + unsafe { + std::env::set_var(ENV_NAME_REMOC_PORT, remoc_port.to_string()); + } let (mock_server, url) = ASYNC_ONCE_HTTP_MOCK.get_or_init(init_http_mock).await; @@ -466,7 +474,9 @@ mod standalone_mode_tests { info!("using ports: {}, {}", http_port, remoc_port); //wait a bit for bootstrapping tokio::time::sleep(Duration::from_millis(50)).await; - std::env::set_var(ENV_NAME_REMOC_PORT, remoc_port.to_string()); + unsafe { + std::env::set_var(ENV_NAME_REMOC_PORT, remoc_port.to_string()); + } let (mock_server, url) = ASYNC_ONCE_HTTP_MOCK.get_or_init(init_http_mock).await; @@ -526,7 +536,9 @@ mod standalone_mode_tests { let (tx, http_port, remoc_port) = init_env().await; info!("using ports: {}, {}", http_port, remoc_port); - std::env::set_var(ENV_NAME_REMOC_PORT, remoc_port.to_string()); + unsafe { + std::env::set_var(ENV_NAME_REMOC_PORT, remoc_port.to_string()); + } let (mock_server, url) = ASYNC_ONCE_HTTP_MOCK.get_or_init(init_http_mock).await; From f3ac3bbf805e03cdc849f9c6091fb84c42bae594 Mon Sep 17 00:00:00 2001 From: sarowar Date: Fri, 12 Jun 2026 21:43:55 +0900 Subject: [PATCH 6/6] Fix and improve GitHub workflows --- .dockerignore | 10 +++++-- .github/workflows/dockerhub-push.yml | 25 ++++++---------- .github/workflows/github-pages.yml | 6 ++-- .github/workflows/rust.yml | 4 +-- Cargo.toml | 2 +- Dockerfile | 43 ++++++++++++++++++++++++---- standalone.Dockerfile | 38 ++++++++++++++++++++++++ 7 files changed, 97 insertions(+), 31 deletions(-) create mode 100644 standalone.Dockerfile diff --git a/.dockerignore b/.dockerignore index 6301bee..430f990 100644 --- a/.dockerignore +++ b/.dockerignore @@ -1,3 +1,7 @@ -* -!target/debug/overload -!target/release/overload \ No newline at end of file +target +.vscode +.github +*.log +.git +.idea +docs \ No newline at end of file diff --git a/.github/workflows/dockerhub-push.yml b/.github/workflows/dockerhub-push.yml index 073842f..c831f43 100644 --- a/.github/workflows/dockerhub-push.yml +++ b/.github/workflows/dockerhub-push.yml @@ -1,7 +1,9 @@ name: Dockerhub on: - push: + workflow_run: + workflows: ["Rust"] + types: [completed] branches: [ main ] release: types: [published] @@ -13,14 +15,10 @@ env: jobs: build: - runs-on: ubuntu-20.04 + runs-on: ubuntu-latest steps: - - name: install lua - run: sudo apt install -y liblua5.3-dev - - uses: actions/checkout@v2 - - name: Run tests for cluster - run: cargo test --features="cluster" --verbose + - uses: actions/checkout@v4 - name: Get version run: | if [[ ${{ github.event_name }} == 'release' ]]; then @@ -36,27 +34,22 @@ jobs: echo "version=latest" >> "$GITHUB_ENV" echo "suffix=-snapshot" >> "$GITHUB_ENV" fi - - name: Build cluster - run: cargo build --bins --features "cluster" --release - name: Login to Github Container registry - uses: docker/login-action@v1 + uses: docker/login-action@v3 with: registry: ghcr.io username: ${{ github.actor }} password: ${{ secrets.GITHUB_TOKEN }} - name: Build cluster image - uses: docker/build-push-action@v2.5.0 + uses: docker/build-push-action@v7 with: context: . push: true tags: ghcr.io/${{ github.repository }}:cluster-${{ env.version }}${{ env.suffix }} - - name: Run standalone tests - run: cargo test --verbose - - name: Build standalone - run: cargo build --bins --release - name: Build & push standalone image - uses: docker/build-push-action@v2.5.0 + uses: docker/build-push-action@v7 with: context: . + file: standalone.Dockerfile push: true tags: ghcr.io/${{ github.repository }}:standalone-${{ env.version }}${{ env.suffix }} diff --git a/.github/workflows/github-pages.yml b/.github/workflows/github-pages.yml index 1f071c8..d3ab20d 100644 --- a/.github/workflows/github-pages.yml +++ b/.github/workflows/github-pages.yml @@ -42,11 +42,11 @@ jobs: - name: build mdBook run: mdbook build docs/ - name: Setup Pages - uses: actions/configure-pages@v2 + uses: actions/configure-pages@v4 - name: Upload artifact - uses: actions/upload-pages-artifact@v1 + uses: actions/upload-pages-artifact@v2 with: path: 'docs/book/html' - name: Deploy to GitHub Pages id: deployment - uses: actions/deploy-pages@v1 + uses: actions/deploy-pages@v4 diff --git a/.github/workflows/rust.yml b/.github/workflows/rust.yml index 63aeeab..e8deb99 100644 --- a/.github/workflows/rust.yml +++ b/.github/workflows/rust.yml @@ -17,13 +17,13 @@ env: jobs: build: - runs-on: ubuntu-22.04 + runs-on: ubuntu-latest steps: - name: install lua run: sudo apt install -y liblua5.3-dev - name: Checkout - uses: actions/checkout@v2 + uses: actions/checkout@v4 - name: Set up cargo cache uses: actions/cache@v3 continue-on-error: false diff --git a/Cargo.toml b/Cargo.toml index 545f997..2a5443c 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -57,4 +57,4 @@ version = "0.14" version = "0.2" [profile.release] -debug = true +debug = "line-tables-only" diff --git a/Dockerfile b/Dockerfile index f2ec249..36fd048 100644 --- a/Dockerfile +++ b/Dockerfile @@ -1,7 +1,38 @@ -FROM ubuntu:20.04 -RUN apt update && \ - apt install -y openssl liblua5.3-0 -ADD target/release/overload /usr/bin/overload -RUN chmod +x /usr/bin/overload +# Build stage +FROM rust:1.96.0-slim-trixie AS builder + +# Install build dependencies +RUN apt-get update && apt-get install -y \ + pkg-config \ + openssl \ + libssl-dev \ + liblua5.3-dev \ + && rm -rf /var/lib/apt/lists/* + +WORKDIR /usr/src/overload +COPY . . + +# Build the application +RUN cargo build --features "cluster" --release + +# Runtime stage +FROM debian:trixie-slim + +# Install runtime dependencies +RUN apt-get update && apt-get install -y \ + ca-certificates \ + libssl3 \ + openssl \ + liblua5.3-0 \ + && rm -rf /var/lib/apt/lists/* + +WORKDIR /usr/bin + +# Copy the binary from the builder stage +COPY --from=builder /usr/src/overload/target/release/overload . + +# Expose the port the app runs on EXPOSE 3030 -ENTRYPOINT /usr/bin/overload + +# Set the startup command +CMD ["/usr/bin/overload"] \ No newline at end of file diff --git a/standalone.Dockerfile b/standalone.Dockerfile new file mode 100644 index 0000000..ba98faa --- /dev/null +++ b/standalone.Dockerfile @@ -0,0 +1,38 @@ +# Build stage +FROM rust:1.96.0-slim-trixie AS builder + +# Install build dependencies +RUN apt-get update && apt-get install -y \ + pkg-config \ + openssl \ + libssl-dev \ + liblua5.3-dev \ + && rm -rf /var/lib/apt/lists/* + +WORKDIR /usr/src/overload +COPY . . + +# Build the application +RUN cargo build --release + +# Runtime stage +FROM debian:trixie-slim + +# Install runtime dependencies +RUN apt-get update && apt-get install -y \ + ca-certificates \ + libssl3 \ + openssl \ + liblua5.3-0 \ + && rm -rf /var/lib/apt/lists/* + +WORKDIR /usr/bin + +# Copy the binary from the builder stage +COPY --from=builder /usr/src/overload/target/release/overload . + +# Expose the port the app runs on +EXPOSE 3030 + +# Set the startup command +CMD ["/usr/bin/overload"] \ No newline at end of file