fix: key a cached workflow-as-code task on its step key, not its name

This commit is contained in:
Ruben Fiszel
2026-09-15 17:33:38 +02:00
parent 93bedbb640
commit e8397ecded
4 changed files with 15 additions and 17 deletions
+1 -1
View File
@@ -66,7 +66,7 @@ const double = task(async (n: number) => {
}, { cache_ttl: 60 });
export const main = workflow(async (n: number) => {
const r = await step("pick", async () => Math.random());
const r = await step("pick", async () => Math.floor(Math.random() * 1e9));
const d = await double(r);
return { fresh: d === r * 2 };
});'
+3 -5
View File
@@ -40,11 +40,9 @@ pub struct WacCheckpoint {
#[serde(skip_serializing_if = "Option::is_none")]
#[serde(default)]
pub _executing_key: Option<String>,
/// With `_executing_key`: the task the child runs and the arguments it was
/// called with, the identity its cached result is keyed on.
#[serde(skip_serializing_if = "Option::is_none")]
#[serde(default)]
pub _executing_task: Option<String>,
/// With `_executing_key`: the arguments the task was called with. A cached
/// result is keyed on both; the key alone is a name and a position, which two
/// tasks can share, and the arguments alone say nothing about which task ran.
#[serde(skip_serializing_if = "Option::is_none")]
#[serde(default)]
pub _executing_args: Option<serde_json::Map<String, Value>>,
@@ -3237,7 +3237,6 @@ pub async fn handle_wac_v2_output(
let child_checkpoint_json = serde_json::json!({
"completed_steps": &checkpoint.completed_steps,
"_executing_key": &step.key,
"_executing_task": &step.name,
"_executing_args": &step.args,
});
sqlx::query(
+11 -10
View File
@@ -1575,15 +1575,16 @@ pub async fn cached_result_path(
}
}
// A workflow-as-code task child carries its parent's arguments, which say
// nothing about the task's own inputs; its result is keyed on the task it
// runs and the arguments that task was called with.
let (task, args) = match wac_task_identity(db, job).await? {
Some((task, args)) => (Some(task), Some(Json(args))),
// nothing about the task's own inputs; its result is keyed on the step it
// runs (a task's name and position, which is what tells two tasks of one
// name apart) and the arguments that task was called with.
let (step, args) = match wac_task_identity(db, job).await? {
Some((step, args)) => (Some(step), Some(Json(args))),
None => (None, job.args.clone()),
};
if let Some(task) = task {
hasher.update(b"wac_task:");
hasher.update(task.as_bytes());
if let Some(step) = step {
hasher.update(b"wac_step:");
hasher.update(step.as_bytes());
}
hash_args(
db,
@@ -1598,7 +1599,7 @@ pub async fn cached_result_path(
Ok(format!("g/results/{:064x}", hasher.finalize()))
}
/// The task name and call arguments a workflow-as-code parent seeded in this
/// The step key and call arguments a workflow-as-code parent seeded in this
/// child's checkpoint at push time; `None` for any job that is not such a child.
async fn wac_task_identity(
db: &DB,
@@ -1609,7 +1610,7 @@ async fn wac_task_identity(
}
let identity: Option<(Option<String>, Option<Json<HashMap<String, Box<RawValue>>>>)> =
sqlx::query_as(
"SELECT workflow_as_code_status->'_checkpoint'->>'_executing_task', \
"SELECT workflow_as_code_status->'_checkpoint'->>'_executing_key', \
workflow_as_code_status->'_checkpoint'->'_executing_args' \
FROM v2_job_status WHERE id = $1",
)
@@ -1617,7 +1618,7 @@ async fn wac_task_identity(
.fetch_optional(db)
.await?;
Ok(match identity {
Some((Some(task), Some(Json(args)))) => Some((task, args)),
Some((Some(step), Some(Json(args)))) => Some((step, args)),
_ => None,
})
}