Merge pull request #8797 from appwrite/feat-migration

Feat migration
This commit is contained in:
Christy Jacob 2024-11-12 10:27:24 +01:00 committed by GitHub
commit 9151abc951
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
15 changed files with 169 additions and 100 deletions

View file

@ -127,6 +127,11 @@ jobs:
Messaging, Messaging,
Migrations Migrations
] ]
tables-mode: [
'Project',
'Shared V1',
'Shared V2',
]
steps: steps:
- name: checkout - name: checkout
@ -145,11 +150,11 @@ jobs:
docker compose up -d docker compose up -d
sleep 30 sleep 30
- name: Run ${{matrix.service}} Tests - name: Run ${{ matrix.service }} tests with ${{ matrix.tables-mode }} table mode
run: docker compose exec -T appwrite test /usr/src/code/tests/e2e/Services/${{matrix.service}} --debug run: docker compose exec -T appwrite test /usr/src/code/tests/e2e/Services/${{ matrix.service }} --debug
env:
- name: Run ${{matrix.service}} Shared Tables Tests _APP_DATABASE_SHARED_TABLES: ${{ matrix.table_mode == 'Shared V1' || matrix.table_mode == 'Shared V2' && 'database_db_main' || '' }}
run: _APP_DATABASE_SHARED_TABLES=database_db_main docker compose exec -T appwrite test /usr/src/code/tests/e2e/Services/${{matrix.service}} --debug _APP_DATABASE_SHARED_TABLES_V1: ${{ matrix.table_mode == 'Shared V1' && 'database_db_main' || '' }}
benchmarking: benchmarking:
name: Benchmark name: Benchmark

View file

@ -114,8 +114,9 @@ CLI::setResource('getProjectDB', function (Group $pools, Database $dbForConsole,
if (isset($databases[$dsn->getHost()])) { if (isset($databases[$dsn->getHost()])) {
$database = $databases[$dsn->getHost()]; $database = $databases[$dsn->getHost()];
$sharedTables = \explode(',', System::getEnv('_APP_DATABASE_SHARED_TABLES', ''));
if ($dsn->getHost() === System::getEnv('_APP_DATABASE_SHARED_TABLES', '')) { if (\in_array($dsn->getHost(), $sharedTables)) {
$database $database
->setSharedTables(true) ->setSharedTables(true)
->setTenant($project->getInternalId()) ->setTenant($project->getInternalId())
@ -136,10 +137,10 @@ CLI::setResource('getProjectDB', function (Group $pools, Database $dbForConsole,
->getResource(); ->getResource();
$database = new Database($dbAdapter, $cache); $database = new Database($dbAdapter, $cache);
$databases[$dsn->getHost()] = $database; $databases[$dsn->getHost()] = $database;
$sharedTables = \explode(',', System::getEnv('_APP_DATABASE_SHARED_TABLES', ''));
if ($dsn->getHost() === System::getEnv('_APP_DATABASE_SHARED_TABLES', '')) { if (\in_array($dsn->getHost(), $sharedTables)) {
$database $database
->setSharedTables(true) ->setSharedTables(true)
->setTenant($project->getInternalId()) ->setTenant($project->getInternalId())

View file

@ -686,7 +686,7 @@ return [
], ],
Exception::ATTRIBUTE_LIMIT_EXCEEDED => [ Exception::ATTRIBUTE_LIMIT_EXCEEDED => [
'name' => Exception::ATTRIBUTE_LIMIT_EXCEEDED, 'name' => Exception::ATTRIBUTE_LIMIT_EXCEEDED,
'description' => 'The maximum number of attributes has been reached.', 'description' => 'The maximum number or size of attributes for this collection has been reached.',
'code' => 400, 'code' => 400,
], ],
Exception::ATTRIBUTE_VALUE_INVALID => [ Exception::ATTRIBUTE_VALUE_INVALID => [

View file

@ -153,7 +153,7 @@ function createAttribute(string $databaseId, string $collectionId, Document $att
} catch (DuplicateException) { } catch (DuplicateException) {
throw new Exception(Exception::ATTRIBUTE_ALREADY_EXISTS); throw new Exception(Exception::ATTRIBUTE_ALREADY_EXISTS);
} catch (LimitException) { } catch (LimitException) {
throw new Exception(Exception::ATTRIBUTE_LIMIT_EXCEEDED, 'Attribute limit exceeded'); throw new Exception(Exception::ATTRIBUTE_LIMIT_EXCEEDED);
} catch (\Throwable $e) { } catch (\Throwable $e) {
$dbForProject->purgeCachedDocument('database_' . $db->getInternalId(), $collectionId); $dbForProject->purgeCachedDocument('database_' . $db->getInternalId(), $collectionId);
$dbForProject->purgeCachedCollection('database_' . $db->getInternalId() . '_collection_' . $collection->getInternalId()); $dbForProject->purgeCachedCollection('database_' . $db->getInternalId() . '_collection_' . $collection->getInternalId());
@ -197,7 +197,7 @@ function createAttribute(string $databaseId, string $collectionId, Document $att
throw new Exception(Exception::ATTRIBUTE_ALREADY_EXISTS); throw new Exception(Exception::ATTRIBUTE_ALREADY_EXISTS);
} catch (LimitException) { } catch (LimitException) {
$dbForProject->deleteDocument('attributes', $attribute->getId()); $dbForProject->deleteDocument('attributes', $attribute->getId());
throw new Exception(Exception::ATTRIBUTE_LIMIT_EXCEEDED, 'Attribute limit exceeded'); throw new Exception(Exception::ATTRIBUTE_LIMIT_EXCEEDED);
} catch (\Throwable $e) { } catch (\Throwable $e) {
$dbForProject->purgeCachedDocument('database_' . $db->getInternalId(), $relatedCollection->getId()); $dbForProject->purgeCachedDocument('database_' . $db->getInternalId(), $relatedCollection->getId());
$dbForProject->purgeCachedCollection('database_' . $db->getInternalId() . '_collection_' . $relatedCollection->getInternalId()); $dbForProject->purgeCachedCollection('database_' . $db->getInternalId() . '_collection_' . $relatedCollection->getInternalId());
@ -393,6 +393,8 @@ function updateAttribute(
throw new Exception(Exception::ATTRIBUTE_INVALID_RESIZE); throw new Exception(Exception::ATTRIBUTE_INVALID_RESIZE);
} catch (NotFoundException) { } catch (NotFoundException) {
throw new Exception(Exception::ATTRIBUTE_NOT_FOUND); throw new Exception(Exception::ATTRIBUTE_NOT_FOUND);
} catch (LimitException) {
throw new Exception(Exception::ATTRIBUTE_LIMIT_EXCEEDED);
} }
} }
@ -2627,7 +2629,8 @@ App::post('/v1/databases/:databaseId/collections/:collectionId/indexes')
$validator = new IndexValidator( $validator = new IndexValidator(
$collection->getAttribute('attributes'), $collection->getAttribute('attributes'),
$dbForProject->getAdapter()->getMaxIndexLength() $dbForProject->getAdapter()->getMaxIndexLength(),
$dbForProject->getAdapter()->getInternalIndexesKeys(),
); );
if (!$validator->isValid($index)) { if (!$validator->isValid($index)) {
throw new Exception(Exception::INDEX_INVALID, $validator->getDescription()); throw new Exception(Exception::INDEX_INVALID, $validator->getDescription());

View file

@ -122,6 +122,10 @@ App::post('/v1/projects')
$projectId = ($projectId == 'unique()') ? ID::unique() : $projectId; $projectId = ($projectId == 'unique()') ? ID::unique() : $projectId;
if ($projectId === 'console') {
throw new Exception(Exception::PROJECT_RESERVED_PROJECT, "'console' is a reserved project.");
}
$databases = Config::getParam('pools-database', []); $databases = Config::getParam('pools-database', []);
$databaseOverride = System::getEnv('_APP_DATABASE_OVERRIDE'); $databaseOverride = System::getEnv('_APP_DATABASE_OVERRIDE');
@ -132,16 +136,14 @@ App::post('/v1/projects')
$dsn = $databases[array_rand($databases)]; $dsn = $databases[array_rand($databases)];
} }
if ($projectId === 'console') {
throw new Exception(Exception::PROJECT_RESERVED_PROJECT, "'console' is a reserved project.");
}
// TODO: Temporary until all projects are using shared tables. // TODO: Temporary until all projects are using shared tables.
if ($dsn === System::getEnv('_APP_DATABASE_SHARED_TABLES', '')) { $sharedTables = \explode(',', System::getEnv('_APP_DATABASE_SHARED_TABLES', ''));
if (\in_array($dsn, $sharedTables)) {
$schema = 'appwrite'; $schema = 'appwrite';
$database = 'appwrite'; $database = 'appwrite';
$namespace = System::getEnv('_APP_DATABASE_SHARED_NAMESPACE', ''); $namespace = System::getEnv('_APP_DATABASE_SHARED_NAMESPACE', '');
$dsn = $schema . '://' . System::getEnv('_APP_DATABASE_SHARED_TABLES', '') . '?database=' . $database; $dsn = $schema . '://' . $dsn . '?database=' . $database;
if (!empty($namespace)) { if (!empty($namespace)) {
$dsn .= '&namespace=' . $namespace; $dsn .= '&namespace=' . $namespace;
@ -195,11 +197,18 @@ App::post('/v1/projects')
$adapter = $pools->get($dsn->getHost())->pop()->getResource(); $adapter = $pools->get($dsn->getHost())->pop()->getResource();
$dbForProject = new Database($adapter, $cache); $dbForProject = new Database($adapter, $cache);
$sharedTables = \explode(',', System::getEnv('_APP_DATABASE_SHARED_TABLES', ''));
$sharedTablesV1 = \explode(',', System::getEnv('_APP_DATABASE_SHARED_TABLES_V1', ''));
if ($dsn->getHost() === System::getEnv('_APP_DATABASE_SHARED_TABLES', '')) { $projectTables = !\in_array($dsn->getHost(), $sharedTables);
$sharedTablesV1 = \in_array($dsn->getHost(), $sharedTablesV1);
$sharedTablesV2 = !$projectTables && !$sharedTablesV1;
$sharedTables = $sharedTablesV1 || $sharedTablesV2;
if ($sharedTables) {
$dbForProject $dbForProject
->setSharedTables(true) ->setSharedTables(true)
->setTenant($project->getInternalId()) ->setTenant($sharedTablesV1 ? $project->getInternalId() : null)
->setNamespace($dsn->getParam('namespace')); ->setNamespace($dsn->getParam('namespace'));
} else { } else {
$dbForProject $dbForProject
@ -208,34 +217,70 @@ App::post('/v1/projects')
->setNamespace('_' . $project->getInternalId()); ->setNamespace('_' . $project->getInternalId());
} }
$dbForProject->create(); $create = true;
$audit = new Audit($dbForProject); try {
$audit->setup(); $dbForProject->create();
} catch (Duplicate) {
$create = false;
}
$abuse = new TimeLimit('', 0, 1, $dbForProject); if ($create || $projectTables) {
$abuse->setup(); $audit = new Audit($dbForProject);
$audit->setup();
/** @var array $collections */ $abuse = new TimeLimit('', 0, 1, $dbForProject);
$collections = Config::getParam('collections', [])['projects'] ?? []; $abuse->setup();
}
foreach ($collections as $key => $collection) { if (!$create && $sharedTablesV1) {
if (($collection['$collection'] ?? '') !== Database::METADATA) { $attributes = \array_map(fn ($attribute) => new Document($attribute), Audit::ATTRIBUTES);
continue; $indexes = \array_map(fn (array $index) => new Document($index), Audit::INDEXES);
} $dbForProject->createDocument(Database::METADATA, new Document([
'$id' => ID::custom('audit'),
'$permissions' => [Permission::create(Role::any())],
'name' => 'audit',
'attributes' => $attributes,
'indexes' => $indexes,
'documentSecurity' => true
]));
$attributes = \array_map(function (array $attribute) { $attributes = \array_map(fn ($attribute) => new Document($attribute), TimeLimit::ATTRIBUTES);
return new Document($attribute); $indexes = \array_map(fn (array $index) => new Document($index), TimeLimit::INDEXES);
}, $collection['attributes']); $dbForProject->createDocument(Database::METADATA, new Document([
'$id' => ID::custom('abuse'),
'$permissions' => [Permission::create(Role::any())],
'name' => 'abuse',
'attributes' => $attributes,
'indexes' => $indexes,
'documentSecurity' => true
]));
}
$indexes = \array_map(function (array $index) { if ($create || $sharedTablesV1) {
return new Document($index); /** @var array $collections */
}, $collection['indexes']); $collections = Config::getParam('collections', [])['projects'] ?? [];
try { foreach ($collections as $key => $collection) {
$dbForProject->createCollection($key, $attributes, $indexes); if (($collection['$collection'] ?? '') !== Database::METADATA) {
} catch (Duplicate) { continue;
// Collection already exists }
$attributes = \array_map(fn ($attribute) => new Document($attribute), $collection['attributes']);
$indexes = \array_map(fn (array $index) => new Document($index), $collection['indexes']);
try {
$dbForProject->createCollection($key, $attributes, $indexes);
} catch (Duplicate) {
$dbForProject->createDocument(Database::METADATA, new Document([
'$id' => ID::custom($key),
'$permissions' => [Permission::create(Role::any())],
'name' => $key,
'attributes' => $attributes,
'indexes' => $indexes,
'documentSecurity' => true
]));
}
} }
} }

View file

@ -16,6 +16,7 @@ use Utopia\CLI\Console;
use Utopia\Config\Config; use Utopia\Config\Config;
use Utopia\Database\Database; use Utopia\Database\Database;
use Utopia\Database\Document; use Utopia\Database\Document;
use Utopia\Database\Exception\Duplicate;
use Utopia\Database\Helpers\ID; use Utopia\Database\Helpers\ID;
use Utopia\Database\Helpers\Permission; use Utopia\Database\Helpers\Permission;
use Utopia\Database\Helpers\Role; use Utopia\Database\Helpers\Role;
@ -91,7 +92,7 @@ $http->on(Constant::EVENT_START, function (Server $http) use ($payloadSize, $reg
try { try {
Console::success('[Setup] - Creating database: appwrite...'); Console::success('[Setup] - Creating database: appwrite...');
$dbForConsole->create(); $dbForConsole->create();
} catch (\Throwable $e) { } catch (Duplicate) {
Console::success('[Setup] - Skip: metadata table already exists'); Console::success('[Setup] - Skip: metadata table already exists');
} }
@ -223,7 +224,7 @@ $http->on(Constant::EVENT_START, function (Server $http) use ($payloadSize, $reg
}); });
}); });
$http->on('request', function (SwooleRequest $swooleRequest, SwooleResponse $swooleResponse) use ($register) { $http->on(Constant::EVENT_REQUEST, function (SwooleRequest $swooleRequest, SwooleResponse $swooleResponse) use ($register) {
App::setResource('swooleRequest', fn () => $swooleRequest); App::setResource('swooleRequest', fn () => $swooleRequest);
App::setResource('swooleResponse', fn () => $swooleResponse); App::setResource('swooleResponse', fn () => $swooleResponse);

View file

@ -1432,7 +1432,9 @@ App::setResource('dbForProject', function (Group $pools, Database $dbForConsole,
$dsn = new DSN('mysql://' . $project->getAttribute('database')); $dsn = new DSN('mysql://' . $project->getAttribute('database'));
} }
if ($dsn->getHost() === System::getEnv('_APP_DATABASE_SHARED_TABLES', '')) { $sharedTables = \explode(',', System::getEnv('_APP_DATABASE_SHARED_TABLES', ''));
if (\in_array($dsn->getHost(), $sharedTables)) {
$database $database
->setSharedTables(true) ->setSharedTables(true)
->setTenant($project->getInternalId()) ->setTenant($project->getInternalId())
@ -1487,7 +1489,9 @@ App::setResource('getProjectDB', function (Group $pools, Database $dbForConsole,
->setTimeout(APP_DATABASE_TIMEOUT_MILLISECONDS) ->setTimeout(APP_DATABASE_TIMEOUT_MILLISECONDS)
->setMaxQueryValues(APP_DATABASE_QUERY_MAX_VALUES); ->setMaxQueryValues(APP_DATABASE_QUERY_MAX_VALUES);
if ($dsn->getHost() === System::getEnv('_APP_DATABASE_SHARED_TABLES', '')) { $sharedTables = \explode(',', System::getEnv('_APP_DATABASE_SHARED_TABLES', ''));
if (\in_array($dsn->getHost(), $sharedTables)) {
$database $database
->setSharedTables(true) ->setSharedTables(true)
->setTenant($project->getInternalId()) ->setTenant($project->getInternalId())

View file

@ -92,7 +92,9 @@ if (!function_exists('getProjectDB')) {
$database = new Database($adapter, getCache()); $database = new Database($adapter, getCache());
if ($dsn->getHost() === System::getEnv('_APP_DATABASE_SHARED_TABLES', '')) { $sharedTables = \explode(',', System::getEnv('_APP_DATABASE_SHARED_TABLES', ''));
if (\in_array($dsn->getHost(), $sharedTables)) {
$database $database
->setSharedTables(true) ->setSharedTables(true)
->setTenant($project->getInternalId()) ->setTenant($project->getInternalId())

View file

@ -93,7 +93,9 @@ Server::setResource('dbForProject', function (Cache $cache, Registry $register,
$dsn = new DSN('mysql://' . $project->getAttribute('database')); $dsn = new DSN('mysql://' . $project->getAttribute('database'));
} }
if ($dsn->getHost() === System::getEnv('_APP_DATABASE_SHARED_TABLES', '')) { $sharedTables = \explode(',', System::getEnv('_APP_DATABASE_SHARED_TABLES', ''));
if (\in_array($dsn->getHost(), $sharedTables)) {
$database $database
->setSharedTables(true) ->setSharedTables(true)
->setTenant($project->getInternalId()) ->setTenant($project->getInternalId())
@ -126,7 +128,9 @@ Server::setResource('getProjectDB', function (Group $pools, Database $dbForConso
if (isset($databases[$dsn->getHost()])) { if (isset($databases[$dsn->getHost()])) {
$database = $databases[$dsn->getHost()]; $database = $databases[$dsn->getHost()];
if ($dsn->getHost() === System::getEnv('_APP_DATABASE_SHARED_TABLES', '')) { $sharedTables = \explode(',', System::getEnv('_APP_DATABASE_SHARED_TABLES', ''));
if (\in_array($dsn->getHost(), $sharedTables)) {
$database $database
->setSharedTables(true) ->setSharedTables(true)
->setTenant($project->getInternalId()) ->setTenant($project->getInternalId())
@ -150,7 +154,9 @@ Server::setResource('getProjectDB', function (Group $pools, Database $dbForConso
$databases[$dsn->getHost()] = $database; $databases[$dsn->getHost()] = $database;
if ($dsn->getHost() === System::getEnv('_APP_DATABASE_SHARED_TABLES', '')) { $sharedTables = \explode(',', System::getEnv('_APP_DATABASE_SHARED_TABLES', ''));
if (\in_array($dsn->getHost(), $sharedTables)) {
$database $database
->setSharedTables(true) ->setSharedTables(true)
->setTenant($project->getInternalId()) ->setTenant($project->getInternalId())

View file

@ -45,13 +45,13 @@
"ext-sockets": "*", "ext-sockets": "*",
"appwrite/php-runtimes": "0.16.*", "appwrite/php-runtimes": "0.16.*",
"appwrite/php-clamav": "2.0.*", "appwrite/php-clamav": "2.0.*",
"utopia-php/abuse": "0.43.0", "utopia-php/abuse": "0.43.*",
"utopia-php/analytics": "0.10.*", "utopia-php/analytics": "0.10.*",
"utopia-php/audit": "0.43.0", "utopia-php/audit": "0.43.*",
"utopia-php/cache": "0.11.*", "utopia-php/cache": "0.11.*",
"utopia-php/cli": "0.15.*", "utopia-php/cli": "0.15.*",
"utopia-php/config": "0.2.*", "utopia-php/config": "0.2.*",
"utopia-php/database": "0.53.16", "utopia-php/database": "0.53.20",
"utopia-php/domains": "0.5.*", "utopia-php/domains": "0.5.*",
"utopia-php/dsn": "0.2.1", "utopia-php/dsn": "0.2.1",
"utopia-php/framework": "0.33.*", "utopia-php/framework": "0.33.*",

86
composer.lock generated
View file

@ -4,7 +4,7 @@
"Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies", "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies",
"This file is @generated automatically" "This file is @generated automatically"
], ],
"content-hash": "b358198535c1867eabed7c0f99135a57", "content-hash": "217b0c1b6c156d51bf5a2674f87a7630",
"packages": [ "packages": [
{ {
"name": "adhocore/jwt", "name": "adhocore/jwt",
@ -1430,16 +1430,16 @@
}, },
{ {
"name": "utopia-php/abuse", "name": "utopia-php/abuse",
"version": "0.43.0", "version": "0.43.1",
"source": { "source": {
"type": "git", "type": "git",
"url": "https://github.com/utopia-php/abuse.git", "url": "https://github.com/utopia-php/abuse.git",
"reference": "6346a3b4c5177a43160035a7289e30fdfb0790d6" "reference": "e404c21e8dcf6a310bc83cf1d74e716b105598fa"
}, },
"dist": { "dist": {
"type": "zip", "type": "zip",
"url": "https://api.github.com/repos/utopia-php/abuse/zipball/6346a3b4c5177a43160035a7289e30fdfb0790d6", "url": "https://api.github.com/repos/utopia-php/abuse/zipball/e404c21e8dcf6a310bc83cf1d74e716b105598fa",
"reference": "6346a3b4c5177a43160035a7289e30fdfb0790d6", "reference": "e404c21e8dcf6a310bc83cf1d74e716b105598fa",
"shasum": "" "shasum": ""
}, },
"require": { "require": {
@ -1475,9 +1475,9 @@
], ],
"support": { "support": {
"issues": "https://github.com/utopia-php/abuse/issues", "issues": "https://github.com/utopia-php/abuse/issues",
"source": "https://github.com/utopia-php/abuse/tree/0.43.0" "source": "https://github.com/utopia-php/abuse/tree/0.43.1"
}, },
"time": "2024-08-30T05:17:23+00:00" "time": "2024-10-23T04:29:12+00:00"
}, },
{ {
"name": "utopia-php/analytics", "name": "utopia-php/analytics",
@ -1527,16 +1527,16 @@
}, },
{ {
"name": "utopia-php/audit", "name": "utopia-php/audit",
"version": "0.43.0", "version": "0.43.1",
"source": { "source": {
"type": "git", "type": "git",
"url": "https://github.com/utopia-php/audit.git", "url": "https://github.com/utopia-php/audit.git",
"reference": "cef22b5dc6a6d28fcd522f41c7bf7ded4a4dfd3e" "reference": "04a47dd1f5f92e2d50e971a06bcc9e759325d277"
}, },
"dist": { "dist": {
"type": "zip", "type": "zip",
"url": "https://api.github.com/repos/utopia-php/audit/zipball/cef22b5dc6a6d28fcd522f41c7bf7ded4a4dfd3e", "url": "https://api.github.com/repos/utopia-php/audit/zipball/04a47dd1f5f92e2d50e971a06bcc9e759325d277",
"reference": "cef22b5dc6a6d28fcd522f41c7bf7ded4a4dfd3e", "reference": "04a47dd1f5f92e2d50e971a06bcc9e759325d277",
"shasum": "" "shasum": ""
}, },
"require": { "require": {
@ -1568,9 +1568,9 @@
], ],
"support": { "support": {
"issues": "https://github.com/utopia-php/audit/issues", "issues": "https://github.com/utopia-php/audit/issues",
"source": "https://github.com/utopia-php/audit/tree/0.43.0" "source": "https://github.com/utopia-php/audit/tree/0.43.1"
}, },
"time": "2024-08-30T05:17:36+00:00" "time": "2024-10-23T04:27:59+00:00"
}, },
{ {
"name": "utopia-php/cache", "name": "utopia-php/cache",
@ -1770,16 +1770,16 @@
}, },
{ {
"name": "utopia-php/database", "name": "utopia-php/database",
"version": "0.53.16", "version": "0.53.20",
"source": { "source": {
"type": "git", "type": "git",
"url": "https://github.com/utopia-php/database.git", "url": "https://github.com/utopia-php/database.git",
"reference": "6661edffeef05b59e16d102b989a72f7f78cf7de" "reference": "e43f8ee26e06ee8812737e63642dbd7ee7c9dc04"
}, },
"dist": { "dist": {
"type": "zip", "type": "zip",
"url": "https://api.github.com/repos/utopia-php/database/zipball/6661edffeef05b59e16d102b989a72f7f78cf7de", "url": "https://api.github.com/repos/utopia-php/database/zipball/e43f8ee26e06ee8812737e63642dbd7ee7c9dc04",
"reference": "6661edffeef05b59e16d102b989a72f7f78cf7de", "reference": "e43f8ee26e06ee8812737e63642dbd7ee7c9dc04",
"shasum": "" "shasum": ""
}, },
"require": { "require": {
@ -1820,9 +1820,9 @@
], ],
"support": { "support": {
"issues": "https://github.com/utopia-php/database/issues", "issues": "https://github.com/utopia-php/database/issues",
"source": "https://github.com/utopia-php/database/tree/0.53.16" "source": "https://github.com/utopia-php/database/tree/0.53.20"
}, },
"time": "2024-11-06T03:07:16+00:00" "time": "2024-11-12T00:23:36+00:00"
}, },
{ {
"name": "utopia-php/domains", "name": "utopia-php/domains",
@ -2222,16 +2222,16 @@
}, },
{ {
"name": "utopia-php/migration", "name": "utopia-php/migration",
"version": "0.6.11", "version": "0.6.12",
"source": { "source": {
"type": "git", "type": "git",
"url": "https://github.com/utopia-php/migration.git", "url": "https://github.com/utopia-php/migration.git",
"reference": "4d167914d3f7fa1fe816b2b2c6f221e70166bfd7" "reference": "9a8c905af4cece5c5ec9542a5b534befce067260"
}, },
"dist": { "dist": {
"type": "zip", "type": "zip",
"url": "https://api.github.com/repos/utopia-php/migration/zipball/4d167914d3f7fa1fe816b2b2c6f221e70166bfd7", "url": "https://api.github.com/repos/utopia-php/migration/zipball/9a8c905af4cece5c5ec9542a5b534befce067260",
"reference": "4d167914d3f7fa1fe816b2b2c6f221e70166bfd7", "reference": "9a8c905af4cece5c5ec9542a5b534befce067260",
"shasum": "" "shasum": ""
}, },
"require": { "require": {
@ -2272,9 +2272,9 @@
], ],
"support": { "support": {
"issues": "https://github.com/utopia-php/migration/issues", "issues": "https://github.com/utopia-php/migration/issues",
"source": "https://github.com/utopia-php/migration/tree/0.6.11" "source": "https://github.com/utopia-php/migration/tree/0.6.12"
}, },
"time": "2024-10-31T06:19:57+00:00" "time": "2024-11-12T00:31:53+00:00"
}, },
{ {
"name": "utopia-php/mongo", "name": "utopia-php/mongo",
@ -2542,16 +2542,16 @@
}, },
{ {
"name": "utopia-php/queue", "name": "utopia-php/queue",
"version": "0.7.1", "version": "0.7.2",
"source": { "source": {
"type": "git", "type": "git",
"url": "https://github.com/utopia-php/queue.git", "url": "https://github.com/utopia-php/queue.git",
"reference": "94c240d9f6383829807ce7b2d737f04b159fd3e8" "reference": "40fdd9799d0a11dd33fca06f8223032a47dce2f6"
}, },
"dist": { "dist": {
"type": "zip", "type": "zip",
"url": "https://api.github.com/repos/utopia-php/queue/zipball/94c240d9f6383829807ce7b2d737f04b159fd3e8", "url": "https://api.github.com/repos/utopia-php/queue/zipball/40fdd9799d0a11dd33fca06f8223032a47dce2f6",
"reference": "94c240d9f6383829807ce7b2d737f04b159fd3e8", "reference": "40fdd9799d0a11dd33fca06f8223032a47dce2f6",
"shasum": "" "shasum": ""
}, },
"require": { "require": {
@ -2597,9 +2597,9 @@
], ],
"support": { "support": {
"issues": "https://github.com/utopia-php/queue/issues", "issues": "https://github.com/utopia-php/queue/issues",
"source": "https://github.com/utopia-php/queue/tree/0.7.1" "source": "https://github.com/utopia-php/queue/tree/0.7.2"
}, },
"time": "2024-11-05T17:00:38+00:00" "time": "2024-11-11T10:04:02+00:00"
}, },
{ {
"name": "utopia-php/registry", "name": "utopia-php/registry",
@ -2817,16 +2817,16 @@
}, },
{ {
"name": "utopia-php/vcs", "name": "utopia-php/vcs",
"version": "0.8.3", "version": "0.8.5",
"source": { "source": {
"type": "git", "type": "git",
"url": "https://github.com/utopia-php/vcs.git", "url": "https://github.com/utopia-php/vcs.git",
"reference": "a032ed0611a8f4467aeaa9484f73223074457337" "reference": "7622330628d53844a3873ca873338150756bab82"
}, },
"dist": { "dist": {
"type": "zip", "type": "zip",
"url": "https://api.github.com/repos/utopia-php/vcs/zipball/a032ed0611a8f4467aeaa9484f73223074457337", "url": "https://api.github.com/repos/utopia-php/vcs/zipball/7622330628d53844a3873ca873338150756bab82",
"reference": "a032ed0611a8f4467aeaa9484f73223074457337", "reference": "7622330628d53844a3873ca873338150756bab82",
"shasum": "" "shasum": ""
}, },
"require": { "require": {
@ -2860,9 +2860,9 @@
], ],
"support": { "support": {
"issues": "https://github.com/utopia-php/vcs/issues", "issues": "https://github.com/utopia-php/vcs/issues",
"source": "https://github.com/utopia-php/vcs/tree/0.8.3" "source": "https://github.com/utopia-php/vcs/tree/0.8.5"
}, },
"time": "2024-11-05T17:10:09+00:00" "time": "2024-11-11T18:33:10+00:00"
}, },
{ {
"name": "utopia-php/websocket", "name": "utopia-php/websocket",
@ -6923,16 +6923,16 @@
}, },
{ {
"name": "twig/twig", "name": "twig/twig",
"version": "v3.14.1", "version": "v3.14.2",
"source": { "source": {
"type": "git", "type": "git",
"url": "https://github.com/twigphp/Twig.git", "url": "https://github.com/twigphp/Twig.git",
"reference": "f405356d20fb43603bcadc8b09bfb676cb04a379" "reference": "0b6f9d8370bb3b7f1ce5313ed8feb0fafd6e399a"
}, },
"dist": { "dist": {
"type": "zip", "type": "zip",
"url": "https://api.github.com/repos/twigphp/Twig/zipball/f405356d20fb43603bcadc8b09bfb676cb04a379", "url": "https://api.github.com/repos/twigphp/Twig/zipball/0b6f9d8370bb3b7f1ce5313ed8feb0fafd6e399a",
"reference": "f405356d20fb43603bcadc8b09bfb676cb04a379", "reference": "0b6f9d8370bb3b7f1ce5313ed8feb0fafd6e399a",
"shasum": "" "shasum": ""
}, },
"require": { "require": {
@ -6986,7 +6986,7 @@
], ],
"support": { "support": {
"issues": "https://github.com/twigphp/Twig/issues", "issues": "https://github.com/twigphp/Twig/issues",
"source": "https://github.com/twigphp/Twig/tree/v3.14.1" "source": "https://github.com/twigphp/Twig/tree/v3.14.2"
}, },
"funding": [ "funding": [
{ {
@ -6998,7 +6998,7 @@
"type": "tidelift" "type": "tidelift"
} }
], ],
"time": "2024-11-06T18:17:38+00:00" "time": "2024-11-07T12:36:22+00:00"
}, },
{ {
"name": "webmozart/glob", "name": "webmozart/glob",

View file

@ -193,6 +193,7 @@ services:
- _APP_EXPERIMENT_LOGGING_PROVIDER - _APP_EXPERIMENT_LOGGING_PROVIDER
- _APP_EXPERIMENT_LOGGING_CONFIG - _APP_EXPERIMENT_LOGGING_CONFIG
- _APP_DATABASE_SHARED_TABLES - _APP_DATABASE_SHARED_TABLES
- _APP_DATABASE_SHARED_TABLES_V1
appwrite-console: appwrite-console:
<<: *x-logging <<: *x-logging

View file

@ -494,12 +494,13 @@ class Deletes extends Action
]; ];
$limit = \count($projectCollectionIds) + 25; $limit = \count($projectCollectionIds) + 25;
$sharedTables = \explode(',', System::getEnv('_APP_DATABASE_SHARED_TABLES', ''));
while (true) { while (true) {
$collections = $dbForProject->listCollections($limit); $collections = $dbForProject->listCollections($limit);
foreach ($collections as $collection) { foreach ($collections as $collection) {
if ($dsn->getHost() !== System::getEnv('_APP_DATABASE_SHARED_TABLES', '') || !\in_array($collection->getId(), $projectCollectionIds)) { if (\in_array($dsn->getHost(), $sharedTables) || !\in_array($collection->getId(), $projectCollectionIds)) {
try { try {
$dbForProject->deleteCollection($collection->getId()); $dbForProject->deleteCollection($collection->getId());
} catch (Throwable $e) { } catch (Throwable $e) {
@ -517,7 +518,7 @@ class Deletes extends Action
} }
} }
if ($dsn->getHost() === System::getEnv('_APP_DATABASE_SHARED_TABLES', '')) { if (\in_array($dsn->getHost(), $sharedTables)) {
$collectionsIds = \array_map(fn ($collection) => $collection->getId(), $collections); $collectionsIds = \array_map(fn ($collection) => $collection->getId(), $collections);
if (empty(\array_diff($collectionsIds, $projectCollectionIds))) { if (empty(\array_diff($collectionsIds, $projectCollectionIds))) {
@ -571,7 +572,7 @@ class Deletes extends Action
], $dbForConsole); ], $dbForConsole);
// Delete metadata table // Delete metadata table
if ($dsn->getHost() !== System::getEnv('_APP_DATABASE_SHARED_TABLES', '')) { if (\in_array($dsn->getHost(), $sharedTables)) {
$dbForProject->deleteCollection('_metadata'); $dbForProject->deleteCollection('_metadata');
} else { } else {
$this->deleteByGroup('_metadata', [], $dbForProject); $this->deleteByGroup('_metadata', [], $dbForProject);

View file

@ -94,7 +94,7 @@ class Func extends Model
]) ])
->addRule('schedule', [ ->addRule('schedule', [
'type' => self::TYPE_STRING, 'type' => self::TYPE_STRING,
'description' => 'Function execution schedult in CRON format.', 'description' => 'Function execution schedule in CRON format.',
'default' => '', 'default' => '',
'example' => '5 4 * * *', 'example' => '5 4 * * *',
]) ])

View file

@ -1362,7 +1362,7 @@ class DatabasesCustomServerTest extends Scope
]); ]);
$this->assertEquals(400, $tooWide['headers']['status-code']); $this->assertEquals(400, $tooWide['headers']['status-code']);
$this->assertEquals('Attribute limit exceeded', $tooWide['body']['message']); $this->assertEquals('attribute_limit_exceeded', $tooWide['body']['type']);
} }
public function testIndexLimitException() public function testIndexLimitException()