mirror of
https://github.com/appwrite/appwrite
synced 2026-05-20 23:48:23 +00:00
Merge branch 'debug-whitelist-console' of https://github.com/appwrite/appwrite into multi-region-support
This commit is contained in:
commit
3d333633e4
11 changed files with 163 additions and 141 deletions
15
.github/workflows/tests.yml
vendored
15
.github/workflows/tests.yml
vendored
|
|
@ -127,6 +127,11 @@ jobs:
|
|||
Messaging,
|
||||
Migrations
|
||||
]
|
||||
tables-mode: [
|
||||
'Project',
|
||||
'Shared V1',
|
||||
'Shared V2',
|
||||
]
|
||||
|
||||
steps:
|
||||
- name: checkout
|
||||
|
|
@ -145,11 +150,11 @@ jobs:
|
|||
docker compose up -d
|
||||
sleep 30
|
||||
|
||||
- name: Run ${{matrix.service}} Tests
|
||||
run: docker compose exec -T appwrite test /usr/src/code/tests/e2e/Services/${{matrix.service}} --debug
|
||||
|
||||
- name: Run ${{matrix.service}} Shared Tables Tests
|
||||
run: _APP_DATABASE_SHARED_TABLES=database_db_main docker compose exec -T appwrite test /usr/src/code/tests/e2e/Services/${{matrix.service}} --debug
|
||||
- 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
|
||||
env:
|
||||
_APP_DATABASE_SHARED_TABLES: ${{ matrix.table_mode == 'Shared V1' || matrix.table_mode == 'Shared V2' && 'database_db_main' || '' }}
|
||||
_APP_DATABASE_SHARED_TABLES_V1: ${{ matrix.table_mode == 'Shared V1' && 'database_db_main' || '' }}
|
||||
|
||||
benchmarking:
|
||||
name: Benchmark
|
||||
|
|
|
|||
|
|
@ -686,7 +686,7 @@ return [
|
|||
],
|
||||
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,
|
||||
],
|
||||
Exception::ATTRIBUTE_VALUE_INVALID => [
|
||||
|
|
|
|||
|
|
@ -153,7 +153,7 @@ function createAttribute(string $databaseId, string $collectionId, Document $att
|
|||
} catch (DuplicateException) {
|
||||
throw new Exception(Exception::ATTRIBUTE_ALREADY_EXISTS);
|
||||
} catch (LimitException) {
|
||||
throw new Exception(Exception::ATTRIBUTE_LIMIT_EXCEEDED, 'Attribute limit exceeded');
|
||||
throw new Exception(Exception::ATTRIBUTE_LIMIT_EXCEEDED);
|
||||
} catch (\Throwable $e) {
|
||||
$dbForProject->purgeCachedDocument('database_' . $db->getInternalId(), $collectionId);
|
||||
$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);
|
||||
} catch (LimitException) {
|
||||
$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) {
|
||||
$dbForProject->purgeCachedDocument('database_' . $db->getInternalId(), $relatedCollection->getId());
|
||||
$dbForProject->purgeCachedCollection('database_' . $db->getInternalId() . '_collection_' . $relatedCollection->getInternalId());
|
||||
|
|
@ -393,6 +393,8 @@ function updateAttribute(
|
|||
throw new Exception(Exception::ATTRIBUTE_INVALID_RESIZE);
|
||||
} catch (NotFoundException) {
|
||||
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(
|
||||
$collection->getAttribute('attributes'),
|
||||
$dbForProject->getAdapter()->getMaxIndexLength()
|
||||
$dbForProject->getAdapter()->getMaxIndexLength(),
|
||||
$dbForProject->getAdapter()->getInternalIndexesKeys(),
|
||||
);
|
||||
if (!$validator->isValid($index)) {
|
||||
throw new Exception(Exception::INDEX_INVALID, $validator->getDescription());
|
||||
|
|
|
|||
|
|
@ -136,6 +136,16 @@ App::post('/v1/projects')
|
|||
$dsn = $databases[array_rand($databases)];
|
||||
}
|
||||
|
||||
$dsns = [
|
||||
'fra' => 'database_db_fra1_self_hosted_0_0',
|
||||
'syd' => 'database_db_syd1_self_hosted_0_0',
|
||||
'nyc' => 'database_db_nyc1_self_hosted_0_0',
|
||||
];
|
||||
|
||||
if (isset($dsns[$region])) {
|
||||
$dsn = $dsns[$region];
|
||||
}
|
||||
|
||||
// TODO: Temporary until all projects are using shared tables.
|
||||
$sharedTables = \explode(',', System::getEnv('_APP_DATABASE_SHARED_TABLES', ''));
|
||||
|
||||
|
|
|
|||
|
|
@ -63,7 +63,7 @@ function router(App $utopia, Database $dbForConsole, callable $getProjectDB, Swo
|
|||
}
|
||||
|
||||
if (System::getEnv('_APP_OPTIONS_ROUTER_PROTECTION', 'disabled') === 'enabled') {
|
||||
if ($host !== 'localhost' && $host !== APP_HOSTNAME_INTERNAL) { // localhost allowed for proxy, APP_HOSTNAME_INTERNAL allowed for migrations
|
||||
if ($host !== 'localhost' && $host !== APP_HOSTNAME_INTERNAL && $host !== System::getEnv('_APP_CONSOLE_DOMAIN', '')) {
|
||||
throw new AppwriteException(AppwriteException::GENERAL_ACCESS_FORBIDDEN, 'Router protection does not allow accessing Appwrite over this domain. Please add it as custom domain to your project or disable _APP_OPTIONS_ROUTER_PROTECTION environment variable.');
|
||||
}
|
||||
}
|
||||
|
|
@ -438,7 +438,7 @@ App::init()
|
|||
});
|
||||
|
||||
App::init()
|
||||
->groups(['api', 'web'])
|
||||
->groups(['api'])
|
||||
->inject('utopia')
|
||||
->inject('swooleRequest')
|
||||
->inject('request')
|
||||
|
|
|
|||
|
|
@ -61,8 +61,6 @@ include __DIR__ . '/controllers/general.php';
|
|||
|
||||
$http->on(Constant::EVENT_START, function (Server $http) use ($payloadSize, $register) {
|
||||
$app = new App('UTC');
|
||||
$app->setCompression(true);
|
||||
$app->setCompressionMinSize(intval(System::getEnv('_APP_COMPRESSION_MIN_SIZE_BYTES', '1024'))); // 1KB
|
||||
|
||||
go(function () use ($register, $app) {
|
||||
$pools = $register->get('pools');
|
||||
|
|
|
|||
|
|
@ -51,7 +51,7 @@
|
|||
"utopia-php/cache": "0.11.*",
|
||||
"utopia-php/cli": "0.15.*",
|
||||
"utopia-php/config": "0.2.*",
|
||||
"utopia-php/database": "0.53.18",
|
||||
"utopia-php/database": "0.53.20",
|
||||
"utopia-php/domains": "0.5.*",
|
||||
"utopia-php/dsn": "0.2.1",
|
||||
"utopia-php/framework": "0.33.*",
|
||||
|
|
|
|||
52
composer.lock
generated
52
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": "bd9b8f5f8fe295deb07002ca0a953949",
|
||||
"content-hash": "217b0c1b6c156d51bf5a2674f87a7630",
|
||||
"packages": [
|
||||
{
|
||||
"name": "adhocore/jwt",
|
||||
|
|
@ -1770,16 +1770,16 @@
|
|||
},
|
||||
{
|
||||
"name": "utopia-php/database",
|
||||
"version": "0.53.18",
|
||||
"version": "0.53.20",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/utopia-php/database.git",
|
||||
"reference": "895176b61b969d326bf2e36695606b8a33132094"
|
||||
"reference": "e43f8ee26e06ee8812737e63642dbd7ee7c9dc04"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/utopia-php/database/zipball/895176b61b969d326bf2e36695606b8a33132094",
|
||||
"reference": "895176b61b969d326bf2e36695606b8a33132094",
|
||||
"url": "https://api.github.com/repos/utopia-php/database/zipball/e43f8ee26e06ee8812737e63642dbd7ee7c9dc04",
|
||||
"reference": "e43f8ee26e06ee8812737e63642dbd7ee7c9dc04",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
|
|
@ -1820,9 +1820,9 @@
|
|||
],
|
||||
"support": {
|
||||
"issues": "https://github.com/utopia-php/database/issues",
|
||||
"source": "https://github.com/utopia-php/database/tree/0.53.18"
|
||||
"source": "https://github.com/utopia-php/database/tree/0.53.20"
|
||||
},
|
||||
"time": "2024-11-08T04:02:13+00:00"
|
||||
"time": "2024-11-12T00:23:36+00:00"
|
||||
},
|
||||
{
|
||||
"name": "utopia-php/domains",
|
||||
|
|
@ -2222,16 +2222,16 @@
|
|||
},
|
||||
{
|
||||
"name": "utopia-php/migration",
|
||||
"version": "0.6.11",
|
||||
"version": "0.6.12",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/utopia-php/migration.git",
|
||||
"reference": "4d167914d3f7fa1fe816b2b2c6f221e70166bfd7"
|
||||
"reference": "9a8c905af4cece5c5ec9542a5b534befce067260"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/utopia-php/migration/zipball/4d167914d3f7fa1fe816b2b2c6f221e70166bfd7",
|
||||
"reference": "4d167914d3f7fa1fe816b2b2c6f221e70166bfd7",
|
||||
"url": "https://api.github.com/repos/utopia-php/migration/zipball/9a8c905af4cece5c5ec9542a5b534befce067260",
|
||||
"reference": "9a8c905af4cece5c5ec9542a5b534befce067260",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
|
|
@ -2272,9 +2272,9 @@
|
|||
],
|
||||
"support": {
|
||||
"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",
|
||||
|
|
@ -2542,16 +2542,16 @@
|
|||
},
|
||||
{
|
||||
"name": "utopia-php/queue",
|
||||
"version": "0.7.1",
|
||||
"version": "0.7.2",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/utopia-php/queue.git",
|
||||
"reference": "94c240d9f6383829807ce7b2d737f04b159fd3e8"
|
||||
"reference": "40fdd9799d0a11dd33fca06f8223032a47dce2f6"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/utopia-php/queue/zipball/94c240d9f6383829807ce7b2d737f04b159fd3e8",
|
||||
"reference": "94c240d9f6383829807ce7b2d737f04b159fd3e8",
|
||||
"url": "https://api.github.com/repos/utopia-php/queue/zipball/40fdd9799d0a11dd33fca06f8223032a47dce2f6",
|
||||
"reference": "40fdd9799d0a11dd33fca06f8223032a47dce2f6",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
|
|
@ -2597,9 +2597,9 @@
|
|||
],
|
||||
"support": {
|
||||
"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",
|
||||
|
|
@ -2817,16 +2817,16 @@
|
|||
},
|
||||
{
|
||||
"name": "utopia-php/vcs",
|
||||
"version": "0.8.3",
|
||||
"version": "0.8.5",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/utopia-php/vcs.git",
|
||||
"reference": "a032ed0611a8f4467aeaa9484f73223074457337"
|
||||
"reference": "7622330628d53844a3873ca873338150756bab82"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/utopia-php/vcs/zipball/a032ed0611a8f4467aeaa9484f73223074457337",
|
||||
"reference": "a032ed0611a8f4467aeaa9484f73223074457337",
|
||||
"url": "https://api.github.com/repos/utopia-php/vcs/zipball/7622330628d53844a3873ca873338150756bab82",
|
||||
"reference": "7622330628d53844a3873ca873338150756bab82",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
|
|
@ -2860,9 +2860,9 @@
|
|||
],
|
||||
"support": {
|
||||
"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",
|
||||
|
|
@ -7052,7 +7052,7 @@
|
|||
],
|
||||
"aliases": [],
|
||||
"minimum-stability": "stable",
|
||||
"stability-flags": [],
|
||||
"stability-flags": {},
|
||||
"prefer-stable": false,
|
||||
"prefer-lowest": false,
|
||||
"platform": {
|
||||
|
|
|
|||
|
|
@ -92,6 +92,7 @@ class Databases extends Action
|
|||
* @throws Authorization
|
||||
* @throws Conflict
|
||||
* @throws \Exception
|
||||
* @throws \Throwable
|
||||
*/
|
||||
private function createAttribute(Document $database, Document $collection, Document $attribute, Document $project, Database $dbForConsole, Database $dbForProject): void
|
||||
{
|
||||
|
|
@ -169,7 +170,6 @@ class Databases extends Action
|
|||
|
||||
$dbForProject->updateDocument('attributes', $attribute->getId(), $attribute->setAttribute('status', 'available'));
|
||||
} catch (\Throwable $e) {
|
||||
// TODO: Send non DatabaseExceptions to Sentry
|
||||
Console::error($e->getMessage());
|
||||
|
||||
if ($e instanceof DatabaseException) {
|
||||
|
|
@ -192,15 +192,17 @@ class Databases extends Action
|
|||
$relatedAttribute->setAttribute('status', 'failed')
|
||||
);
|
||||
}
|
||||
|
||||
throw $e;
|
||||
} finally {
|
||||
$this->trigger($database, $collection, $attribute, $project, $projectId, $events);
|
||||
}
|
||||
|
||||
if ($type === Database::VAR_RELATIONSHIP && $options['twoWay']) {
|
||||
$dbForProject->purgeCachedDocument('database_' . $database->getInternalId(), $relatedCollection->getId());
|
||||
}
|
||||
if ($type === Database::VAR_RELATIONSHIP && $options['twoWay']) {
|
||||
$dbForProject->purgeCachedDocument('database_' . $database->getInternalId(), $relatedCollection->getId());
|
||||
}
|
||||
|
||||
$dbForProject->purgeCachedDocument('database_' . $database->getInternalId(), $collectionId);
|
||||
$dbForProject->purgeCachedDocument('database_' . $database->getInternalId(), $collectionId);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -214,6 +216,7 @@ class Databases extends Action
|
|||
* @throws Authorization
|
||||
* @throws Conflict
|
||||
* @throws \Exception
|
||||
* @throws \Throwable
|
||||
**/
|
||||
private function deleteAttribute(Document $database, Document $collection, Document $attribute, Document $project, Database $dbForConsole, Database $dbForProject): void
|
||||
{
|
||||
|
|
@ -247,113 +250,116 @@ class Databases extends Action
|
|||
// - stuck: attribute was available but cannot be removed
|
||||
|
||||
try {
|
||||
if ($status !== 'failed') {
|
||||
if ($type === Database::VAR_RELATIONSHIP) {
|
||||
if ($options['twoWay']) {
|
||||
$relatedCollection = $dbForProject->getDocument('database_' . $database->getInternalId(), $options['relatedCollection']);
|
||||
if ($relatedCollection->isEmpty()) {
|
||||
throw new DatabaseException('Collection not found');
|
||||
try {
|
||||
if ($status !== 'failed') {
|
||||
if ($type === Database::VAR_RELATIONSHIP) {
|
||||
if ($options['twoWay']) {
|
||||
$relatedCollection = $dbForProject->getDocument('database_' . $database->getInternalId(), $options['relatedCollection']);
|
||||
if ($relatedCollection->isEmpty()) {
|
||||
throw new DatabaseException('Collection not found');
|
||||
}
|
||||
$relatedAttribute = $dbForProject->getDocument('attributes', $database->getInternalId() . '_' . $relatedCollection->getInternalId() . '_' . $options['twoWayKey']);
|
||||
}
|
||||
$relatedAttribute = $dbForProject->getDocument('attributes', $database->getInternalId() . '_' . $relatedCollection->getInternalId() . '_' . $options['twoWayKey']);
|
||||
}
|
||||
|
||||
if (!$dbForProject->deleteRelationship('database_' . $database->getInternalId() . '_collection_' . $collection->getInternalId(), $key)) {
|
||||
$dbForProject->updateDocument('attributes', $relatedAttribute->getId(), $relatedAttribute->setAttribute('status', 'stuck'));
|
||||
throw new DatabaseException('Failed to delete Relationship');
|
||||
if (!$dbForProject->deleteRelationship('database_' . $database->getInternalId() . '_collection_' . $collection->getInternalId(), $key)) {
|
||||
$dbForProject->updateDocument('attributes', $relatedAttribute->getId(), $relatedAttribute->setAttribute('status', 'stuck'));
|
||||
throw new DatabaseException('Failed to delete Relationship');
|
||||
}
|
||||
} elseif (!$dbForProject->deleteAttribute('database_' . $database->getInternalId() . '_collection_' . $collection->getInternalId(), $key)) {
|
||||
throw new DatabaseException('Failed to delete Attribute');
|
||||
}
|
||||
} elseif (!$dbForProject->deleteAttribute('database_' . $database->getInternalId() . '_collection_' . $collection->getInternalId(), $key)) {
|
||||
throw new DatabaseException('Failed to delete Attribute');
|
||||
}
|
||||
}
|
||||
|
||||
$dbForProject->deleteDocument('attributes', $attribute->getId());
|
||||
$dbForProject->deleteDocument('attributes', $attribute->getId());
|
||||
|
||||
if (!$relatedAttribute->isEmpty()) {
|
||||
$dbForProject->deleteDocument('attributes', $relatedAttribute->getId());
|
||||
}
|
||||
} catch (\Throwable $e) {
|
||||
// TODO: Send non DatabaseExceptions to Sentry
|
||||
Console::error($e->getMessage());
|
||||
|
||||
if ($e instanceof DatabaseException) {
|
||||
$attribute->setAttribute('error', $e->getMessage());
|
||||
if (!$relatedAttribute->isEmpty()) {
|
||||
$relatedAttribute->setAttribute('error', $e->getMessage());
|
||||
$dbForProject->deleteDocument('attributes', $relatedAttribute->getId());
|
||||
}
|
||||
} catch (\Throwable $e) {
|
||||
Console::error($e->getMessage());
|
||||
|
||||
if ($e instanceof DatabaseException) {
|
||||
$attribute->setAttribute('error', $e->getMessage());
|
||||
if (!$relatedAttribute->isEmpty()) {
|
||||
$relatedAttribute->setAttribute('error', $e->getMessage());
|
||||
}
|
||||
}
|
||||
}
|
||||
$dbForProject->updateDocument(
|
||||
'attributes',
|
||||
$attribute->getId(),
|
||||
$attribute->setAttribute('status', 'stuck')
|
||||
);
|
||||
if (!$relatedAttribute->isEmpty()) {
|
||||
$dbForProject->updateDocument(
|
||||
'attributes',
|
||||
$relatedAttribute->getId(),
|
||||
$relatedAttribute->setAttribute('status', 'stuck')
|
||||
$attribute->getId(),
|
||||
$attribute->setAttribute('status', 'stuck')
|
||||
);
|
||||
if (!$relatedAttribute->isEmpty()) {
|
||||
$dbForProject->updateDocument(
|
||||
'attributes',
|
||||
$relatedAttribute->getId(),
|
||||
$relatedAttribute->setAttribute('status', 'stuck')
|
||||
);
|
||||
}
|
||||
|
||||
throw $e;
|
||||
} finally {
|
||||
$this->trigger($database, $collection, $attribute, $project, $projectId, $events);
|
||||
}
|
||||
} finally {
|
||||
$this->trigger($database, $collection, $attribute, $project, $projectId, $events);
|
||||
}
|
||||
|
||||
// The underlying database removes/rebuilds indexes when attribute is removed
|
||||
// Update indexes table with changes
|
||||
/** @var Document[] $indexes */
|
||||
$indexes = $collection->getAttribute('indexes', []);
|
||||
// The underlying database removes/rebuilds indexes when attribute is removed
|
||||
// Update indexes table with changes
|
||||
/** @var Document[] $indexes */
|
||||
$indexes = $collection->getAttribute('indexes', []);
|
||||
|
||||
foreach ($indexes as $index) {
|
||||
/** @var string[] $attributes */
|
||||
$attributes = $index->getAttribute('attributes');
|
||||
$lengths = $index->getAttribute('lengths');
|
||||
$orders = $index->getAttribute('orders');
|
||||
foreach ($indexes as $index) {
|
||||
/** @var string[] $attributes */
|
||||
$attributes = $index->getAttribute('attributes');
|
||||
$lengths = $index->getAttribute('lengths');
|
||||
$orders = $index->getAttribute('orders');
|
||||
|
||||
$found = \array_search($key, $attributes);
|
||||
$found = \array_search($key, $attributes);
|
||||
|
||||
if ($found !== false) {
|
||||
// If found, remove entry from attributes, lengths, and orders
|
||||
// array_values wraps array_diff to reindex array keys
|
||||
// when found attribute is removed from array
|
||||
$attributes = \array_values(\array_diff($attributes, [$attributes[$found]]));
|
||||
$lengths = \array_values(\array_diff($lengths, isset($lengths[$found]) ? [$lengths[$found]] : []));
|
||||
$orders = \array_values(\array_diff($orders, isset($orders[$found]) ? [$orders[$found]] : []));
|
||||
if ($found !== false) {
|
||||
// If found, remove entry from attributes, lengths, and orders
|
||||
// array_values wraps array_diff to reindex array keys
|
||||
// when found attribute is removed from array
|
||||
$attributes = \array_values(\array_diff($attributes, [$attributes[$found]]));
|
||||
$lengths = \array_values(\array_diff($lengths, isset($lengths[$found]) ? [$lengths[$found]] : []));
|
||||
$orders = \array_values(\array_diff($orders, isset($orders[$found]) ? [$orders[$found]] : []));
|
||||
|
||||
if (empty($attributes)) {
|
||||
$dbForProject->deleteDocument('indexes', $index->getId());
|
||||
} else {
|
||||
$index
|
||||
->setAttribute('attributes', $attributes, Document::SET_TYPE_ASSIGN)
|
||||
->setAttribute('lengths', $lengths, Document::SET_TYPE_ASSIGN)
|
||||
->setAttribute('orders', $orders, Document::SET_TYPE_ASSIGN);
|
||||
|
||||
// Check if an index exists with the same attributes and orders
|
||||
$exists = false;
|
||||
foreach ($indexes as $existing) {
|
||||
if (
|
||||
$existing->getAttribute('key') !== $index->getAttribute('key') // Ignore itself
|
||||
&& $existing->getAttribute('attributes') === $index->getAttribute('attributes')
|
||||
&& $existing->getAttribute('orders') === $index->getAttribute('orders')
|
||||
) {
|
||||
$exists = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if ($exists) { // Delete the duplicate if created, else update in db
|
||||
$this->deleteIndex($database, $collection, $index, $project, $dbForConsole, $dbForProject);
|
||||
if (empty($attributes)) {
|
||||
$dbForProject->deleteDocument('indexes', $index->getId());
|
||||
} else {
|
||||
$dbForProject->updateDocument('indexes', $index->getId(), $index);
|
||||
$index
|
||||
->setAttribute('attributes', $attributes, Document::SET_TYPE_ASSIGN)
|
||||
->setAttribute('lengths', $lengths, Document::SET_TYPE_ASSIGN)
|
||||
->setAttribute('orders', $orders, Document::SET_TYPE_ASSIGN);
|
||||
|
||||
// Check if an index exists with the same attributes and orders
|
||||
$exists = false;
|
||||
foreach ($indexes as $existing) {
|
||||
if (
|
||||
$existing->getAttribute('key') !== $index->getAttribute('key') // Ignore itself
|
||||
&& $existing->getAttribute('attributes') === $index->getAttribute('attributes')
|
||||
&& $existing->getAttribute('orders') === $index->getAttribute('orders')
|
||||
) {
|
||||
$exists = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if ($exists) { // Delete the duplicate if created, else update in db
|
||||
$this->deleteIndex($database, $collection, $index, $project, $dbForConsole, $dbForProject);
|
||||
} else {
|
||||
$dbForProject->updateDocument('indexes', $index->getId(), $index);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
} finally {
|
||||
$dbForProject->purgeCachedDocument('database_' . $database->getInternalId(), $collectionId);
|
||||
$dbForProject->purgeCachedCollection('database_' . $database->getInternalId() . '_collection_' . $collection->getInternalId());
|
||||
|
||||
$dbForProject->purgeCachedDocument('database_' . $database->getInternalId(), $collectionId);
|
||||
$dbForProject->purgeCachedCollection('database_' . $database->getInternalId() . '_collection_' . $collection->getInternalId());
|
||||
|
||||
if (!$relatedCollection->isEmpty() && !$relatedAttribute->isEmpty()) {
|
||||
$dbForProject->purgeCachedDocument('database_' . $database->getInternalId(), $relatedCollection->getId());
|
||||
$dbForProject->purgeCachedCollection('database_' . $database->getInternalId() . '_collection_' . $relatedCollection->getInternalId());
|
||||
if (!$relatedCollection->isEmpty() && !$relatedAttribute->isEmpty()) {
|
||||
$dbForProject->purgeCachedDocument('database_' . $database->getInternalId(), $relatedCollection->getId());
|
||||
$dbForProject->purgeCachedCollection('database_' . $database->getInternalId() . '_collection_' . $relatedCollection->getInternalId());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -369,6 +375,7 @@ class Databases extends Action
|
|||
* @throws Conflict
|
||||
* @throws Structure
|
||||
* @throws DatabaseException
|
||||
* @throws \Throwable
|
||||
*/
|
||||
private function createIndex(Document $database, Document $collection, Document $index, Document $project, Database $dbForConsole, Database $dbForProject): void
|
||||
{
|
||||
|
|
@ -400,9 +407,7 @@ class Databases extends Action
|
|||
}
|
||||
$dbForProject->updateDocument('indexes', $index->getId(), $index->setAttribute('status', 'available'));
|
||||
} catch (\Throwable $e) {
|
||||
// TODO: Send non DatabaseExceptions to Sentry
|
||||
Console::error($e->getMessage());
|
||||
|
||||
if ($e instanceof DatabaseException) {
|
||||
$index->setAttribute('error', $e->getMessage());
|
||||
}
|
||||
|
|
@ -411,11 +416,12 @@ class Databases extends Action
|
|||
$index->getId(),
|
||||
$index->setAttribute('status', 'failed')
|
||||
);
|
||||
|
||||
throw $e;
|
||||
} finally {
|
||||
$this->trigger($database, $collection, $index, $project, $projectId, $events);
|
||||
$dbForProject->purgeCachedDocument('database_' . $database->getInternalId(), $collectionId);
|
||||
}
|
||||
|
||||
$dbForProject->purgeCachedDocument('database_' . $database->getInternalId(), $collectionId);
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -430,6 +436,7 @@ class Databases extends Action
|
|||
* @throws Conflict
|
||||
* @throws Structure
|
||||
* @throws DatabaseException
|
||||
* @throws \Throwable
|
||||
*/
|
||||
private function deleteIndex(Document $database, Document $collection, Document $index, Document $project, Database $dbForConsole, Database $dbForProject): void
|
||||
{
|
||||
|
|
@ -458,7 +465,6 @@ class Databases extends Action
|
|||
$dbForProject->deleteDocument('indexes', $index->getId());
|
||||
$index->setAttribute('status', 'deleted');
|
||||
} catch (\Throwable $e) {
|
||||
// TODO: Send non DatabaseExceptions to Sentry
|
||||
Console::error($e->getMessage());
|
||||
|
||||
if ($e instanceof DatabaseException) {
|
||||
|
|
@ -469,11 +475,13 @@ class Databases extends Action
|
|||
$index->getId(),
|
||||
$index->setAttribute('status', 'stuck')
|
||||
);
|
||||
|
||||
throw $e;
|
||||
|
||||
} finally {
|
||||
$this->trigger($database, $collection, $index, $project, $projectId, $events);
|
||||
$dbForProject->purgeCachedDocument('database_' . $database->getInternalId(), $collection->getId());
|
||||
}
|
||||
|
||||
$dbForProject->purgeCachedDocument('database_' . $database->getInternalId(), $collection->getId());
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
|||
|
|
@ -268,8 +268,6 @@ class Migrations extends Action
|
|||
$transfer = $source = $destination = null;
|
||||
|
||||
try {
|
||||
$migration = $this->dbForProject->getDocument('migrations', $migration->getId());
|
||||
|
||||
if (
|
||||
$migration->getAttribute('source') === SourceAppwrite::getName() &&
|
||||
empty($migration->getAttribute('credentials', []))
|
||||
|
|
|
|||
|
|
@ -1362,7 +1362,7 @@ class DatabasesCustomServerTest extends Scope
|
|||
]);
|
||||
|
||||
$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()
|
||||
|
|
|
|||
Loading…
Reference in a new issue