diff --git a/app/config/collections2.php b/app/config/collections2.php index 08161c966d..c94fd02060 100644 --- a/app/config/collections2.php +++ b/app/config/collections2.php @@ -60,7 +60,7 @@ $collections = [ 'required' => false, 'signed' => true, 'array' => false, - 'filters' => ['subQuery'], + 'filters' => ['subQueryAttributes'], ], [ '$id' => 'indexes', @@ -69,7 +69,7 @@ $collections = [ 'required' => false, 'signed' => true, 'array' => false, - 'filters' => ['json'], + 'filters' => ['subQueryIndexes'], ], [ '$id' => 'search', @@ -228,13 +228,100 @@ $collections = [ ], ], 'indexes' => [ - // [filters - // '$id' => '_key_unique', - // 'type' => Database::INDEX_UNIQUE, - // 'attributes' => ['key', 'collectionId'], - // 'lengths' => [Database::LENGTH_KEY, Database::LENGTH_KEY], - // 'orders' => [Database::ORDER_ASC, Database::ORDER_ASC], - // ], + [ + '$id' => '_key_collection', + 'type' => Database::INDEX_KEY, + 'attributes' => ['collectionId'], + 'lengths' => [Database::LENGTH_KEY], + 'orders' => [Database::ORDER_ASC], + ], + ], + ], + + 'indexes' => [ + '$collection' => Database::METADATA, + '$id' => 'attributes', + 'name' => 'Attributes', + 'attributes' => [ + [ + '$id' => 'collectionId', + 'type' => Database::VAR_STRING, + 'format' => '', + 'size' => Database::LENGTH_KEY, + 'signed' => true, + 'required' => false, + 'default' => null, + 'array' => false, + 'filters' => [], + ], + [ + '$id' => 'key', + 'type' => Database::VAR_STRING, + 'format' => '', + 'size' => Database::LENGTH_KEY, + 'signed' => true, + 'required' => false, + 'default' => null, + 'array' => false, + 'filters' => [], + ], + [ + '$id' => 'type', + 'type' => Database::VAR_STRING, + 'format' => '', + 'size' => 256, + 'signed' => true, + 'required' => false, + 'default' => null, + 'array' => false, + 'filters' => [], + ], + [ + '$id' => 'status', + 'type' => Database::VAR_STRING, + 'format' => '', + 'size' => 256, + 'signed' => true, + 'required' => false, + 'default' => null, + 'array' => false, + 'filters' => [], + ], + [ + '$id' => 'attributes', + 'type' => Database::VAR_STRING, + 'format' => '', + 'size' => Database::LENGTH_KEY, + 'signed' => true, + 'required' => false, + 'default' => null, + 'array' => true, + 'filters' => [], + ], + [ + '$id' => 'lengths', + 'type' => Database::VAR_INTEGER, + 'format' => '', + 'size' => 0, + 'signed' => true, + 'required' => false, + 'default' => null, + 'array' => true, + 'filters' => [], + ], + [ + '$id' => 'orders', + 'type' => Database::VAR_STRING, + 'format' => '', + 'size' => 255, + 'signed' => true, + 'required' => false, + 'default' => null, + 'array' => true, + 'filters' => [], + ], + ], + 'indexes' => [ [ '$id' => '_key_collection', 'type' => Database::INDEX_KEY, diff --git a/app/controllers/api/database.php b/app/controllers/api/database.php index 730d9e571b..7199e000e3 100644 --- a/app/controllers/api/database.php +++ b/app/controllers/api/database.php @@ -922,14 +922,22 @@ App::post('/v1/database/collections/:collectionId/indexes') } // TODO@kodumbeats should $lengths be a part of the response model? - $index = new Document([ - '$collection' => $collectionId, - '$id' => $indexId, - 'type' => $type, - 'attributes' => $attributes, - 'lengths' => $lengths, - 'orders' => $orders, - ]); + try { + $index = $dbForInternal->createDocument('indexes', new Document([ + '$id' => $collectionId.'_'.$indexId, + 'key' => $indexId, + 'status' => 'processing', // processing, available, failed, deleting + 'collectionId' => $collectionId, + 'type' => $type, + 'attributes' => $attributes, + 'lengths' => $lengths, + 'orders' => $orders, + ])); + } catch (DuplicateException $th) { + throw new Exception('Attribute already exists', 409); + } + + $dbForInternal->purgeDocument('collections', $collectionId); $database ->setParam('type', DATABASE_TYPE_CREATE_INDEX) @@ -944,7 +952,6 @@ App::post('/v1/database/collections/:collectionId/indexes') $response->setStatusCode(Response::STATUS_CODE_CREATED); $response->dynamic($index, Response::MODEL_INDEX); - }); App::get('/v1/database/collections/:collectionId/indexes') diff --git a/app/init.php b/app/init.php index f099588df8..fa6fdca42c 100644 --- a/app/init.php +++ b/app/init.php @@ -176,7 +176,7 @@ DatabaseOld::addFilter('encrypt', } ); -Database::addFilter('subQuery', +Database::addFilter('subQueryAttributes', function($value) { return null; }, @@ -188,6 +188,18 @@ Database::addFilter('subQuery', } ); +Database::addFilter('subQueryIndexes', + function($value) { + return null; + }, + function($value, Document $document, Database $database) { + return $database + ->find('indexes', [ + new Query('collectionId', Query::TYPE_EQUAL, [$document->getId()]) + ], 100, 0, ['_id']); + } +); + Database::addFilter('encrypt', function($value) { $key = App::getEnv('_APP_OPENSSL_KEY_V1'); diff --git a/app/workers/database.php b/app/workers/database.php index c9b82923c6..a1a2d16b34 100644 --- a/app/workers/database.php +++ b/app/workers/database.php @@ -125,19 +125,28 @@ class DatabaseV1 extends Worker */ protected function createIndex(Document $collection, Document $index, string $projectId): void { + $dbForInternal = $this->getInternalDB($projectId); $dbForExternal = $this->getExternalDB($projectId); $collectionId = $collection->getId(); - $id = $index->getAttribute('$id', ''); + $key = $index->getAttribute('key', ''); $type = $index->getAttribute('type', ''); $attributes = $index->getAttribute('attributes', []); $lengths = $index->getAttribute('lengths', []); $orders = $index->getAttribute('orders', []); - $success = $dbForExternal->createIndex($collectionId, $id, $type, $attributes, $lengths, $orders); - if ($success) { - $dbForExternal->removeIndexInQueue($collectionId, $id); + try { + if(!$dbForExternal->createIndex($collectionId, $key, $type, $attributes, $lengths, $orders)) { + throw new Exception('Failed to create Index'); + } + + $dbForInternal->updateDocument('indexes', $index->getId(), $index->setAttribute('status', 'available')); + } catch (\Throwable $th) { + Console::error($th->getMessage()); + $dbForInternal->updateDocument('indexes', $index->getId(), $index->setAttribute('status', 'failed')); } + + $dbForInternal->purgeDocument('collections', $collectionId); } /** @@ -147,11 +156,23 @@ class DatabaseV1 extends Worker */ protected function deleteIndex(Document $collection, Document $index, string $projectId): void { + $dbForInternal = $this->getInternalDB($projectId); $dbForExternal = $this->getExternalDB($projectId); $collectionId = $collection->getId(); - $id = $index->getAttribute('$id'); + $key = $index->getAttribute('key'); - $success = $dbForExternal->deleteIndex($collectionId, $id); + try { + if(!$dbForExternal->deleteIndex($collectionId, $key)) { + throw new Exception('Failed to delete Attribute'); + } + + $dbForInternal->deleteDocument('indexes', $index->getId()); + } catch (\Throwable $th) { + Console::error($th->getMessage()); + $dbForInternal->updateDocument('indexes', $index->getId(), $index->setAttribute('status', 'failed')); + } + + $dbForInternal->purgeDocument('collections', $collectionId); } }