Merge branch '1.8.x' into feat-mongodb

This commit is contained in:
Jake Barnby
2026-02-14 04:50:00 +00:00
committed by GitHub
12 changed files with 79 additions and 65 deletions
+2 -1
View File
@@ -134,4 +134,5 @@ _APP_PROJECT_REGIONS=default
_APP_FUNCTIONS_CREATION_ABUSE_LIMIT=5000
_APP_STATS_USAGE_DUAL_WRITING_DBS=database_db_main
_APP_TRUSTED_HEADERS=x-forwarded-for
_APP_POOL_ADAPTER=stack
_APP_POOL_ADAPTER=stack
_APP_WORKER_SCREENSHOTS_ROUTER=http://appwrite
+1 -5
View File
@@ -30,9 +30,6 @@ use Utopia\Pools\Group;
use Utopia\Queue\Broker\Pool as BrokerPool;
use Utopia\Queue\Publisher;
use Utopia\Registry\Registry;
use Utopia\Span\Exporter;
use Utopia\Span\Span;
use Utopia\Span\Storage;
use Utopia\System\System;
use Utopia\Telemetry\Adapter\None as NoTelemetry;
@@ -340,6 +337,5 @@ $cli
$cli->shutdown()->action(fn () => Timer::clearAll());
Runtime::enableCoroutine(SWOOLE_HOOK_ALL);
Span::setStorage(new Storage\Coroutine());
Span::addExporter(new Exporter\Stdout());
require_once __DIR__ . '/init/span.php';
run($cli->run(...));
+2 -11
View File
@@ -52,6 +52,7 @@ use Utopia\Logger\Log;
use Utopia\Logger\Log\User;
use Utopia\Logger\Logger;
use Utopia\Platform\Service;
use Utopia\Span\Span;
use Utopia\System\System;
use Utopia\Validator;
use Utopia\Validator\Text;
@@ -1245,17 +1246,7 @@ Http::error()
$trace = $error->getTrace();
if (php_sapi_name() === 'cli') {
Console::error('[Error] Timestamp: ' . date('c', time()));
if ($route) {
Console::error('[Error] Method: ' . $route->getMethod());
Console::error('[Error] URL: ' . $route->getPath());
}
Console::error('[Error] Type: ' . get_class($error));
Console::error('[Error] Message: ' . $message);
Console::error('[Error] File: ' . $file);
Console::error('[Error] Line: ' . $line);
Span::error($error);
}
switch ($class) {
+39 -21
View File
@@ -1,6 +1,7 @@
<?php
require_once __DIR__ . '/../vendor/autoload.php';
require_once __DIR__ . '/init/span.php';
use Appwrite\Utopia\Request;
use Appwrite\Utopia\Response;
@@ -31,6 +32,7 @@ use Utopia\Http\Http;
use Utopia\Logger\Log;
use Utopia\Logger\Log\User;
use Utopia\Pools\Group;
use Utopia\Span\Span;
use Utopia\System\System;
const DOMAIN_SYNC_TIMER = 30; // 30 seconds
@@ -167,7 +169,6 @@ $http->on(Constant::EVENT_WORKER_START, function ($server, $workerId) use (&$fil
$files = new Files();
$files->load(__DIR__ . '/../public');
}
Console::success('Worker ' . ++$workerId . ' started successfully');
});
$http->on(Constant::EVENT_WORKER_STOP, function ($server, $workerId) {
@@ -207,7 +208,8 @@ function createDatabase(Http $app, string $resourceKey, string $dbName, array $c
}
}
Console::success("[Setup] - $dbName database init started...");
Span::init("database.setup");
Span::add('database.name', $dbName);
$attempts = 0;
while (true) {
@@ -218,6 +220,7 @@ function createDatabase(Http $app, string $resourceKey, string $dbName, array $c
break; // exit loop on success
} catch (\Exception $e) {
if ($e instanceof DuplicateException) {
Span::add('database.exists', true);
Console::info(" └── Skip: metadata table already exists");
break;
}
@@ -232,6 +235,7 @@ function createDatabase(Http $app, string $resourceKey, string $dbName, array $c
}
// Process collections
$collectionsCreated = 0;
foreach ($collections as $key => $collection) {
if (($collection['$collection'] ?? '') !== Database::METADATA) {
continue;
@@ -241,8 +245,6 @@ function createDatabase(Http $app, string $resourceKey, string $dbName, array $c
continue;
}
Console::info(" └── Creating collection: {$collection['$id']}...");
$attributes = array_map(fn ($attr) => new Document([
'$id' => ID::custom($attr['$id']),
'type' => $attr['type'],
@@ -264,14 +266,19 @@ function createDatabase(Http $app, string $resourceKey, string $dbName, array $c
]), $collection['indexes']);
$database->createCollection($key, $attributes, $indexes);
$collectionsCreated++;
}
Span::add('database.collections_created', $collectionsCreated);
if ($extraSetup) {
$extraSetup($database);
}
Span::current()?->finish();
}
$http->on(Constant::EVENT_START, function (Server $http) use ($payloadSize, $register) {
$http->on(Constant::EVENT_START, function (Server $http) use ($payloadSize, $totalWorkers, $register) {
$app = new Http('UTC');
go(function () use ($register, $app) {
@@ -296,7 +303,6 @@ $http->on(Constant::EVENT_START, function (Server $http) use ($payloadSize, $reg
}
if ($dbForPlatform->getDocument('buckets', 'default')->isEmpty()) {
Console::info(" └── Creating default bucket...");
$dbForPlatform->createDocument('buckets', new Document([
'$id' => ID::custom('default'),
'$collection' => ID::custom('buckets'),
@@ -319,7 +325,6 @@ $http->on(Constant::EVENT_START, function (Server $http) use ($payloadSize, $reg
$bucket = $dbForPlatform->getDocument('buckets', 'default');
Console::info(" └── Creating files collection for default bucket...");
$files = $collections['buckets']['files'] ?? [];
if (empty($files)) {
throw new Exception('Files collection is not configured.');
@@ -349,7 +354,6 @@ $http->on(Constant::EVENT_START, function (Server $http) use ($payloadSize, $reg
}
if ($authorization->skip(fn () => $dbForPlatform->getDocument('buckets', 'screenshots')->isEmpty())) {
Console::info(" └── Creating screenshots bucket...");
$authorization->skip(fn () => $dbForPlatform->createDocument('buckets', new Document([
'$id' => ID::custom('screenshots'),
'$collection' => ID::custom('buckets'),
@@ -367,7 +371,6 @@ $http->on(Constant::EVENT_START, function (Server $http) use ($payloadSize, $reg
$bucket = $authorization->skip(fn () => $dbForPlatform->getDocument('buckets', 'screenshots'));
Console::info(" └── Creating files collection for screenshots bucket...");
$files = $collections['buckets']['files'] ?? [];
if (empty($files)) {
throw new Exception('Files collection is not configured.');
@@ -405,6 +408,9 @@ $http->on(Constant::EVENT_START, function (Server $http) use ($payloadSize, $reg
$cache = $app->getResource('cache');
foreach ($sharedTablesV2 as $hostname) {
Span::init('database.setup');
Span::add('database.hostname', $hostname);
$adapter = new DatabasePool($pools->get($hostname));
$dbForProject = (new Database($adapter, $cache))
->setDatabase('appwrite')
@@ -422,6 +428,7 @@ $http->on(Constant::EVENT_START, function (Server $http) use ($payloadSize, $reg
$dbForProject->create();
break; // exit loop on success
} catch (DuplicateException) {
Span::add('database.exists', true);
Console::success('[Setup] - Skip: metadata table already exists');
break;
} catch (\Throwable $e) {
@@ -439,6 +446,7 @@ $http->on(Constant::EVENT_START, function (Server $http) use ($payloadSize, $reg
$audit->setup();
}
$collectionsCreated = 0;
foreach ($projectCollections as $key => $collection) {
if (($collection['$collection'] ?? '') !== Database::METADATA) {
continue;
@@ -450,17 +458,21 @@ $http->on(Constant::EVENT_START, function (Server $http) use ($payloadSize, $reg
$attributes = \array_map(fn ($attribute) => new Document($attribute), $collection['attributes']);
$indexes = \array_map(fn (array $index) => new Document($index), $collection['indexes']);
Console::success('[Setup] - Creating project collection: ' . $collection['$id'] . '...');
$dbForProject->createCollection($key, $attributes, $indexes);
$collectionsCreated++;
}
}
Console::success('[Setup] - Server database init completed...');
Span::add('database.collections_created', $collectionsCreated);
Span::current()?->finish();
}
});
Console::success('Server started successfully (max payload is ' . number_format($payloadSize) . ' bytes)');
Console::info("Master pid {$http->master_pid}, manager pid {$http->manager_pid}");
Span::init('http.server.start');
Span::add('server.workers', $totalWorkers);
Span::add('server.payload_size', $payloadSize);
Span::add('server.master_pid', $http->master_pid);
Span::add('server.manager_pid', $http->manager_pid);
Span::current()?->finish();
// Start the task that starts fetching custom domains
$http->task([], 0);
@@ -473,12 +485,16 @@ $http->on(Constant::EVENT_START, function (Server $http) use ($payloadSize, $reg
});
$http->on(Constant::EVENT_REQUEST, function (SwooleRequest $swooleRequest, SwooleResponse $swooleResponse) use ($register, &$files) {
Span::init('http.request');
Http::setResource('swooleRequest', fn () => $swooleRequest);
Http::setResource('swooleResponse', fn () => $swooleResponse);
$request = new Request($swooleRequest);
$response = new Response($swooleResponse);
Span::add('http.method', $request->getMethod());
if ($files instanceof Files && $files->isFileLoaded($request->getURI())) {
$time = (60 * 60 * 24 * 45); // 45 days cache
@@ -507,7 +523,12 @@ $http->on(Constant::EVENT_REQUEST, function (SwooleRequest $swooleRequest, Swool
$authorization->addRole(Role::any()->toString());
$app->run($request, $response);
$route = $app->getRoute();
Span::add('http.path', $route?->getPath() ?? 'unknown');
} catch (\Throwable $th) {
Span::error($th);
$version = System::getEnv('_APP_VERSION', 'UNKNOWN');
$logger = $app->getResource("logger");
@@ -570,12 +591,6 @@ $http->on(Constant::EVENT_REQUEST, function (SwooleRequest $swooleRequest, Swool
}
}
Console::error('[Error] Type: ' . get_class($th));
Console::error('[Error] Message: ' . $th->getMessage());
Console::error('[Error] File: ' . $th->getFile());
Console::error('[Error] Line: ' . $th->getLine());
Console::error('[Error] Trace: ' . $th->getTraceAsString());
$swooleResponse->setStatusCode(500);
$output = ((Http::isDevelopment())) ? [
@@ -592,6 +607,9 @@ $http->on(Constant::EVENT_REQUEST, function (SwooleRequest $swooleRequest, Swool
];
$swooleResponse->end(\json_encode($output));
} finally {
Span::add('http.response.code', $response->getStatusCode());
Span::current()?->finish();
}
});
+8
View File
@@ -0,0 +1,8 @@
<?php
use Utopia\Span\Exporter;
use Utopia\Span\Span;
use Utopia\Span\Storage;
Span::setStorage(new Storage\Coroutine());
Span::addExporter(new Exporter\Pretty());
+1 -5
View File
@@ -45,17 +45,13 @@ use Utopia\Queue\Message;
use Utopia\Queue\Publisher;
use Utopia\Queue\Server;
use Utopia\Registry\Registry;
use Utopia\Span\Exporter;
use Utopia\Span\Span;
use Utopia\Span\Storage;
use Utopia\Storage\Device\Telemetry as TelemetryDevice;
use Utopia\System\System;
use Utopia\Telemetry\Adapter as Telemetry;
use Utopia\Telemetry\Adapter\None as NoTelemetry;
Runtime::enableCoroutine();
Span::setStorage(new Storage\Coroutine());
Span::addExporter(new Exporter\Stdout());
require_once __DIR__ . '/init/span.php';
global $register;
Server::setResource('register', fn () => $register);
+2 -1
View File
@@ -59,7 +59,7 @@
"utopia-php/detector": "0.2.*",
"utopia-php/domains": "1.*",
"utopia-php/emails": "0.6.*",
"utopia-php/dns": "1.5.*",
"utopia-php/dns": "1.6.*",
"utopia-php/dsn": "0.2.1",
"utopia-php/framework": "0.33.*",
"utopia-php/fetch": "0.5.*",
@@ -70,6 +70,7 @@
"utopia-php/migration": "1.5.*",
"utopia-php/platform": "0.7.*",
"utopia-php/pools": "1.*",
"utopia-php/span": "1.1.*",
"utopia-php/preloader": "0.2.*",
"utopia-php/queue": "0.15.*",
"utopia-php/registry": "0.5.*",
Generated
+15 -14
View File
@@ -3948,22 +3948,22 @@
},
{
"name": "utopia-php/dns",
"version": "1.5.4",
"version": "1.6.2",
"source": {
"type": "git",
"url": "https://github.com/utopia-php/dns.git",
"reference": "ee831a6f2ceb28babb042ea65539c26ea4530bf6"
"reference": "98c70520213a41e2fe1867e5b110273c06bf1cab"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/utopia-php/dns/zipball/ee831a6f2ceb28babb042ea65539c26ea4530bf6",
"reference": "ee831a6f2ceb28babb042ea65539c26ea4530bf6",
"url": "https://api.github.com/repos/utopia-php/dns/zipball/98c70520213a41e2fe1867e5b110273c06bf1cab",
"reference": "98c70520213a41e2fe1867e5b110273c06bf1cab",
"shasum": ""
},
"require": {
"php": ">=8.3",
"utopia-php/domains": "1.0.*",
"utopia-php/span": "1.0.*",
"utopia-php/span": "1.1.*",
"utopia-php/telemetry": "*",
"utopia-php/validators": "0.*"
},
@@ -3999,9 +3999,9 @@
],
"support": {
"issues": "https://github.com/utopia-php/dns/issues",
"source": "https://github.com/utopia-php/dns/tree/1.5.4"
"source": "https://github.com/utopia-php/dns/tree/1.6.2"
},
"time": "2026-02-02T10:40:38+00:00"
"time": "2026-02-13T12:29:08+00:00"
},
{
"name": "utopia-php/domains",
@@ -4909,25 +4909,26 @@
},
{
"name": "utopia-php/span",
"version": "1.0.0",
"version": "1.1.4",
"source": {
"type": "git",
"url": "https://github.com/utopia-php/span.git",
"reference": "f2f6c499ded3a776e8019902e83d140ff0f89693"
"reference": "49d04aa588a2cdbbc9381ee7a1c129469e0f905c"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/utopia-php/span/zipball/f2f6c499ded3a776e8019902e83d140ff0f89693",
"reference": "f2f6c499ded3a776e8019902e83d140ff0f89693",
"url": "https://api.github.com/repos/utopia-php/span/zipball/49d04aa588a2cdbbc9381ee7a1c129469e0f905c",
"reference": "49d04aa588a2cdbbc9381ee7a1c129469e0f905c",
"shasum": ""
},
"require": {
"php": ">=8.1"
"php": ">=8.2"
},
"require-dev": {
"laravel/pint": "^1.0",
"phpstan/phpstan": "^2.0",
"phpunit/phpunit": "^10.0",
"rector/rector": "^2.3",
"swoole/ide-helper": "^5.0"
},
"suggest": {
@@ -4946,9 +4947,9 @@
"description": "Simple span tracing library for PHP with coroutine support",
"support": {
"issues": "https://github.com/utopia-php/span/issues",
"source": "https://github.com/utopia-php/span/tree/1.0.0"
"source": "https://github.com/utopia-php/span/tree/1.1.4"
},
"time": "2026-01-12T20:05:10+00:00"
"time": "2026-02-13T10:58:12+00:00"
},
{
"name": "utopia-php/storage",
+1
View File
@@ -572,6 +572,7 @@ services:
environment:
# Specific
- _APP_BROWSER_HOST
- _APP_WORKER_SCREENSHOTS_ROUTER
# Basic
- _APP_ENV
- _APP_WORKER_PER_CORE
@@ -301,7 +301,7 @@ class Create extends Base
if ($async) {
if (is_null($scheduledAt)) {
if (System::getEnv('_APP_REGION') !== 'nyc') { // TODO: Remove region check
if ($project->getId() != '6862e6a6000cce69f9da') {
$execution = $authorization->skip(fn () => $dbForProject->createDocument('executions', $execution));
}
$queueForFunctions
@@ -344,7 +344,7 @@ class Create extends Base
->setAttribute('scheduleInternalId', $schedule->getSequence())
->setAttribute('scheduledAt', $scheduledAt);
if (System::getEnv('_APP_REGION') !== 'nyc') { // TODO: Remove region check
if ($project->getId() != '6862e6a6000cce69f9da') {
$execution = $authorization->skip(fn () => $dbForProject->createDocument('executions', $execution));
}
}
@@ -505,7 +505,7 @@ class Create extends Base
->addMetric(str_replace(['{resourceType}', '{resourceInternalId}'], [RESOURCE_TYPE_FUNCTIONS, $function->getSequence()], METRIC_RESOURCE_TYPE_ID_EXECUTIONS_MB_SECONDS), (int)(($spec['memory'] ?? APP_COMPUTE_MEMORY_DEFAULT) * $execution->getAttribute('duration', 0) * ($spec['cpus'] ?? APP_COMPUTE_CPUS_DEFAULT)))
;
if (System::getEnv('_APP_REGION') !== 'nyc') { // TODO: Remove region check
if ($project->getId() != '6862e6a6000cce69f9da') {
$execution = $authorization->skip(fn () => $dbForProject->createDocument('executions', $execution));
}
}
@@ -111,15 +111,16 @@ class Screenshots extends Action
throw new \Exception('Bucket not found');
}
$routerHost = System::getEnv('_APP_WORKER_SCREENSHOTS_ROUTER', 'http://appwrite');
$configs = [
'screenshotLight' => [
'headers' => [ 'x-appwrite-hostname' => $rule->getAttribute('domain') ],
'url' => 'http://appwrite/?appwrite-preview=1&appwrite-theme=light',
'url' => $routerHost . '/?appwrite-preview=1&appwrite-theme=light',
'theme' => 'light'
],
'screenshotDark' => [
'headers' => [ 'x-appwrite-hostname' => $rule->getAttribute('domain') ],
'url' => 'http://appwrite/?appwrite-preview=1&appwrite-theme=dark',
'url' => $routerHost . '/?appwrite-preview=1&appwrite-theme=dark',
'theme' => 'dark'
],
];
+2 -2
View File
@@ -7,7 +7,6 @@ use Utopia\Database\Database;
use Utopia\Database\Document;
use Utopia\Platform\Action;
use Utopia\Queue\Message;
use Utopia\System\System;
class Executions extends Action
{
@@ -45,7 +44,8 @@ class Executions extends Action
throw new Exception('Missing execution');
}
if (System::getEnv('_APP_REGION') !== 'nyc') { // TODO: Remove region check
$project = new Document($payload['project'] ?? []);
if ($project->getId() != '6862e6a6000cce69f9da') {
$dbForProject->upsertDocument('executions', $execution);
}
}