diff --git a/backend/.sqlx/query-19f0abd79372698f378cb6deea3ee6d098a2758d16ede000809bd9a09660b604.json b/backend/.sqlx/query-19f0abd79372698f378cb6deea3ee6d098a2758d16ede000809bd9a09660b604.json new file mode 100644 index 0000000000..8796b86902 --- /dev/null +++ b/backend/.sqlx/query-19f0abd79372698f378cb6deea3ee6d098a2758d16ede000809bd9a09660b604.json @@ -0,0 +1,20 @@ +{ + "db_name": "PostgreSQL", + "query": "SELECT created_at FROM metrics WHERE id = 'telemetry' ORDER BY created_at DESC LIMIT 1", + "describe": { + "columns": [ + { + "ordinal": 0, + "name": "created_at", + "type_info": "Timestamptz" + } + ], + "parameters": { + "Left": [] + }, + "nullable": [ + false + ] + }, + "hash": "19f0abd79372698f378cb6deea3ee6d098a2758d16ede000809bd9a09660b604" +} diff --git a/backend/.sqlx/query-6776dc50f184188756ad7fe263b0304333536768527525a43bdd45aedffa3c4f.json b/backend/.sqlx/query-6776dc50f184188756ad7fe263b0304333536768527525a43bdd45aedffa3c4f.json new file mode 100644 index 0000000000..4187b628b7 --- /dev/null +++ b/backend/.sqlx/query-6776dc50f184188756ad7fe263b0304333536768527525a43bdd45aedffa3c4f.json @@ -0,0 +1,22 @@ +{ + "db_name": "PostgreSQL", + "query": "SELECT pg_try_advisory_xact_lock($1)", + "describe": { + "columns": [ + { + "ordinal": 0, + "name": "pg_try_advisory_xact_lock", + "type_info": "Bool" + } + ], + "parameters": { + "Left": [ + "Int8" + ] + }, + "nullable": [ + null + ] + }, + "hash": "6776dc50f184188756ad7fe263b0304333536768527525a43bdd45aedffa3c4f" +} diff --git a/backend/Cargo.lock b/backend/Cargo.lock index 0ee755b3ec..0dfc4ee458 100644 --- a/backend/Cargo.lock +++ b/backend/Cargo.lock @@ -10490,7 +10490,6 @@ dependencies = [ "chrono", "chrono-tz 0.10.0", "cookie 0.17.0", - "crc", "cron", "datafusion", "futures", @@ -10597,6 +10596,7 @@ dependencies = [ "bytes", "chrono", "const_format", + "crc", "cron", "futures-core", "gethostname", diff --git a/backend/ee-repo-ref.txt b/backend/ee-repo-ref.txt index 994e59747a..44f2972329 100644 --- a/backend/ee-repo-ref.txt +++ b/backend/ee-repo-ref.txt @@ -1 +1 @@ -3d37b6c31155265d8d026ae9d6ced0b433078f87 \ No newline at end of file +0f5f42d2f8f5f1af05c8086f3dc7ad38d83750df diff --git a/backend/src/main.rs b/backend/src/main.rs index aa6993cf92..0a59e4af07 100644 --- a/backend/src/main.rs +++ b/backend/src/main.rs @@ -745,9 +745,8 @@ Windmill Community Edition {GIT_VERSION} Ok(()) as anyhow::Result<()> }; - let instance_name = rd_string(8); if mode == Mode::Server || mode == Mode::Standalone { - schedule_stats(instance_name, &db, &HTTP_CLIENT).await; + schedule_stats(&db, &HTTP_CLIENT).await; } #[cfg(feature = "enterprise")] diff --git a/backend/windmill-api/Cargo.toml b/backend/windmill-api/Cargo.toml index fd8bedf0f9..e4b6b5d71b 100644 --- a/backend/windmill-api/Cargo.toml +++ b/backend/windmill-api/Cargo.toml @@ -97,7 +97,6 @@ jsonwebtoken = { workspace = true } matchit.workspace = true pin-project.workspace = true -crc.workspace = true http.workspace = true async-stream.workspace = true ulid.workspace = true diff --git a/backend/windmill-api/src/db.rs b/backend/windmill-api/src/db.rs index 470a21bccc..72ef2e1680 100644 --- a/backend/windmill-api/src/db.rs +++ b/backend/windmill-api/src/db.rs @@ -15,6 +15,7 @@ use sqlx::{ PgConnection, Pool, Postgres, }; use windmill_audit::audit_ee::{AuditAuthor, AuditAuthorable}; +use windmill_common::utils::generate_lock_id; use windmill_common::{ db::{Authable, Authed}, error::Error, @@ -29,13 +30,6 @@ async fn current_database(conn: &mut PgConnection) -> Result i64 { - const CRC_IEEE: crc::Crc = crc::Crc::::new(&crc::CRC_32_ISO_HDLC); - // 0x3d32ad9e chosen by fair dice roll - 0x3d32ad9e * (CRC_IEEE.checksum(database_name.as_bytes()) as i64) -} - struct CustomMigrator { inner: PoolConnection, } diff --git a/backend/windmill-api/src/lib.rs b/backend/windmill-api/src/lib.rs index 97d2865e2e..c73972529a 100644 --- a/backend/windmill-api/src/lib.rs +++ b/backend/windmill-api/src/lib.rs @@ -39,9 +39,8 @@ use tower_http::{ trace::TraceLayer, }; use windmill_common::db::UserDB; -use windmill_common::utils::rd_string; use windmill_common::worker::ALL_TAGS; -use windmill_common::BASE_URL; +use windmill_common::{BASE_URL, INSTANCE_NAME}; use crate::scim_ee::has_scim_token; use windmill_common::error::AppError; @@ -373,8 +372,6 @@ pub async fn run_server( ) }; - let instance_name = rd_string(5); - let listener = tokio::net::TcpListener::bind(addr).await.unwrap(); let port = listener.local_addr().map(|x| x.port()).unwrap_or(8000); let ip = listener @@ -385,7 +382,7 @@ pub async fn run_server( let server = axum::serve(listener, app.into_make_service()); tracing::info!( - instance = %instance_name, + instance = %*INSTANCE_NAME, "server started on port={} and addr={}", port, ip diff --git a/backend/windmill-api/src/settings.rs b/backend/windmill-api/src/settings.rs index 395387ebd6..8a72a5459a 100644 --- a/backend/windmill-api/src/settings.rs +++ b/backend/windmill-api/src/settings.rs @@ -24,9 +24,9 @@ use axum::{ #[cfg(feature = "enterprise")] use axum::extract::Query; +use serde::Deserialize; #[cfg(feature = "enterprise")] use windmill_common::ee::{send_critical_alert, CriticalAlertKind, CriticalErrorChannel}; -use serde::Deserialize; use windmill_common::{ error::{self, JsonResult, Result}, global_settings::{ @@ -298,7 +298,13 @@ async fn list_global_settings() -> JsonResult { pub async fn send_stats(Extension(db): Extension, authed: ApiAuthed) -> Result { require_super_admin(&db, &authed.email).await?; - windmill_common::stats_ee::send_stats(&"manual".to_string(), &HTTP_CLIENT, &db).await?; + windmill_common::stats_ee::send_stats( + &HTTP_CLIENT, + &db, + true, + windmill_common::stats_ee::SendStatsReason::Manual, + ) + .await?; Ok("Sent stats".to_string()) } @@ -357,8 +363,13 @@ pub async fn renew_license_key( authed: ApiAuthed, ) -> Result { require_super_admin(&db, &authed.email).await?; - windmill_common::stats_ee::send_stats(&"manual".to_string(), &HTTP_CLIENT, &db).await?; - let result = windmill_common::ee::renew_license_key(&HTTP_CLIENT, &db, license_key, true).await; + let result = windmill_common::ee::renew_license_key( + &HTTP_CLIENT, + &db, + license_key, + windmill_common::ee::RenewReason::Manual, + ) + .await; if result != "success" { return Err(error::Error::BadRequest(format!( diff --git a/backend/windmill-common/Cargo.toml b/backend/windmill-common/Cargo.toml index 09acf22157..546c339575 100644 --- a/backend/windmill-common/Cargo.toml +++ b/backend/windmill-common/Cargo.toml @@ -56,6 +56,7 @@ mail-send.workspace = true futures-core.workspace = true async-stream.workspace = true const_format.workspace = true +crc.workspace = true [target.'cfg(not(target_env = "msvc"))'.dependencies] tikv-jemalloc-ctl = { optional = true, workspace = true } diff --git a/backend/windmill-common/src/ee.rs b/backend/windmill-common/src/ee.rs index 2f32756e45..d2b215a5ad 100644 --- a/backend/windmill-common/src/ee.rs +++ b/backend/windmill-common/src/ee.rs @@ -52,12 +52,19 @@ pub async fn schedule_key_renewal(_http_client: &reqwest::Client, _db: &crate::d // Implementation is not open source } +#[cfg(feature = "enterprise")] +pub enum RenewReason { + Manual, + Schedule, + OnStart, +} + #[cfg(feature = "enterprise")] pub async fn renew_license_key( _http_client: &reqwest::Client, _db: &crate::db::DB, _key: Option, - _manual: bool, + _reason: RenewReason, ) -> String { // Implementation is not open source "".to_string() diff --git a/backend/windmill-common/src/lib.rs b/backend/windmill-common/src/lib.rs index cd8059251e..0f25e12e46 100644 --- a/backend/windmill-common/src/lib.rs +++ b/backend/windmill-common/src/lib.rs @@ -95,6 +95,8 @@ lazy_static::lazy_static! { pub static ref JOB_RETENTION_SECS: Arc> = Arc::new(RwLock::new(0)); + pub static ref INSTANCE_NAME: String = rd_string(5); + } pub async fn shutdown_signal( @@ -141,6 +143,7 @@ pub async fn shutdown_signal( use tokio::sync::RwLock; #[cfg(feature = "prometheus")] use tokio::task::JoinHandle; +use utils::rd_string; #[cfg(feature = "prometheus")] pub async fn serve_metrics( diff --git a/backend/windmill-common/src/stats_ee.rs b/backend/windmill-common/src/stats_ee.rs index 48845d5f51..c6dc9946bf 100644 --- a/backend/windmill-common/src/stats_ee.rs +++ b/backend/windmill-common/src/stats_ee.rs @@ -8,11 +8,7 @@ pub async fn get_disable_stats_setting(_db: &DB) -> bool { false } -pub async fn schedule_stats( - _instance_name: String, - _db: &DB, - _http_client: &reqwest::Client, -) -> () { +pub async fn schedule_stats(_db: &DB, _http_client: &reqwest::Client) -> () { // stats details are closed source } @@ -23,10 +19,17 @@ struct JobsUsage { count: i64, } +pub enum SendStatsReason { + Manual, + Schedule, + OnStart, +} + pub async fn send_stats( - _instance_name: &String, _http_client: &reqwest::Client, _db: &DB, + _skip_job_usage: bool, + _reason: SendStatsReason, ) -> Result<()> { // stats details are closed source Ok(()) diff --git a/backend/windmill-common/src/utils.rs b/backend/windmill-common/src/utils.rs index 8676878352..d5f9c5c099 100644 --- a/backend/windmill-common/src/utils.rs +++ b/backend/windmill-common/src/utils.rs @@ -189,7 +189,7 @@ pub fn calculate_hash(s: &str) -> String { format!("{:x}", hasher.finalize()) } -pub async fn get_uid(db: &DB) -> Result { +pub async fn get_uid<'c, E: sqlx::Executor<'c, Database = Postgres>>(db: E) -> Result { let mut uid = LICENSE_KEY_ID.read().await.clone(); if uid == "" { @@ -228,6 +228,13 @@ impl std::fmt::Display for Mode { } } +// inspired from rails: https://github.com/rails/rails/blob/6e49cc77ab3d16c06e12f93158eaf3e507d4120e/activerecord/lib/active_record/migration.rb#L1308 +pub fn generate_lock_id(database_name: &str) -> i64 { + const CRC_IEEE: crc::Crc = crc::Crc::::new(&crc::CRC_32_ISO_HDLC); + // 0x3d32ad9e chosen by fair dice roll + 0x3d32ad9e * (CRC_IEEE.checksum(database_name.as_bytes()) as i64) +} + pub async fn send_email( subject: &str, content: &str, diff --git a/backend/windmill-queue/src/jobs.rs b/backend/windmill-queue/src/jobs.rs index eca874aa63..8989e9ce9d 100644 --- a/backend/windmill-queue/src/jobs.rs +++ b/backend/windmill-queue/src/jobs.rs @@ -482,6 +482,7 @@ where } } +#[cfg(feature = "enterprise")] #[derive(Deserialize)] struct RawFlowFailureModule { #[cfg(feature = "enterprise")]