mirror of
https://github.com/windmill-labs/windmill.git
synced 2026-10-03 08:02:19 +00:00
fix: stop running deleted script versions from worker caches (#11456)
* fix: stop running deleted script versions from worker caches Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> * refactor: reuse script cache invalidate and test the deletion notify payload Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> * fix: keep a deleted copy from shadowing the same hash in another workspace Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> * fix: drop deletions missed while down and fills racing the eviction Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> * fix: batch deletion events, evict path caches and cover version pruning Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> * fix: evict the raw-import cache on both passes and split large deletion events Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> --------- Co-authored-by: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Opus 5.5
parent
840567fbe5
commit
d2830cb4a0
@@ -17,7 +17,7 @@ use windmill_common::{
|
||||
utils::{BulkDeleteRequest, WithStarredInfoQuery, HTTP_CLIENT},
|
||||
webhook::{WebhookMessage, WebhookShared},
|
||||
workspaces::{check_deploy_rules, RuleCheckResult},
|
||||
DB,
|
||||
DeletedScriptVersions, DB,
|
||||
};
|
||||
use windmill_queue::schedule::clear_schedule;
|
||||
|
||||
@@ -818,6 +818,16 @@ fn invalidate_script_path_caches(w_id: &str, script_path: &str) {
|
||||
RAW_SCRIPT_LATEST_HASH_CACHE.remove(&format!("{w_id}:{script_path}"));
|
||||
}
|
||||
|
||||
/// [`DeletedScriptVersions::evict`], plus this crate's own path -> hash cache. Run by the
|
||||
/// deleting process after its commit and by every process on the deletion event.
|
||||
pub fn evict_deleted_script_versions(deleted: DeletedScriptVersions) {
|
||||
deleted.evict_with(|deleted| {
|
||||
for path in &deleted.paths {
|
||||
RAW_SCRIPT_LATEST_HASH_CACHE.remove(&format!("{}:{path}", deleted.workspace_id));
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
/// What a script deploy still has to do once its transaction has committed.
|
||||
enum PostCommitDeploy {
|
||||
/// Everything, for a deploy with no dependency job to hand it to.
|
||||
@@ -4161,6 +4171,8 @@ async fn delete_script_by_hash(
|
||||
// the script was never a pipeline member.
|
||||
clear_script_triggers(&mut *tx, &w_id, &script.path, AssetUsageKind::Script).await?;
|
||||
clear_macro_registry(&mut *tx, &w_id, &script.path).await?;
|
||||
let deleted = DeletedScriptVersions::new(&w_id, [(script.path.clone(), hash.0)]);
|
||||
deleted.notify(&mut *tx).await?;
|
||||
|
||||
audit_log(
|
||||
&mut *tx,
|
||||
@@ -4173,6 +4185,7 @@ async fn delete_script_by_hash(
|
||||
)
|
||||
.await?;
|
||||
tx.commit().await?;
|
||||
evict_deleted_script_versions(deleted);
|
||||
|
||||
webhook.send_message(
|
||||
w_id.clone(),
|
||||
@@ -4240,14 +4253,24 @@ async fn delete_script_by_path(
|
||||
.fetch_all(&mut *tx)
|
||||
.await?;
|
||||
|
||||
let script = sqlx::query_scalar!(
|
||||
"DELETE FROM script WHERE path = $1 AND workspace_id = $2 RETURNING path",
|
||||
let deleted_hashes = sqlx::query_scalar!(
|
||||
"DELETE FROM script WHERE path = $1 AND workspace_id = $2 RETURNING hash",
|
||||
path,
|
||||
w_id
|
||||
)
|
||||
.fetch_one(&mut *tx)
|
||||
.fetch_all(&mut *tx)
|
||||
.await
|
||||
.map_err(|e| Error::internal_err(format!("deleting script by path {w_id}: {e:#}")))?;
|
||||
if deleted_hashes.is_empty() {
|
||||
return Err(Error::NotFound(format!(
|
||||
"script {path} not found in {w_id}"
|
||||
)));
|
||||
}
|
||||
let script = path.to_string();
|
||||
let deleted = DeletedScriptVersions::new(
|
||||
&w_id,
|
||||
deleted_hashes.into_iter().map(|h| (script.clone(), h)),
|
||||
);
|
||||
|
||||
// After the DELETE, never before: every dbt writer locks the `script` row
|
||||
// first, so taking a sidecar ahead of it deadlocks one of the pair. The
|
||||
@@ -4287,6 +4310,7 @@ async fn delete_script_by_path(
|
||||
// the script was never a pipeline member.
|
||||
clear_script_triggers(&mut *tx, &w_id, path, AssetUsageKind::Script).await?;
|
||||
clear_macro_registry(&mut *tx, &w_id, path).await?;
|
||||
deleted.notify(&mut *tx).await?;
|
||||
|
||||
if !query.keep_captures.unwrap_or(false) {
|
||||
sqlx::query!(
|
||||
@@ -4317,6 +4341,7 @@ async fn delete_script_by_path(
|
||||
)
|
||||
.await?;
|
||||
tx.commit().await?;
|
||||
evict_deleted_script_versions(deleted);
|
||||
|
||||
handle_deployment_metadata(
|
||||
&authed.email,
|
||||
@@ -4412,14 +4437,21 @@ async fn delete_scripts_bulk(
|
||||
}
|
||||
}
|
||||
|
||||
let mut deleted_paths = sqlx::query_scalar!(
|
||||
"DELETE FROM script WHERE workspace_id = $1 AND path = ANY($2) RETURNING path",
|
||||
w_id,
|
||||
&request.paths
|
||||
)
|
||||
.fetch_all(&mut *tx)
|
||||
.await
|
||||
.map_err(|e| Error::internal_err(format!("deleting scripts in bulk {w_id}: {e:#}")))?;
|
||||
let deleted = DeletedScriptVersions::new(
|
||||
&w_id,
|
||||
sqlx::query!(
|
||||
"DELETE FROM script WHERE workspace_id = $1 AND path = ANY($2) RETURNING path, hash",
|
||||
w_id,
|
||||
&request.paths
|
||||
)
|
||||
.fetch_all(&mut *tx)
|
||||
.await
|
||||
.map_err(|e| Error::internal_err(format!("deleting scripts in bulk {w_id}: {e:#}")))?
|
||||
.into_iter()
|
||||
.map(|r| (r.path, r.hash)),
|
||||
);
|
||||
deleted.notify(&mut *tx).await?;
|
||||
let deleted_paths = deleted.paths.clone();
|
||||
|
||||
// Same reason as the single-path delete, over every requested path rather
|
||||
// than the deleted ones: a path that had no script left can still hold state.
|
||||
@@ -4428,10 +4460,6 @@ async fn delete_scripts_bulk(
|
||||
windmill_common::dbt_manifest::clear_dbt_editor_graphs(&mut tx, &w_id, p).await?;
|
||||
}
|
||||
|
||||
// remove duplicates from deleted_paths
|
||||
deleted_paths.sort();
|
||||
deleted_paths.dedup();
|
||||
|
||||
sqlx::query!(
|
||||
"DELETE FROM draft WHERE workspace_id = $1 AND path = ANY($2) AND typ = 'script'",
|
||||
w_id,
|
||||
@@ -4472,6 +4500,7 @@ async fn delete_scripts_bulk(
|
||||
.await?;
|
||||
|
||||
tx.commit().await?;
|
||||
evict_deleted_script_versions(deleted);
|
||||
|
||||
try_join_all(deleted_paths.iter().map(|path| {
|
||||
handle_deployment_metadata(
|
||||
|
||||
Reference in New Issue
Block a user