fix(uploads): reset queueForEvents on idempotent chunked-upload retry

The early-return branches added in #12138 for already-complete chunked
uploads bypass the trailing $queueForEvents->setParam('bucketId', ...)
calls. The action returns cleanly, the shutdown hook then calls
Event::generateEvents with empty params, throws \InvalidArgumentException,
and the error handler maps it to HTTP 500.

Reset the queue on each early-return path so the shutdown short-circuits
on the empty event string -- the resource was created on a previous
request and that request already fired the event; replaying it would
double-trigger webhooks/functions.

Applied to Storage Files Create, Functions Deployments Create, and
Sites Deployments Create -- all three endpoints share the same pattern
introduced by #12138.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
Damodar Lohani
2026-05-25 06:36:25 +00:00
co-authored by Claude Opus 4.7
parent 03555fa365
commit d6ca57d008
3 changed files with 9 additions and 0 deletions
@@ -227,6 +227,7 @@ class Create extends Action
}
if ($completed) {
$queueForEvents->reset();
return;
}
@@ -249,6 +250,8 @@ class Create extends Action
$metadata = \array_merge($deployment->getAttribute('sourceMetadata', []), $metadata);
if ($uploaded === $chunks) {
$queueForEvents->reset();
$response
->setStatusCode(Response::STATUS_CODE_ACCEPTED)
->dynamic($deployment, Response::MODEL_DEPLOYMENT);
@@ -227,6 +227,7 @@ class Create extends Action
}
if ($completed) {
$queueForEvents->reset();
return;
}
@@ -257,6 +258,8 @@ class Create extends Action
$metadata = \array_merge($deployment->getAttribute('sourceMetadata', []), $metadata);
if ($uploaded === $chunks) {
$queueForEvents->reset();
$response
->setStatusCode(Response::STATUS_CODE_ACCEPTED)
->dynamic($deployment, Response::MODEL_DEPLOYMENT);
@@ -320,6 +320,7 @@ class Create extends Action
}
if ($completed) {
$queueForEvents->reset();
return;
}
@@ -337,6 +338,8 @@ class Create extends Action
throw new Exception(Exception::STORAGE_FILE_ALREADY_EXISTS);
}
$queueForEvents->reset();
$response
->setStatusCode(Response::STATUS_CODE_OK)
->dynamic($file, Response::MODEL_FILE);