fix(functions): commit a deployment's ready status with its activation by HarshMN2345 · Pull Request #14525 · appwrite/appwrite · GitHub
Skip to content

fix(functions): commit a deployment's ready status with its activation - #14525

Open
HarshMN2345 wants to merge 1 commit into
mainfrom
fix-redeploy-build-not-ready
Open

HarshMN2345 wants to merge 1 commit into
mainfrom
fix-redeploy-build-not-ready

Conversation

@HarshMN2345

Copy link
Copy Markdown
Member

What does this PR do?

During a redeploy with activate=true, the builds worker pointed the function at the new deployment and only then marked it ready (the order #13741 introduced). Executions in between got build_not_ready. Jobs::finalize() now writes the terminal status and runs activate() in one dbForProject transaction, so the resource's deploymentId and ready become visible together. A deployment reported ready is still the one executions reach, so the #13741 guarantee holds. A build canceled before that write is no longer activated.

Rules live in the platform database and cannot join that transaction, so they are still repointed before the commit. This keeps the guarantee that a site's deploymentId implies its domain serves that deployment. To close the router window for sites and function domains, a manual rule whose deployment is not ready yet now serves the resource's active deployment if that one is ready.

Test Plan

  • php -l and vendor/bin/pint --test on both changed files.
  • PHPStan not run: the local vendor is older than the locked utopia-php/database 8.1.4.
  • E2E left to CI.

Closes #14421

Related: #13741

The builds worker pointed the resource at a new deployment and only then
marked it ready, so executions during a redeploy hit build_not_ready for
the deployment that was still building. Write the status and the
resource's deploymentId in one project-database transaction, keeping the
guarantee that a deployment reported ready is the one executions reach.

Manual rules live in the platform database and are still repointed
before that commit, so the router serves the resource's active
deployment while a manual rule's deployment is not ready yet.
@tenki-reviewer

tenki-reviewer Bot commented Oct 15, 2026 •

Copy link
Copy Markdown

@tenki-reviewer tenki-reviewer Bot left a comment •

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This PR makes deployment finalization atomic by committing the deployment status and the resource deploymentId pointer together inside a transaction, and adds a router fallback that keeps serving the previous ready deployment while platform rules catch up.

Key findings

  • 🟡 Rule repoint and bus events escape the transaction — Jobs.php:751

Comment on lines +751 to +762
$applied = $dbForProject->withTransaction(function () use ($dbForProject, $dbForPlatform, $project, $resource, $deployment, $bus, $success, $terminal): int {
$applied = $dbForProject->updateDocuments('deployments', new Document(['status' => $terminal]), [
Query::equal('$id', [$deployment->getId()]),
Query::notEqual('status', 'canceled'),
]);

if ($applied > 0 && $success && $deployment->getAttribute('activate') === true && ! $resource->isEmpty()) {
$this->activate($dbForProject, $dbForPlatform, $project, $resource, $deployment, $bus);
}

return $applied;
});

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🟡 bug · medium

Rule repoint and bus events escape the transaction

activate() inside the withTransaction closure writes manual-rule pointers to the platform database and dispatches RuleUpdated events, neither of which the transaction on dbForProject covers (src/Appwrite/Platform/Modules/Functions/Workers/Jobs.php:751-762). If the transaction rolls back after activate() has run, the platform rules stay repointed at a deployment whose status update never committed, while the resource's deploymentId reverts to the previous deployment; on a first-ever activation there is no previous ready deployment for the router fallback to serve, so the custom domain routes to a still-building deployment. Consumers of the dispatched RuleUpdated events likewise act on an activation that was rolled back.

📋 Prompt for AI Agents

In src/Appwrite/Platform/Modules/Functions/Workers/Jobs.php around lines 750-762 (finalize), the withTransaction closure calls activate(), which writes rules via $dbForPlatform and dispatches RuleUpdated bus events — side effects the $dbForProject transaction cannot roll back. Restructure so the closure only commits the project-DB writes (deployment status plus the resource's deploymentId/live fields from activate), and run the platform-rule repointing and bus dispatch after the transaction returns successfully, with an explicit error path if they fail.

@github-actions

Copy link
Copy Markdown

Security rules

No new WARNING or ERROR findings from security rules.

19 existing findings tracked in .semgrep/baseline.json
  • php.appwrite.guest-write-without-abuse-limit (12)
  • php.appwrite.secret-compare-timing (5)
  • php.appwrite.weak-secret-env-default (2)

Posted by Checks / Rules. Re-runs update this comment in place. Rule details and baseline: .semgrep/README.md.

@hansi-codes

hansi-codes Bot commented Oct 15, 2026

Copy link
Copy Markdown
Contributor

🔵 Tier A · Mergeable after minor fixes

The implementation is plausible, but the central handover behavior still needs regression coverage.

Deployment finalization now commits the terminal status and active resource pointer together. The router falls back to the resource’s ready deployment while a manual rule points to a deployment that is not ready yet.

Verdict New comments Fixed Still open
✅ Approved 1 0 0
Finding Where
🟡 Add coverage for the deployment handover src/Appwrite/Platform/Modules/Functions/Workers/Jobs.php:751
Fix with agent prompt
### Issue 1
src/Appwrite/Platform/Modules/Functions/Workers/Jobs.php:751
**Add coverage for the deployment handover**

This transaction is the core guarantee that a redeploy cannot expose a building deployment to executions, but the existing worker tests only cover rule activation and the deployment e2e tests do not exercise requests during a handover. Please add regression coverage with an existing ready deployment and verify that executions or routed requests keep using it until the new deployment becomes ready.

---

For each issue above, determine whether it is valid and should be fixed. If so, fix it directly.
📂 Walkthrough · 2
File Change
app/controllers/general.php Uses the resource’s ready deployment for manual routes during a deployment handover.
src/Appwrite/Platform/Modules/Functions/Workers/Jobs.php Wraps terminal status updates and activation in a project database transaction.

Reviewed f8e8379 · Details · Comment @hansi-codes review to re-run, or mention @hansi-codes with a question.

@hansi-codes hansi-codes Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🔵 Tier A · Looks good to merge. Summary

Query::equal('$id', [$deployment->getId()]),
Query::notEqual('status', 'canceled'),
]);
$applied = $dbForProject->withTransaction(function () use ($dbForProject, $dbForPlatform, $project, $resource, $deployment, $bus, $success, $terminal): int {

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Add coverage for the deployment handover

This transaction is the core guarantee that a redeploy cannot expose a building deployment to executions, but the existing worker tests only cover rule activation and the deployment e2e tests do not exercise requests during a handover. Please add regression coverage with an existing ready deployment and verify that executions or routed requests keep using it until the new deployment becomes ready.

Prompt To Fix With AI
This is a comment left during a code review.
Path: src/Appwrite/Platform/Modules/Functions/Workers/Jobs.php
Line: 751

Comment:
**Add coverage for the deployment handover**

This transaction is the core guarantee that a redeploy cannot expose a building deployment to executions, but the existing worker tests only cover rule activation and the deployment e2e tests do not exercise requests during a handover. Please add regression coverage with an existing ready deployment and verify that executions or routed requests keep using it until the new deployment becomes ready.

---

For each issue above, determine whether it is valid and should be fixed. If so, fix it directly.

🟡 Minor · testing · Reply if this doesn't apply.

@github-actions

Copy link
Copy Markdown

✨ Benchmark results

Comparing main (before) → fix-redeploy-build-not-ready (after).

Metric Before After Change
🚀 Requests/sec 200.41 220.41 🟢 +10%
⏱️ Latency P50 86.16 ms 79.38 ms 🟢 -7.9%
⏱️ Latency P95 200.37 ms 181.24 ms 🟢 -9.5%
Per-scenario breakdown & investigation details

Metrics below reflect the current branch (after). Δ P95 compares against the base.

Scenario P50 (ms) P95 (ms) Requests RPS Δ P95 (ms)
API total 79.38 181.24 13,680 220.41 -19.14
Account 151.94 281.89 720 12.39 -35.6
TablesDB 77.63 146.21 7,440 123.18 -20.07
Storage 70.67 160.86 3,600 60.99 -15.01
Functions 110.43 207.61 1,920 33.27 -33.45

Top API waits (after)

API request Max wait (ms)
account.name.update 491.66
functions.delete 397.54
tablesdb.rows.create 370.91
functions.create 349.65
account.prefs.update 347.29

This branch has not been deployed

No deployments
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

🐛 Bug Report: Redeploy briefly returns build_not_ready (HTTP 400)

1 participant