From efb8087a9b971f5f8d8ccbeda63c6c026c3752ce Mon Sep 17 00:00:00 2001 From: kodumbeats Date: Tue, 23 Nov 2021 12:03:51 -0500 Subject: [PATCH 1/3] Purge external database cache on deleteAttribute --- app/controllers/api/database.php | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/app/controllers/api/database.php b/app/controllers/api/database.php index df16918fd..396c1955e 100644 --- a/app/controllers/api/database.php +++ b/app/controllers/api/database.php @@ -1189,13 +1189,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 +1221,7 @@ App::delete('/v1/database/collections/:collectionId/attributes/:attributeId') } $dbForInternal->deleteCachedDocument('collections', $collectionId); + $dbForExternal->deleteCachedCollection($collection->getId()); $database ->setParam('type', DATABASE_TYPE_DELETE_ATTRIBUTE) From c7bc0559953559a8e4269e625dc9750eeb0b9b4a Mon Sep 17 00:00:00 2001 From: kodumbeats Date: Tue, 23 Nov 2021 12:04:08 -0500 Subject: [PATCH 2/3] Purge external database cache on createAttribute --- app/controllers/api/database.php | 50 +++++++++++++++++++++----------- 1 file changed, 33 insertions(+), 17 deletions(-) diff --git a/app/controllers/api/database.php b/app/controllers/api/database.php index 396c1955e..af9775299 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); }); From 27d1405af0791c8e74b985403bab16bdbcaa7021 Mon Sep 17 00:00:00 2001 From: kodumbeats Date: Tue, 23 Nov 2021 12:39:01 -0500 Subject: [PATCH 3/3] Test for purged document cache on deleteAttribute --- .../Database/DatabaseCustomServerTest.php | 25 +++++++++++++++++++ 1 file changed, 25 insertions(+) diff --git a/tests/e2e/Services/Database/DatabaseCustomServerTest.php b/tests/e2e/Services/Database/DatabaseCustomServerTest.php index fba1b09c1..9f8c7130e 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'],