mirror of
https://github.com/appwrite/appwrite
synced 2026-05-22 08:28:42 +00:00
Merge branch '1.6.x' into fix-redirect-validator-v2
This commit is contained in:
commit
d2a4361e8d
5 changed files with 245 additions and 428 deletions
|
|
@ -45,13 +45,13 @@
|
|||
"ext-sockets": "*",
|
||||
"appwrite/php-runtimes": "0.16.*",
|
||||
"appwrite/php-clamav": "2.0.*",
|
||||
"utopia-php/abuse": "0.47.*",
|
||||
"utopia-php/abuse": "0.48.*",
|
||||
"utopia-php/analytics": "0.10.*",
|
||||
"utopia-php/audit": "0.47.*",
|
||||
"utopia-php/audit": "0.48.*",
|
||||
"utopia-php/cache": "0.11.*",
|
||||
"utopia-php/cli": "0.15.*",
|
||||
"utopia-php/config": "0.2.*",
|
||||
"utopia-php/database": "0.56.4",
|
||||
"utopia-php/database": "0.57.*",
|
||||
"utopia-php/domains": "0.5.*",
|
||||
"utopia-php/dsn": "0.2.1",
|
||||
"utopia-php/framework": "0.33.*",
|
||||
|
|
|
|||
82
composer.lock
generated
82
composer.lock
generated
|
|
@ -4,7 +4,7 @@
|
|||
"Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies",
|
||||
"This file is @generated automatically"
|
||||
],
|
||||
"content-hash": "3cd37ea04612e04b9e76eb51c5da41dd",
|
||||
"content-hash": "8927ec7d3cfa460ce223e4c13cf61ada",
|
||||
"packages": [
|
||||
{
|
||||
"name": "adhocore/jwt",
|
||||
|
|
@ -3136,16 +3136,16 @@
|
|||
},
|
||||
{
|
||||
"name": "utopia-php/abuse",
|
||||
"version": "0.47.0",
|
||||
"version": "0.48.0",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/utopia-php/abuse.git",
|
||||
"reference": "2b52bb362234d4072b647ed57db1b3be030f57c2"
|
||||
"reference": "8387c65cc7148af58adbbede06eedc1a7b568e57"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/utopia-php/abuse/zipball/2b52bb362234d4072b647ed57db1b3be030f57c2",
|
||||
"reference": "2b52bb362234d4072b647ed57db1b3be030f57c2",
|
||||
"url": "https://api.github.com/repos/utopia-php/abuse/zipball/8387c65cc7148af58adbbede06eedc1a7b568e57",
|
||||
"reference": "8387c65cc7148af58adbbede06eedc1a7b568e57",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
|
|
@ -3153,13 +3153,13 @@
|
|||
"ext-pdo": "*",
|
||||
"ext-redis": "*",
|
||||
"php": ">=8.0",
|
||||
"utopia-php/database": "0.56.*"
|
||||
"utopia-php/database": "0.57.*"
|
||||
},
|
||||
"require-dev": {
|
||||
"laravel/pint": "1.5.*",
|
||||
"phpbench/phpbench": "^1.2",
|
||||
"phpstan/phpstan": "^1.9",
|
||||
"phpunit/phpunit": "^9.4"
|
||||
"laravel/pint": "1.*",
|
||||
"phpbench/phpbench": "1.*",
|
||||
"phpstan/phpstan": "1.*",
|
||||
"phpunit/phpunit": "9.*"
|
||||
},
|
||||
"type": "library",
|
||||
"autoload": {
|
||||
|
|
@ -3181,9 +3181,9 @@
|
|||
],
|
||||
"support": {
|
||||
"issues": "https://github.com/utopia-php/abuse/issues",
|
||||
"source": "https://github.com/utopia-php/abuse/tree/0.47.0"
|
||||
"source": "https://github.com/utopia-php/abuse/tree/0.48.0"
|
||||
},
|
||||
"time": "2025-01-15T02:41:02+00:00"
|
||||
"time": "2025-01-23T04:40:14+00:00"
|
||||
},
|
||||
{
|
||||
"name": "utopia-php/analytics",
|
||||
|
|
@ -3233,26 +3233,26 @@
|
|||
},
|
||||
{
|
||||
"name": "utopia-php/audit",
|
||||
"version": "0.47.0",
|
||||
"version": "0.48.0",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/utopia-php/audit.git",
|
||||
"reference": "1ebd5784ba68645073426f2f04a67726a1bde4d7"
|
||||
"reference": "6aab185fce3ba7878b0f26cc8b4eefa1663fb395"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/utopia-php/audit/zipball/1ebd5784ba68645073426f2f04a67726a1bde4d7",
|
||||
"reference": "1ebd5784ba68645073426f2f04a67726a1bde4d7",
|
||||
"url": "https://api.github.com/repos/utopia-php/audit/zipball/6aab185fce3ba7878b0f26cc8b4eefa1663fb395",
|
||||
"reference": "6aab185fce3ba7878b0f26cc8b4eefa1663fb395",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
"php": ">=8.0",
|
||||
"utopia-php/database": "0.56.*"
|
||||
"utopia-php/database": "0.57.*"
|
||||
},
|
||||
"require-dev": {
|
||||
"laravel/pint": "1.5.*",
|
||||
"phpstan/phpstan": "^1.8",
|
||||
"phpunit/phpunit": "^9.3"
|
||||
"laravel/pint": "1.*",
|
||||
"phpstan/phpstan": "1.*",
|
||||
"phpunit/phpunit": "9.*"
|
||||
},
|
||||
"type": "library",
|
||||
"autoload": {
|
||||
|
|
@ -3274,9 +3274,9 @@
|
|||
],
|
||||
"support": {
|
||||
"issues": "https://github.com/utopia-php/audit/issues",
|
||||
"source": "https://github.com/utopia-php/audit/tree/0.47.0"
|
||||
"source": "https://github.com/utopia-php/audit/tree/0.48.0"
|
||||
},
|
||||
"time": "2025-01-15T02:40:53+00:00"
|
||||
"time": "2025-01-23T04:40:07+00:00"
|
||||
},
|
||||
{
|
||||
"name": "utopia-php/cache",
|
||||
|
|
@ -3476,16 +3476,16 @@
|
|||
},
|
||||
{
|
||||
"name": "utopia-php/database",
|
||||
"version": "0.56.4",
|
||||
"version": "0.57.2",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/utopia-php/database.git",
|
||||
"reference": "240478a60797124a885ceac40046fe47c22415b7"
|
||||
"reference": "bd6f080dd9f4210349a6a862fa6da65a4d9d6339"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/utopia-php/database/zipball/240478a60797124a885ceac40046fe47c22415b7",
|
||||
"reference": "240478a60797124a885ceac40046fe47c22415b7",
|
||||
"url": "https://api.github.com/repos/utopia-php/database/zipball/bd6f080dd9f4210349a6a862fa6da65a4d9d6339",
|
||||
"reference": "bd6f080dd9f4210349a6a862fa6da65a4d9d6339",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
|
|
@ -3526,9 +3526,9 @@
|
|||
],
|
||||
"support": {
|
||||
"issues": "https://github.com/utopia-php/database/issues",
|
||||
"source": "https://github.com/utopia-php/database/tree/0.56.4"
|
||||
"source": "https://github.com/utopia-php/database/tree/0.57.2"
|
||||
},
|
||||
"time": "2025-01-20T09:22:08+00:00"
|
||||
"time": "2025-01-23T05:19:02+00:00"
|
||||
},
|
||||
{
|
||||
"name": "utopia-php/domains",
|
||||
|
|
@ -3929,35 +3929,35 @@
|
|||
},
|
||||
{
|
||||
"name": "utopia-php/migration",
|
||||
"version": "0.6.15",
|
||||
"version": "0.6.16",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/utopia-php/migration.git",
|
||||
"reference": "e849ec3e7ad38f5f5273ebb0132b112639cdf01c"
|
||||
"reference": "a1da9b75a0e406ea8caca0d61b57a4d206ea0715"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/utopia-php/migration/zipball/e849ec3e7ad38f5f5273ebb0132b112639cdf01c",
|
||||
"reference": "e849ec3e7ad38f5f5273ebb0132b112639cdf01c",
|
||||
"url": "https://api.github.com/repos/utopia-php/migration/zipball/a1da9b75a0e406ea8caca0d61b57a4d206ea0715",
|
||||
"reference": "a1da9b75a0e406ea8caca0d61b57a4d206ea0715",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
"appwrite/appwrite": "11.1.*",
|
||||
"appwrite/appwrite": "11.*",
|
||||
"ext-curl": "*",
|
||||
"ext-openssl": "*",
|
||||
"php": "8.3.*",
|
||||
"utopia-php/database": "0.56.*",
|
||||
"php": ">=8.3",
|
||||
"utopia-php/database": "0.57.*",
|
||||
"utopia-php/dsn": "0.2.*",
|
||||
"utopia-php/framework": "0.33.*",
|
||||
"utopia-php/storage": "0.18.*"
|
||||
},
|
||||
"require-dev": {
|
||||
"ext-pdo": "*",
|
||||
"laravel/pint": "1.17.*",
|
||||
"phpstan/phpstan": "1.11.*",
|
||||
"phpunit/phpunit": "11.2.*",
|
||||
"laravel/pint": "1.*",
|
||||
"phpstan/phpstan": "1.*",
|
||||
"phpunit/phpunit": "11.*",
|
||||
"utopia-php/cli": "0.16.*",
|
||||
"vlucas/phpdotenv": "5.6.*"
|
||||
"vlucas/phpdotenv": "5.*"
|
||||
},
|
||||
"type": "library",
|
||||
"autoload": {
|
||||
|
|
@ -3979,9 +3979,9 @@
|
|||
],
|
||||
"support": {
|
||||
"issues": "https://github.com/utopia-php/migration/issues",
|
||||
"source": "https://github.com/utopia-php/migration/tree/0.6.15"
|
||||
"source": "https://github.com/utopia-php/migration/tree/0.6.16"
|
||||
},
|
||||
"time": "2025-01-15T04:55:08+00:00"
|
||||
"time": "2025-01-23T04:34:02+00:00"
|
||||
},
|
||||
{
|
||||
"name": "utopia-php/mongo",
|
||||
|
|
|
|||
|
|
@ -30,16 +30,13 @@ class Usage extends Action
|
|||
*/
|
||||
public function __construct()
|
||||
{
|
||||
|
||||
$this
|
||||
->desc('Usage worker')
|
||||
->inject('message')
|
||||
->inject('project')
|
||||
->inject('getProjectDB')
|
||||
->inject('queueForUsageDump')
|
||||
->callback(function (Message $message, Document $project, callable $getProjectDB, UsageDump $queueForUsageDump) {
|
||||
$this->action($message, $project, $getProjectDB, $queueForUsageDump);
|
||||
});
|
||||
->desc('Usage worker')
|
||||
->inject('message')
|
||||
->inject('project')
|
||||
->inject('getProjectDB')
|
||||
->inject('queueForUsageDump')
|
||||
->callback([$this, 'action']);
|
||||
|
||||
$this->aggregationInterval = (int) System::getEnv('_APP_USAGE_AGGREGATION_INTERVAL', '20');
|
||||
$this->lastTriggeredTime = time();
|
||||
|
|
@ -61,7 +58,6 @@ class Usage extends Action
|
|||
throw new Exception('Missing payload');
|
||||
}
|
||||
|
||||
|
||||
if (empty($project->getAttribute('database'))) {
|
||||
var_dump($payload);
|
||||
return;
|
||||
|
|
|
|||
|
|
@ -7,7 +7,7 @@ use Utopia\CLI\Console;
|
|||
use Utopia\Database\Database;
|
||||
use Utopia\Database\DateTime;
|
||||
use Utopia\Database\Document;
|
||||
use Utopia\Database\Exception\Duplicate;
|
||||
use Utopia\Database\Exception\NotFound;
|
||||
use Utopia\Platform\Action;
|
||||
use Utopia\Queue\Message;
|
||||
use Utopia\System\System;
|
||||
|
|
@ -38,9 +38,7 @@ class UsageDump extends Action
|
|||
$this
|
||||
->inject('message')
|
||||
->inject('getProjectDB')
|
||||
->callback(function (Message $message, callable $getProjectDB) {
|
||||
$this->action($message, $getProjectDB);
|
||||
});
|
||||
->callback([$this, 'action']);
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -57,230 +55,247 @@ class UsageDump extends Action
|
|||
throw new Exception('Missing payload');
|
||||
}
|
||||
|
||||
try {
|
||||
foreach ($payload['stats'] ?? [] as $stats) {
|
||||
$project = new Document($stats['project'] ?? []);
|
||||
$numberOfKeys = !empty($stats['keys']) ? \count($stats['keys']) : 0;
|
||||
$receivedAt = $stats['receivedAt'] ?? 'NONE';
|
||||
if ($numberOfKeys === 0) {
|
||||
continue;
|
||||
}
|
||||
|
||||
foreach ($payload['stats'] ?? [] as $stats) {
|
||||
$project = new Document($stats['project'] ?? []);
|
||||
|
||||
/**
|
||||
* End temp bug fallback
|
||||
*/
|
||||
$numberOfKeys = !empty($stats['keys']) ? count($stats['keys']) : 0;
|
||||
$receivedAt = $stats['receivedAt'] ?? 'NONE';
|
||||
if ($numberOfKeys === 0) {
|
||||
continue;
|
||||
}
|
||||
|
||||
console::log('['.DateTime::now().'] Id: '.$project->getId(). ' InternalId: '.$project->getInternalId(). ' Db: '.$project->getAttribute('database').' ReceivedAt: '.$receivedAt. ' Keys: '.$numberOfKeys);
|
||||
|
||||
try {
|
||||
$dbForProject = $getProjectDB($project);
|
||||
$projectDocuments = [];
|
||||
$databaseCache = [];
|
||||
$collectionSizeCache = [];
|
||||
|
||||
Console::log('['.DateTime::now().'] Id: '.$project->getId(). ' InternalId: '.$project->getInternalId(). ' Db: '.$project->getAttribute('database').' ReceivedAt: '.$receivedAt. ' Keys: '.$numberOfKeys . ' Started');
|
||||
$start = \microtime(true);
|
||||
|
||||
foreach ($stats['keys'] ?? [] as $key => $value) {
|
||||
if ($value == 0) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (str_contains($key, METRIC_DATABASES_STORAGE)) {
|
||||
try {
|
||||
$this->handleDatabaseStorage($key, $dbForProject);
|
||||
} catch (\Exception $e) {
|
||||
console::error('[' . DateTime::now() . '] failed to calculate database storage for key [' . $key . '] ' . $e->getMessage());
|
||||
}
|
||||
continue;
|
||||
}
|
||||
|
||||
foreach ($this->periods as $period => $format) {
|
||||
$time = 'inf' === $period ? null : date($format, time());
|
||||
$time = 'inf' === $period ? null : \date($format, \time());
|
||||
$id = \md5("{$time}_{$period}_{$key}");
|
||||
|
||||
try {
|
||||
$dbForProject->createDocument('stats', new Document([
|
||||
'$id' => $id,
|
||||
'period' => $period,
|
||||
'time' => $time,
|
||||
'metric' => $key,
|
||||
'value' => $value,
|
||||
'region' => System::getEnv('_APP_REGION', 'default'),
|
||||
]));
|
||||
} catch (Duplicate $th) {
|
||||
if ($value < 0) {
|
||||
$dbForProject->decreaseDocumentAttribute(
|
||||
'stats',
|
||||
$id,
|
||||
'value',
|
||||
abs($value)
|
||||
);
|
||||
} else {
|
||||
$dbForProject->increaseDocumentAttribute(
|
||||
'stats',
|
||||
$id,
|
||||
'value',
|
||||
$value
|
||||
);
|
||||
}
|
||||
if (\str_contains($key, METRIC_DATABASES_STORAGE)) {
|
||||
$this->handleDatabaseStorage(
|
||||
$id,
|
||||
$key,
|
||||
$time,
|
||||
$period,
|
||||
$dbForProject,
|
||||
$projectDocuments,
|
||||
$databaseCache,
|
||||
$collectionSizeCache
|
||||
);
|
||||
continue;
|
||||
}
|
||||
|
||||
$projectDocuments[] = new Document([
|
||||
'$id' => $id,
|
||||
'period' => $period,
|
||||
'time' => $time,
|
||||
'metric' => $key,
|
||||
'value' => $value,
|
||||
'region' => System::getEnv('_APP_REGION', 'default'),
|
||||
]);
|
||||
}
|
||||
}
|
||||
} catch (\Exception $e) {
|
||||
console::error('[' . DateTime::now() . '] project [' . $project->getInternalId() . '] database [' . $project['database'] . '] ' . ' ' . $e->getMessage());
|
||||
|
||||
$dbForProject->createOrUpdateDocumentsWithIncrease(
|
||||
collection: 'stats',
|
||||
attribute: 'value',
|
||||
documents: $projectDocuments
|
||||
);
|
||||
|
||||
$end = \microtime(true);
|
||||
Console::log('['.DateTime::now().'] Id: '.$project->getId(). ' InternalId: '.$project->getInternalId(). ' Db: '.$project->getAttribute('database').' ReceivedAt: '.$receivedAt. ' Keys: '.$numberOfKeys. ' Time: '.($end - $start).'s');
|
||||
}
|
||||
} catch (\Exception $e) {
|
||||
Console::error('[' . DateTime::now() . '] Error processing stats: ' . $e->getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
private function handleDatabaseStorage(string $key, Database $dbForProject): void
|
||||
{
|
||||
$data = explode('.', $key);
|
||||
$start = microtime(true);
|
||||
private function handleDatabaseStorage(
|
||||
string $id,
|
||||
string $key,
|
||||
?string $time,
|
||||
string $period,
|
||||
Database $dbForProject,
|
||||
array &$projectDocuments,
|
||||
array &$databaseCache,
|
||||
array &$collectionSizeCache,
|
||||
): void {
|
||||
$data = \explode('.', $key);
|
||||
$value = 0;
|
||||
$previousValue = 0;
|
||||
|
||||
$updateMetric = function (Database $dbForProject, int $value, string $key, string $period, string|null $time) {
|
||||
$id = \md5("{$time}_{$period}_{$key}");
|
||||
try {
|
||||
$previousValue = $dbForProject
|
||||
->getDocument('stats', $id)
|
||||
->getAttribute('value', 0);
|
||||
} catch (\Exception) {
|
||||
// No previous value
|
||||
}
|
||||
|
||||
try {
|
||||
$dbForProject->createDocument('stats', new Document([
|
||||
'$id' => $id,
|
||||
'period' => $period,
|
||||
'time' => $time,
|
||||
'metric' => $key,
|
||||
'value' => $value,
|
||||
'region' => System::getEnv('_APP_REGION', 'default'),
|
||||
]));
|
||||
} catch (Duplicate $th) {
|
||||
if ($value < 0) {
|
||||
$dbForProject->decreaseDocumentAttribute(
|
||||
'stats',
|
||||
$id,
|
||||
'value',
|
||||
abs($value)
|
||||
);
|
||||
} else {
|
||||
$dbForProject->increaseDocumentAttribute(
|
||||
'stats',
|
||||
$id,
|
||||
'value',
|
||||
$value
|
||||
);
|
||||
switch (\count($data)) {
|
||||
case METRIC_COLLECTION_LEVEL_STORAGE:
|
||||
$databaseInternalId = $data[0];
|
||||
$collectionInternalId = $data[1];
|
||||
$collectionId = "database_{$databaseInternalId}_collection_{$collectionInternalId}";
|
||||
|
||||
if (!isset($collectionSizeCache[$collectionId])) {
|
||||
try {
|
||||
$collectionSizeCache[$collectionId] = $dbForProject->getSizeOfCollection($collectionId);
|
||||
} catch (\Exception $e) {
|
||||
if (!$e instanceof NotFound) {
|
||||
throw $e;
|
||||
}
|
||||
$collectionSizeCache[$collectionId] = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
foreach ($this->periods as $period => $format) {
|
||||
$time = 'inf' === $period ? null : date($format, time());
|
||||
$id = \md5("{$time}_{$period}_{$key}");
|
||||
$value = $collectionSizeCache[$collectionId];
|
||||
|
||||
$value = 0;
|
||||
$previousValue = 0;
|
||||
try {
|
||||
$previousValue = ($dbForProject->getDocument('stats', $id))->getAttribute('value', 0);
|
||||
} catch (\Exception $e) {
|
||||
// No previous value
|
||||
}
|
||||
|
||||
switch (count($data)) {
|
||||
// Collection Level
|
||||
case METRIC_COLLECTION_LEVEL_STORAGE:
|
||||
Console::log('[' . DateTime::now() . '] Collection Level Storage Calculation [' . $key . ']');
|
||||
$databaseInternalId = $data[0];
|
||||
$collectionInternalId = $data[1];
|
||||
|
||||
try {
|
||||
$value = $dbForProject->getSizeOfCollection('database_' . $databaseInternalId . '_collection_' . $collectionInternalId);
|
||||
} catch (\Exception $e) {
|
||||
// Collection not found
|
||||
if ($e->getMessage() !== 'Collection not found') {
|
||||
throw $e;
|
||||
}
|
||||
}
|
||||
|
||||
// Compare with previous value
|
||||
$diff = $value - $previousValue;
|
||||
|
||||
if ($diff === 0) {
|
||||
break;
|
||||
}
|
||||
|
||||
// Update Collection
|
||||
$updateMetric($dbForProject, $diff, $key, $period, $time);
|
||||
|
||||
// Update Database
|
||||
$databaseKey = str_replace(['{databaseInternalId}'], [$data[0]], METRIC_DATABASE_ID_STORAGE);
|
||||
$updateMetric($dbForProject, $diff, $databaseKey, $period, $time);
|
||||
|
||||
// Update Project
|
||||
$projectKey = METRIC_DATABASES_STORAGE;
|
||||
$updateMetric($dbForProject, $diff, $projectKey, $period, $time);
|
||||
$diff = $value - $previousValue;
|
||||
if ($diff === 0) {
|
||||
break;
|
||||
// Database Level
|
||||
case METRIC_DATABASE_LEVEL_STORAGE:
|
||||
Console::log('[' . DateTime::now() . '] Database Level Storage Calculation [' . $key . ']');
|
||||
$databaseInternalId = $data[0];
|
||||
}
|
||||
|
||||
$collections = [];
|
||||
$keys = [
|
||||
$key,
|
||||
\str_replace(['{databaseInternalId}'], [$data[0]], METRIC_DATABASE_ID_STORAGE),
|
||||
METRIC_DATABASES_STORAGE
|
||||
];
|
||||
|
||||
foreach ($keys as $metric) {
|
||||
$projectDocuments[] = $this->createStatsDocument($id, $period, $time, $metric, $diff);
|
||||
}
|
||||
break;
|
||||
|
||||
case METRIC_DATABASE_LEVEL_STORAGE:
|
||||
$databaseInternalId = $data[0];
|
||||
$databaseId = "database_{$databaseInternalId}";
|
||||
|
||||
if (!isset($databaseCache[$databaseId])) {
|
||||
try {
|
||||
$collections = $dbForProject->find('database_' . $databaseInternalId);
|
||||
$databaseCache[$databaseId] = $dbForProject->find($databaseId);
|
||||
} catch (\Exception $e) {
|
||||
// Database not found
|
||||
if ($e->getMessage() !== 'Collection not found') {
|
||||
if (!$e instanceof NotFound) {
|
||||
throw $e;
|
||||
}
|
||||
$databaseCache[$databaseId] = [];
|
||||
}
|
||||
}
|
||||
|
||||
foreach ($collections as $collection) {
|
||||
foreach ($databaseCache[$databaseId] as $collection) {
|
||||
$collectionId = "{$databaseId}_collection_{$collection->getInternalId()}";
|
||||
|
||||
if (!isset($collectionSizeCache[$collectionId])) {
|
||||
try {
|
||||
$value += $dbForProject->getSizeOfCollection('database_' . $databaseInternalId . '_collection_' . $collection->getInternalId());
|
||||
$collectionSizeCache[$collectionId] = $dbForProject->getSizeOfCollection($collectionId);
|
||||
} catch (\Exception $e) {
|
||||
// Collection not found
|
||||
if ($e->getMessage() !== 'Collection not found') {
|
||||
if (!$e instanceof NotFound) {
|
||||
throw $e;
|
||||
}
|
||||
$collectionSizeCache[$collectionId] = 0;
|
||||
}
|
||||
}
|
||||
$value += $collectionSizeCache[$collectionId];
|
||||
}
|
||||
|
||||
$diff = $value - $previousValue;
|
||||
if ($diff === 0) {
|
||||
break;
|
||||
}
|
||||
|
||||
$keys = [
|
||||
\str_replace(['{databaseInternalId}'], [$data[0]], METRIC_DATABASE_ID_STORAGE),
|
||||
METRIC_DATABASES_STORAGE
|
||||
];
|
||||
|
||||
foreach ($keys as $metric) {
|
||||
$projectDocuments[] = $this->createStatsDocument($id, $period, $time, $metric, $diff);
|
||||
}
|
||||
break;
|
||||
|
||||
case METRIC_PROJECT_LEVEL_STORAGE:
|
||||
if (!isset($databaseCache['*'])) {
|
||||
try {
|
||||
$databaseCache['*'] = $dbForProject->find('databases');
|
||||
} catch (\Exception $e) {
|
||||
if (!$e instanceof NotFound) {
|
||||
throw $e;
|
||||
}
|
||||
$databaseCache['*'] = [];
|
||||
}
|
||||
}
|
||||
|
||||
foreach ($databaseCache['*'] as $database) {
|
||||
$databaseId = "database_{$database->getInternalId()}";
|
||||
if (!isset($databaseCache[$databaseId])) {
|
||||
try {
|
||||
$databaseCache[$databaseId] = $dbForProject->find($databaseId);
|
||||
} catch (\Exception $e) {
|
||||
if (!$e instanceof NotFound) {
|
||||
throw $e;
|
||||
}
|
||||
$databaseCache[$databaseId] = [];
|
||||
}
|
||||
}
|
||||
|
||||
$diff = $value - $previousValue;
|
||||
foreach ($databaseCache[$databaseId] as $collection) {
|
||||
$collectionId = "{$databaseId}_collection_{$collection->getInternalId()}";
|
||||
|
||||
if ($diff === 0) {
|
||||
break;
|
||||
}
|
||||
|
||||
// Update Database
|
||||
$databaseKey = str_replace(['{databaseInternalId}'], [$data[0]], METRIC_DATABASE_ID_STORAGE);
|
||||
$updateMetric($dbForProject, $diff, $databaseKey, $period, $time);
|
||||
|
||||
// Update Project
|
||||
$projectKey = METRIC_DATABASES_STORAGE;
|
||||
$updateMetric($dbForProject, $diff, $projectKey, $period, $time);
|
||||
break;
|
||||
// Project Level
|
||||
case METRIC_PROJECT_LEVEL_STORAGE:
|
||||
Console::log('[' . DateTime::now() . '] Project Level Storage Calculation [' . $key . ']');
|
||||
// Get all project databases
|
||||
$databases = $dbForProject->find('database');
|
||||
|
||||
// Recalculate all databases
|
||||
foreach ($databases as $database) {
|
||||
$collections = $dbForProject->find('database_' . $database->getInternalId());
|
||||
|
||||
foreach ($collections as $collection) {
|
||||
if (!isset($collectionSizeCache[$collectionId])) {
|
||||
try {
|
||||
$value += $dbForProject->getSizeOfCollection('database_' . $database->getInternalId() . '_collection_' . $collection->getInternalId());
|
||||
$collectionSizeCache[$collectionId] = $dbForProject->getSizeOfCollection($collectionId);
|
||||
} catch (\Exception $e) {
|
||||
// Collection not found
|
||||
if ($e->getMessage() !== 'Collection not found') {
|
||||
if (!$e instanceof NotFound) {
|
||||
throw $e;
|
||||
}
|
||||
$collectionSizeCache[$collectionId] = 0;
|
||||
}
|
||||
}
|
||||
$value += $collectionSizeCache[$collectionId];
|
||||
}
|
||||
}
|
||||
|
||||
$diff = $value - $previousValue;
|
||||
|
||||
// Update Project
|
||||
$projectKey = METRIC_DATABASES_STORAGE;
|
||||
$updateMetric($dbForProject, $diff, $projectKey, $period, $time);
|
||||
$diff = $value - $previousValue;
|
||||
if ($diff === 0) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
$keys = [
|
||||
METRIC_DATABASES_STORAGE
|
||||
];
|
||||
|
||||
foreach ($keys as $metric) {
|
||||
$projectDocuments[] = $this->createStatsDocument($id, $period, $time, $metric, $diff);
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
$end = microtime(true);
|
||||
|
||||
console::log('[' . DateTime::now() . '] DB Storage Calculation [' . $key . '] took ' . (($end - $start) * 1000) . ' milliseconds');
|
||||
private function createStatsDocument(
|
||||
string $id,
|
||||
string $period,
|
||||
?string $time,
|
||||
string $key,
|
||||
int $diff,
|
||||
): Document {
|
||||
return new Document([
|
||||
'$id' => $id,
|
||||
'period' => $period,
|
||||
'time' => $time,
|
||||
'metric' => $key,
|
||||
'value' => $diff,
|
||||
'region' => System::getEnv('_APP_REGION', 'default'),
|
||||
]);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -651,200 +651,6 @@ class UsageTest extends Scope
|
|||
];
|
||||
}
|
||||
|
||||
// /** @depends testDatabaseStoragePrepare */
|
||||
// #[Retry(count: 1)]
|
||||
// public function testDatabaseStorageStatsCreateDocument(array $data): array
|
||||
// {
|
||||
// $databaseId = $data['databaseId'];
|
||||
// $collectionId = $data['collectionId'];
|
||||
|
||||
// $originalProjectMetrics = $this->client->call(
|
||||
// Client::METHOD_GET,
|
||||
// '/project/usage',
|
||||
// $this->getConsoleHeaders(),
|
||||
// [
|
||||
// 'period' => '1d',
|
||||
// 'startDate' => self::getToday(),
|
||||
// 'endDate' => self::getTomorrow(),
|
||||
// ]
|
||||
// );
|
||||
|
||||
// $this->assertEquals(200, $originalProjectMetrics['headers']['status-code']);
|
||||
// $this->assertArrayHasKey('databasesStorageTotal', $originalProjectMetrics['body']);
|
||||
|
||||
// $originalProjectMetrics = $originalProjectMetrics['body'];
|
||||
|
||||
// $originalDatabaseMetrics = $this->client->call(
|
||||
// Client::METHOD_GET,
|
||||
// '/databases/' . $databaseId . '/usage?range=30d',
|
||||
// $this->getConsoleHeaders()
|
||||
// );
|
||||
|
||||
// $this->assertEquals(200, $originalDatabaseMetrics['headers']['status-code']);
|
||||
// $this->assertArrayHasKey('storageTotal', $originalDatabaseMetrics['body']);
|
||||
// $originalDatabaseMetrics = $originalDatabaseMetrics['body'];
|
||||
|
||||
// // Create documents
|
||||
// for ($i = 0; $i < 100; $i++) {
|
||||
// $response = $this->client->call(
|
||||
// Client::METHOD_POST,
|
||||
// '/databases/' . $databaseId . '/collections/' . $collectionId . '/documents',
|
||||
// array_merge([
|
||||
// 'content-type' => 'application/json',
|
||||
// 'x-appwrite-project' => $this->getProject()['$id']
|
||||
// ], $this->getHeaders()),
|
||||
// [
|
||||
// 'documentId' => 'unique()',
|
||||
// 'data' => ['data' => str_repeat('a', 10000)],
|
||||
// ]
|
||||
// );
|
||||
|
||||
// $this->assertEquals(201, $response['headers']['status-code']);
|
||||
// }
|
||||
|
||||
// sleep(self::WAIT);
|
||||
|
||||
// for ($i = 0; $i < 3; $i++) {
|
||||
// try {
|
||||
// $newProjectMetrics = $this->client->call(
|
||||
// Client::METHOD_GET,
|
||||
// '/project/usage',
|
||||
// $this->getConsoleHeaders(),
|
||||
// [
|
||||
// 'period' => '1d',
|
||||
// 'startDate' => self::getToday(),
|
||||
// 'endDate' => self::getTomorrow(),
|
||||
// ]
|
||||
// );
|
||||
|
||||
// $this->assertEquals(200, $newProjectMetrics['headers']['status-code']);
|
||||
// $this->assertArrayHasKey('databasesStorageTotal', $newProjectMetrics['body']);
|
||||
// $this->assertGreaterThan($originalProjectMetrics['databasesStorageTotal'], $newProjectMetrics['body']['databasesStorageTotal']);
|
||||
|
||||
// $newProjectMetrics = $newProjectMetrics['body'];
|
||||
|
||||
// $newDatabaseMetrics = $this->client->call(
|
||||
// Client::METHOD_GET,
|
||||
// '/databases/' . $databaseId . '/usage?range=30d',
|
||||
// $this->getConsoleHeaders()
|
||||
// );
|
||||
|
||||
// $this->assertEquals(200, $newDatabaseMetrics['headers']['status-code']);
|
||||
// $this->assertArrayHasKey('storageTotal', $newDatabaseMetrics['body']);
|
||||
// $this->assertGreaterThan($originalDatabaseMetrics['storageTotal'], $newDatabaseMetrics['body']['storageTotal']);
|
||||
|
||||
// $newDatabaseMetrics = $newDatabaseMetrics['body'];
|
||||
|
||||
// return [
|
||||
// 'databaseId' => $databaseId,
|
||||
// 'collectionId' => $collectionId,
|
||||
// 'currentProjectMetrics' => $newProjectMetrics,
|
||||
// 'currentDatabaseMetrics' => $newDatabaseMetrics,
|
||||
// ];
|
||||
// } catch (ExpectationFailedException $e) {
|
||||
// if ($i === 2) {
|
||||
// throw $e;
|
||||
// }
|
||||
// sleep(self::WAIT);
|
||||
// continue;
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
|
||||
// /** @depends testDatabaseStorageStatsCreateDocument */
|
||||
// #[Retry(count: 1)]
|
||||
// public function testDatabaseStorageStatsDeleteDocument(array $data): array
|
||||
// {
|
||||
// $databaseId = $data['databaseId'];
|
||||
// $collectionId = $data['collectionId'];
|
||||
// $currentProjectMetrics = $data['currentProjectMetrics'];
|
||||
// $currentDatabaseMetrics = $data['currentDatabaseMetrics'];
|
||||
|
||||
// $documents = $this->client->call(
|
||||
// Client::METHOD_GET,
|
||||
// '/databases/' . $databaseId . '/collections/' . $collectionId . '/documents',
|
||||
// array_merge([
|
||||
// 'x-appwrite-project' => $this->getProject()['$id']
|
||||
// ], $this->getHeaders()),
|
||||
// [
|
||||
// 'queries' => [
|
||||
// Query::limit(50)->toString()
|
||||
// ]
|
||||
// ]
|
||||
// );
|
||||
|
||||
// foreach ($documents['body']['documents'] as $document) {
|
||||
// $response = $this->client->call(
|
||||
// Client::METHOD_DELETE,
|
||||
// '/databases/' . $databaseId . '/collections/' . $collectionId . '/documents/' . $document['$id'],
|
||||
// array_merge([
|
||||
// 'x-appwrite-project' => $this->getProject()['$id']
|
||||
// ], $this->getHeaders())
|
||||
// );
|
||||
|
||||
// $this->assertEquals(204, $response['headers']['status-code']);
|
||||
// }
|
||||
|
||||
// sleep(self::WAIT);
|
||||
|
||||
// for ($i = 0; $i < 3; $i++) {
|
||||
// try {
|
||||
// $newProjectMetrics = $this->client->call(
|
||||
// Client::METHOD_GET,
|
||||
// '/project/usage',
|
||||
// $this->getConsoleHeaders(),
|
||||
// [
|
||||
// 'period' => '1d',
|
||||
// 'startDate' => self::getToday(),
|
||||
// 'endDate' => self::getTomorrow(),
|
||||
// ]
|
||||
// );
|
||||
|
||||
// $this->assertEquals(200, $newProjectMetrics['headers']['status-code']);
|
||||
// $this->assertArrayHasKey('databasesStorageTotal', $newProjectMetrics['body']);
|
||||
// $this->assertLessThan($currentProjectMetrics['databasesStorageTotal'], $newProjectMetrics['body']['databasesStorageTotal']);
|
||||
|
||||
// $newProjectMetrics = $newProjectMetrics['body'];
|
||||
|
||||
// $newDatabaseMetrics = $this->client->call(
|
||||
// Client::METHOD_GET,
|
||||
// '/databases/' . $databaseId . '/usage?range=30d',
|
||||
// $this->getConsoleHeaders()
|
||||
// );
|
||||
|
||||
// $this->assertEquals(200, $newDatabaseMetrics['headers']['status-code']);
|
||||
// $this->assertArrayHasKey('storageTotal', $newDatabaseMetrics['body']);
|
||||
// $this->assertLessThan($currentDatabaseMetrics['storageTotal'], $newDatabaseMetrics['body']['storageTotal']);
|
||||
|
||||
// $newDatabaseMetrics = $newDatabaseMetrics['body'];
|
||||
|
||||
// return [
|
||||
// 'databaseId' => $databaseId,
|
||||
// 'collectionId' => $collectionId,
|
||||
// 'currentProjectMetrics' => $newProjectMetrics,
|
||||
// 'currentDatabaseMetrics' => $newDatabaseMetrics,
|
||||
// ];
|
||||
// } catch (ExpectationFailedException $e) {
|
||||
// if ($i === 2) {
|
||||
// throw $e;
|
||||
// }
|
||||
// sleep(self::WAIT);
|
||||
// continue;
|
||||
// }
|
||||
// }
|
||||
|
||||
// $newProjectMetrics = $this->client->call(
|
||||
// Client::METHOD_GET,
|
||||
// '/project/usage',
|
||||
// $this->getConsoleHeaders(),
|
||||
// [
|
||||
// 'period' => '1d',
|
||||
// 'startDate' => self::getToday(),
|
||||
// 'endDate' => self::getTomorrow(),
|
||||
// ]
|
||||
// );
|
||||
// }
|
||||
|
||||
/** @depends testDatabaseStats */
|
||||
public function testPrepareFunctionsStats(array $data): array
|
||||
{
|
||||
|
|
|
|||
Loading…
Reference in a new issue