mirror of
https://github.com/windmill-labs/windmill.git
synced 2026-08-21 08:02:26 +00:00
test: de-flake asset-dispatch by bypassing cross-DB script-hash caches (#9820)
Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -54,6 +54,14 @@ async fn seed_script(
|
||||
.bind(language)
|
||||
.execute(db)
|
||||
.await?;
|
||||
// These tests use #[sqlx::test] isolated DBs that share one workspace id and
|
||||
// reuse script paths, while the same path is seeded with different content
|
||||
// (hence different hashes) across tests. The process-global deployed-script
|
||||
// caches are keyed by (workspace, path)/(workspace, hash), so a concurrent
|
||||
// test resolves a path to a hash that lives in another test's DB and the
|
||||
// dispatch 404s. Disable them so every resolution reads the test's own DB.
|
||||
windmill_common::DEPLOYED_SCRIPT_CACHE_DISABLED
|
||||
.store(true, std::sync::atomic::Ordering::Relaxed);
|
||||
Ok(h)
|
||||
}
|
||||
|
||||
|
||||
@@ -285,6 +285,16 @@ lazy_static::lazy_static! {
|
||||
|
||||
const LATEST_VERSION_ID_CACHE_TTL: std::time::Duration = std::time::Duration::from_secs(60);
|
||||
|
||||
/// Test hook: disables the process-global deployed-script hash/info caches so
|
||||
/// every resolution reads the current DB. Integration tests use `#[sqlx::test]`
|
||||
/// isolated DBs that share one workspace id and reuse script paths, so a cache
|
||||
/// keyed by `(workspace, path)`/`(workspace, hash)` resolves a path to a hash
|
||||
/// that lives in a *different* test's DB — and when the info cache misses for
|
||||
/// that foreign hash the lookup 404s in the wrong DB. Always `false` in
|
||||
/// production (the caches are TTL/LRU-bounded against real deploys).
|
||||
pub static DEPLOYED_SCRIPT_CACHE_DISABLED: std::sync::atomic::AtomicBool =
|
||||
std::sync::atomic::AtomicBool::new(false);
|
||||
|
||||
pub async fn shutdown_signal(
|
||||
tx: KillpillSender,
|
||||
mut rx: tokio::sync::broadcast::Receiver<()>,
|
||||
@@ -1305,8 +1315,12 @@ pub fn get_latest_deployed_hash_for_path<'e>(
|
||||
) -> impl Future<Output = error::Result<ScriptHashInfo<ScriptRunnableSettingsHandle>>> + Send + 'e {
|
||||
async move {
|
||||
let cache_key = (w_id.to_string(), script_path.to_string());
|
||||
let use_cache = !DEPLOYED_SCRIPT_CACHE_DISABLED.load(std::sync::atomic::Ordering::Relaxed);
|
||||
let mut computed_hash = None;
|
||||
let hash = match DEPLOYED_SCRIPT_HASH_CACHE.get(&cache_key) {
|
||||
let hash = match DEPLOYED_SCRIPT_HASH_CACHE
|
||||
.get(&cache_key)
|
||||
.filter(|_| use_cache)
|
||||
{
|
||||
Some(cached_hash)
|
||||
if cached_hash.expires_at > std::time::Instant::now()
|
||||
&& db.as_ref().is_none_or(|x| {
|
||||
@@ -1349,13 +1363,15 @@ pub fn get_latest_deployed_hash_for_path<'e>(
|
||||
};
|
||||
|
||||
let hash = utils::not_found_if_none(hash, "script", script_path)?;
|
||||
DEPLOYED_SCRIPT_HASH_CACHE.insert(
|
||||
cache_key,
|
||||
ExpiringLatestVersionId {
|
||||
id: hash,
|
||||
expires_at: std::time::Instant::now() + LATEST_VERSION_ID_CACHE_TTL,
|
||||
},
|
||||
);
|
||||
if use_cache {
|
||||
DEPLOYED_SCRIPT_HASH_CACHE.insert(
|
||||
cache_key,
|
||||
ExpiringLatestVersionId {
|
||||
id: hash,
|
||||
expires_at: std::time::Instant::now() + LATEST_VERSION_ID_CACHE_TTL,
|
||||
},
|
||||
);
|
||||
}
|
||||
|
||||
hash
|
||||
}
|
||||
@@ -1387,9 +1403,10 @@ pub async fn get_script_info_for_hash<'e, E: sqlx::PgExecutor<'e>>(
|
||||
hash: i64,
|
||||
) -> error::Result<ScriptHashInfo<ScriptRunnableSettingsHandle>> {
|
||||
let key = (w_id.to_string(), hash);
|
||||
let use_cache = !DEPLOYED_SCRIPT_CACHE_DISABLED.load(std::sync::atomic::Ordering::Relaxed);
|
||||
|
||||
let mut computed_hash = None;
|
||||
match DEPLOYED_SCRIPT_INFO_CACHE.get(&key) {
|
||||
match DEPLOYED_SCRIPT_INFO_CACHE.get(&key).filter(|_| use_cache) {
|
||||
Some(info)
|
||||
if db_authed.as_ref().is_none_or(|x| {
|
||||
let r = HASH_PERMS_CACHE.check_perms_in_cache(x.authed, scripts::ScriptHash(hash));
|
||||
@@ -1418,7 +1435,9 @@ pub async fn get_script_info_for_hash<'e, E: sqlx::PgExecutor<'e>>(
|
||||
|
||||
let info = utils::not_found_if_none(info, "script", &hash.to_string())?;
|
||||
|
||||
DEPLOYED_SCRIPT_INFO_CACHE.insert(key, info.clone());
|
||||
if use_cache {
|
||||
DEPLOYED_SCRIPT_INFO_CACHE.insert(key, info.clone());
|
||||
}
|
||||
|
||||
Ok(info)
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user