Skip to content

fix: health db queues#10482

Merged
loks0n merged 1 commit into1.8.xfrom
fix-db-queues
Sep 12, 2025
Merged

fix: health db queues#10482
loks0n merged 1 commit into1.8.xfrom
fix-db-queues

Conversation

@loks0n
Copy link
Copy Markdown
Member

@loks0n loks0n commented Sep 12, 2025

No description provided.

@loks0n loks0n requested a review from abnegate September 12, 2025 09:08
@coderabbitai
Copy link
Copy Markdown
Contributor

coderabbitai bot commented Sep 12, 2025

📝 Walkthrough

Walkthrough

  • app/controllers/api/health.php: The v1 health database queue endpoint now selects the queue by name via setQueue($name) before calling getSize(), changing the specific queue measured for the threshold check; error handling and response paths are unchanged.
  • src/Appwrite/Event/Database.php: Replaces the public getQueue(): string method with setProject(Document $project): self. The method now reads the database attribute from the provided Document, builds a DSN (with fallback), sets the queue host from the DSN, and returns parent::setProject($project).

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~20 minutes

Possibly related PRs

Suggested reviewers

  • abnegate
  • ChiragAgg5k

Pre-merge checks (1 passed, 1 warning, 1 inconclusive)

❌ Failed checks (1 warning, 1 inconclusive)
Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 50.00% which is insufficient. The required threshold is 80.00%. You can run @coderabbitai generate docstrings to improve docstring coverage.
Description Check ❓ Inconclusive No pull request description was included in the provided context, so I cannot determine whether the description relates to the changeset. Please provide the PR description or paste its contents; the description should briefly state the change (e.g., health endpoint now selects DB queue by name before measuring size) and any impact so this check can be re-evaluated.
✅ Passed checks (1 passed)
Check name Status Explanation
Title Check ✅ Passed The title "fix: health db queues" is concise and directly related to the primary change in the diff (fixing how the health endpoint measures database queue sizes), so it communicates the main intent and is scan-friendly for history/review.

Tip

👮 Agentic pre-merge checks are now available in preview!

Pro plan users can now enable pre-merge checks in their settings to enforce checklists before merging PRs.

  • Built-in checks – Quickly apply ready-made checks to enforce title conventions, require pull request descriptions that follow templates, validate linked issues for compliance, and more.
  • Custom agentic checks – Define your own rules using CodeRabbit’s advanced agentic capabilities to enforce organization-specific policies and workflows. For example, you can instruct CodeRabbit’s agent to verify that API documentation is updated whenever API schema files are modified in a PR. Note: Upto 5 custom checks are currently allowed during the preview period. Pricing for this feature will be announced in a few weeks.

Please see the documentation for more information.

Example:

reviews:
  pre_merge_checks:
    custom_checks:
      - name: "Undocumented Breaking Changes"
        mode: "warning"
        instructions: |
          Pass/fail criteria: All breaking changes to public APIs, CLI flags, environment variables, configuration keys, database schemas, or HTTP/GraphQL endpoints must be documented in the "Breaking Change" section of the PR description and in CHANGELOG.md. Exclude purely internal or private changes (e.g., code not exported from package entry points or explicitly marked as internal).

Please share your feedback with us on this Discord post.


📜 Recent review details

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 06a9daf and 39a190f.

📒 Files selected for processing (2)
  • app/controllers/api/health.php (1 hunks)
  • src/Appwrite/Event/Database.php (1 hunks)
🚧 Files skipped from review as they are similar to previous changes (1)
  • app/controllers/api/health.php
🧰 Additional context used
🧬 Code graph analysis (1)
src/Appwrite/Event/Database.php (1)
src/Appwrite/Event/Event.php (1)
  • setProject (140-144)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (19)
  • GitHub Check: E2E Service Test (Migrations)
  • GitHub Check: E2E Service Test (Teams)
  • GitHub Check: E2E Service Test (Storage)
  • GitHub Check: E2E Service Test (Tokens)
  • GitHub Check: E2E Service Test (Realtime)
  • GitHub Check: E2E Service Test (Locale)
  • GitHub Check: E2E Service Test (Proxy)
  • GitHub Check: E2E Service Test (Functions)
  • GitHub Check: E2E Service Test (Projects)
  • GitHub Check: E2E Service Test (Databases/TablesDB)
  • GitHub Check: E2E Service Test (Health)
  • GitHub Check: E2E Service Test (Console)
  • GitHub Check: E2E Service Test (Databases/Legacy)
  • GitHub Check: E2E Service Test (Avatars)
  • GitHub Check: E2E Service Test (Site Screenshots)
  • GitHub Check: E2E Service Test (Dev Keys)
  • GitHub Check: E2E General Test
  • GitHub Check: Unit Test
  • GitHub Check: scan
✨ Finishing touches
  • 📝 Generate Docstrings
🧪 Generate unit tests
  • Create PR with unit tests
  • Post copyable unit tests in a comment
  • Commit unit tests in branch fix-db-queues

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

@loks0n loks0n changed the title fix: db queues fix: health db queues Sep 12, 2025
@github-actions
Copy link
Copy Markdown

github-actions bot commented Sep 12, 2025

Security Scan Results for PR

Docker Image Scan Results

Package Version Vulnerability Severity
golang.org/x/crypto v0.31.0 CVE-2025-22869 HIGH
golang.org/x/oauth2 v0.24.0 CVE-2025-22868 HIGH
stdlib 1.22.10 CVE-2025-47907 HIGH

Source Code Scan Results

🎉 No vulnerabilities found!

Copy link
Copy Markdown
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 1

📜 Review details

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 918912c and 0ee77e8.

📒 Files selected for processing (2)
  • app/controllers/api/health.php (1 hunks)
  • src/Appwrite/Event/Database.php (1 hunks)
🧰 Additional context used
🧬 Code graph analysis (2)
app/controllers/api/health.php (1)
src/Appwrite/Event/Event.php (2)
  • setQueue (95-100)
  • getSize (648-652)
src/Appwrite/Event/Database.php (2)
src/Appwrite/Event/Event.php (2)
  • setProject (140-144)
  • Event (10-653)
src/Appwrite/Utopia/Response/Model/Document.php (1)
  • Document (8-112)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (3)
  • GitHub Check: Setup & Build Appwrite Image
  • GitHub Check: Setup & Build Appwrite Image
  • GitHub Check: scan
🔇 Additional comments (2)
src/Appwrite/Event/Database.php (1)

164-175: Preserve explicit queue when setProject() is called

setProject() assigns $this->queue from the project's DSN and will overwrite a queue previously set via setQueue(); either (a) only assign $this->queue when empty/null, or (b) document that setProject takes precedence.

Location: src/Appwrite/Event/Database.php — setProject (lines 164–175).

Repo search for setQueue(...)->setProject(...) returned no matches; manual verification recommended.

app/controllers/api/health.php (1)

541-541: LGTM: queue selection by name before size check

Chaining setQueue($name)->getSize() correctly scopes the size to the requested database queue.

Comment on lines 164 to 178
public function setProject(Document $project): Event
{
try {
$dsn = new DSN($this->getProject()->getAttribute('database'));
$dsn = new DSN($project->getAttribute('database'));
} catch (\InvalidArgumentException) {
// TODO: Temporary until all projects are using shared tables
$dsn = new DSN('mysql://' . $this->getProject()->getAttribute('database'));
$dsn = new DSN('mysql://' . $project->getAttribute('database'));
}

$this->queue = $dsn->getHost();
return $this->queue;

return parent::setProject($project);
}
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.

🛠️ Refactor suggestion

Preserve fluent API: return self, not Event

Other setters in this class return self; aligning setProject avoids breaking chaining/static analysis.

-    public function setProject(Document $project): Event
+    public function setProject(Document $project): self
     {
         try {
             $dsn = new DSN($project->getAttribute('database'));
         } catch (\InvalidArgumentException) {
             // TODO: Temporary until all projects are using shared tables
             $dsn = new DSN('mysql://' . $project->getAttribute('database'));
         }
-        $this->queue = $dsn->getHost();
+        // Avoid clobbering a queue explicitly set earlier in a chain
+        if (empty($this->queue)) {
+            $this->queue = $dsn->getHost();
+        }
 
-        return parent::setProject($project);
+        return parent::setProject($project);
     }
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
public function setProject(Document $project): Event
{
try {
$dsn = new DSN($this->getProject()->getAttribute('database'));
$dsn = new DSN($project->getAttribute('database'));
} catch (\InvalidArgumentException) {
// TODO: Temporary until all projects are using shared tables
$dsn = new DSN('mysql://' . $this->getProject()->getAttribute('database'));
$dsn = new DSN('mysql://' . $project->getAttribute('database'));
}
$this->queue = $dsn->getHost();
return $this->queue;
return parent::setProject($project);
}
public function setProject(Document $project): self
{
try {
$dsn = new DSN($project->getAttribute('database'));
} catch (\InvalidArgumentException) {
// TODO: Temporary until all projects are using shared tables
$dsn = new DSN('mysql://' . $project->getAttribute('database'));
}
// Avoid clobbering a queue explicitly set earlier in a chain
if (empty($this->queue)) {
$this->queue = $dsn->getHost();
}
return parent::setProject($project);
}
🤖 Prompt for AI Agents
In src/Appwrite/Event/Database.php around lines 164-175, the method currently
declares a return type of Event and returns parent::setProject($project),
breaking the class' fluent API; change the signature to return self, call
parent::setProject($project) for side effects (without returning it), and then
return $this so callers can chain setters and static analysis sees the fluent
type.

@github-actions
Copy link
Copy Markdown

github-actions bot commented Sep 12, 2025

✨ Benchmark results

  • Requests per second: 1,245
  • Requests with 200 status code: 224,074
  • P99 latency: 0.156410302

⚡ Benchmark Comparison

Metric This PR Latest version
RPS 1,245 988
200 224,074 177,925
P99 0.156410302 0.193966229

Copy link
Copy Markdown
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 1

🧹 Nitpick comments (1)
app/controllers/api/health.php (1)

535-541: Constrain the database queue name input

Right now any 256-char string passes. Add a lightweight prefix/charset check to avoid cross-queue introspection via arbitrary names.

Apply:

         $threshold = \intval($threshold);
+        // Only allow database_* queues with a conservative charset.
+        if (!\preg_match('/^database_[A-Za-z0-9._-]+$/', $name)) {
+            throw new Exception(Exception::GENERAL_SERVER_ERROR, 'Invalid database queue name.');
+        }
-        $size = $queueForDatabase->setQueue($name)->getSize();
+        $size = (clone $queueForDatabase)->setQueue($name)->getSize();
📜 Review details

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 0ee77e8 and 5c9dff5.

📒 Files selected for processing (2)
  • app/controllers/api/health.php (1 hunks)
  • src/Appwrite/Event/Database.php (1 hunks)
🚧 Files skipped from review as they are similar to previous changes (1)
  • src/Appwrite/Event/Database.php
🧰 Additional context used
🧬 Code graph analysis (1)
app/controllers/api/health.php (1)
src/Appwrite/Event/Event.php (2)
  • setQueue (95-100)
  • getSize (648-652)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (16)
  • GitHub Check: E2E Service Test (GraphQL)
  • GitHub Check: E2E Service Test (Sites)
  • GitHub Check: E2E Service Test (Projects)
  • GitHub Check: E2E Service Test (FunctionsSchedule)
  • GitHub Check: E2E Service Test (Proxy)
  • GitHub Check: E2E Service Test (Health)
  • GitHub Check: E2E Service Test (Console)
  • GitHub Check: E2E Service Test (Site Screenshots)
  • GitHub Check: E2E Service Test (Account)
  • GitHub Check: E2E Service Test (Databases/TablesDB)
  • GitHub Check: E2E Service Test (Functions)
  • GitHub Check: E2E Service Test (Dev Keys)
  • GitHub Check: E2E General Test
  • GitHub Check: Unit Test
  • GitHub Check: Benchmark
  • GitHub Check: scan

Copy link
Copy Markdown
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 1

♻️ Duplicate comments (1)
src/Appwrite/Event/Database.php (1)

164-178: Fix return type to preserve fluent API and align with parent signature

Return self, call parent::setProject($project) for side effects, and then return $this;. This keeps chaining and static analysis intact.

-    public function setProject(Document $project): Event
+    public function setProject(Document $project): self
     {
-        $database = $project->getAttribute('database');
-        if (!empty($database) || $project->getId() === 'console') {
-            try {
-                $dsn = new DSN($database);
-            } catch (\InvalidArgumentException) {
-                // TODO: Temporary until all projects are using shared tables
-                $dsn = new DSN("mysql://$database");
-            }
-            $this->queue = $dsn->getHost();
-        }
-
-        return parent::setProject($project);
+        // Update base state
+        parent::setProject($project);
+
+        $database = (string) $project->getAttribute('database', '');
+        $dsn = null;
+
+        if ($database !== '') {
+            try {
+                $dsn = new DSN($database);
+            } catch (\InvalidArgumentException) {
+                try {
+                    // TODO: Temporary until all projects are using shared tables
+                    $dsn = new DSN('mysql://' . ltrim($database, '/'));
+                } catch (\InvalidArgumentException) {
+                    // Leave $dsn null if still invalid
+                }
+            }
+        }
+
+        if ($dsn) {
+            $host = (string) $dsn->getHost();
+            if ($host !== '' && empty($this->queue)) {
+                $this->queue = $host;
+            }
+        }
+
+        return $this;
     }
📜 Review details

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 0ee77e8 and 5c9dff5.

📒 Files selected for processing (2)
  • app/controllers/api/health.php (1 hunks)
  • src/Appwrite/Event/Database.php (1 hunks)
🚧 Files skipped from review as they are similar to previous changes (1)
  • app/controllers/api/health.php
🧰 Additional context used
🧬 Code graph analysis (1)
src/Appwrite/Event/Database.php (2)
src/Appwrite/Event/Event.php (2)
  • setProject (140-144)
  • Event (10-653)
src/Appwrite/Utopia/Response/Model/Document.php (1)
  • Document (8-112)
🪛 GitHub Actions: Tests
src/Appwrite/Event/Database.php

[error] 169-169: Appwrite\Event\Database: DSN construction failed due to null DSN (environment misconfiguration).

Comment on lines +166 to 175
$database = $project->getAttribute('database');
if (!empty($database) || $project->getId() === 'console') {
try {
$dsn = new DSN($database);
} catch (\InvalidArgumentException) {
// TODO: Temporary until all projects are using shared tables
$dsn = new DSN("mysql://$database");
}
$this->queue = $dsn->getHost();
}
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.

💡 Verification agent

🧩 Analysis chain

Harden DSN handling to stop null/empty DSN crashes and avoid clobbering queue

Current logic attempts DSN construction even when $database is empty (due to || $project->getId() === 'console'), which can yield an invalid DSN or empty host and cause the reported pipeline failure. Guard against empty values, wrap the fallback in a second try/catch, and only set the queue when we have a non-empty host. Also, avoid overwriting a previously chosen queue.

To confirm no callers rely on the removed console special-case, search for code paths that set an empty/absent database attribute on the console project:


🏁 Script executed:

#!/bin/bash
# Inspect references to the console project and database attribute usage
rg -nC2 "getId\(\)\s*===\s*'console'|['\"]database['\"]" --type=php

Length of output: 174606


Harden DSN handling — prevent empty/console DSN from clobbering queue

Current code (src/Appwrite/Event/Database.php:166-175) will attempt to build a DSN when $database may be empty because of || $project->getId() === 'console', which can produce an empty host and overwrite $this->queue. Repo search shows many console-specific early-returns and DSN patterns (app/cli.php, app/worker.php, app/init/resources.php, app/init/registers.php), so this file is an outlier and must be hardened.

  • Guard: don't construct a DSN when $database is empty; if the console project needs special handling, return/use the platform/console connection instead of passing empty values into DSN.
  • Fallback: only attempt the "mysql://$database" fallback when $database is non-empty; wrap the fallback in its own try/catch.
  • Assigning queue: set $this->queue = $dsn->getHost() only when the host is non-empty and do not overwrite an existing non-empty $this->queue.

src/Appwrite/Event/Database.php:166-175 — apply fixes above.

🧰 Tools
🪛 GitHub Actions: Tests

[error] 169-169: Appwrite\Event\Database: DSN construction failed due to null DSN (environment misconfiguration).

🤖 Prompt for AI Agents
In src/Appwrite/Event/Database.php around lines 166-175, avoid building a DSN
when $database is empty or when this is the console project: first check that
$database is non-empty before attempting new DSN(), and if the project is
console handle it via the platform/console connection path instead of falling
through to DSN logic; only attempt the "mysql://$database" fallback when
$database is non-empty and wrap that fallback in its own try/catch; after
resolving a DSN only assign $this->queue = $dsn->getHost() if getHost() returns
a non-empty value and only overwrite $this->queue when it is currently empty to
prevent clobbering an existing queue value.

@loks0n loks0n merged commit b5c5887 into 1.8.x Sep 12, 2025
41 checks passed
@coderabbitai coderabbitai bot mentioned this pull request Sep 22, 2025
2 tasks
@stnguyen90 stnguyen90 deleted the fix-db-queues branch October 1, 2025 23:58
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.

2 participants