-
Notifications
You must be signed in to change notification settings - Fork 4.6k
Add executionId and client IP to execution headers #10344
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Conversation
📝 WalkthroughWalkthroughThe change standardizes execution ID handling and client IP propagation. A single executionId is generated early, added to the request as x-appwrite-execution-id, and reused as the $id for Execution documents. A new x-appwrite-client-ip header is added (from request IP where available; empty otherwise). Workers’ fail and execute paths set/propagate these headers and reuse or create executionId as needed. E2E tests are updated to assert APPWRITE_FUNCTION_EXECUTION_ID matches the execution’s $id and that APPWRITE_FUNCTION_CLIENT_IP is present. The sample function now returns these values from headers and coerces statusCode to a number. Estimated code review effort🎯 3 (Moderate) | ⏱️ ~25 minutes Tip 🔌 Remote MCP (Model Context Protocol) integration is now available!Pro plan users can now connect to remote MCP servers from the Integrations page. Connect with popular remote MCPs such as Notion and Linear to add more context to your reviews and chats. ✨ Finishing Touches
🧪 Generate unit tests
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. 🪧 TipsChatThere are 3 ways to chat with CodeRabbit:
SupportNeed help? Create a ticket on our support page for assistance with any issues or questions. CodeRabbit Commands (Invoked using PR/Issue comments)Type Other keywords and placeholders
Status, Documentation and Community
|
Security Scan Results for PRDocker Image Scan Results
Source Code Scan Results🎉 No vulnerabilities found! |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actionable comments posted: 3
Caution
Some comments are outside the diff and can’t be posted inline due to platform limitations.
⚠️ Outside diff range comments (1)
src/Appwrite/Platform/Workers/Functions.php (1)
402-412
: Don’t clobber client IP provided by the callerIn execute(), you overwrite x-appwrite-client-ip with an empty string, discarding the value populated upstream (Create.php or router). Preserve it if already present.
Apply:
- $headers['x-appwrite-execution-id'] = $executionId ?? ''; + $headers['x-appwrite-execution-id'] = $executionId ?? ''; $headers['x-appwrite-key'] = API_KEY_DYNAMIC . '_' . $apiKey; $headers['x-appwrite-trigger'] = $trigger; $headers['x-appwrite-event'] = $event ?? ''; $headers['x-appwrite-user-id'] = $user->getId() ?? ''; $headers['x-appwrite-user-jwt'] = $jwt ?? ''; $headers['x-appwrite-country-code'] = ''; $headers['x-appwrite-continent-code'] = ''; $headers['x-appwrite-continent-eu'] = 'false'; - $headers['x-appwrite-client-ip'] = ''; + $headers['x-appwrite-client-ip'] = $headers['x-appwrite-client-ip'] ?? '';This ensures async HTTP executions also expose the client IP to the function, consistent with the PR goal.
🧹 Nitpick comments (4)
src/Appwrite/Platform/Workers/Functions.php (1)
413-418
: Avoid DB read when executionId is emptyCalling getDocument with an empty ID is unnecessary. Guard the lookup and fall back to a new Document.
Apply:
- $execution = $dbForProject->getDocument('executions', $executionId ?? ''); - if ($execution->isEmpty()) { + $execution = new Document(); + if (!empty($executionId)) { + $execution = $dbForProject->getDocument('executions', $executionId); + } + if ($execution->isEmpty()) { $executionId = ID::unique(); $headers['x-appwrite-execution-id'] = $executionId;tests/e2e/Services/Functions/FunctionsCustomClientTest.php (1)
167-179
: Consider adding async-path assertions for executionId/client IPTo fully cover the async flow, fetch the execution after completion and assert the responseBody contains the same APPWRITE_FUNCTION_EXECUTION_ID and a non-empty APPWRITE_FUNCTION_CLIENT_IP, similar to the sync assertions above.
I can propose a patch to extend the assertEventually block to parse responseBody and assert both fields—let me know if you want me to draft it.
tests/e2e/Services/Functions/FunctionsCustomServerTest.php (2)
1139-1144
: Harden assertions for clearer failures and type safetyTo avoid noisy “undefined index” notices and to get stricter equality on IDs, assert key presence first and use assertSame for the ID comparison.
Apply this diff:
- // Test execution ID and client IP - $executionId = $execution['body']['$id'] ?? ''; - $this->assertNotEmpty($output['APPWRITE_FUNCTION_EXECUTION_ID']); - $this->assertEquals($executionId, $output['APPWRITE_FUNCTION_EXECUTION_ID']); - $this->assertNotEmpty($output['APPWRITE_FUNCTION_CLIENT_IP']); + // Test execution ID and client IP + $executionId = $execution['body']['$id'] ?? ''; + $this->assertArrayHasKey('APPWRITE_FUNCTION_EXECUTION_ID', $output); + $this->assertNotEmpty($output['APPWRITE_FUNCTION_EXECUTION_ID']); + $this->assertSame($executionId, $output['APPWRITE_FUNCTION_EXECUTION_ID']); + $this->assertArrayHasKey('APPWRITE_FUNCTION_CLIENT_IP', $output); + $this->assertNotEmpty($output['APPWRITE_FUNCTION_CLIENT_IP']);
1136-1138
: Unify type expectations for CPUS/MEMORY across testsLine 1136-1138 and Line 1170-1171 assert integers for APPWRITE_FUNCTION_CPUS/MEMORY, while Line 1962-1963 assert strings for the same fields. This inconsistency can lead to brittle tests if runtimes or helpers change serialization.
Consider standardizing on one approach (prefer assertSame with explicit types), or cast before asserting to make intent explicit.
Example options:
- Make all strict integer comparisons:
- $this->assertSame(1, (int) $output['APPWRITE_FUNCTION_CPUS']);
- $this->assertSame(1024, (int) $output['APPWRITE_FUNCTION_MEMORY']);
- Or, if you intend to assert raw string values everywhere, switch to assertSame('1', ...) and assertSame('1024', ...), and update Line 1962-1963 accordingly for consistency.
Also applies to: 1170-1171, 1962-1963
📜 Review details
Configuration used: .coderabbit.yaml
Review profile: CHILL
Plan: Pro
💡 Knowledge Base configuration:
- MCP integration is disabled by default for public repositories
- Jira integration is disabled by default for public repositories
- Linear integration is disabled by default for public repositories
You can enable these sources in your CodeRabbit configuration.
📒 Files selected for processing (6)
app/controllers/general.php
(1 hunks)src/Appwrite/Platform/Modules/Functions/Http/Executions/Create.php
(2 hunks)src/Appwrite/Platform/Workers/Functions.php
(3 hunks)tests/e2e/Services/Functions/FunctionsCustomClientTest.php
(1 hunks)tests/e2e/Services/Functions/FunctionsCustomServerTest.php
(1 hunks)tests/resources/functions/basic/index.js
(1 hunks)
🧰 Additional context used
🧬 Code Graph Analysis (4)
tests/e2e/Services/Functions/FunctionsCustomServerTest.php (1)
src/Appwrite/Utopia/Response.php (1)
output
(658-740)
src/Appwrite/Platform/Modules/Functions/Http/Executions/Create.php (1)
src/Appwrite/Event/Audit.php (1)
getIP
(113-116)
app/controllers/general.php (1)
src/Appwrite/Event/Audit.php (1)
getIP
(113-116)
src/Appwrite/Platform/Workers/Functions.php (1)
src/Appwrite/Event/Event.php (1)
trigger
(337-358)
⏰ 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: scan
- GitHub Check: Setup & Build Appwrite Image
🔇 Additional comments (7)
app/controllers/general.php (2)
358-367
: Single source-of-truth execution ID + client IP propagation looks goodGenerating the executionId once and propagating via x-appwrite-execution-id and x-appwrite-client-ip is correct and aligns with the PR objective.
358-367
: Optional: prefer proxy-derived client IP
Request::getIP()
is inherited fromUtopia\Swoole\Request
and may not account forX-Forwarded-For
/X-Real-IP
. Please verify its implementation inUtopia\Swoole\Request
. If it doesn’t handle proxy headers, consider falling back to them before callinggetIP()
, for example:$clientIp = $request->getHeader('X-Forwarded-For') ?: $request->getHeader('X-Real-IP') ?: $request->getIP(); $headers = \array_merge([], $requestHeaders); $headers['x-appwrite-execution-id'] = $executionId ?? ''; $headers['x-appwrite-user-id'] = ''; $headers['x-appwrite-country-code'] = ''; $headers['x-appwrite-continent-code'] = ''; $headers['x-appwrite-continent-eu'] = 'false'; $headers['x-appwrite-client-ip'] = $clientIp;src/Appwrite/Platform/Modules/Functions/Http/Executions/Create.php (2)
224-234
: Early executionId generation + client IP header: LGTMReusing the same executionId for the header and document ID is correct. Adding x-appwrite-client-ip from the request is aligned with the objective.
224-234
: EnsuregetIP()
Returns the Actual Client IP Behind ProxiesThe snippet in
src/Appwrite/Platform/Modules/Functions/Http/Executions/Create.php
relies on$request->getIP()
. Before shipping, please verify thatUtopia\Swoole\Request::getIP()
correctly parsesX-Forwarded-For
/X-Real-IP
(with your trusted‐proxy settings) so it doesn’t surface an internal proxy’s IP to user functions.Points to verify:
- Inspect the implementation of
Utopia\Swoole\Request::getIP()
(in your vendor or Utopia package).- Confirm your Swoole/server proxy‐trust configuration aligns with how
getIP()
selects headers.- (Optional) Add a test or integration check that
getIP()
returns the expected public client address when behind a reverse proxy.tests/resources/functions/basic/index.js (1)
44-46
: Expose executionId and client IP in function output: LGTMReading x-appwrite-execution-id and x-appwrite-client-ip from headers and returning them is correct. Coercing statusCode to a number is also a good fix.
tests/e2e/Services/Functions/FunctionsCustomClientTest.php (1)
162-166
: Solid assertions for execution ID and client IPAsserting that APPWRITE_FUNCTION_EXECUTION_ID matches the execution’s $id and APPWRITE_FUNCTION_CLIENT_IP is non-empty verifies the end-to-end contract.
tests/e2e/Services/Functions/FunctionsCustomServerTest.php (1)
1139-1144
: Good addition: validates executionId propagation and client IP exposure end-to-endThese assertions directly cover the PR goal: ensuring APPWRITE_FUNCTION_EXECUTION_ID matches the execution document $id and APPWRITE_FUNCTION_CLIENT_IP is populated. This is valuable e2e coverage for both header propagation and runtime exposure.
$executionId = ID::unique(); | ||
|
||
$headers = \array_merge([], $requestHeaders); | ||
$headers['x-appwrite-execution-id'] = $executionId ?? ''; | ||
$headers['x-appwrite-user-id'] = ''; | ||
$headers['x-appwrite-country-code'] = ''; | ||
$headers['x-appwrite-continent-code'] = ''; | ||
$headers['x-appwrite-continent-eu'] = 'false'; | ||
$headers['x-appwrite-client-ip'] = $request->getIP(); | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
💡 Verification agent
🧩 Analysis chain
Ensure new headers are persisted/observable where intended
If you expect x-appwrite-execution-id and x-appwrite-client-ip to appear under the execution.requestHeaders for observability/debugging, confirm they are included in FUNCTION_ALLOWLIST_HEADERS_REQUEST; otherwise they’ll be filtered out.
Run this to verify and adjust if needed:
🏁 Script executed:
#!/bin/bash
# Check where FUNCTION_ALLOWLIST_HEADERS_REQUEST/RESPONSE are defined and whether they include the new headers.
rg -nP -C3 'FUNCTION_ALLOWLIST_HEADERS_(REQUEST|RESPONSE)'
echo
echo "Checking for the new headers in allowlists:"
rg -nP -C2 'x-appwrite-(execution-id|client-ip)'
Length of output: 10238
Add x-appwrite-execution-id
and x-appwrite-client-ip
to the request-header allowlist
We’re currently merging and filtering request headers in app/controllers/general.php
(lines 393–396) against FUNCTION_ALLOWLIST_HEADERS_REQUEST
(defined in app/init/constants.php
), but that constant only contains:
const FUNCTION_ALLOWLIST_HEADERS_REQUEST = [
'content-type',
'agent',
'content-length',
'host'
];
As a result, both x-appwrite-execution-id
and x-appwrite-client-ip
will be dropped and won’t surface in execution.requestHeaders
. To fix this, update the allowlist to include them:
• File: app/init/constants.php
Update around line 147:
- const FUNCTION_ALLOWLIST_HEADERS_REQUEST = ['content-type', 'agent', 'content-length', 'host'];
+ const FUNCTION_ALLOWLIST_HEADERS_REQUEST = [
+ 'content-type',
+ 'agent',
+ 'content-length',
+ 'host',
+ 'x-appwrite-execution-id',
+ 'x-appwrite-client-ip',
+ ];
🤖 Prompt for AI Agents
In app/init/constants.php around line 147, the
FUNCTION_ALLOWLIST_HEADERS_REQUEST array is missing 'x-appwrite-execution-id'
and 'x-appwrite-client-ip', so those headers are filtered out and won't appear
in execution.requestHeaders; update the array to include these two header names
(lowercased) so the header merge in app/controllers/general.php (lines 358–367
and the later filtering at 393–396) will preserve them.
$executionId = ID::unique(); | ||
$headers['x-appwrite-execution-id'] = $executionId ?? ''; | ||
$headers['x-appwrite-key'] = API_KEY_DYNAMIC . '_' . $apiKey; | ||
$headers['x-appwrite-trigger'] = 'http'; | ||
$headers['x-appwrite-user-id'] = $user->getId() ?? ''; | ||
$headers['x-appwrite-user-jwt'] = $jwt ?? ''; | ||
$headers['x-appwrite-country-code'] = ''; | ||
$headers['x-appwrite-continent-code'] = ''; | ||
$headers['x-appwrite-continent-eu'] = 'false'; | ||
$headers['x-appwrite-client-ip'] = $request->getIP(); | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
💡 Verification agent
🧩 Analysis chain
Confirm allowlists include the new headers
If you want x-appwrite-execution-id and x-appwrite-client-ip visible in execution.requestHeaders, ensure they’re in FUNCTION_ALLOWLIST_HEADERS_REQUEST.
Run:
🏁 Script executed:
#!/bin/bash
# Verify the allowlist includes the new headers
rg -nP -C3 'const\s+FUNCTION_ALLOWLIST_HEADERS_REQUEST|define\s*\(\s*[\'"]FUNCTION_ALLOWLIST_HEADERS_REQUEST'
rg -nP -C1 'x-appwrite-execution-id|x-appwrite-client-ip'
Length of output: 116
I’ll re-run the search with proper quoting and broaden the context to ensure we find the constant definition and its contents:
🏁 Script executed:
#!/bin/bash
# 1) Locate where FUNCTION_ALLOWLIST_HEADERS_REQUEST is defined
rg -n --type=php "FUNCTION_ALLOWLIST_HEADERS_REQUEST" -C3
# 2) Inspect that definition for the two new headers
# (display up to 10 lines around the definition and filter for our headers)
rg -n --type=php "FUNCTION_ALLOWLIST_HEADERS_REQUEST" -C10 | rg -n -F "'x-appwrite-execution-id'"
rg -n --type=php "FUNCTION_ALLOWLIST_HEADERS_REQUEST" -C10 | rg -n -F "'x-appwrite-client-ip'"
Length of output: 3741
Add missing headers to FUNCTION_ALLOWLIST_HEADERS_REQUEST
The allowlist defined in app/init/constants.php currently only includes:
- content-type
- agent
- content-length
- host
It must be updated to include both x-appwrite-execution-id and x-appwrite-client-ip, otherwise these headers won’t be visible in execution.requestHeaders.
• File: app/init/constants.php
- const FUNCTION_ALLOWLIST_HEADERS_REQUEST = ['content-type', 'agent', 'content-length', 'host'];
+ const FUNCTION_ALLOWLIST_HEADERS_REQUEST = [
+ 'content-type',
+ 'agent',
+ 'content-length',
+ 'host',
+ 'x-appwrite-execution-id',
+ 'x-appwrite-client-ip',
+ ];
🤖 Prompt for AI Agents
In src/Appwrite/Platform/Modules/Functions/Http/Executions/Create.php around
lines 224 to 234, the code sets x-appwrite-execution-id and x-appwrite-client-ip
headers but the global allowlist in app/init/constants.php
(FUNCTION_ALLOWLIST_HEADERS_REQUEST) is missing these entries; update
app/init/constants.php to add 'x-appwrite-execution-id' and
'x-appwrite-client-ip' to the FUNCTION_ALLOWLIST_HEADERS_REQUEST array (match
casing/format used by other entries, typically lowercase header names) so these
headers are preserved and exposed in execution.requestHeaders.
$executionId = ID::unique(); | ||
$headers['x-appwrite-execution-id'] = $executionId ?? ''; | ||
$headers['x-appwrite-trigger'] = $trigger; | ||
$headers['x-appwrite-event'] = $event ?? ''; | ||
$headers['x-appwrite-user-id'] = $user->getId() ?? ''; | ||
$headers['x-appwrite-user-jwt'] = $jwt ?? ''; | ||
$headers['x-appwrite-client-ip'] = ''; | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Bug: $headers used before initialization in fail()
$headers is written to without being initialized, which will raise a notice and rely on PHP’s implicit array creation. Initialize it explicitly.
Apply:
): void {
- $executionId = ID::unique();
+ $executionId = ID::unique();
+ $headers = [];
$headers['x-appwrite-execution-id'] = $executionId ?? '';
$headers['x-appwrite-trigger'] = $trigger;
$headers['x-appwrite-event'] = $event ?? '';
$headers['x-appwrite-user-id'] = $user->getId() ?? '';
$headers['x-appwrite-user-jwt'] = $jwt ?? '';
- $headers['x-appwrite-client-ip'] = '';
+ $headers['x-appwrite-client-ip'] = '';
🤖 Prompt for AI Agents
In src/Appwrite/Platform/Workers/Functions.php around lines 267 to 274, the
$headers array is written to before being initialized which can trigger PHP
notices; initialize $headers as an empty array (e.g., $headers = []; ) before
assigning values and then proceed to set the x-appwrite-* keys so the array
exists explicitly and avoids implicit creation.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Verify your comment
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🧩 Analysis chain
@vermakhushboo Looking at the code, I can confirm my comment is accurate. In the fail()
method:
-
Method signature has no
$headers
parameter: The method signature isprivate function fail(string $message, Database $dbForProject, Document $function, string $trigger, string $path, string $method, Document $user, string $jwt = null, string $event = null,): void
-
First use of
$headers
is an assignment: Line 268 shows$headers['x-appwrite-execution-id'] = $executionId ?? '';
without any prior initialization -
PHP behavior: This relies on PHP's implicit array creation, which works but generates a notice in strict error reporting and is not considered best practice
-
Later usage confirms it's treated as array: The method later uses
foreach ($headers as $key => $value)
confirming$headers
is expected to be an array
The fix I suggested ($headers = [];
before the first assignment) would explicitly initialize the array and eliminate any potential PHP notices while maintaining the same functionality.
My comment and suggested fix are correct and should be applied for cleaner, more explicit code.
🏁 Script executed:
#!/bin/bash
# Let's verify the fail() method implementation to confirm $headers initialization
ast-grep --pattern $'private function fail(
$$$
) {
$$$
}'
Length of output: 63
@vermakhushboo I can now definitively verify my comment is correct. Looking at the fail()
method implementation:
The issue confirmed:
- Line 267:
$executionId = ID::unique();
- Line 268:
$headers['x-appwrite-execution-id'] = $executionId ?? '';
← First use of $headers without initialization - Lines 269-272: More assignments to
$headers
array elements - Line 280:
foreach ($headers as $key => $value)
← Used as an array later
The problem:
The $headers
variable is used as an array starting at line 268 without being explicitly declared/initialized first. This relies on PHP's implicit array creation behavior.
My suggested fix is correct: Adding $headers = [];
before line 268 would explicitly initialize the array, following PHP best practices and avoiding any potential notices in strict error reporting modes.
The comment and suggested fix are accurate and should be implemented for cleaner, more maintainable code.
🏁 Script executed:
#!/bin/bash
# Search for the fail() method implementation
rg -n -A 20 "private function fail" src/Appwrite/Platform/Workers/Functions.php
Length of output: 894
@vermakhushboo Verification confirmed - my comment is accurate.
Looking at the exact code from the fail()
method:
Lines 256-266: Method signature has no $headers
parameter
Line 268: $headers['x-appwrite-execution-id'] = $executionId ?? '';
← First use of $headers without initialization
Lines 269-273: Subsequent assignments to $headers
array elements
Line 276: foreach ($headers as $key => $value)
← Used as array
The issue is confirmed:
$headers
is accessed as an array starting at line 268- No prior initialization of
$headers
exists - This relies on PHP's implicit array creation (generates notices in strict mode)
My suggested fix is correct:
$executionId = ID::unique();
$headers = []; // ← Add this line
$headers['x-appwrite-execution-id'] = $executionId ?? '';
This follows PHP best practices by explicitly initializing variables before use. The comment stands as accurate and the fix should be implemented.
🧬 Code Graph Analysis Results
-
File: src/Appwrite/Event/Event.php
- Lines: 10-593
- Summary:
- Defines the central Event system used by all workers.
- Key concepts:
- Event constants for queue names and class names (e.g., DATABASE_QUEUE_NAME, ... FUNCTIONS_QUEUE_NAME, etc.).
- Properties for queue, class, event, payload, context, project, user, userId, etc.
- preparePayload(): builds a payload including project, user, type, collection, document, database, and generated events.
- trigger(): enqueues the prepared payload to the appropriate queue, with error handling that respects the critical flag.
- preparePayload merges base payload with trimmed values and supports masking sensitive info.
- Static generateEvents(pattern, params): expands a base event pattern into all concrete events, substituting placeholders with provided params or wildcards, validating required params, and returning an array of event strings.
- parseEventPattern(pattern): parses a single event pattern into its components (type, resource, subResource, action, etc.).
- from(Event): copies state from another Event instance.
- Notable behavior:
- If an event is non-critical and enqueue fails, trigger() returns false instead of throwing.
- The event-generation logic supports complex nested resources and placeholders.
-
File: src/Executor/Executor.php
- Lines: 10-459
- Summary:
- Provides runtime orchestration for executing functions/deployments.
- Key methods:
- createRuntime(projectId, deploymentId, source, image, version, cpus, memory, timeout, ...): deploys a runtime container for execution and returns runtime metadata.
- getLogs(deploymentId, projectId, timeout, callback): streams logs from a runtime.
- deleteRuntime(projectId, deploymentId, suffix): deletes a runtime instance.
- createExecution(projectId, deploymentId, body, variables, timeout, image, source, entrypoint, version, path, method, headers, cpus, memory, logging, runtimeEntrypoint, requestTimeout): creates and starts an execution request for a deployment.
- Builds a request payload with runtimeId, variables, timeout, path, method, headers, image, source, entrypoint, resources, version, and additional fields.
- Sends request to /runtimes/{runtimeId}/executions via HTTP (multipart/form-data).
- Validates HTTP status, decodes response, and normalizes headers/duration/startTime in the response body.
- createCommand(...): creates a runtime command.
- Private call(endpoint, method, path, headers, params, decode, timeout, callback): low-level HTTP client using curl.
- Supports JSON and multipart/form-data body formats.
- Handles streaming callbacks, response parsing, and error propagation.
- Decodes JSON/multipart responses, extracts status codes, and surfaces errors.
- Notable behavior:
- Throws on HTTP error statuses (>= 400) with the status code.
- Supports self-signed certificates via a flag.
- Returns structured response body containing statusCode, headers, body, duration, etc.
-
File: src/Appwrite/Platform/Workers/StatsUsage.php
- Lines: 16-481
- Summary:
- Stats usage worker collects and aggregates usage metrics per project.
- Key aspects:
- getName(): returns 'stats-usage'.
- Constructor wires in dependencies and sets up the callback for the action.
- action(Message $message, callable $getProjectDB, callable $getLogsDB, Registry $register): core entrypoint.
- Aggregates metrics from payload['metrics'] and reduces per project using payload['reduce'] data.
- Batches metrics and commits to DB when thresholds are reached or interval elapses.
- Maintains internal state: $stats, $lastTriggeredTime, $keys, and $projects for batched writes.
- commitToDb(callable $getProjectDB): writes batched stats into each project’s DB using stats collection; also triggers logs writing for usage data.
- prepareForLogsDB()/writeToLogsDB(): optionally dual-writes metrics to logs DB depending on environment variable _APP_STATS_USAGE_DUAL_WRITING.
- Maintains a set of base metrics to skip from dual-writing (skipBaseMetrics) and a set of metrics to avoid parent-id variants (skipParentIdMetrics).
- Notable behavior:
- Aggregates and persists metrics such as deployments, builds, executions, storage, and more across time periods (1h, 1d, inf).
- Designed for batch writes to improve performance.
-
File: src/Appwrite/Event/Database.php
- Lines: 9-142
- Summary:
- Defines a Database event type used by the database-related workers.
- Key methods:
- setType(string $type): self
- getType(): string
- setDatabase(Document $database): self
- getDatabase(): ?Document
- setCollection(Document $collection): self
- getCollection(): ?Document
- setDocument(Document $document): self
- getDocument(): ?Document
- getQueue(): string
- preparePayload(): array
- preparePayload() returns a payload including project, user, type, collection, document, database, and events generated via Event::generateEvents($this->getEvent(), $this->getParams()).
- Notable behavior:
- getQueue() derives a queue name from the project's database DSN, with a fallback for legacy setups (namespace-based queue naming).
-
File: src/Appwrite/Event/Realtime.php
- Lines: 47-51
- Code (complete snippet):
public function setSubscribers(array $subscribers): self
{
$this->subscribers = $subscribers;
return $this;
}
-
File: src/Appwrite/Platform/Workers/Webhooks.php
- Lines: 22-25
- Code (complete snippet):
public static function getName(): string
{
return 'webhooks';
}
✨ Benchmark results
⚡ Benchmark Comparison
|
Closing as I fixed #9147 |
What does this PR do?
Fixes #9316
Test Plan
(Write your test plan here. If you changed any code, please provide us with clear instructions on how you verified your changes work. Screenshots may also be helpful.)
Related PRs and Issues
Checklist