diff --git a/app/controllers/api/database.php b/app/controllers/api/database.php index df16918fd2..af97752996 100644 --- a/app/controllers/api/database.php +++ b/app/controllers/api/database.php @@ -40,13 +40,14 @@ use DeviceDetector\DeviceDetector; * @param Utopia\Database\Document $attribute * @param Appwrite\Utopia\Response $response * @param Utopia\Database\Database $dbForInternal + * @param Utopia\Database\Database $dbForExternal * @param Appwrite\Event\Event $database * @param Appwrite\Event\Event $audits * @param Appwrite\Stats\Stats $usage * * @return Document Newly created attribute document */ -function createAttribute($collectionId, $attribute, $response, $dbForInternal, $database, $audits, $usage): Document +function createAttribute($collectionId, $attribute, $response, $dbForInternal, $dbForExternal, $database, $audits, $usage): Document { $attributeId = $attribute->getId(); $type = $attribute->getAttribute('type', ''); @@ -107,6 +108,7 @@ function createAttribute($collectionId, $attribute, $response, $dbForInternal, $ } $dbForInternal->deleteCachedDocument('collections', $collectionId); + $dbForExternal->deleteCachedCollection($collectionId); // Pass clone of $attribute object to workers // so we can later modify Document to fit response model @@ -688,12 +690,14 @@ App::post('/v1/database/collections/:collectionId/attributes/string') ->param('array', false, new Boolean(), 'Is attribute an array?', true) ->inject('response') ->inject('dbForInternal') + ->inject('dbForExternal') ->inject('database') ->inject('audits') ->inject('usage') - ->action(function ($collectionId, $attributeId, $size, $required, $default, $array, $response, $dbForInternal, $database, $audits, $usage) { + ->action(function ($collectionId, $attributeId, $size, $required, $default, $array, $response, $dbForInternal, $dbForExternal, $database, $audits, $usage) { /** @var Appwrite\Utopia\Response $response */ /** @var Utopia\Database\Database $dbForInternal*/ + /** @var Utopia\Database\Database $dbForExternal*/ /** @var Appwrite\Event\Event $database */ /** @var Appwrite\Event\Event $audits */ /** @var Appwrite\Stats\Stats $usage */ @@ -711,7 +715,7 @@ App::post('/v1/database/collections/:collectionId/attributes/string') 'required' => $required, 'default' => $default, 'array' => $array, - ]), $response, $dbForInternal, $database, $audits, $usage); + ]), $response, $dbForInternal, $dbForExternal, $database, $audits, $usage); $response->dynamic($attribute, Response::MODEL_ATTRIBUTE_STRING); }); @@ -735,12 +739,14 @@ App::post('/v1/database/collections/:collectionId/attributes/email') ->param('array', false, new Boolean(), 'Is attribute an array?', true) ->inject('response') ->inject('dbForInternal') + ->inject('dbForExternal') ->inject('database') ->inject('audits') ->inject('usage') - ->action(function ($collectionId, $attributeId, $required, $default, $array, $response, $dbForInternal, $database, $audits, $usage) { + ->action(function ($collectionId, $attributeId, $required, $default, $array, $response, $dbForInternal, $dbForExternal, $database, $audits, $usage) { /** @var Appwrite\Utopia\Response $response */ /** @var Utopia\Database\Database $dbForInternal*/ + /** @var Utopia\Database\Database $dbForExternal*/ /** @var Appwrite\Event\Event $database */ /** @var Appwrite\Event\Event $audits */ /** @var Appwrite\Stats\Stats $usage */ @@ -753,7 +759,7 @@ App::post('/v1/database/collections/:collectionId/attributes/email') 'default' => $default, 'array' => $array, 'format' => APP_DATABASE_ATTRIBUTE_EMAIL, - ]), $response, $dbForInternal, $database, $audits, $usage); + ]), $response, $dbForInternal, $dbForExternal, $database, $audits, $usage); $response->dynamic($attribute, Response::MODEL_ATTRIBUTE_EMAIL); }); @@ -778,12 +784,14 @@ App::post('/v1/database/collections/:collectionId/attributes/enum') ->param('array', false, new Boolean(), 'Is attribute an array?', true) ->inject('response') ->inject('dbForInternal') + ->inject('dbForExternal') ->inject('database') ->inject('audits') ->inject('usage') - ->action(function ($collectionId, $attributeId, $elements, $required, $default, $array, $response, $dbForInternal, $database, $audits, $usage) { + ->action(function ($collectionId, $attributeId, $elements, $required, $default, $array, $response, $dbForInternal, $dbForExternal, $database, $audits, $usage) { /** @var Appwrite\Utopia\Response $response */ /** @var Utopia\Database\Database $dbForInternal*/ + /** @var Utopia\Database\Database $dbForExternal*/ /** @var Appwrite\Event\Event $database */ /** @var Appwrite\Event\Event $audits */ /** @var Appwrite\Stats\Stats $usage */ @@ -808,7 +816,7 @@ App::post('/v1/database/collections/:collectionId/attributes/enum') 'array' => $array, 'format' => APP_DATABASE_ATTRIBUTE_ENUM, 'formatOptions' => ['elements' => $elements], - ]), $response, $dbForInternal, $database, $audits, $usage); + ]), $response, $dbForInternal, $dbForExternal, $database, $audits, $usage); $response->dynamic($attribute, Response::MODEL_ATTRIBUTE_ENUM); }); @@ -832,12 +840,14 @@ App::post('/v1/database/collections/:collectionId/attributes/ip') ->param('array', false, new Boolean(), 'Is attribute an array?', true) ->inject('response') ->inject('dbForInternal') + ->inject('dbForExternal') ->inject('database') ->inject('audits') ->inject('usage') - ->action(function ($collectionId, $attributeId, $required, $default, $array, $response, $dbForInternal, $database, $audits, $usage) { + ->action(function ($collectionId, $attributeId, $required, $default, $array, $response, $dbForInternal, $dbForExternal, $database, $audits, $usage) { /** @var Appwrite\Utopia\Response $response */ /** @var Utopia\Database\Database $dbForInternal*/ + /** @var Utopia\Database\Database $dbForExternal*/ /** @var Appwrite\Event\Event $database */ /** @var Appwrite\Event\Event $audits */ /** @var Appwrite\Stats\Stats $usage */ @@ -850,7 +860,7 @@ App::post('/v1/database/collections/:collectionId/attributes/ip') 'default' => $default, 'array' => $array, 'format' => APP_DATABASE_ATTRIBUTE_IP, - ]), $response, $dbForInternal, $database, $audits, $usage); + ]), $response, $dbForInternal, $dbForExternal, $database, $audits, $usage); $response->dynamic($attribute, Response::MODEL_ATTRIBUTE_IP); }); @@ -874,10 +884,11 @@ App::post('/v1/database/collections/:collectionId/attributes/url') ->param('array', false, new Boolean(), 'Is attribute an array?', true) ->inject('response') ->inject('dbForInternal') + ->inject('dbForExternal') ->inject('database') ->inject('audits') ->inject('usage') - ->action(function ($collectionId, $attributeId, $required, $default, $array, $response, $dbForInternal, $database, $audits, $usage) { + ->action(function ($collectionId, $attributeId, $required, $default, $array, $response, $dbForInternal, $dbForExternal, $database, $audits, $usage) { /** @var Appwrite\Utopia\Response $response */ /** @var Utopia\Database\Database $dbForExternal*/ /** @var Appwrite\Event\Event $database */ @@ -892,7 +903,7 @@ App::post('/v1/database/collections/:collectionId/attributes/url') 'default' => $default, 'array' => $array, 'format' => APP_DATABASE_ATTRIBUTE_URL, - ]), $response, $dbForInternal, $database, $audits, $usage); + ]), $response, $dbForInternal, $dbForExternal, $database, $audits, $usage); $response->dynamic($attribute, Response::MODEL_ATTRIBUTE_URL); }); @@ -918,12 +929,14 @@ App::post('/v1/database/collections/:collectionId/attributes/integer') ->param('array', false, new Boolean(), 'Is attribute an array?', true) ->inject('response') ->inject('dbForInternal') + ->inject('dbForExternal') ->inject('database') ->inject('audits') ->inject('usage') - ->action(function ($collectionId, $attributeId, $required, $min, $max, $default, $array, $response, $dbForInternal, $database, $audits, $usage) { + ->action(function ($collectionId, $attributeId, $required, $min, $max, $default, $array, $response, $dbForInternal, $dbForExternal, $database, $audits, $usage) { /** @var Appwrite\Utopia\Response $response */ /** @var Utopia\Database\Database $dbForInternal*/ + /** @var Utopia\Database\Database $dbForExternal*/ /** @var Appwrite\Event\Event $database */ /** @var Appwrite\Event\Event $audits */ /** @var Appwrite\Stats\Stats $usage */ @@ -954,7 +967,7 @@ App::post('/v1/database/collections/:collectionId/attributes/integer') 'min' => $min, 'max' => $max, ], - ]), $response, $dbForInternal, $database, $audits, $usage); + ]), $response, $dbForInternal, $dbForExternal, $database, $audits, $usage); $formatOptions = $attribute->getAttribute('formatOptions', []); @@ -987,12 +1000,14 @@ App::post('/v1/database/collections/:collectionId/attributes/float') ->param('array', false, new Boolean(), 'Is attribute an array?', true) ->inject('response') ->inject('dbForInternal') + ->inject('dbForExternal') ->inject('database') ->inject('audits') ->inject('usage') - ->action(function ($collectionId, $attributeId, $required, $min, $max, $default, $array, $response, $dbForInternal, $database, $audits, $usage) { + ->action(function ($collectionId, $attributeId, $required, $min, $max, $default, $array, $response, $dbForInternal, $dbForExternal,$database, $audits, $usage) { /** @var Appwrite\Utopia\Response $response */ /** @var Utopia\Database\Database $dbForInternal*/ + /** @var Utopia\Database\Database $dbForExternal*/ /** @var Appwrite\Event\Event $database */ /** @var Appwrite\Event\Event $audits */ /** @var Appwrite\Stats\Stats $usage */ @@ -1023,7 +1038,7 @@ App::post('/v1/database/collections/:collectionId/attributes/float') 'min' => $min, 'max' => $max, ], - ]), $response, $dbForInternal, $database, $audits, $usage); + ]), $response, $dbForInternal, $dbForExternal, $database, $audits, $usage); $formatOptions = $attribute->getAttribute('formatOptions', []); @@ -1054,10 +1069,11 @@ App::post('/v1/database/collections/:collectionId/attributes/boolean') ->param('array', false, new Boolean(), 'Is attribute an array?', true) ->inject('response') ->inject('dbForInternal') + ->inject('dbForExternal') ->inject('database') ->inject('audits') ->inject('usage') - ->action(function ($collectionId, $attributeId, $required, $default, $array, $response, $dbForInternal, $database, $audits, $usage) { + ->action(function ($collectionId, $attributeId, $required, $default, $array, $response, $dbForInternal, $dbForExternal, $database, $audits, $usage) { /** @var Appwrite\Utopia\Response $response */ /** @var Utopia\Database\Database $dbForInternal*/ /** @var Appwrite\Event\Event $database */ @@ -1071,7 +1087,7 @@ App::post('/v1/database/collections/:collectionId/attributes/boolean') 'required' => $required, 'default' => $default, 'array' => $array, - ]), $response, $dbForInternal, $database, $audits, $usage); + ]), $response, $dbForInternal, $dbForExternal, $database, $audits, $usage); $response->dynamic($attribute, Response::MODEL_ATTRIBUTE_BOOLEAN); }); @@ -1189,13 +1205,15 @@ App::delete('/v1/database/collections/:collectionId/attributes/:attributeId') ->param('attributeId', '', new Key(), 'Attribute ID.') ->inject('response') ->inject('dbForInternal') + ->inject('dbForExternal') ->inject('database') ->inject('events') ->inject('audits') ->inject('usage') - ->action(function ($collectionId, $attributeId, $response, $dbForInternal, $database, $events, $audits, $usage) { + ->action(function ($collectionId, $attributeId, $response, $dbForInternal, $dbForExternal, $database, $events, $audits, $usage) { /** @var Appwrite\Utopia\Response $response */ /** @var Utopia\Database\Database $dbForInternal */ + /** @var Utopia\Database\Database $dbForExternal */ /** @var Appwrite\Event\Event $database */ /** @var Appwrite\Event\Event $events */ /** @var Appwrite\Event\Event $audits */ @@ -1219,6 +1237,7 @@ App::delete('/v1/database/collections/:collectionId/attributes/:attributeId') } $dbForInternal->deleteCachedDocument('collections', $collectionId); + $dbForExternal->deleteCachedCollection($collection->getId()); $database ->setParam('type', DATABASE_TYPE_DELETE_ATTRIBUTE) diff --git a/tests/e2e/Services/Database/DatabaseCustomServerTest.php b/tests/e2e/Services/Database/DatabaseCustomServerTest.php index fba1b09c16..9f8c7130e4 100644 --- a/tests/e2e/Services/Database/DatabaseCustomServerTest.php +++ b/tests/e2e/Services/Database/DatabaseCustomServerTest.php @@ -193,6 +193,22 @@ class DatabaseCustomServerTest extends Scope // Wait for database worker to finish creating attributes sleep(2); + // Creating document to ensure cache is purged on schema change + $document = $this->client->call(Client::METHOD_POST, '/database/collections/' . $actors['body']['$id'] . '/documents', array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + 'x-appwrite-key' => $this->getProject()['apiKey'] + ]), [ + 'documentId' => 'unique()', + 'data' => [ + 'firstName' => 'lorem', + 'lastName' => 'ipsum', + 'unneeded' => 'dolor' + ], + 'read' => ['role:all'], + 'write' => ['role:all'], + ]); + $index = $this->client->call(Client::METHOD_POST, '/database/collections/' . $actors['body']['$id'] . '/indexes', array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], @@ -236,6 +252,15 @@ class DatabaseCustomServerTest extends Scope sleep(2); + // Check document to ensure cache is purged on schema change + $document = $this->client->call(Client::METHOD_GET, '/database/collections/' . $actors['body']['$id'] . '/documents/' . $document['body']['$id'], array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + 'x-appwrite-key' => $this->getProject()['apiKey'] + ])); + + $this->assertNotContains($unneededId, $document['body']); + $collection = $this->client->call(Client::METHOD_GET, '/database/collections/' . $actors['body']['$id'], array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'],