From b249584b92a73d0f85929f4fa0aa1512fd9df700 Mon Sep 17 00:00:00 2001 From: Khushboo Verma Date: Fri, 9 May 2025 17:46:29 +0530 Subject: [PATCH 01/29] 1.7.x ce migration --- src/Appwrite/Migration/Version/V23.php | 407 ++++++++++++++++++++++++- 1 file changed, 405 insertions(+), 2 deletions(-) diff --git a/src/Appwrite/Migration/Version/V23.php b/src/Appwrite/Migration/Version/V23.php index dec7e8e9d3..9fa9666469 100644 --- a/src/Appwrite/Migration/Version/V23.php +++ b/src/Appwrite/Migration/Version/V23.php @@ -7,6 +7,10 @@ use Exception; use Throwable; use Utopia\CLI\Console; use Utopia\Database\Database; +use Utopia\Database\DateTime; +use Utopia\Database\Document; +use Utopia\Database\Query; +use Utopia\Database\Validator\Authorization; class V23 extends Migration { @@ -16,8 +20,8 @@ class V23 extends Migration public function execute(): void { /** - * Disable SubQueries for Performance. - */ + * Disable SubQueries for Performance. + */ foreach (['subQueryIndexes', 'subQueryPlatforms', 'subQueryDomains', 'subQueryKeys', 'subQueryWebhooks', 'subQuerySessions', 'subQueryTokens', 'subQueryMemberships', 'subQueryVariables', 'subQueryChallenges', 'subQueryProjectVariables', 'subQueryTargets', 'subQueryTopicTargets'] as $name) { Database::addFilter( $name, @@ -28,6 +32,12 @@ class V23 extends Migration Console::info('Migrating Collections'); $this->migrateCollections(); + + Console::info('Migrating Documents'); + $this->forEachDocument([$this, 'fixDocument']); + + Console::log('Cleaning Up Collections'); + $this->cleanCollections(); } /** @@ -53,6 +63,10 @@ class V23 extends Migration $this->projectDB->setNamespace("_$internalProjectId"); switch ($id) { + case '_metadata': + $this->createCollection('sites'); + $this->createCollection('resourceTokens'); + break; case 'memberships': // Create roles index try { @@ -61,9 +75,398 @@ class V23 extends Migration Console::warning("'_key_roles' from {$id}: {$th->getMessage()}"); } break; + case 'migrations': + $attributesToCreate = [ + 'options', + 'resourceId', + 'resourceType' + ]; + foreach ($attributesToCreate as $attribute) { + try { + $this->createAttributeFromCollection($this->projectDB, $id, $attribute); + } catch (\Throwable $th) { + Console::warning("$attribute from {$id}: {$th->getMessage()}"); + } + } + + try { + $this->createIndexFromCollection($this->projectDB, $id, '_key_resource_id'); + } catch (Throwable $th) { + Console::warning("'_key_resource_id' from {$id}: {$th->getMessage()}"); + } + + $this->projectDB->purgeCachedCollection($id); + break; + case 'functions': + $attributesToCreate = [ + 'deploymentId', + 'deploymentCreatedAt', + 'latestDeploymentId', + 'latestDeploymentInternalId', + 'latestDeploymentCreatedAt', + 'latestDeploymentStatus', + ]; + foreach ($attributesToCreate as $attribute) { + try { + $this->createAttributeFromCollection($this->projectDB, $id, $attribute); + } catch (\Throwable $th) { + Console::warning("$attribute from {$id}: {$th->getMessage()}"); + } + } + + try { + $this->createIndexFromCollection($this->projectDB, $id, '_key_deploymentId'); + } catch (Throwable $th) { + Console::warning("'_key_deploymentId' from {$id}: {$th->getMessage()}"); + } + + $this->projectDB->purgeCachedCollection($id); + break; + case 'deployments': + $attributesToCreate = [ + 'buildCommands', + 'sourcePath', + 'buildOutput', + 'adapter', + 'fallbackFile', + 'sourceSize', + 'sourceMetadata', + 'sourceChunksTotal', + 'sourceChunksUploaded', + 'screenshotLight', + 'screenshotDark', + 'buildStartAt', + 'buildEndAt', + 'buildDuration', + 'buildSize', + 'status', + 'buildPath', + 'buildLogs', + 'totalSize', + ]; + foreach ($attributesToCreate as $attribute) { + try { + $this->createAttributeFromCollection($this->projectDB, $id, $attribute); + } catch (\Throwable $th) { + Console::warning("$attribute from {$id}: {$th->getMessage()}"); + } + } + + $indexesToCreate = [ + '_key_sourceSize', + '_key_buildSize', + '_key_totalSize', + '_key_buildDuration', + '_key_type', + '_key_status', + ]; + foreach ($indexesToCreate as $index) { + try { + $this->createIndexFromCollection($this->projectDB, $id, $index); + } catch (\Throwable $th) { + Console::warning("'$index' from {$id}: {$th->getMessage()}"); + } + } + + $this->projectDB->purgeCachedCollection($id); + break; + case 'executions': + $attributesToCreate = [ + 'resourceInternalId', + 'resourceId', + 'resourceType' + ]; + foreach ($attributesToCreate as $attribute) { + try { + $this->createAttributeFromCollection($this->projectDB, $id, $attribute); + } catch (\Throwable $th) { + Console::warning("$attribute from {$id}: {$th->getMessage()}"); + } + } + + try { + $this->createIndexFromCollection($this->projectDB, $id, '_key_resource'); + } catch (Throwable $th) { + Console::warning("'_key_resource' from {$id}: {$th->getMessage()}"); + } + + $this->projectDB->purgeCachedCollection($id); + break; + case 'variables': + try { + $this->createAttributeFromCollection($this->projectDB, $id, 'secret'); + } catch (\Throwable $th) { + Console::warning("'secret' from {$id}: {$th->getMessage()}"); + } + + $this->projectDB->purgeCachedCollection($id); + + break; + default: + break; } usleep(50000); } } + + /** + * Fix run on each document + * + * @param Document $document + * @return Document + */ + protected function fixDocument(Document $document): Document + { + switch ($document->getCollection()) { + case 'functions': + /* + 1. Convert "deployment" to "deploymentId" + --- Fetch activeDeployment from "deploymentId" + 2. Fill "deploymentCreatedAt" with deployment's "$createdAt" + --- Fetch latestDeployment using find() + 3. Fill latestDeploymentId with latestDeployment's "$id" + 4. Fill latestDeploymentInternalId with latestDeployment's "$internalId" + 5. Fill latestDeploymentCreatedAt with latestDeployment's "$createdAt" + 6. Fill latestDeploymentStatus with latestDeployment's build's "status" + + (some deployment attributes needs dual writing from deployment's write action too) + */ + + $document->setAttribute('deploymentId', $document->getAttribute('deployment')); + + $deploymentId = $document->getAttribute('deploymentId'); + $deployment = Authorization::skip(fn () => $this->projectDB->getDocument('deployments', $deploymentId)); + $document->setAttribute('deploymentCreatedAt', $deployment->getCreatedAt()); + + $latestDeployments = Authorization::skip(fn () => $this->projectDB->find('deployments', [ + Query::orderDesc(), + Query::limit(1), + ])); + $latestDeployment = $latestDeployments[0] ?? new Document(); + $latestBuild = Authorization::skip(fn () => $this->projectDB->getDocument('builds', $latestDeployment->getAttribute('buildId', ''))); + $document + ->setAttribute('latestDeploymentId', $latestDeployment->getId()) + ->setAttribute('latestDeploymentInternalId', $latestDeployment->getInternalId()) + ->setAttribute('latestDeploymentCreatedAt', $latestDeployment->getCreatedAt()) + ->setAttribute('latestDeploymentStatus', $latestBuild->getAttribute('status')); + break; + case 'deployments': + /* + --- Support for functions dual writing, if function's deploymentId is current deployment + 1. Fill function's "deploymentCreatedAt" with deployment's "$createdAt" + --- Support for functions dual writing, if this is most recent deployment + 2. Fill function's "latestDeploymentId" with deployment's "$id" + 3. Fill function's "latestDeploymentInternalId" with deployment's "$internalId" + 4. Fill function's "latestDeploymentCreatedAt" with deployment's "$createdAt" + 5. Fill function's "latestDeploymentStatus" with deployment's "$status" + --- Actual deployment dual write + 6. Convert "commands" to "buildCommands" + 7. Convert "path" to "sourcePath" + 8. Convert "size" to "sourceSize" + 9. Convert "metadata" to "sourceMetadata" + 10. Convert "chunksTotal" to "sourceChunksTotal" + 11. Convert "chunksUploaded" to "sourceChunksUploaded" + 12. Convert build's "startTime" to "buildStartAt" + 13. Convert build's "endTime" to "buildEndAt" + 14. Convert build's "duration" to "buildDuration" + 15. Convert build's "size" to "buildSize" + 16. Convert build's "status" to "status" + 17. Convert build's "path" to "buildPath" + 18. Convert build's "logs" to "buildLogs" + 19. Fill "totalSize" with "buildSize" plus "sourceSize" + */ + + $function = Authorization::skip(fn () => $this->projectDB->getDocument('functions', $document->getAttribute('resourceId'))); + if (!$function->isEmpty()) { + $activeDeploymentId = $function->getAttribute('deployment', $function->getAttribute('deploymentId', '')); + if ($activeDeploymentId === $document->getId()) { + $function->setAttribute('deploymentCreatedAt', $document->getCreatedAt()); + $function = Authorization::skip(fn () => $this->projectDB->updateDocument('functions', $function->getId(), $function)); + } else { + $latestDeployments = Authorization::skip(fn () => $this->projectDB->find('deployments', [ + Query::limit(1), + Query::equal('resourceType', ['functions']), + Query::equal('resourceId', [$function->getId()]), + Query::orderDesc() + ])); + $latestDeployment = $latestDeployments[0] ? $latestDeployments[0] : new Document(); + + if (!$latestDeployment->isEmpty()) { + if ($latestDeployment->getId() === $document->getId()) { + $function + ->setAttribute("latestDeploymentId", $document->getId()) + ->setAttribute("latestDeploymentInternalId", $document->getInternalId()) + ->setAttribute("latestDeploymentCreatedAt", $document->getCreatedAt()) + ->setAttribute("latestDeploymentStatus", $document->getAttribute('status')) + ; + + $function = Authorization::skip(fn () => $this->projectDB->updateDocument('functions', $function->getId(), $function)); + } + } + } + } + + $document + ->setAttribute("buildCommands", $document->getAttribute("commands")) + ->setAttribute("sourcePath", $document->getAttribute("path")) + ->setAttribute("sourceSize", $document->getAttribute("size")) + ->setAttribute("sourceMetadata", $document->getAttribute("metadata")) + ->setAttribute("sourceChunksTotal", $document->getAttribute("chunksTotal")) + ->setAttribute("sourceChunksUploaded", $document->getAttribute("chunksUploaded")) + ; + + $build = new Document(); + + if (!empty($document->getAttribute('buildId'))) { + $build = Authorization::skip(fn () => $this->projectDB->getDocument('builds', $document->getAttribute('buildId'))); + } + + $document + ->setAttribute("buildStartAt", $build->getAttribute("startTime", DateTime::now())) + ->setAttribute("buildEndAt", $build->getAttribute("endTime", null)) + ->setAttribute("buildDuration", $build->getAttribute("duration", 0)) + ->setAttribute("buildSize", $build->getAttribute("size", 0)) + ->setAttribute("status", $build->getAttribute("status", "processing")) + ->setAttribute("buildPath", $build->getAttribute("path", "")) + ->setAttribute("buildLogs", $build->getAttribute("logs", "")) + ; + + $totalSize = $document->getAttribute('buildSize', 0) + $document->getAttribute('sourceSize', 0); + $document->setAttribute("totalSize", $totalSize); + break; + case 'executions': + /* + 1. Convert "functionInternalId" to "resourceInternalId" + 2. Convert "functionId" to "resourceId" + 3. Fill "resourceType" with "functions" + */ + $document + ->setAttribute('resourceInternalId', $document->getAttribute('functionInternalId')) + ->setAttribute('resourceId', $document->getAttribute('functionId')) + ->setAttribute('resourceType', 'functions'); + break; + case 'variables': + /* + 1. Fill "secret" with "false" + */ + $document->setAttribute('secret', false); + break; + case 'migrations': + /* + 1. Fill "options" with "[]" + */ + $document->setAttribute('options', []); + break; + } + return $document; + } + + private function cleanCollections(): void + { + $internalProjectId = $this->project->getInternalId(); + $collectionType = match ($internalProjectId) { + 'console' => 'console', + default => 'projects', + }; + + $collections = $this->collections[$collectionType]; + foreach ($collections as $collection) { + $id = $collection['$id']; + + Console::log("Migrating Collection \"{$id}\""); + + $this->projectDB->setNamespace("_$internalProjectId"); + + switch ($id) { + case '_metadata': + $this->projectDB->deleteCollection('builds'); + break; + case 'functions': + try { + $this->projectDB->deleteAttribute($id, 'deployment'); + } catch (\Throwable $th) { + Console::warning("'deployment' from {$id}: {$th->getMessage()}"); + } + + $indexesToDelete = [ + '_key_deployment' + ]; + foreach ($indexesToDelete as $index) { + try { + $this->projectDB->deleteIndex($id, $index); + } catch (\Throwable $th) { + Console::warning("'$index' from {$id}: {$th->getMessage()}"); + } + } + + $this->projectDB->purgeCachedCollection($id); + break; + case 'deployments': + $attributesToDelete = [ + 'buildInternalId', + 'buildId', + 'commands', + 'path', + 'size', + 'metadata', + 'chunksTotal', + 'chunksUploaded', + ]; + foreach ($attributesToDelete as $attribute) { + try { + $this->projectDB->deleteAttribute($id, $attribute); + } catch (\Throwable $th) { + Console::warning("'$attribute' from {$id}: {$th->getMessage()}"); + } + } + + $indexesToDelete = [ + '_key_buildId', + '_key_size' + ]; + foreach ($indexesToDelete as $index) { + try { + $this->projectDB->deleteIndex($id, $index); + } catch (\Throwable $th) { + Console::warning("'$index' from {$id}: {$th->getMessage()}"); + } + } + + $this->projectDB->purgeCachedCollection($id); + break; + case 'executions': + $attributesToDelete = [ + 'functionId', + 'functionInternalId', + 'search' + ]; + foreach ($attributesToDelete as $attribute) { + try { + $this->projectDB->deleteAttribute($id, $attribute); + } catch (\Throwable $th) { + Console::warning("'$attribute' from {$id}: {$th->getMessage()}"); + } + } + + $indexesToDelete = [ + '_key_function', + '_fulltext_search' + ]; + foreach ($indexesToDelete as $index) { + try { + $this->projectDB->deleteIndex($id, $index); + } catch (\Throwable $th) { + Console::warning("'$index' from {$id}: {$th->getMessage()}"); + } + } + + $this->projectDB->purgeCachedCollection($id); + break; + default: + break; + } + usleep(50000); + } + } } From a3cb7c81a25af33c37fbec605734680c5aa4abf4 Mon Sep 17 00:00:00 2001 From: Khushboo Verma Date: Tue, 13 May 2025 15:22:09 +0530 Subject: [PATCH 02/29] Add V23 migration and remove coroutines --- app/config/collections/common.php | 22 ++ src/Appwrite/Migration/Migration.php | 37 +-- src/Appwrite/Migration/Version/V23.php | 341 ++++++++++++++++++------- 3 files changed, 289 insertions(+), 111 deletions(-) diff --git a/app/config/collections/common.php b/app/config/collections/common.php index f006a01d1e..060052c920 100644 --- a/app/config/collections/common.php +++ b/app/config/collections/common.php @@ -1101,6 +1101,28 @@ return [ 'array' => false, 'filters' => ['json', 'encrypt'], ], + [ + '$id' => ID::custom('scopes'), + 'type' => Database::VAR_STRING, + 'format' => '', + 'size' => Database::LENGTH_KEY, + 'signed' => true, + 'required' => false, + 'default' => null, + 'array' => true, + 'filters' => [], + ], + [ + '$id' => ID::custom('expire'), + 'type' => Database::VAR_DATETIME, + 'format' => '', + 'size' => 0, + 'required' => true, + 'signed' => false, + 'default' => null, + 'array' => false, + 'filters' => ['datetime'], + ], ], 'indexes' => [ [ diff --git a/src/Appwrite/Migration/Migration.php b/src/Appwrite/Migration/Migration.php index 17e93f43f5..2f0c83e8d1 100644 --- a/src/Appwrite/Migration/Migration.php +++ b/src/Appwrite/Migration/Migration.php @@ -3,7 +3,6 @@ namespace Appwrite\Migration; use Exception; -use Swoole\Runtime; use Utopia\CLI\Console; use Utopia\Config\Config; use Utopia\Database\Database; @@ -13,8 +12,6 @@ use Utopia\Database\Query; use Utopia\Database\Validator\Authorization; use Utopia\System\System; -Runtime::enableCoroutine(SWOOLE_HOOK_ALL); - abstract class Migration { /** @@ -119,10 +116,6 @@ abstract class Migration '$id' => ID::custom('audit'), '$collection' => Database::METADATA ], - 'abuse' => [ - '$id' => ID::custom('abuse'), - '$collection' => Database::METADATA - ] ], $projectCollections); } @@ -179,25 +172,23 @@ abstract class Migration Console::log('Migrating Collection ' . $collection['$id'] . ':'); foreach ($this->documentsIterator($collection['$id']) as $document) { - go(function (Document $document, callable $callback) { - if (empty($document->getId()) || empty($document->getCollection())) { - return; - } + if (empty($document->getId()) || empty($document->getCollection())) { + continue; + } - $old = $document->getArrayCopy(); - $new = call_user_func($callback, $document); + $old = $document->getArrayCopy(); + $new = call_user_func($callback, $document); - if (is_null($new) || $new->getArrayCopy() == $old) { - return; - } + if (is_null($new) || $new->getArrayCopy() == $old) { + continue; + } - try { - $this->projectDB->updateDocument($document->getCollection(), $document->getId(), $document); - } catch (\Throwable $th) { - Console::error('Failed to update document: ' . $th->getMessage()); - return; - } - }, $document, $callback); + try { + $this->projectDB->updateDocument($document->getCollection(), $document->getId(), $document); + } catch (\Throwable $th) { + Console::error('Failed to update document: ' . $th->getMessage()); + continue; + } } } } diff --git a/src/Appwrite/Migration/Version/V23.php b/src/Appwrite/Migration/Version/V23.php index 9fa9666469..5ea25431bf 100644 --- a/src/Appwrite/Migration/Version/V23.php +++ b/src/Appwrite/Migration/Version/V23.php @@ -7,7 +7,6 @@ use Exception; use Throwable; use Utopia\CLI\Console; use Utopia\Database\Database; -use Utopia\Database\DateTime; use Utopia\Database\Document; use Utopia\Database\Query; use Utopia\Database\Validator\Authorization; @@ -66,6 +65,75 @@ class V23 extends Migration case '_metadata': $this->createCollection('sites'); $this->createCollection('resourceTokens'); + if ($internalProjectId === 'console') { + $this->createCollection('devKeys'); + } + break; + case 'identities': + $attributesToCreate = [ + 'scopes', + 'expire', + ]; + foreach ($attributesToCreate as $attribute) { + try { + $this->createAttributeFromCollection($this->projectDB, $id, $attribute); + } catch (\Throwable $th) { + Console::warning("$attribute from {$id}: {$th->getMessage()}"); + } + } + $this->projectDB->purgeCachedCollection($id); + break; + case 'projects': + try { + $this->createAttributeFromCollection($this->projectDB, $id, 'devKeys'); + } catch (Throwable $th) { + Console::warning("'devKeys' from {$id}: {$th->getMessage()}"); + } + $this->projectDB->purgeCachedCollection($id); + break; + case 'rules': + $attributesToCreate = [ + 'type', + 'trigger', + 'redirectUrl', + 'redirectStatusCode', + 'deploymentResourceType', + 'deploymentId', + 'deploymentInternalId', + 'deploymentResourceId', + 'deploymentResourceInternalId', + 'deploymentVcsProviderBranch', + 'search' + ]; + foreach ($attributesToCreate as $attribute) { + try { + $this->createAttributeFromCollection($this->projectDB, $id, $attribute); + } catch (\Throwable $th) { + Console::warning("$attribute from {$id}: {$th->getMessage()}"); + } + } + + $indexesToCreate = [ + '_key_search', + '_key_type', + '_key_trigger', + '_key_deploymentResourceType', + '_key_deploymentResourceId', + '_key_deploymentResourceInternalId', + '_key_deploymentId', + '_key_deploymentInternalId', + '_key_deploymentVcsProviderBranch', + ]; + foreach ($indexesToCreate as $index) { + try { + $this->createIndexFromCollection($this->projectDB, $id, $index); + } catch (\Throwable $th) { + Console::warning("'$index' from {$id}: {$th->getMessage()}"); + } + } + + $this->projectDB->purgeCachedCollection($id); + break; case 'memberships': // Create roles index @@ -135,8 +203,8 @@ class V23 extends Migration 'sourceChunksUploaded', 'screenshotLight', 'screenshotDark', - 'buildStartAt', - 'buildEndAt', + 'buildStartedAt', + 'buildEndedAt', 'buildDuration', 'buildSize', 'status', @@ -219,21 +287,87 @@ class V23 extends Migration protected function fixDocument(Document $document): Document { switch ($document->getCollection()) { - case 'functions': + case 'rules': /* - 1. Convert "deployment" to "deploymentId" - --- Fetch activeDeployment from "deploymentId" - 2. Fill "deploymentCreatedAt" with deployment's "$createdAt" - --- Fetch latestDeployment using find() - 3. Fill latestDeploymentId with latestDeployment's "$id" - 4. Fill latestDeploymentInternalId with latestDeployment's "$internalId" - 5. Fill latestDeploymentCreatedAt with latestDeployment's "$createdAt" - 6. Fill latestDeploymentStatus with latestDeployment's build's "status" - - (some deployment attributes needs dual writing from deployment's write action too) + 1. Convert "resourceType" to "type". Convert "function" to "deployment" + 2. Convert "resourceId" to "deploymentResourceId" + 3. Convert "resourceInternalId" to "deploymentResourceInternalId" + 4. Fill "trigger" with "manual" + 5. Fill "deploymentResourceType". If "resourceType" is "function", set "deploymentResourceType" to "function" + 6. Fill "search" with "{$id} {domain}" + 7. Fill "deploymentId" and "deploymentInternalId". If "deploymentResourceType" is "function", get project DB, and find function with ID "resourceId". Then fill rule's "deploymentId" with function's "deployment", and "deploymentId" as backup */ - $document->setAttribute('deploymentId', $document->getAttribute('deployment')); + $type = $document->getAttribute('resourceType'); + if ($type === 'function') { + $type = 'deployment'; + } + + $deploymentResourceType = null; + if ($document->getAttribute('resourceType') === 'function') { + $deploymentResourceType = 'function'; + } + + $resourceId = $document->getAttribute('resourceId'); + + $document + ->setAttribute('type', $type) + ->setAttribute('deploymentResourceId', $resourceId) + ->setAttribute('deploymentResourceInternalId', $document->getAttribute('resourceInternalId')) + ->setAttribute('trigger', 'manual') + ->setAttribute('deploymentResourceType', $deploymentResourceType) + ->setAttribute('search', \implode(" ", [$document->getId(), $document->getAttribute('domain', '')])) + ; + + if ($deploymentResourceType === 'function') { + if ($this->project->getInternalId() !== 'console') { + $function = Authorization::skip(fn () => $this->projectDB->getDocument('functions', $resourceId)); + + $document + ->setAttribute('deploymentId', $function->getAttribute('deployment', $function->getAttribute('deploymentId', ''))) + ->setAttribute('deploymentInternalId', $function->getAttribute('deployment', $function->getAttribute('deploymentId', ''))) + ; + } + } + break; + case 'variables': + /* + 1. Fill "secret" with "false" + */ + $document->setAttribute('secret', false); + break; + case 'executions': + /* + 1. Convert "functionInternalId" to "resourceInternalId" + 2. Convert "functionId" to "resourceId" + 3. Fill "resourceType" with "functions" + */ + $document + ->setAttribute('resourceInternalId', $document->getAttribute('functionInternalId')) + ->setAttribute('resourceId', $document->getAttribute('functionId')) + ->setAttribute('resourceType', 'functions'); + break; + case 'migrations': + /* + 1. Fill "options" with "[]" + */ + $document->setAttribute('options', []); + break; + case 'functions': + /* + 1. Convert "deployment" to "deploymentId" + --- Fetch activeDeployment from "deploymentId" + 2. Fill "deploymentCreatedAt" with deployment's "$createdAt" + --- Fetch latestDeployment using find() + 3. Fill latestDeploymentId with latestDeployment's "$id" + 4. Fill latestDeploymentInternalId with latestDeployment's "$internalId" + 5. Fill latestDeploymentCreatedAt with latestDeployment's "$createdAt" + 6. Fill latestDeploymentStatus with latestDeployment's build's "status" + */ + + if ($document->getAttribute('deployment')) { + $document->setAttribute('deploymentId', $document->getAttribute('deployment')); + } $deploymentId = $document->getAttribute('deploymentId'); $deployment = Authorization::skip(fn () => $this->projectDB->getDocument('deployments', $deploymentId)); @@ -242,6 +376,8 @@ class V23 extends Migration $latestDeployments = Authorization::skip(fn () => $this->projectDB->find('deployments', [ Query::orderDesc(), Query::limit(1), + Query::equal('resourceId', [$document->getId()]), + Query::equal('resourceType', ['functions']), ])); $latestDeployment = $latestDeployments[0] ?? new Document(); $latestBuild = Authorization::skip(fn () => $this->projectDB->getDocument('builds', $latestDeployment->getAttribute('buildId', ''))); @@ -253,60 +389,30 @@ class V23 extends Migration break; case 'deployments': /* - --- Support for functions dual writing, if function's deploymentId is current deployment - 1. Fill function's "deploymentCreatedAt" with deployment's "$createdAt" - --- Support for functions dual writing, if this is most recent deployment - 2. Fill function's "latestDeploymentId" with deployment's "$id" - 3. Fill function's "latestDeploymentInternalId" with deployment's "$internalId" - 4. Fill function's "latestDeploymentCreatedAt" with deployment's "$createdAt" - 5. Fill function's "latestDeploymentStatus" with deployment's "$status" - --- Actual deployment dual write - 6. Convert "commands" to "buildCommands" - 7. Convert "path" to "sourcePath" - 8. Convert "size" to "sourceSize" - 9. Convert "metadata" to "sourceMetadata" - 10. Convert "chunksTotal" to "sourceChunksTotal" - 11. Convert "chunksUploaded" to "sourceChunksUploaded" - 12. Convert build's "startTime" to "buildStartAt" - 13. Convert build's "endTime" to "buildEndAt" - 14. Convert build's "duration" to "buildDuration" - 15. Convert build's "size" to "buildSize" - 16. Convert build's "status" to "status" - 17. Convert build's "path" to "buildPath" - 18. Convert build's "logs" to "buildLogs" - 19. Fill "totalSize" with "buildSize" plus "sourceSize" + 6. Convert "commands" to "buildCommands" + 7. Convert "path" to "sourcePath" + 8. Convert "size" to "sourceSize" + 9. Convert "metadata" to "sourceMetadata" + 10. Convert "chunksTotal" to "sourceChunksTotal" + 11. Convert "chunksUploaded" to "sourceChunksUploaded" + --- Get build of deployment + 12. Convert build's "startTime" to "buildStartedAt" + 13. Convert build's "endTime" to "buildEndedAt" + 14. Convert build's "duration" to "buildDuration" + 15. Convert build's "size" to "buildSize" + 16. Convert build's "status" to "status" + 17. Convert build's "path" to "buildPath" + 18. Convert build's "logs" to "buildLogs" + 19. Fill "totalSize" with "buildSize" plus "sourceSize" + --- Support for functions dual writing, if function's deploymentId is current deployment + 1. Fill function's "deploymentCreatedAt" with deployment's "$createdAt" + --- Support for functions dual writing, if this is most recent deployment + 2. Fill function's "latestDeploymentId" with deployment's "$id" + 3. Fill function's "latestDeploymentInternalId" with deployment's "$internalId" + 4. Fill function's "latestDeploymentCreatedAt" with deployment's "$createdAt" + 5. Fill function's "latestDeploymentStatus" with deployment's "$status" */ - $function = Authorization::skip(fn () => $this->projectDB->getDocument('functions', $document->getAttribute('resourceId'))); - if (!$function->isEmpty()) { - $activeDeploymentId = $function->getAttribute('deployment', $function->getAttribute('deploymentId', '')); - if ($activeDeploymentId === $document->getId()) { - $function->setAttribute('deploymentCreatedAt', $document->getCreatedAt()); - $function = Authorization::skip(fn () => $this->projectDB->updateDocument('functions', $function->getId(), $function)); - } else { - $latestDeployments = Authorization::skip(fn () => $this->projectDB->find('deployments', [ - Query::limit(1), - Query::equal('resourceType', ['functions']), - Query::equal('resourceId', [$function->getId()]), - Query::orderDesc() - ])); - $latestDeployment = $latestDeployments[0] ? $latestDeployments[0] : new Document(); - - if (!$latestDeployment->isEmpty()) { - if ($latestDeployment->getId() === $document->getId()) { - $function - ->setAttribute("latestDeploymentId", $document->getId()) - ->setAttribute("latestDeploymentInternalId", $document->getInternalId()) - ->setAttribute("latestDeploymentCreatedAt", $document->getCreatedAt()) - ->setAttribute("latestDeploymentStatus", $document->getAttribute('status')) - ; - - $function = Authorization::skip(fn () => $this->projectDB->updateDocument('functions', $function->getId(), $function)); - } - } - } - } - $document ->setAttribute("buildCommands", $document->getAttribute("commands")) ->setAttribute("sourcePath", $document->getAttribute("path")) @@ -323,41 +429,69 @@ class V23 extends Migration } $document - ->setAttribute("buildStartAt", $build->getAttribute("startTime", DateTime::now())) - ->setAttribute("buildEndAt", $build->getAttribute("endTime", null)) + ->setAttribute("buildStartedAt", $build->getAttribute("startTime", null)) + ->setAttribute("buildEndedAt", $build->getAttribute("endTime", null)) ->setAttribute("buildDuration", $build->getAttribute("duration", 0)) ->setAttribute("buildSize", $build->getAttribute("size", 0)) - ->setAttribute("status", $build->getAttribute("status", "processing")) + ->setAttribute("status", $build->getAttribute("status", null)) ->setAttribute("buildPath", $build->getAttribute("path", "")) ->setAttribute("buildLogs", $build->getAttribute("logs", "")) ; $totalSize = $document->getAttribute('buildSize', 0) + $document->getAttribute('sourceSize', 0); $document->setAttribute("totalSize", $totalSize); + + $function = Authorization::skip(fn () => $this->projectDB->getDocument('functions', $document->getAttribute('resourceId'))); + if (!$function->isEmpty()) { + $activeDeploymentId = $function->getAttribute('deployment', $function->getAttribute('deploymentId', '')); + if ($activeDeploymentId === $document->getId()) { + $function->setAttribute('deploymentCreatedAt', $document->getCreatedAt()); + + $function = Authorization::skip(fn () => $this->projectDB->updateDocument('functions', $function->getId(), $function)); + } else { + $latestDeployments = Authorization::skip(fn () => $this->projectDB->find('deployments', [ + Query::orderDesc(), + Query::limit(1), + Query::equal('resourceType', ['functions']), + Query::equal('resourceId', [$function->getId()]), + ])); + $latestDeployment = $latestDeployments[0] ? $latestDeployments[0] : new Document(); + + if (!$latestDeployment->isEmpty()) { + if ($latestDeployment->getId() === $document->getId()) { + $function + ->setAttribute("latestDeploymentId", $document->getId()) + ->setAttribute("latestDeploymentInternalId", $document->getInternalId()) + ->setAttribute("latestDeploymentCreatedAt", $document->getCreatedAt()) + ->setAttribute("latestDeploymentStatus", $document->getAttribute('status')) + ; + + $function = Authorization::skip(fn () => $this->projectDB->updateDocument('functions', $function->getId(), $function)); + } + } + } + } break; - case 'executions': - /* - 1. Convert "functionInternalId" to "resourceInternalId" - 2. Convert "functionId" to "resourceId" - 3. Fill "resourceType" with "functions" - */ - $document - ->setAttribute('resourceInternalId', $document->getAttribute('functionInternalId')) - ->setAttribute('resourceId', $document->getAttribute('functionId')) - ->setAttribute('resourceType', 'functions'); + case 'builds': + /** + 1. Trigger deployments document update + */ + if (!empty($document->getAttribute('deploymentId'))) { + $deployment = Authorization::skip(fn () => $this->projectDB->getDocument('deployments', $document->getAttribute('deploymentId'))); + if (!$deployment->isEmpty()) { + $deployment = $this->fixDocument($deployment); + + Authorization::skip(fn () => $this->projectDB->updateDocument('deployments', $deployment->getId(), $deployment)); + } + } break; - case 'variables': - /* - 1. Fill "secret" with "false" - */ - $document->setAttribute('secret', false); - break; - case 'migrations': /* 1. Fill "options" with "[]" */ $document->setAttribute('options', []); break; + default: + break; } return $document; } @@ -380,7 +514,38 @@ class V23 extends Migration switch ($id) { case '_metadata': - $this->projectDB->deleteCollection('builds'); + if ($this->projectDB->exists('builds')) { + $this->projectDB->deleteCollection('builds'); + } + break; + case 'rules': + $attributesToDelete = [ + 'resourceId', + 'resourceInternalId', + 'resourceType', + ]; + foreach ($attributesToDelete as $attribute) { + try { + $this->projectDB->deleteAttribute($id, $attribute); + } catch (\Throwable $th) { + Console::warning("'$attribute' from {$id}: {$th->getMessage()}"); + } + } + + $indexesToDelete = [ + '_key_resourceId', + '_key_resourceInternalId', + '_key_resourceType', + ]; + foreach ($indexesToDelete as $index) { + try { + $this->projectDB->deleteIndex($id, $index); + } catch (\Throwable $th) { + Console::warning("'$index' from {$id}: {$th->getMessage()}"); + } + } + + $this->projectDB->purgeCachedCollection($id); break; case 'functions': try { From 25a13d36662d21a08e289c3038aa30218b2461c9 Mon Sep 17 00:00:00 2001 From: Khushboo Verma Date: Tue, 13 May 2025 15:40:21 +0530 Subject: [PATCH 03/29] Sync with cloud --- src/Appwrite/Migration/Version/V23.php | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/Appwrite/Migration/Version/V23.php b/src/Appwrite/Migration/Version/V23.php index 5ea25431bf..ab986cab55 100644 --- a/src/Appwrite/Migration/Version/V23.php +++ b/src/Appwrite/Migration/Version/V23.php @@ -577,6 +577,7 @@ class V23 extends Migration 'metadata', 'chunksTotal', 'chunksUploaded', + 'search' ]; foreach ($attributesToDelete as $attribute) { try { @@ -588,7 +589,8 @@ class V23 extends Migration $indexesToDelete = [ '_key_buildId', - '_key_size' + '_key_size', + '_key_search' ]; foreach ($indexesToDelete as $index) { try { From ae2bc1f7408d9a5968338015cfd2621bc72977bb Mon Sep 17 00:00:00 2001 From: Jake Barnby Date: Fri, 16 May 2025 14:56:52 +1200 Subject: [PATCH 04/29] Fix expire required --- app/config/collections/common.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/config/collections/common.php b/app/config/collections/common.php index 2bde67452e..e77d5403d2 100644 --- a/app/config/collections/common.php +++ b/app/config/collections/common.php @@ -1117,7 +1117,7 @@ return [ 'type' => Database::VAR_DATETIME, 'format' => '', 'size' => 0, - 'required' => true, + 'required' => false, 'signed' => false, 'default' => null, 'array' => false, From a23548fba5bb89ca7ed6d053099533bb291fa9c6 Mon Sep 17 00:00:00 2001 From: Jake Barnby Date: Fri, 16 May 2025 14:57:18 +1200 Subject: [PATCH 05/29] Add domains + dnsRecords to platform --- app/config/collections/platform.php | 368 +++++++++++++++++++++++++++- 1 file changed, 366 insertions(+), 2 deletions(-) diff --git a/app/config/collections/platform.php b/app/config/collections/platform.php index 84f0731443..4836f566aa 100644 --- a/app/config/collections/platform.php +++ b/app/config/collections/platform.php @@ -225,7 +225,7 @@ return [ '$id' => ID::custom('templates'), 'type' => Database::VAR_STRING, 'format' => '', - 'size' => 1000000, // TODO make sure size fits + 'size' => 1_000_000, // TODO make sure size fits 'signed' => true, 'required' => false, 'default' => [], @@ -1890,5 +1890,369 @@ return [ 'name' => 'vcsCommentLocks', 'attributes' => [], 'indexes' => [] - ] + ], + + 'domains' => [ + '$collection' => ID::custom(Database::METADATA), + '$id' => ID::custom('domains'), + 'name' => 'Domains', + 'attributes' => [ + [ + '$id' => ID::custom('teamInternalId'), + 'type' => Database::VAR_STRING, + 'format' => '', + 'size' => Database::LENGTH_KEY, + 'signed' => true, + 'required' => true, + 'default' => null, + 'array' => false, + 'filters' => [], + ], + [ + '$id' => ID::custom('teamId'), + 'type' => Database::VAR_STRING, + 'format' => '', + 'size' => Database::LENGTH_KEY, + 'signed' => true, + 'required' => false, + 'default' => null, + 'array' => false, + 'filters' => [], + ], + [ + '$id' => ID::custom('domain'), + 'type' => Database::VAR_STRING, + 'format' => '', + 'size' => 255, + 'signed' => true, + 'required' => true, + 'default' => null, + 'array' => false, + 'filters' => [], + ], + [ + '$id' => ID::custom('registrar'), + 'type' => Database::VAR_STRING, + 'format' => '', + 'size' => Database::LENGTH_KEY, + 'signed' => true, + 'required' => false, + 'default' => null, // e.g. "appwrite" or "third_party" + 'array' => false, + 'filters' => [], + ], + [ + '$id' => ID::custom('nameservers'), + 'type' => Database::VAR_STRING, + 'format' => '', + 'size' => 255, + 'signed' => true, + 'required' => false, + 'default' => '', // "Appwrite" or empty string + 'array' => false, + 'filters' => [], + ], + [ + '$id' => ID::custom('expire'), + 'type' => Database::VAR_DATETIME, + 'format' => '', + 'size' => 0, + 'signed' => false, + 'required' => false, + 'default' => null, + 'array' => false, + 'filters' => ['datetime'], + ], + [ + '$id' => ID::custom('renewal'), + 'type' => Database::VAR_DATETIME, + 'format' => '', + 'size' => 0, + 'signed' => false, + 'required' => false, + 'default' => null, + 'array' => false, + 'filters' => ['datetime'], + ], + [ + '$id' => ID::custom('autoRenewal'), + 'type' => Database::VAR_BOOLEAN, + 'signed' => true, + 'size' => 0, + 'format' => '', + 'filters' => [], + 'required' => false, + 'default' => false, + 'array' => false, + ], + [ + '$id' => ID::custom('renewalPrice'), + 'type' => Database::VAR_INTEGER, + 'format' => '', + 'size' => 0, + 'signed' => false, + 'required' => false, + 'default' => 0, + 'array' => false, + 'filters' => [], + ], + [ + '$id' => ID::custom('search'), + 'type' => Database::VAR_STRING, + 'format' => '', + 'size' => 16384, + 'signed' => true, + 'required' => false, + 'default' => null, + 'array' => false, + 'filters' => [], + ], + ], + 'indexes' => [ + [ + '$id' => ID::custom('_key_search'), + 'type' => Database::INDEX_FULLTEXT, + 'attributes' => ['search'], + 'lengths' => [], + 'orders' => [], + ], + [ + '$id' => ID::custom('_key_teamInternalId'), + 'type' => Database::INDEX_KEY, + 'attributes' => ['teamInternalId'], + 'lengths' => [Database::LENGTH_KEY], + 'orders' => [Database::ORDER_ASC], + ], + [ + '$id' => ID::custom('_key_domain'), + 'type' => Database::INDEX_KEY, + 'attributes' => ['domain'], + 'lengths' => [Database::LENGTH_KEY], + 'orders' => [Database::ORDER_ASC], + ], + [ + '$id' => ID::custom('_key_teamId_domain'), + 'type' => Database::INDEX_UNIQUE, + 'attributes' => ['teamId', 'domain'], + 'lengths' => [], + 'orders' => [], + ], + [ + '$id' => ID::custom('_key_expire'), + 'type' => Database::INDEX_KEY, + 'attributes' => ['expire'], + 'lengths' => [], + 'orders' => [], + ], + [ + '$id' => ID::custom('_key_registrar'), + 'type' => Database::INDEX_KEY, + 'attributes' => ['registrar'], + 'lengths' => [], + 'orders' => [], + ], + [ + '$id' => ID::custom('_key_nameservers'), + 'type' => Database::INDEX_KEY, + 'attributes' => ['nameservers'], + 'lengths' => [], + 'orders' => [], + ], + [ + '$id' => ID::custom('_key_renewalPrice'), + 'type' => Database::INDEX_KEY, + 'attributes' => ['renewalPrice'], + 'lengths' => [], + 'orders' => [], + ], + [ + '$id' => ID::custom('_key_renewal'), + 'type' => Database::INDEX_KEY, + 'attributes' => ['renewal'], + 'lengths' => [], + 'orders' => [], + ], + [ + '$id' => ID::custom('_key_autoRenewal'), + 'type' => Database::INDEX_KEY, + 'attributes' => ['autoRenewal'], + 'lengths' => [], + 'orders' => [], + ], + ], + ], + + 'dnsRecords' => [ + '$collection' => ID::custom(Database::METADATA), + '$id' => ID::custom('dnsRecords'), + 'name' => 'DNS Records', + 'attributes' => [ + [ + '$id' => ID::custom('domainInternalId'), + 'type' => Database::VAR_STRING, + 'format' => '', + 'size' => Database::LENGTH_KEY, + 'signed' => true, + 'required' => true, + 'default' => null, + 'array' => false, + 'filters' => [], + ], + [ + '$id' => ID::custom('domainId'), + 'type' => Database::VAR_STRING, + 'format' => '', + 'size' => Database::LENGTH_KEY, + 'signed' => true, + 'required' => false, + 'default' => null, + 'array' => false, + 'filters' => [], + ], + [ + '$id' => ID::custom('type'), + 'type' => Database::VAR_STRING, + 'format' => '', + 'size' => Database::LENGTH_KEY, + 'signed' => true, + 'required' => true, + 'default' => null, + 'array' => false, + 'filters' => [], + ], + [ + '$id' => ID::custom('name'), + 'type' => Database::VAR_STRING, + 'format' => '', + 'size' => 255, + 'signed' => true, + 'required' => true, + 'default' => null, + 'array' => false, + 'filters' => [], + ], + [ + '$id' => ID::custom('value'), + 'type' => Database::VAR_STRING, + 'format' => '', + 'size' => 16384, + 'signed' => true, + 'required' => true, + 'default' => null, + 'array' => false, + 'filters' => [], + ], + [ + '$id' => ID::custom('ttl'), + 'type' => Database::VAR_INTEGER, + 'format' => '', + 'size' => 0, + 'signed' => true, + 'required' => false, + 'default' => 3600, + 'array' => false, + 'filters' => [], + ], + [ + '$id' => ID::custom('priority'), + 'type' => Database::VAR_INTEGER, + 'format' => '', + 'size' => 0, + 'signed' => true, + 'required' => false, + 'default' => 0, + 'array' => false, + 'filters' => [], + ], + [ + '$id' => ID::custom('weight'), + 'type' => Database::VAR_INTEGER, + 'format' => '', + 'size' => 0, + 'signed' => true, + 'required' => false, + 'default' => 0, + 'array' => false, + 'filters' => [], + ], + [ + '$id' => ID::custom('port'), + 'type' => Database::VAR_INTEGER, + 'format' => '', + 'size' => 0, + 'signed' => false, // Port numbers are always positive + 'required' => false, + 'default' => 0, + 'array' => false, + 'filters' => [], + ], + [ + '$id' => ID::custom('lock'), + 'type' => Database::VAR_BOOLEAN, + 'signed' => true, + 'size' => 0, + 'format' => '', + 'filters' => [], + 'required' => false, + 'default' => false, + 'array' => false, + ], + [ + '$id' => ID::custom('comment'), + 'type' => Database::VAR_STRING, + 'format' => '', + 'size' => 16384, + 'signed' => true, + 'required' => true, + 'default' => null, + 'array' => false, + 'filters' => [], + ], + ], + 'indexes' => [ + [ + '$id' => ID::custom('_key_domainInternalId'), + 'type' => Database::INDEX_KEY, + 'attributes' => ['domainInternalId'], + 'lengths' => [Database::LENGTH_KEY], + 'orders' => [Database::ORDER_ASC], + ], + [ + '$id' => ID::custom('_key_domainId'), + 'type' => Database::INDEX_KEY, + 'attributes' => ['domainId'], + 'lengths' => [Database::LENGTH_KEY], + 'orders' => [Database::ORDER_ASC], + ], + // New indexes based on allowed query attributes + [ + '$id' => ID::custom('_key_type'), + 'type' => Database::INDEX_KEY, + 'attributes' => ['type'], + 'lengths' => [], + 'orders' => [], + ], + [ + '$id' => ID::custom('_key_name'), + 'type' => Database::INDEX_KEY, + 'attributes' => ['name'], + 'lengths' => [], + 'orders' => [], + ], + [ + '$id' => ID::custom('_key_lock'), + 'type' => Database::INDEX_KEY, + 'attributes' => ['lock'], + 'lengths' => [], + 'orders' => [], + ], + [ + '$id' => ID::custom('_key_priority'), + 'type' => Database::INDEX_KEY, + 'attributes' => ['priority'], + 'lengths' => [], + 'orders' => [], + ], + ], + ], ]; From 56fda6a34b5fcea718586c8afe62c0c7fcf68e0a Mon Sep 17 00:00:00 2001 From: Jake Barnby Date: Fri, 16 May 2025 17:23:17 +1200 Subject: [PATCH 06/29] Add migration options --- app/config/collections/projects.php | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/app/config/collections/projects.php b/app/config/collections/projects.php index 48a0938a1c..3913fa8b00 100644 --- a/app/config/collections/projects.php +++ b/app/config/collections/projects.php @@ -2374,6 +2374,17 @@ return [ 'array' => false, 'filters' => [], ], + [ + '$id' => ID::custom('options'), + 'type' => Database::VAR_STRING, + 'format' => '', + 'size' => 65536, + 'signed' => true, + 'required' => false, + 'default' => [], + 'array' => false, + 'filters' => ['json'], + ] ], 'indexes' => [ [ From 73447331656026765770ef3c70da938b17058188 Mon Sep 17 00:00:00 2001 From: Jake Barnby Date: Fri, 16 May 2025 17:24:11 +1200 Subject: [PATCH 07/29] Use db loop methods, update names --- src/Appwrite/Migration/Migration.php | 261 +++++++++++++------------ src/Appwrite/Migration/Version/V15.php | 160 +++++++-------- src/Appwrite/Migration/Version/V16.php | 10 +- src/Appwrite/Migration/Version/V17.php | 66 +++---- src/Appwrite/Migration/Version/V18.php | 30 +-- src/Appwrite/Migration/Version/V19.php | 154 +++++++-------- src/Appwrite/Migration/Version/V20.php | 92 ++++----- src/Appwrite/Migration/Version/V21.php | 34 ++-- src/Appwrite/Migration/Version/V22.php | 8 +- 9 files changed, 410 insertions(+), 405 deletions(-) diff --git a/src/Appwrite/Migration/Migration.php b/src/Appwrite/Migration/Migration.php index 096c5f2568..aa8254b0eb 100644 --- a/src/Appwrite/Migration/Migration.php +++ b/src/Appwrite/Migration/Migration.php @@ -7,6 +7,11 @@ use Utopia\CLI\Console; use Utopia\Config\Config; use Utopia\Database\Database; use Utopia\Database\Document; +use Utopia\Database\Exception\Conflict; +use Utopia\Database\Exception\Duplicate; +use Utopia\Database\Exception\Limit; +use Utopia\Database\Exception\Structure; +use Utopia\Database\Exception\Timeout; use Utopia\Database\Helpers\ID; use Utopia\Database\PDO; use Utopia\Database\Query; @@ -15,33 +20,18 @@ use Utopia\System\System; abstract class Migration { - /** - * @var int - */ protected int $limit = 100; - /** - * @var Document - */ protected Document $project; - /** - * @var Database - */ - protected Database $projectDB; + protected Database $dbForProject; - /** - * @var Database - */ - protected Database $consoleDB; + protected Database $dbForPlatform; - /** - * @var PDO - */ protected PDO $pdo; /** - * @var array + * @var array */ public static array $versions = [ '1.0.0-RC1' => 'V15', @@ -95,7 +85,7 @@ abstract class Migration ]; /** - * @var array + * @var array> */ protected array $collections; @@ -106,34 +96,34 @@ abstract class Migration $this->collections = Config::getParam('collections', []); - $projectCollections = $this->collections['projects']; - - $this->collections['projects'] = array_merge([ + $this->collections['projects'][] = [ '_metadata' => [ '$id' => ID::custom('_metadata'), '$collection' => Database::METADATA - ], + ] + ]; + + $this->collections['projects'][] = [ 'audit' => [ '$id' => ID::custom('audit'), '$collection' => Database::METADATA ], - ], $projectCollections); + ]; } /** * Set project for migration. * * @param Document $project - * @param Database $projectDB - * @param Database $oldConsoleDB - * + * @param Database $dbForProject + * @param Database $dbForPlatform * @return self */ - public function setProject(Document $project, Database $projectDB, Database $consoleDB): self + public function setProject(Document $project, Database $dbForProject, Database $dbForPlatform): self { $this->project = $project; - $this->projectDB = $projectDB; - $this->consoleDB = $consoleDB; + $this->dbForProject = $dbForProject; + $this->dbForPlatform = $dbForPlatform; return $this; } @@ -142,7 +132,7 @@ abstract class Migration * Set PDO for Migration. * * @param PDO $pdo - * @return \Appwrite\Migration\Migration + * @return Migration */ public function setPDO(PDO $pdo): self { @@ -155,87 +145,51 @@ abstract class Migration * Iterates through every document. * * @param callable $callback + * @throws Exception */ public function forEachDocument(callable $callback): void { - $internalProjectId = $this->project->getInternalId(); + $projectInternalId = $this->project->getInternalId(); - $collections = match ($internalProjectId) { + $collections = match ($projectInternalId) { 'console' => $this->collections['console'], default => $this->collections['projects'], }; foreach ($collections as $collection) { + // Only migrate top-level collections if ($collection['$collection'] !== Database::METADATA) { continue; } - Console::log('Migrating Collection ' . $collection['$id'] . ':'); + Console::log('Migrating collection ' . $collection['$id'] . '...'); - foreach ($this->documentsIterator($collection['$id']) as $document) { + $this->dbForProject->foreach($collection['$id'], function(Document $document) use ($collection, $callback) { if (empty($document->getId()) || empty($document->getCollection())) { - continue; + return; } $old = $document->getArrayCopy(); - $new = call_user_func($callback, $document); + $new = $callback($document); - if (is_null($new) || $new->getArrayCopy() == $old) { - continue; + if ($new === null || $new->getArrayCopy() == $old) { + return; } try { - $this->projectDB->updateDocument($document->getCollection(), $document->getId(), $document); + $this->dbForProject->updateDocument( + $document->getCollection(), + $document->getId(), + $document + ); } catch (\Throwable $th) { - Console::error('Failed to update document: ' . $th->getMessage()); - continue; + Console::error("Failed to update document \"{$document->getId()}\" in collection \"{$collection['$id']}\":" . $th->getMessage()); + return; } - } + }); } } - /** - * Provides an iterator for all documents on a collection. - * - * @param string $collectionId - * @return iterable - * @throws \Exception - */ - public function documentsIterator(string $collectionId, $queries = []): iterable - { - $sum = 0; - $nextDocument = null; - $collectionCount = $this->projectDB->count($collectionId); - $queries[] = Query::limit($this->limit); - - do { - if ($nextDocument !== null) { - $cursorQueryIndex = \array_search('cursorAfter', \array_map(fn (Query $query) => $query->getMethod(), $queries)); - - if ($cursorQueryIndex !== false) { - $queries[$cursorQueryIndex] = Query::cursorAfter($nextDocument); - } else { - $queries[] = Query::cursorAfter($nextDocument); - } - } - - $documents = $this->projectDB->find($collectionId, $queries); - $count = count($documents); - $sum += $count; - - Console::log($sum . ' / ' . $collectionCount); - foreach ($documents as $document) { - yield $document; - } - - if ($count !== $this->limit) { - $nextDocument = null; - } else { - $nextDocument = end($documents); - } - } while (!is_null($nextDocument)); - } - /** * Creates collection from the config collection. * @@ -253,54 +207,42 @@ abstract class Migration default => 'projects', }; - if (!$this->projectDB->exists(System::getEnv('_APP_DB_SCHEMA', 'appwrite'), $name)) { + if (!$this->dbForProject->getCollection($id)->isEmpty()) { $attributes = []; $indexes = []; $collection = $this->collections[$collectionType][$id]; - foreach ($collection['attributes'] as $attribute) { - $attributes[] = new Document([ - '$id' => $attribute['$id'], - 'type' => $attribute['type'], - 'size' => $attribute['size'], - 'required' => $attribute['required'], - 'default' => $attribute['default'] ?? null, - 'signed' => $attribute['signed'], - 'array' => $attribute['array'], - 'filters' => $attribute['filters'], - ]); + $attributes[] = new Document($attribute); } - foreach ($collection['indexes'] as $index) { - $indexes[] = new Document([ - '$id' => $index['$id'], - 'type' => $index['type'], - 'attributes' => $index['attributes'], - 'lengths' => $index['lengths'], - 'orders' => $index['orders'], - ]); + $indexes[] = new Document($index); } - try { - $this->projectDB->createCollection($name, $attributes, $indexes); - } catch (\Throwable $th) { - throw $th; - } + $this->dbForProject->createCollection($name, $attributes, $indexes); } } /** - * Creates attribute from collections.php + * Creates attributes from collections.php * - * @param \Utopia\Database\Database $database + * @param Database $database * @param string $collectionId - * @param string $attributeId + * @param array $attributeIds + * @param string|null $from * @return void - * @throws \Exception - * @throws \Utopia\Database\Exception\Duplicate - * @throws \Utopia\Database\Exception\Limit + * @throws \Utopia\Database\Exception + * @throws \Utopia\Database\Exception\Authorization + * @throws Conflict + * @throws Duplicate + * @throws Limit + * @throws Structure */ - public function createAttributeFromCollection(Database $database, string $collectionId, string $attributeId, string $from = null): void + public function createAttributesFromCollection( + Database $database, + string $collectionId, + array $attributeIds, + string $from = null + ): void { $from ??= $collectionId; @@ -315,13 +257,75 @@ abstract class Migration $collection = $this->collections[$collectionType][$from] ?? null; - if (is_null($collection)) { + if ($collection === null) { + throw new Exception("Collection {$from} not found"); + } + + $attributes = []; + foreach ($attributeIds as $attributeId) { + $attribute = $collection['attributes'][$attributeId] ?? null; + + if ($attribute === null) { + throw new Exception("Attribute {$attributeId} not found"); + } + + $attribute['filters'] ??= []; + $attribute['default'] ??= null; + $attribute['default'] = \in_array('json', $attribute['filters']) + ? \json_encode($attribute['default']) + : $attribute['default']; + + $attributes[] = $attribute; + } + + $database->createAttributes( + collection: $collectionId, + attributes: $attributes, + ); + } + + /** + * Creates attribute from collections.php + * + * @param Database $database + * @param string $collectionId + * @param string $attributeId + * @param string|null $from + * @return void + * @throws \Utopia\Database\Exception + * @throws \Utopia\Database\Exception\Authorization + * @throws Conflict + * @throws Duplicate + * @throws Limit + * @throws Structure + */ + public function createAttributeFromCollection( + Database $database, + string $collectionId, + string $attributeId, + string $from = null + ): void + { + $from ??= $collectionId; + + $collectionType = match ($this->project->getInternalId()) { + 'console' => 'console', + default => 'projects', + }; + + if ($from === 'files') { + $collectionType = 'buckets'; + } + + $collection = $this->collections[$collectionType][$from] ?? null; + + if ($collection === null) { throw new Exception("Collection {$from} not found"); } $attributes = $collection['attributes']; - $attributeKey = array_search($attributeId, array_column($attributes, '$id')); + $attributeKey = \array_search($attributeId, \array_column($attributes, '$id')); if ($attributeKey === false) { throw new Exception("Attribute {$attributeId} not found"); @@ -336,9 +340,9 @@ abstract class Migration id: $attributeId, type: $attribute['type'], size: $attribute['size'], - required: $attribute['required'] ?? false, - default: in_array('json', $filters) ? json_encode($default) : $default, - signed: $attribute['signed'] ?? false, + required: $attribute['required'], + default: \in_array('json', $filters) ? \json_encode($default) : $default, + signed: $attribute['signed'] ?? true, array: $attribute['array'] ?? false, format: $attribute['format'] ?? '', formatOptions: $attribute['formatOptions'] ?? [], @@ -349,14 +353,14 @@ abstract class Migration /** * Creates index from collections.php * - * @param \Utopia\Database\Database $database + * @param Database $database * @param string $collectionId * @param string $indexId * @param string|null $from * @return void * @throws \Exception - * @throws \Utopia\Database\Exception\Duplicate - * @throws \Utopia\Database\Exception\Limit + * @throws Duplicate + * @throws Limit */ public function createIndexFromCollection(Database $database, string $collectionId, string $indexId, string $from = null): void { @@ -369,13 +373,13 @@ abstract class Migration $collection = $this->collections[$collectionType][$from] ?? null; - if (is_null($collection)) { + if ($collection === null) { throw new Exception("Collection {$collectionId} not found"); } $indexes = $collection['indexes']; - $indexKey = array_search($indexId, array_column($indexes, '$id')); + $indexKey = \array_search($indexId, \array_column($indexes, '$id')); if ($indexKey === false) { throw new Exception("Index {$indexId} not found"); @@ -400,10 +404,11 @@ abstract class Migration * @param string $attribute * @param string $type * @return void + * @throws \Utopia\Database\Exception */ protected function changeAttributeInternalType(string $collection, string $attribute, string $type): void { - $stmt = $this->pdo->prepare("ALTER TABLE `{$this->projectDB->getDatabase()}`.`_{$this->project->getInternalId()}_{$collection}` MODIFY `$attribute` $type;"); + $stmt = $this->pdo->prepare("ALTER TABLE `{$this->dbForProject->getDatabase()}`.`_{$this->project->getInternalId()}_{$collection}` MODIFY `$attribute` $type;"); try { $stmt->execute(); diff --git a/src/Appwrite/Migration/Version/V15.php b/src/Appwrite/Migration/Version/V15.php index ca20b6d7b3..8eab916f19 100644 --- a/src/Appwrite/Migration/Version/V15.php +++ b/src/Appwrite/Migration/Version/V15.php @@ -114,7 +114,7 @@ class V15 extends Migration $bucket->setAttribute('compression', 'none'); } - $this->projectDB->updateDocument('buckets', $bucket->getId(), $bucket); + $this->dbForProject->updateDocument('buckets', $bucket->getId(), $bucket); /** * Migrating stats for every Bucket. @@ -134,13 +134,13 @@ class V15 extends Migration table: $bucketTable, addCreatePermission: false ); - $this->projectDB->updateDocument($bucketTable, $file->getId(), $file); + $this->dbForProject->updateDocument($bucketTable, $file->getId(), $file); } $this->removeWritePermissions($bucketTable); } try { - $this->projectDB->deleteAttribute('buckets', 'permission'); + $this->dbForProject->deleteAttribute('buckets', 'permission'); } catch (\Throwable $th) { Console::warning("'permissions' from buckets: {$th->getMessage()}"); } @@ -188,10 +188,10 @@ class V15 extends Migration addCreatePermission: false ); - $this->projectDB->updateDocument('databases', $database->getId(), $database); + $this->dbForProject->updateDocument('databases', $database->getId(), $database); try { - $this->createAttributeFromCollection($this->projectDB, $databaseTable, 'documentSecurity', 'collections'); + $this->createAttributeFromCollection($this->dbForProject, $databaseTable, 'documentSecurity', 'collections'); } catch (\Throwable $th) { Console::warning("'documentSecurity' from {$databaseTable}: {$th->getMessage()}"); } @@ -231,7 +231,7 @@ class V15 extends Migration $collection->setAttribute('documentSecurity', $collection->getAttribute('permissions') === 'document'); } - $this->projectDB->updateDocument($databaseTable, $collection->getId(), $collection); + $this->dbForProject->updateDocument($databaseTable, $collection->getId(), $collection); /** * Migrating stats for single Collections. @@ -270,14 +270,14 @@ class V15 extends Migration addCreatePermission: false ); - $this->projectDB->updateDocument($collectionTable, $document->getId(), $document); + $this->dbForProject->updateDocument($collectionTable, $document->getId(), $document); } $this->removeWritePermissions($collectionTable); } $this->removeWritePermissions($databaseTable); try { - $this->projectDB->deleteAttribute("database_{$database->getInternalId()}", 'permission'); + $this->dbForProject->deleteAttribute("database_{$database->getInternalId()}", 'permission'); } catch (\Throwable $th) { Console::warning("'permission' from {$databaseTable}: {$th->getMessage()}"); } @@ -293,7 +293,7 @@ class V15 extends Migration protected function removeWritePermissions(string $table): void { try { - $this->pdo->prepare("DELETE FROM `{$this->projectDB->getDatabase()}`.`_{$this->project->getInternalId()}_{$table}_perms` WHERE _type = 'write'")->execute(); + $this->pdo->prepare("DELETE FROM `{$this->dbForProject->getDatabase()}`.`_{$this->project->getInternalId()}_{$table}_perms` WHERE _type = 'write'")->execute(); } catch (\Throwable $th) { Console::warning("Remove 'write' permissions from {$table}: {$th->getMessage()}"); } @@ -309,7 +309,7 @@ class V15 extends Migration */ protected function getSQLColumnTypes(string $table): array { - $query = $this->pdo->prepare("SELECT COLUMN_NAME, DATA_TYPE FROM INFORMATION_SCHEMA.COLUMNS WHERE table_name = '_{$this->project->getInternalId()}_{$table}' AND table_schema = '{$this->projectDB->getDatabase()}'"); + $query = $this->pdo->prepare("SELECT COLUMN_NAME, DATA_TYPE FROM INFORMATION_SCHEMA.COLUMNS WHERE table_name = '_{$this->project->getInternalId()}_{$table}' AND table_schema = '{$this->dbForProject->getDatabase()}'"); $query->execute(); return array_reduce($query->fetchAll(), function (array $carry, array $item) { @@ -331,8 +331,8 @@ class V15 extends Migration if ($columns[$attribute] === 'int') { try { - $this->pdo->prepare("ALTER TABLE IF EXISTS `{$this->projectDB->getDatabase()}`.`_{$this->project->getInternalId()}_{$table}` MODIFY {$attribute} VARCHAR(64)")->execute(); - $this->pdo->prepare("UPDATE `{$this->projectDB->getDatabase()}`.`_{$this->project->getInternalId()}_{$table}` SET {$attribute} = IF({$attribute} = 0, NULL, FROM_UNIXTIME({$attribute}))")->execute(); + $this->pdo->prepare("ALTER TABLE IF EXISTS `{$this->dbForProject->getDatabase()}`.`_{$this->project->getInternalId()}_{$table}` MODIFY {$attribute} VARCHAR(64)")->execute(); + $this->pdo->prepare("UPDATE `{$this->dbForProject->getDatabase()}`.`_{$this->project->getInternalId()}_{$table}` SET {$attribute} = IF({$attribute} = 0, NULL, FROM_UNIXTIME({$attribute}))")->execute(); $columns[$attribute] = 'varchar'; } catch (\Throwable $th) { Console::warning($th->getMessage()); @@ -341,7 +341,7 @@ class V15 extends Migration if ($columns[$attribute] === 'varchar') { try { - $this->pdo->prepare("ALTER TABLE IF EXISTS `{$this->projectDB->getDatabase()}`.`_{$this->project->getInternalId()}_{$table}` MODIFY {$attribute} DATETIME(3)")->execute(); + $this->pdo->prepare("ALTER TABLE IF EXISTS `{$this->dbForProject->getDatabase()}`.`_{$this->project->getInternalId()}_{$table}` MODIFY {$attribute} DATETIME(3)")->execute(); } catch (\Throwable $th) { Console::warning($th->getMessage()); } @@ -355,11 +355,11 @@ class V15 extends Migration /** * Add datetime filter. */ - $this->projectDB->updateAttributeFilters($table, ID::custom($attribute), ['datetime']); + $this->dbForProject->updateAttributeFilters($table, ID::custom($attribute), ['datetime']); /** * Change data type to DateTime. */ - $this->projectDB->updateAttribute( + $this->dbForProject->updateAttribute( collection: $table, id: $attribute, type: Database::VAR_DATETIME, @@ -370,7 +370,7 @@ class V15 extends Migration } } - $this->projectDB->purgeCachedCollection($table); + $this->dbForProject->purgeCachedCollection($table); } /** @@ -387,7 +387,7 @@ class V15 extends Migration if (!array_key_exists('_permissions', $columns)) { try { - $this->pdo->prepare("ALTER TABLE IF EXISTS `{$this->projectDB->getDatabase()}`.`_{$this->project->getInternalId()}_{$table}` ADD `_permissions` MEDIUMTEXT DEFAULT NULL")->execute(); + $this->pdo->prepare("ALTER TABLE IF EXISTS `{$this->dbForProject->getDatabase()}`.`_{$this->project->getInternalId()}_{$table}` ADD `_permissions` MEDIUMTEXT DEFAULT NULL")->execute(); } catch (\Throwable $th) { Console::warning("Add '_permissions' column to '{$table}': {$th->getMessage()}"); } @@ -408,7 +408,7 @@ class V15 extends Migration { $table ??= $document->getCollection(); - $query = $this->pdo->prepare("SELECT * FROM `{$this->projectDB->getDatabase()}`.`_{$this->project->getInternalId()}_{$table}_perms` WHERE _document = '{$document->getId()}'"); + $query = $this->pdo->prepare("SELECT * FROM `{$this->dbForProject->getDatabase()}`.`_{$this->project->getInternalId()}_{$table}_perms` WHERE _document = '{$document->getId()}'"); $query->execute(); $results = $query->fetchAll(); $permissions = []; @@ -466,7 +466,7 @@ class V15 extends Migration Console::log("Migrating Collection \"{$id}\""); - $this->projectDB->setNamespace("_{$this->project->getInternalId()}"); + $this->dbForProject->setNamespace("_{$this->project->getInternalId()}"); switch ($id) { case '_metadata': @@ -477,7 +477,7 @@ class V15 extends Migration $this->createCollection('cache'); Console::log('Created new Collection "variables" collection'); $this->createCollection('variables'); - $this->projectDB->purgeCachedCollection($id); + $this->dbForProject->purgeCachedCollection($id); break; case 'abuse': @@ -509,7 +509,7 @@ class V15 extends Migration /** * Create 'compression' attribute */ - $this->createAttributeFromCollection($this->projectDB, $id, 'compression'); + $this->createAttributeFromCollection($this->dbForProject, $id, 'compression'); } catch (\Throwable $th) { Console::warning("'compression' from {$id}: {$th->getMessage()}"); } @@ -518,7 +518,7 @@ class V15 extends Migration /** * Create 'fileSecurity' attribute */ - $this->createAttributeFromCollection($this->projectDB, $id, 'fileSecurity'); + $this->createAttributeFromCollection($this->dbForProject, $id, 'fileSecurity'); } catch (\Throwable $th) { Console::warning("'fileSecurity' from {$id}: {$th->getMessage()}"); } @@ -527,7 +527,7 @@ class V15 extends Migration /** * Create '_key_enabled' index */ - $this->createIndexFromCollection($this->projectDB, $id, '_key_enabled'); + $this->createIndexFromCollection($this->dbForProject, $id, '_key_enabled'); } catch (\Throwable $th) { Console::warning("'_key_enabled' from {$id}: {$th->getMessage()}"); } @@ -536,7 +536,7 @@ class V15 extends Migration /** * Create '_key_name' index */ - $this->createIndexFromCollection($this->projectDB, $id, '_key_name'); + $this->createIndexFromCollection($this->dbForProject, $id, '_key_name'); } catch (\Throwable $th) { Console::warning("'_key_name' from {$id}: {$th->getMessage()}"); } @@ -545,7 +545,7 @@ class V15 extends Migration /** * Create '_key_fileSecurity' index */ - $this->createIndexFromCollection($this->projectDB, $id, '_key_fileSecurity'); + $this->createIndexFromCollection($this->dbForProject, $id, '_key_fileSecurity'); } catch (\Throwable $th) { Console::warning("'_key_fileSecurity' from {$id}: {$th->getMessage()}"); } @@ -554,7 +554,7 @@ class V15 extends Migration /** * Create '_key_maximumFileSize' index */ - $this->createIndexFromCollection($this->projectDB, $id, '_key_maximumFileSize'); + $this->createIndexFromCollection($this->dbForProject, $id, '_key_maximumFileSize'); } catch (\Throwable $th) { Console::warning("'_key_maximumFileSize' from {$id}: {$th->getMessage()}"); } @@ -563,7 +563,7 @@ class V15 extends Migration /** * Create '_key_encryption' index */ - $this->createIndexFromCollection($this->projectDB, $id, '_key_encryption'); + $this->createIndexFromCollection($this->dbForProject, $id, '_key_encryption'); } catch (\Throwable $th) { Console::warning("'_key_encryption' from {$id}: {$th->getMessage()}"); } @@ -572,7 +572,7 @@ class V15 extends Migration /** * Create '_key_antivirus' index */ - $this->createIndexFromCollection($this->projectDB, $id, '_key_antivirus'); + $this->createIndexFromCollection($this->dbForProject, $id, '_key_antivirus'); } catch (\Throwable $th) { Console::warning("'_key_antivirus' from {$id}: {$th->getMessage()}"); } @@ -611,7 +611,7 @@ class V15 extends Migration /** * Create '_key_entrypoint' index */ - $this->createIndexFromCollection($this->projectDB, $id, '_key_entrypoint'); + $this->createIndexFromCollection($this->dbForProject, $id, '_key_entrypoint'); } catch (\Throwable $th) { Console::warning("'_key_entrypoint' from {$id}: {$th->getMessage()}"); } @@ -620,7 +620,7 @@ class V15 extends Migration /** * Create '_key_size' index */ - $this->createIndexFromCollection($this->projectDB, $id, '_key_size'); + $this->createIndexFromCollection($this->dbForProject, $id, '_key_size'); } catch (\Throwable $th) { Console::warning("'_key_size' from {$id}: {$th->getMessage()}"); } @@ -629,7 +629,7 @@ class V15 extends Migration /** * Create '_key_buildId' index */ - $this->createIndexFromCollection($this->projectDB, $id, '_key_buildId'); + $this->createIndexFromCollection($this->dbForProject, $id, '_key_buildId'); } catch (\Throwable $th) { Console::warning("'_key_buildId' from {$id}: {$th->getMessage()}"); } @@ -638,7 +638,7 @@ class V15 extends Migration /** * Create '_key_activate' index */ - $this->createIndexFromCollection($this->projectDB, $id, '_key_activate'); + $this->createIndexFromCollection($this->dbForProject, $id, '_key_activate'); } catch (\Throwable $th) { Console::warning("'_key_activate' from {$id}: {$th->getMessage()}"); } @@ -662,7 +662,7 @@ class V15 extends Migration /** * Create 'stdout' attribute */ - $this->createAttributeFromCollection($this->projectDB, $id, 'stdout'); + $this->createAttributeFromCollection($this->dbForProject, $id, 'stdout'); } catch (\Throwable $th) { Console::warning("'stdout' from {$id}: {$th->getMessage()}"); } @@ -671,7 +671,7 @@ class V15 extends Migration /** * Rename 'time' to 'duration' */ - $this->projectDB->renameAttribute($id, 'time', 'duration'); + $this->dbForProject->renameAttribute($id, 'time', 'duration'); } catch (\Throwable $th) { Console::warning("'duration' from {$id}: {$th->getMessage()}"); } @@ -680,7 +680,7 @@ class V15 extends Migration /** * Create '_key_trigger' index */ - $this->createIndexFromCollection($this->projectDB, $id, '_key_trigger'); + $this->createIndexFromCollection($this->dbForProject, $id, '_key_trigger'); } catch (\Throwable $th) { Console::warning("'_key_trigger' from {$id}: {$th->getMessage()}"); } @@ -689,7 +689,7 @@ class V15 extends Migration /** * Create '_key_status' index */ - $this->createIndexFromCollection($this->projectDB, $id, '_key_status'); + $this->createIndexFromCollection($this->dbForProject, $id, '_key_status'); } catch (\Throwable $th) { Console::warning("'_key_status' from {$id}: {$th->getMessage()}"); } @@ -698,7 +698,7 @@ class V15 extends Migration /** * Create '_key_statusCode' index */ - $this->createIndexFromCollection($this->projectDB, $id, '_key_statusCode'); + $this->createIndexFromCollection($this->dbForProject, $id, '_key_statusCode'); } catch (\Throwable $th) { Console::warning("'_key_statusCode' from {$id}: {$th->getMessage()}"); } @@ -707,7 +707,7 @@ class V15 extends Migration /** * Create '_key_duration' index */ - $this->createIndexFromCollection($this->projectDB, $id, '_key_duration'); + $this->createIndexFromCollection($this->dbForProject, $id, '_key_duration'); } catch (\Throwable $th) { Console::warning("'_key_duration' from {$id}: {$th->getMessage()}"); } @@ -751,16 +751,16 @@ class V15 extends Migration 'value' => (string) $value, 'search' => implode(' ', [$variableId, $key, $function->getId()]) ]); - $this->projectDB->createDocument('variables', $variable); + $this->dbForProject->createDocument('variables', $variable); } - $this->projectDB->deleteAttribute('functions', 'vars'); - $this->createAttributeFromCollection($this->projectDB, 'functions', 'vars'); + $this->dbForProject->deleteAttribute('functions', 'vars'); + $this->createAttributeFromCollection($this->dbForProject, 'functions', 'vars'); } try { /** * Create 'scheduleUpdatedAt' attribute */ - $this->createAttributeFromCollection($this->projectDB, $id, 'scheduleUpdatedAt'); + $this->createAttributeFromCollection($this->dbForProject, $id, 'scheduleUpdatedAt'); } catch (\Throwable $th) { Console::warning("'scheduleUpdatedAt' from {$id}: {$th->getMessage()}"); } @@ -768,8 +768,8 @@ class V15 extends Migration /** * Create 'enabled' attribute */ - @$this->projectDB->deleteAttribute($id, 'status'); - $this->createAttributeFromCollection($this->projectDB, $id, 'enabled'); + @$this->dbForProject->deleteAttribute($id, 'status'); + $this->createAttributeFromCollection($this->dbForProject, $id, 'enabled'); } catch (\Throwable $th) { Console::warning("'enabled' from {$id}: {$th->getMessage()}"); } @@ -777,7 +777,7 @@ class V15 extends Migration /** * Create '_key_name' index */ - $this->createIndexFromCollection($this->projectDB, $id, '_key_name'); + $this->createIndexFromCollection($this->dbForProject, $id, '_key_name'); } catch (\Throwable $th) { Console::warning("'_key_name' from {$id}: {$th->getMessage()}"); } @@ -786,7 +786,7 @@ class V15 extends Migration /** * Create '_key_enabled' index */ - $this->createIndexFromCollection($this->projectDB, $id, '_key_enabled'); + $this->createIndexFromCollection($this->dbForProject, $id, '_key_enabled'); } catch (\Throwable $th) { Console::warning("'_key_enabled' from {$id}: {$th->getMessage()}"); } @@ -795,7 +795,7 @@ class V15 extends Migration /** * Create '_key_runtime' index */ - $this->createIndexFromCollection($this->projectDB, $id, '_key_runtime'); + $this->createIndexFromCollection($this->dbForProject, $id, '_key_runtime'); } catch (\Throwable $th) { Console::warning("'_key_runtime' from {$id}: {$th->getMessage()}"); } @@ -804,7 +804,7 @@ class V15 extends Migration /** * Create '_key_deployment' index */ - $this->createIndexFromCollection($this->projectDB, $id, '_key_deployment'); + $this->createIndexFromCollection($this->dbForProject, $id, '_key_deployment'); } catch (\Throwable $th) { Console::warning("'_key_deployment' from {$id}: {$th->getMessage()}"); } @@ -813,7 +813,7 @@ class V15 extends Migration /** * Create '_key_schedule' index */ - $this->createIndexFromCollection($this->projectDB, $id, '_key_schedule'); + $this->createIndexFromCollection($this->dbForProject, $id, '_key_schedule'); } catch (\Throwable $th) { Console::warning("'_key_schedule' from {$id}: {$th->getMessage()}"); } @@ -822,7 +822,7 @@ class V15 extends Migration /** * Create '_key_scheduleNext' index */ - $this->createIndexFromCollection($this->projectDB, $id, '_key_scheduleNext'); + $this->createIndexFromCollection($this->dbForProject, $id, '_key_scheduleNext'); } catch (\Throwable $th) { Console::warning("'_key_scheduleNext' from {$id}: {$th->getMessage()}"); } @@ -831,7 +831,7 @@ class V15 extends Migration /** * Create '_key_schedulePrevious' index */ - $this->createIndexFromCollection($this->projectDB, $id, '_key_schedulePrevious'); + $this->createIndexFromCollection($this->dbForProject, $id, '_key_schedulePrevious'); } catch (\Throwable $th) { Console::warning("'_key_schedulePrevious' from {$id}: {$th->getMessage()}"); } @@ -840,7 +840,7 @@ class V15 extends Migration /** * Create '_key_timeout' index */ - $this->createIndexFromCollection($this->projectDB, $id, '_key_timeout'); + $this->createIndexFromCollection($this->dbForProject, $id, '_key_timeout'); } catch (\Throwable $th) { Console::warning("'_key_timeout' from {$id}: {$th->getMessage()}"); } @@ -863,7 +863,7 @@ class V15 extends Migration /** * Update 'expire' default value */ - $this->projectDB->updateAttributeDefault('keys', 'expire', null); + $this->dbForProject->updateAttributeDefault('keys', 'expire', null); } catch (\Throwable $th) { Console::warning("'expire' from {$id}: {$th->getMessage()}"); } @@ -871,7 +871,7 @@ class V15 extends Migration /** * Create 'accessedAt' attribute */ - $this->createAttributeFromCollection($this->projectDB, $id, 'accessedAt'); + $this->createAttributeFromCollection($this->dbForProject, $id, 'accessedAt'); } catch (\Throwable $th) { Console::warning("'accessedAt' from {$id}: {$th->getMessage()}"); } @@ -880,7 +880,7 @@ class V15 extends Migration /** * Create 'sdks' attribute */ - $this->createAttributeFromCollection($this->projectDB, $id, 'sdks'); + $this->createAttributeFromCollection($this->dbForProject, $id, 'sdks'); } catch (\Throwable $th) { Console::warning("'sdks' from {$id}: {$th->getMessage()}"); } @@ -889,7 +889,7 @@ class V15 extends Migration /** * Create '_key_accessedAt' index */ - $this->createIndexFromCollection($this->projectDB, $id, '_key_accessedAt'); + $this->createIndexFromCollection($this->dbForProject, $id, '_key_accessedAt'); } catch (\Throwable $th) { Console::warning("'_key_accessedAt' from {$id}: {$th->getMessage()}"); } @@ -907,7 +907,7 @@ class V15 extends Migration /** * Create '_key_userId' index */ - $this->createIndexFromCollection($this->projectDB, $id, '_key_userId'); + $this->createIndexFromCollection($this->dbForProject, $id, '_key_userId'); } catch (\Throwable $th) { Console::warning("'_key_userId' from {$id}: {$th->getMessage()}"); } @@ -916,7 +916,7 @@ class V15 extends Migration /** * Create '_key_teamId' index */ - $this->createIndexFromCollection($this->projectDB, $id, '_key_teamId'); + $this->createIndexFromCollection($this->dbForProject, $id, '_key_teamId'); } catch (\Throwable $th) { Console::warning("'_key_teamId' from {$id}: {$th->getMessage()}"); } @@ -925,7 +925,7 @@ class V15 extends Migration /** * Create '_key_invited' index */ - $this->createIndexFromCollection($this->projectDB, $id, '_key_invited'); + $this->createIndexFromCollection($this->dbForProject, $id, '_key_invited'); } catch (\Throwable $th) { Console::warning("'_key_invited' from {$id}: {$th->getMessage()}"); } @@ -934,7 +934,7 @@ class V15 extends Migration /** * Create '_key_joined' index */ - $this->createIndexFromCollection($this->projectDB, $id, '_key_joined'); + $this->createIndexFromCollection($this->dbForProject, $id, '_key_joined'); } catch (\Throwable $th) { Console::warning("'_key_joined' from {$id}: {$th->getMessage()}"); } @@ -943,7 +943,7 @@ class V15 extends Migration /** * Create '_key_confirm' index */ - $this->createIndexFromCollection($this->projectDB, $id, '_key_confirm'); + $this->createIndexFromCollection($this->dbForProject, $id, '_key_confirm'); } catch (\Throwable $th) { Console::warning("'_key_confirm' from {$id}: {$th->getMessage()}"); } @@ -966,7 +966,7 @@ class V15 extends Migration /** * Create '_key_name' index */ - $this->createIndexFromCollection($this->projectDB, $id, '_key_name'); + $this->createIndexFromCollection($this->dbForProject, $id, '_key_name'); } catch (\Throwable $th) { Console::warning("'_key_name' from {$id}: {$th->getMessage()}"); } @@ -1000,8 +1000,8 @@ class V15 extends Migration /** * Re-Create '_key_metric' index */ - @$this->projectDB->deleteIndex($id, '_key_metric'); - $this->createIndexFromCollection($this->projectDB, $id, '_key_period_time'); + @$this->dbForProject->deleteIndex($id, '_key_metric'); + $this->createIndexFromCollection($this->dbForProject, $id, '_key_period_time'); } catch (\Throwable $th) { Console::warning("'_key_period_time' from {$id}: {$th->getMessage()}"); } @@ -1010,8 +1010,8 @@ class V15 extends Migration /** * Re-Create '_key_metric_period' index */ - @$this->projectDB->deleteIndex($id, '_key_metric_period'); - $this->createIndexFromCollection($this->projectDB, $id, '_key_metric_period_time'); + @$this->dbForProject->deleteIndex($id, '_key_metric_period'); + $this->createIndexFromCollection($this->dbForProject, $id, '_key_metric_period_time'); } catch (\Throwable $th) { Console::warning("'_key_metric_period_time' from {$id}: {$th->getMessage()}"); } @@ -1027,7 +1027,7 @@ class V15 extends Migration /** * Create '_key_name' index */ - $this->createIndexFromCollection($this->projectDB, $id, '_key_name'); + $this->createIndexFromCollection($this->dbForProject, $id, '_key_name'); } catch (\Throwable $th) { Console::warning("'_key_name' from {$id}: {$th->getMessage()}"); } @@ -1036,7 +1036,7 @@ class V15 extends Migration /** * Create '_key_total' index */ - $this->createIndexFromCollection($this->projectDB, $id, '_key_total'); + $this->createIndexFromCollection($this->dbForProject, $id, '_key_total'); } catch (\Throwable $th) { Console::warning("'_key_total' from {$id}: {$th->getMessage()}"); } @@ -1062,7 +1062,7 @@ class V15 extends Migration /** * Create 'hash' attribute */ - $this->createAttributeFromCollection($this->projectDB, $id, 'hash'); + $this->createAttributeFromCollection($this->dbForProject, $id, 'hash'); } catch (\Throwable $th) { Console::warning("'hash' from {$id}: {$th->getMessage()}"); } @@ -1071,7 +1071,7 @@ class V15 extends Migration /** * Create 'hashOptions' attribute */ - $this->createAttributeFromCollection($this->projectDB, $id, 'hashOptions'); + $this->createAttributeFromCollection($this->dbForProject, $id, 'hashOptions'); } catch (\Throwable $th) { Console::warning("'hashOptions' from {$id}: {$th->getMessage()}"); } @@ -1124,14 +1124,14 @@ class V15 extends Migration */ $this->populatePermissionsAttribute($user, addCreatePermission: false); - $this->projectDB->updateDocument('users', $user->getId(), $user); + $this->dbForProject->updateDocument('users', $user->getId(), $user); } try { /** * Add datetime filter to password. */ - $this->projectDB->updateAttributeFilters($id, 'password', ['encrypt']); + $this->dbForProject->updateAttributeFilters($id, 'password', ['encrypt']); } catch (\Throwable $th) { Console::warning("Add 'encrypt' filter to 'password' from {$id}: {$th->getMessage()}"); } @@ -1140,7 +1140,7 @@ class V15 extends Migration /** * Create '_key_name' index */ - $this->createIndexFromCollection($this->projectDB, $id, '_key_name'); + $this->createIndexFromCollection($this->dbForProject, $id, '_key_name'); } catch (\Throwable $th) { Console::warning("'_key_name' from {$id}: {$th->getMessage()}"); } @@ -1149,7 +1149,7 @@ class V15 extends Migration /** * Create '_key_status' index */ - $this->createIndexFromCollection($this->projectDB, $id, '_key_status'); + $this->createIndexFromCollection($this->dbForProject, $id, '_key_status'); } catch (\Throwable $th) { Console::warning("'_key_status' from {$id}: {$th->getMessage()}"); } @@ -1158,7 +1158,7 @@ class V15 extends Migration /** * Create '_key_passwordUpdate' index */ - $this->createIndexFromCollection($this->projectDB, $id, '_key_passwordUpdate'); + $this->createIndexFromCollection($this->dbForProject, $id, '_key_passwordUpdate'); } catch (\Throwable $th) { Console::warning("'_key_passwordUpdate' from {$id}: {$th->getMessage()}"); } @@ -1167,7 +1167,7 @@ class V15 extends Migration /** * Create '_key_registration' index */ - $this->createIndexFromCollection($this->projectDB, $id, '_key_registration'); + $this->createIndexFromCollection($this->dbForProject, $id, '_key_registration'); } catch (\Throwable $th) { Console::warning("'_key_registration' from {$id}: {$th->getMessage()}"); } @@ -1176,7 +1176,7 @@ class V15 extends Migration /** * Create '_key_emailVerification' index */ - $this->createIndexFromCollection($this->projectDB, $id, '_key_emailVerification'); + $this->createIndexFromCollection($this->dbForProject, $id, '_key_emailVerification'); } catch (\Throwable $th) { Console::warning("'_key_emailVerification' from {$id}: {$th->getMessage()}"); } @@ -1185,7 +1185,7 @@ class V15 extends Migration /** * Create '_key_phoneVerification' index */ - $this->createIndexFromCollection($this->projectDB, $id, '_key_phoneVerification'); + $this->createIndexFromCollection($this->dbForProject, $id, '_key_phoneVerification'); } catch (\Throwable $th) { Console::warning("'_key_phoneVerification' from {$id}: {$th->getMessage()}"); } @@ -1470,9 +1470,9 @@ class V15 extends Migration $from = $this->pdo->quote($from); $to = $this->pdo->quote($to); - $this->pdo->prepare("UPDATE `{$this->projectDB->getDatabase()}`.`_{$this->project->getInternalId()}_stats` SET metric = {$to} WHERE metric = {$from}")->execute(); + $this->pdo->prepare("UPDATE `{$this->dbForProject->getDatabase()}`.`_{$this->project->getInternalId()}_stats` SET metric = {$to} WHERE metric = {$from}")->execute(); } catch (\Throwable $th) { - Console::warning("Migrating steps from {$this->projectDB->getDatabase()}`.`_{$this->project->getInternalId()}_stats:" . $th->getMessage()); + Console::warning("Migrating steps from {$this->dbForProject->getDatabase()}`.`_{$this->project->getInternalId()}_stats:" . $th->getMessage()); } } diff --git a/src/Appwrite/Migration/Version/V16.php b/src/Appwrite/Migration/Version/V16.php index 49f244598e..34407a0471 100644 --- a/src/Appwrite/Migration/Version/V16.php +++ b/src/Appwrite/Migration/Version/V16.php @@ -45,7 +45,7 @@ class V16 extends Migration Console::log("Migrating Collection \"{$id}\""); - $this->projectDB->setNamespace("_{$this->project->getInternalId()}"); + $this->dbForProject->setNamespace("_{$this->project->getInternalId()}"); switch ($id) { case 'sessions': @@ -53,7 +53,7 @@ class V16 extends Migration /** * Create 'expire' attribute */ - $this->projectDB->deleteAttribute($id, 'expire'); + $this->dbForProject->deleteAttribute($id, 'expire'); } catch (\Throwable $th) { Console::warning("'expire' from {$id}: {$th->getMessage()}"); } @@ -65,7 +65,7 @@ class V16 extends Migration /** * Create 'region' attribute */ - $this->createAttributeFromCollection($this->projectDB, $id, 'region'); + $this->createAttributeFromCollection($this->dbForProject, $id, 'region'); } catch (\Throwable $th) { Console::warning("'region' from {$id}: {$th->getMessage()}"); } @@ -74,7 +74,7 @@ class V16 extends Migration /** * Create '_key_team' index */ - $this->createIndexFromCollection($this->projectDB, $id, '_key_team'); + $this->createIndexFromCollection($this->dbForProject, $id, '_key_team'); } catch (\Throwable $th) { Console::warning("'_key_team' from {$id}: {$th->getMessage()}"); } @@ -85,7 +85,7 @@ class V16 extends Migration /** * Create 'region' attribute */ - $this->createAttributeFromCollection($this->projectDB, $id, 'region'); + $this->createAttributeFromCollection($this->dbForProject, $id, 'region'); } catch (\Throwable $th) { Console::warning("'region' from {$id}: {$th->getMessage()}"); } diff --git a/src/Appwrite/Migration/Version/V17.php b/src/Appwrite/Migration/Version/V17.php index 96c890c65d..f7cb08d6f4 100644 --- a/src/Appwrite/Migration/Version/V17.php +++ b/src/Appwrite/Migration/Version/V17.php @@ -47,8 +47,8 @@ class V17 extends Migration $id = "bucket_{$bucket->getInternalId()}"; try { - $this->projectDB->updateAttribute($id, 'mimeType', Database::VAR_STRING, 255, true, false); - $this->projectDB->purgeCachedCollection($id); + $this->dbForProject->updateAttribute($id, 'mimeType', Database::VAR_STRING, 255, true, false); + $this->dbForProject->purgeCachedCollection($id); } catch (\Throwable $th) { Console::warning("'mimeType' from {$id}: {$th->getMessage()}"); } @@ -67,7 +67,7 @@ class V17 extends Migration Console::log("Migrating Collection \"{$id}\""); - $this->projectDB->setNamespace("_{$this->project->getInternalId()}"); + $this->dbForProject->setNamespace("_{$this->project->getInternalId()}"); switch ($id) { case 'builds': @@ -75,8 +75,8 @@ class V17 extends Migration /** * Create 'size' attribute */ - $this->createAttributeFromCollection($this->projectDB, $id, 'size'); - $this->projectDB->purgeCachedCollection($id); + $this->createAttributeFromCollection($this->dbForProject, $id, 'size'); + $this->dbForProject->purgeCachedCollection($id); } catch (\Throwable $th) { Console::warning("'size' from {$id}: {$th->getMessage()}"); } @@ -87,8 +87,8 @@ class V17 extends Migration /** * Update 'mimeType' attribute size (127->255) */ - $this->projectDB->updateAttribute($id, 'mimeType', Database::VAR_STRING, 255, true, false); - $this->projectDB->purgeCachedCollection($id); + $this->dbForProject->updateAttribute($id, 'mimeType', Database::VAR_STRING, 255, true, false); + $this->dbForProject->purgeCachedCollection($id); } catch (\Throwable $th) { Console::warning("'mimeType' from {$id}: {$th->getMessage()}"); } @@ -97,8 +97,8 @@ class V17 extends Migration /** * Create 'bucketInternalId' attribute */ - $this->createAttributeFromCollection($this->projectDB, $id, 'bucketInternalId'); - $this->projectDB->purgeCachedCollection($id); + $this->createAttributeFromCollection($this->dbForProject, $id, 'bucketInternalId'); + $this->dbForProject->purgeCachedCollection($id); } catch (\Throwable $th) { Console::warning("'deploymentInternalId' from {$id}: {$th->getMessage()}"); } @@ -109,8 +109,8 @@ class V17 extends Migration /** * Delete 'endTime' attribute (use startTime+duration if needed) */ - $this->projectDB->deleteAttribute($id, 'endTime'); - $this->projectDB->purgeCachedCollection($id); + $this->dbForProject->deleteAttribute($id, 'endTime'); + $this->dbForProject->purgeCachedCollection($id); } catch (\Throwable $th) { Console::warning("'endTime' from {$id}: {$th->getMessage()}"); } @@ -119,8 +119,8 @@ class V17 extends Migration /** * Rename 'outputPath' to 'path' */ - $this->projectDB->renameAttribute($id, 'outputPath', 'path'); - $this->projectDB->purgeCachedCollection($id); + $this->dbForProject->renameAttribute($id, 'outputPath', 'path'); + $this->dbForProject->purgeCachedCollection($id); } catch (\Throwable $th) { Console::warning("'path' from {$id}: {$th->getMessage()}"); } @@ -129,8 +129,8 @@ class V17 extends Migration /** * Create 'deploymentInternalId' attribute */ - $this->createAttributeFromCollection($this->projectDB, $id, 'deploymentInternalId'); - $this->projectDB->purgeCachedCollection($id); + $this->createAttributeFromCollection($this->dbForProject, $id, 'deploymentInternalId'); + $this->dbForProject->purgeCachedCollection($id); } catch (\Throwable $th) { Console::warning("'deploymentInternalId' from {$id}: {$th->getMessage()}"); } @@ -141,8 +141,8 @@ class V17 extends Migration /** * Delete 'type' attribute */ - $this->projectDB->deleteAttribute($id, 'type'); - $this->projectDB->purgeCachedCollection($id); + $this->dbForProject->deleteAttribute($id, 'type'); + $this->dbForProject->purgeCachedCollection($id); } catch (\Throwable $th) { Console::warning("'type' from {$id}: {$th->getMessage()}"); } @@ -153,8 +153,8 @@ class V17 extends Migration /** * Create 'resourceInternalId' attribute */ - $this->createAttributeFromCollection($this->projectDB, $id, 'resourceInternalId'); - $this->projectDB->purgeCachedCollection($id); + $this->createAttributeFromCollection($this->dbForProject, $id, 'resourceInternalId'); + $this->dbForProject->purgeCachedCollection($id); } catch (\Throwable $th) { Console::warning("'resourceInternalId' from {$id}: {$th->getMessage()}"); } @@ -165,8 +165,8 @@ class V17 extends Migration /** * Create 'deploymentInternalId' attribute */ - $this->createAttributeFromCollection($this->projectDB, $id, 'deploymentInternalId'); - $this->projectDB->purgeCachedCollection($id); + $this->createAttributeFromCollection($this->dbForProject, $id, 'deploymentInternalId'); + $this->dbForProject->purgeCachedCollection($id); } catch (\Throwable $th) { Console::warning("'deploymentInternalId' from {$id}: {$th->getMessage()}"); } @@ -175,8 +175,8 @@ class V17 extends Migration /** * Create 'scheduleInternalId' attribute */ - $this->createAttributeFromCollection($this->projectDB, $id, 'scheduleInternalId'); - $this->projectDB->purgeCachedCollection($id); + $this->createAttributeFromCollection($this->dbForProject, $id, 'scheduleInternalId'); + $this->dbForProject->purgeCachedCollection($id); } catch (\Throwable $th) { Console::warning("'scheduleInternalId' from {$id}: {$th->getMessage()}"); } @@ -185,8 +185,8 @@ class V17 extends Migration /** * Delete 'scheduleUpdatedAt' attribute */ - $this->projectDB->deleteAttribute($id, 'scheduleUpdatedAt'); - $this->projectDB->purgeCachedCollection($id); + $this->dbForProject->deleteAttribute($id, 'scheduleUpdatedAt'); + $this->dbForProject->purgeCachedCollection($id); } catch (\Throwable $th) { Console::warning("'scheduleUpdatedAt' from {$id}: {$th->getMessage()}"); } @@ -197,8 +197,8 @@ class V17 extends Migration /** * Create 'resourceInternalId' attribute */ - $this->createAttributeFromCollection($this->projectDB, $id, 'resourceInternalId'); - $this->projectDB->purgeCachedCollection($id); + $this->createAttributeFromCollection($this->dbForProject, $id, 'resourceInternalId'); + $this->dbForProject->purgeCachedCollection($id); } catch (\Throwable $th) { Console::warning("'resourceInternalId' from {$id}: {$th->getMessage()}"); } @@ -207,8 +207,8 @@ class V17 extends Migration /** * Create 'buildInternalId' attribute */ - $this->createAttributeFromCollection($this->projectDB, $id, 'buildInternalId'); - $this->projectDB->purgeCachedCollection($id); + $this->createAttributeFromCollection($this->dbForProject, $id, 'buildInternalId'); + $this->dbForProject->purgeCachedCollection($id); } catch (\Throwable $th) { Console::warning("'buildInternalId' from {$id}: {$th->getMessage()}"); } @@ -219,8 +219,8 @@ class V17 extends Migration /** * Create 'functionInternalId' attribute */ - $this->createAttributeFromCollection($this->projectDB, $id, 'functionInternalId'); - $this->projectDB->purgeCachedCollection($id); + $this->createAttributeFromCollection($this->dbForProject, $id, 'functionInternalId'); + $this->dbForProject->purgeCachedCollection($id); } catch (\Throwable $th) { Console::warning("'functionInternalId' from {$id}: {$th->getMessage()}"); } @@ -229,8 +229,8 @@ class V17 extends Migration /** * Create 'deploymentInternalId' attribute */ - $this->createAttributeFromCollection($this->projectDB, $id, 'deploymentInternalId'); - $this->projectDB->purgeCachedCollection($id); + $this->createAttributeFromCollection($this->dbForProject, $id, 'deploymentInternalId'); + $this->dbForProject->purgeCachedCollection($id); } catch (\Throwable $th) { Console::warning("'deploymentInternalId' from {$id}: {$th->getMessage()}"); } diff --git a/src/Appwrite/Migration/Version/V18.php b/src/Appwrite/Migration/Version/V18.php index ac4093aaca..a5fae3789b 100644 --- a/src/Appwrite/Migration/Version/V18.php +++ b/src/Appwrite/Migration/Version/V18.php @@ -26,7 +26,7 @@ class V18 extends Migration } Console::log('Migrating Project: ' . $this->project->getAttribute('name') . ' (' . $this->project->getId() . ')'); - $this->projectDB->setNamespace("_{$this->project->getInternalId()}"); + $this->dbForProject->setNamespace("_{$this->project->getInternalId()}"); $this->addDocumentSecurityToProject(); Console::info('Migrating Databases'); @@ -66,7 +66,7 @@ class V18 extends Migration $documentSecurity = $collection->getAttribute('documentSecurity', false); $permissions = $collection->getPermissions(); - $this->projectDB->updateCollection($collectionTable, $permissions, $documentSecurity); + $this->dbForProject->updateCollection($collectionTable, $permissions, $documentSecurity); } catch (\Throwable $th) { Console::warning($th->getMessage()); } @@ -94,7 +94,7 @@ class V18 extends Migration } try { - $this->projectDB->updateCollection($id, [Permission::create(Role::any())], true); + $this->dbForProject->updateCollection($id, [Permission::create(Role::any())], true); } catch (\Throwable $th) { Console::warning($th->getMessage()); } @@ -105,8 +105,8 @@ class V18 extends Migration /** * Create 'passwordHistory' attribute */ - $this->createAttributeFromCollection($this->projectDB, $id, 'passwordHistory'); - $this->projectDB->purgeCachedCollection($id); + $this->createAttributeFromCollection($this->dbForProject, $id, 'passwordHistory'); + $this->dbForProject->purgeCachedCollection($id); } catch (\Throwable $th) { Console::warning("'passwordHistory' from {$id}: {$th->getMessage()}"); } @@ -116,8 +116,8 @@ class V18 extends Migration /** * Create 'prefs' attribute */ - $this->createAttributeFromCollection($this->projectDB, $id, 'prefs'); - $this->projectDB->purgeCachedCollection($id); + $this->createAttributeFromCollection($this->dbForProject, $id, 'prefs'); + $this->dbForProject->purgeCachedCollection($id); } catch (\Throwable $th) { Console::warning("'prefs' from {$id}: {$th->getMessage()}"); } @@ -127,8 +127,8 @@ class V18 extends Migration /** * Create 'options' attribute */ - $this->createAttributeFromCollection($this->projectDB, $id, 'options'); - $this->projectDB->purgeCachedCollection($id); + $this->createAttributeFromCollection($this->dbForProject, $id, 'options'); + $this->dbForProject->purgeCachedCollection($id); } catch (\Throwable $th) { Console::warning("'options' from {$id}: {$th->getMessage()}"); } @@ -138,7 +138,7 @@ class V18 extends Migration /** * Delete 'userInternalId' attribute */ - $this->projectDB->deleteAttribute($id, 'userInternalId'); + $this->dbForProject->deleteAttribute($id, 'userInternalId'); } catch (\Throwable $th) { Console::warning("'userInternalId' from {$id}: {$th->getMessage()}"); } @@ -200,7 +200,7 @@ class V18 extends Migration $internalBucketId = "bucket_{$this->project->getInternalId()}"; $permissions = $document->getPermissions(); $fileSecurity = $document->getAttribute('fileSecurity', false); - $this->projectDB->updateCollection($internalBucketId, $permissions, $fileSecurity); + $this->dbForProject->updateCollection($internalBucketId, $permissions, $fileSecurity); } catch (\Throwable $th) { Console::warning($th->getMessage()); } @@ -214,8 +214,8 @@ class V18 extends Migration $data = $document->getAttribute('data', []); $mode = $data['mode'] ?? 'default'; $user = match ($mode) { - 'admin' => $this->consoleDB->getDocument('users', $userId), - default => $this->projectDB->getDocument('users', $userId), + 'admin' => $this->dbForPlatform->getDocument('users', $userId), + default => $this->dbForProject->getDocument('users', $userId), }; if ($user->isEmpty()) { @@ -244,7 +244,7 @@ class V18 extends Migration /** * Create 'documentSecurity' column */ - $this->pdo->prepare("ALTER TABLE `{$this->projectDB->getDatabase()}`.`_{$this->project->getInternalId()}__metadata` ADD COLUMN IF NOT EXISTS documentSecurity TINYINT(1);")->execute(); + $this->pdo->prepare("ALTER TABLE `{$this->dbForProject->getDatabase()}`.`_{$this->project->getInternalId()}__metadata` ADD COLUMN IF NOT EXISTS documentSecurity TINYINT(1);")->execute(); } catch (\Throwable $th) { Console::warning($th->getMessage()); } @@ -253,7 +253,7 @@ class V18 extends Migration /** * Set 'documentSecurity' column to 1 if NULL */ - $this->pdo->prepare("UPDATE `{$this->projectDB->getDatabase()}`.`_{$this->project->getInternalId()}__metadata` SET documentSecurity = 1 WHERE documentSecurity IS NULL")->execute(); + $this->pdo->prepare("UPDATE `{$this->dbForProject->getDatabase()}`.`_{$this->project->getInternalId()}__metadata` SET documentSecurity = 1 WHERE documentSecurity IS NULL")->execute(); } catch (\Throwable $th) { Console::warning($th->getMessage()); } diff --git a/src/Appwrite/Migration/Version/V19.php b/src/Appwrite/Migration/Version/V19.php index 4415003bfd..cae27cc6ed 100644 --- a/src/Appwrite/Migration/Version/V19.php +++ b/src/Appwrite/Migration/Version/V19.php @@ -28,7 +28,7 @@ class V19 extends Migration } Console::log('Migrating Project: ' . $this->project->getAttribute('name') . ' (' . $this->project->getId() . ')'); - $this->projectDB->setNamespace("_{$this->project->getInternalId()}"); + $this->dbForProject->setNamespace("_{$this->project->getInternalId()}"); Console::info('Migrating Collections'); $this->migrateCollections(); @@ -55,7 +55,7 @@ class V19 extends Migration protected function migrateDomains(): void { - if ($this->consoleDB->exists($this->consoleDB->getDatabase(), 'domains')) { + if ($this->dbForPlatform->exists($this->dbForPlatform->getDatabase(), 'domains')) { foreach ($this->documentsIterator('domains') as $domain) { $status = 'created'; if ($domain->getAttribute('verification', false)) { @@ -82,7 +82,7 @@ class V19 extends Migration ]); try { - $this->consoleDB->createDocument('rules', $ruleDocument); + $this->dbForPlatform->createDocument('rules', $ruleDocument); } catch (\Throwable $th) { Console::warning("Error migrating domain {$domain->getAttribute('domain')}: {$th->getMessage()}"); } @@ -104,8 +104,8 @@ class V19 extends Migration Console::log("Migrating Bucket {$id} {$bucket->getId()} ({$bucket->getAttribute('name')})"); try { - $this->createAttributeFromCollection($this->projectDB, $id, 'bucketInternalId', 'files'); - $this->projectDB->purgeCachedCollection($id); + $this->createAttributeFromCollection($this->dbForProject, $id, 'bucketInternalId', 'files'); + $this->dbForProject->purgeCachedCollection($id); } catch (\Throwable $th) { Console::warning("'bucketInternalId' from {$id}: {$th->getMessage()}"); } @@ -136,7 +136,7 @@ class V19 extends Migration Console::log("Migrating Collection \"{$id}\""); - $this->projectDB->setNamespace("_$internalProjectId"); + $this->dbForProject->setNamespace("_$internalProjectId"); switch ($id) { case '_metadata': @@ -148,24 +148,24 @@ class V19 extends Migration case 'attributes': case 'indexes': try { - $this->projectDB->updateAttribute($id, 'databaseInternalId', required: true); + $this->dbForProject->updateAttribute($id, 'databaseInternalId', required: true); } catch (\Throwable $th) { Console::warning("'databaseInternalId' from {$id}: {$th->getMessage()}"); } try { - $this->projectDB->updateAttribute($id, 'collectionInternalId', required: true); + $this->dbForProject->updateAttribute($id, 'collectionInternalId', required: true); } catch (\Throwable $th) { Console::warning("'collectionInternalId' from {$id}: {$th->getMessage()}"); } try { - $this->createAttributeFromCollection($this->projectDB, $id, 'error'); + $this->createAttributeFromCollection($this->dbForProject, $id, 'error'); } catch (\Throwable $th) { Console::warning("'error' from {$id}: {$th->getMessage()}"); } - $this->projectDB->purgeCachedCollection($id); + $this->dbForProject->purgeCachedCollection($id); break; case 'buckets': @@ -175,7 +175,7 @@ class V19 extends Migration ]; foreach ($indexesToDelete as $index) { try { - $this->projectDB->deleteIndex($id, $index); + $this->dbForProject->deleteIndex($id, $index); } catch (\Throwable $th) { Console::warning("'$index' from {$id}: {$th->getMessage()}"); } @@ -187,13 +187,13 @@ class V19 extends Migration foreach ($indexesToCreate as $index) { try { - $this->createIndexFromCollection($this->projectDB, $id, $index); + $this->createIndexFromCollection($this->dbForProject, $id, $index); } catch (\Throwable $th) { Console::warning("'$index' from {$id}: {$th->getMessage()}"); } } - $this->projectDB->purgeCachedCollection($id); + $this->dbForProject->purgeCachedCollection($id); break; case 'builds': @@ -204,45 +204,45 @@ class V19 extends Migration ]; foreach ($attributesToCreate as $attribute) { try { - $this->createAttributeFromCollection($this->projectDB, $id, $attribute); + $this->createAttributeFromCollection($this->dbForProject, $id, $attribute); } catch (\Throwable $th) { Console::warning("$attribute from {$id}: {$th->getMessage()}"); } } try { - $this->projectDB->renameAttribute($id, 'outputPath', 'path'); + $this->dbForProject->renameAttribute($id, 'outputPath', 'path'); } catch (\Throwable $th) { Console::warning("'path' from {$id}: {$th->getMessage()}"); } - $this->projectDB->purgeCachedCollection($id); + $this->dbForProject->purgeCachedCollection($id); break; case 'certificates': try { - $this->projectDB->renameAttribute($id, 'log', 'logs'); + $this->dbForProject->renameAttribute($id, 'log', 'logs'); } catch (\Throwable $th) { Console::warning("'logs' from {$id}: {$th->getMessage()}"); } try { - $this->projectDB->updateAttribute($id, 'logs', size: 1000000); + $this->dbForProject->updateAttribute($id, 'logs', size: 1000000); } catch (\Throwable $th) { Console::warning("'logs' from {$id}: {$th->getMessage()}"); } - $this->projectDB->purgeCachedCollection($id); + $this->dbForProject->purgeCachedCollection($id); break; case 'databases': try { - $this->createAttributeFromCollection($this->projectDB, $id, 'enabled'); + $this->createAttributeFromCollection($this->dbForProject, $id, 'enabled'); } catch (\Throwable $th) { Console::warning("'enabled' from {$id}: {$th->getMessage()}"); } - $this->projectDB->purgeCachedCollection($id); + $this->dbForProject->purgeCachedCollection($id); break; case 'deployments': @@ -271,7 +271,7 @@ class V19 extends Migration ]; foreach ($attributesToCreate as $attribute) { try { - $this->createAttributeFromCollection($this->projectDB, $id, $attribute); + $this->createAttributeFromCollection($this->dbForProject, $id, $attribute); } catch (\Throwable $th) { Console::warning("$attribute from {$id}: {$th->getMessage()}"); } @@ -286,7 +286,7 @@ class V19 extends Migration ]; foreach ($indexesToDelete as $index) { try { - $this->projectDB->deleteIndex($id, $index); + $this->dbForProject->deleteIndex($id, $index); } catch (\Throwable $th) { Console::warning("'$index' from {$id}: {$th->getMessage()}"); } @@ -299,13 +299,13 @@ class V19 extends Migration ]; foreach ($indexesToCreate as $index) { try { - $this->createIndexFromCollection($this->projectDB, $id, $index); + $this->createIndexFromCollection($this->dbForProject, $id, $index); } catch (\Throwable $th) { Console::warning("'$index' from {$id}: {$th->getMessage()}"); } } - $this->projectDB->purgeCachedCollection($id); + $this->dbForProject->purgeCachedCollection($id); break; case 'executions': @@ -319,7 +319,7 @@ class V19 extends Migration ]; foreach ($attributesToCreate as $attribute) { try { - $this->createAttributeFromCollection($this->projectDB, $id, $attribute); + $this->createAttributeFromCollection($this->dbForProject, $id, $attribute); } catch (\Throwable $th) { Console::warning("$attribute from {$id}: {$th->getMessage()}"); } @@ -330,43 +330,43 @@ class V19 extends Migration ]; foreach ($attributesToDelete as $attribute) { try { - $this->projectDB->deleteAttribute($id, $attribute); + $this->dbForProject->deleteAttribute($id, $attribute); } catch (\Throwable $th) { Console::warning("'$attribute' from {$id}: {$th->getMessage()}"); } } try { - $this->projectDB->renameAttribute($id, 'stderr', 'errors'); + $this->dbForProject->renameAttribute($id, 'stderr', 'errors'); } catch (\Throwable $th) { Console::warning("'errors' from {$id}: {$th->getMessage()}"); } try { - $this->projectDB->renameAttribute($id, 'stdout', 'logs'); + $this->dbForProject->renameAttribute($id, 'stdout', 'logs'); } catch (\Throwable $th) { Console::warning("'logs' from {$id}: {$th->getMessage()}"); } try { - $this->projectDB->renameAttribute($id, 'statusCode', 'responseStatusCode'); + $this->dbForProject->renameAttribute($id, 'statusCode', 'responseStatusCode'); } catch (\Throwable $th) { Console::warning("'responseStatusCode' from {$id}: {$th->getMessage()}"); } try { - $this->projectDB->deleteIndex($id, '_key_statusCode'); + $this->dbForProject->deleteIndex($id, '_key_statusCode'); } catch (\Throwable $th) { Console::warning("'_key_statusCode' from {$id}: {$th->getMessage()}"); } try { - $this->createIndexFromCollection($this->projectDB, $id, '_key_responseStatusCode'); + $this->createIndexFromCollection($this->dbForProject, $id, '_key_responseStatusCode'); } catch (\Throwable $th) { Console::warning("'_key_responseStatusCode' from {$id}: {$th->getMessage()}"); } - $this->projectDB->purgeCachedCollection($id); + $this->dbForProject->purgeCachedCollection($id); break; case 'files': @@ -378,7 +378,7 @@ class V19 extends Migration ]; foreach ($indexesToDelete as $index) { try { - $this->projectDB->deleteIndex($id, $index); + $this->dbForProject->deleteIndex($id, $index); } catch (\Throwable $th) { Console::warning("'$index' from {$id}: {$th->getMessage()}"); } @@ -387,13 +387,13 @@ class V19 extends Migration $indexesToCreate = $indexesToDelete; foreach ($indexesToCreate as $index) { try { - $this->createIndexFromCollection($this->projectDB, $id, $index); + $this->createIndexFromCollection($this->dbForProject, $id, $index); } catch (\Throwable $th) { Console::warning("'$index' from {$id}: {$th->getMessage()}"); } } - $this->projectDB->purgeCachedCollection($id); + $this->dbForProject->purgeCachedCollection($id); break; case 'functions': @@ -419,7 +419,7 @@ class V19 extends Migration ]; foreach ($attributesToCreate as $attribute) { try { - $this->createAttributeFromCollection($this->projectDB, $id, $attribute); + $this->createAttributeFromCollection($this->dbForProject, $id, $attribute); } catch (\Throwable $th) { Console::warning("'$attribute' from {$id}: {$th->getMessage()}"); } @@ -433,7 +433,7 @@ class V19 extends Migration ]; foreach ($indexesToDelete as $index) { try { - $this->projectDB->deleteIndex($id, $index); + $this->dbForProject->deleteIndex($id, $index); } catch (\Throwable $th) { Console::warning("'$index' from {$id}: {$th->getMessage()}"); } @@ -449,34 +449,34 @@ class V19 extends Migration ]; foreach ($indexesToCreate as $index) { try { - $this->createIndexFromCollection($this->projectDB, $id, $index); + $this->createIndexFromCollection($this->dbForProject, $id, $index); } catch (\Throwable $th) { Console::warning("'$index' from {$id}: {$th->getMessage()}"); } } - $this->projectDB->purgeCachedCollection($id); + $this->dbForProject->purgeCachedCollection($id); break; case 'memberships': try { - $this->projectDB->updateAttribute($id, 'teamInternalId', required: true); + $this->dbForProject->updateAttribute($id, 'teamInternalId', required: true); } catch (\Throwable $th) { Console::warning("'teamInternalId' from {$id}: {$th->getMessage()}"); } - $this->projectDB->purgeCachedCollection($id); + $this->dbForProject->purgeCachedCollection($id); // Intentional fall through to update memberships.userInternalId case 'sessions': case 'tokens': try { - $this->projectDB->updateAttribute($id, 'userInternalId', required: true); + $this->dbForProject->updateAttribute($id, 'userInternalId', required: true); } catch (\Throwable $th) { Console::warning("'userInternalId' from {$id}: {$th->getMessage()}"); } - $this->projectDB->purgeCachedCollection($id); + $this->dbForProject->purgeCachedCollection($id); break; case 'domains': @@ -484,12 +484,12 @@ class V19 extends Migration case 'platforms': case 'webhooks': try { - $this->projectDB->updateAttribute($id, 'projectInternalId', required: true); + $this->dbForProject->updateAttribute($id, 'projectInternalId', required: true); } catch (\Throwable $th) { Console::warning("'projectInternalId' from {$id}: {$th->getMessage()}"); } - $this->projectDB->purgeCachedCollection($id); + $this->dbForProject->purgeCachedCollection($id); break; case 'projects': @@ -500,19 +500,19 @@ class V19 extends Migration ]; foreach ($attributesToCreate as $attribute) { try { - $this->createAttributeFromCollection($this->projectDB, $id, $attribute); + $this->createAttributeFromCollection($this->dbForProject, $id, $attribute); } catch (\Throwable $th) { Console::warning("'$attribute' from {$id}: {$th->getMessage()}"); Console::warning($th->getTraceAsString()); } } - $this->projectDB->purgeCachedCollection($id); + $this->dbForProject->purgeCachedCollection($id); break; case 'stats': try { - $this->projectDB->updateAttribute($id, 'value', signed: true); + $this->dbForProject->updateAttribute($id, 'value', signed: true); } catch (\Throwable $th) { Console::warning("'value' from {$id}: {$th->getMessage()}"); } @@ -539,64 +539,64 @@ class V19 extends Migration // Console::warning("'_key_metric_period_time' from {$id}: {$th->getMessage()}"); // } - $this->projectDB->purgeCachedCollection($id); + $this->dbForProject->purgeCachedCollection($id); break; case 'users': try { - $this->createAttributeFromCollection($this->projectDB, $id, 'labels'); + $this->createAttributeFromCollection($this->dbForProject, $id, 'labels'); } catch (\Throwable $th) { Console::warning("'labels' from {$id}: {$th->getMessage()}"); } try { - $this->createAttributeFromCollection($this->projectDB, $id, 'accessedAt'); + $this->createAttributeFromCollection($this->dbForProject, $id, 'accessedAt'); } catch (\Throwable $th) { Console::warning("'accessedAt' from {$id}: {$th->getMessage()}"); } try { - $this->projectDB->updateAttribute($id, 'search', filters: ['userSearch']); + $this->dbForProject->updateAttribute($id, 'search', filters: ['userSearch']); } catch (\Throwable $th) { Console::warning("'search' from {$id}: {$th->getMessage()}"); } try { - $this->createIndexFromCollection($this->projectDB, $id, '_key_accessedAt'); + $this->createIndexFromCollection($this->dbForProject, $id, '_key_accessedAt'); } catch (\Throwable $th) { Console::warning("'_key_accessedAt' from {$id}: {$th->getMessage()}"); } - $this->projectDB->purgeCachedCollection($id); + $this->dbForProject->purgeCachedCollection($id); break; case 'variables': try { - $this->projectDB->deleteIndex($id, '_key_function'); + $this->dbForProject->deleteIndex($id, '_key_function'); } catch (\Throwable $th) { Console::warning("'_key_function' from {$id}: {$th->getMessage()}"); } try { - $this->projectDB->deleteIndex($id, '_key_uniqueKey'); + $this->dbForProject->deleteIndex($id, '_key_uniqueKey'); } catch (\Throwable $th) { Console::warning("'_key_uniqueKey' from {$id}: {$th->getMessage()}"); } try { - $this->createAttributeFromCollection($this->projectDB, $id, 'resourceType'); + $this->createAttributeFromCollection($this->dbForProject, $id, 'resourceType'); } catch (\Throwable $th) { Console::warning("'resourceType' from {$id}: {$th->getMessage()}"); } try { - $this->projectDB->renameAttribute($id, 'functionInternalId', 'resourceInternalId'); + $this->dbForProject->renameAttribute($id, 'functionInternalId', 'resourceInternalId'); } catch (\Throwable $th) { Console::warning("'resourceInternalId' from {$id}: {$th->getMessage()}"); } try { - $this->projectDB->renameAttribute($id, 'functionId', 'resourceId'); + $this->dbForProject->renameAttribute($id, 'functionId', 'resourceId'); } catch (\Throwable $th) { Console::warning("'resourceId' from {$id}: {$th->getMessage()}"); } @@ -609,13 +609,13 @@ class V19 extends Migration ]; foreach ($indexesToCreate as $index) { try { - $this->createIndexFromCollection($this->projectDB, $id, $index); + $this->createIndexFromCollection($this->dbForProject, $id, $index); } catch (\Throwable $th) { Console::warning("'$index' from {$id}: {$th->getMessage()}"); } } - $this->projectDB->purgeCachedCollection($id); + $this->dbForProject->purgeCachedCollection($id); break; default: @@ -654,10 +654,10 @@ class V19 extends Migration ]) as $attribute ) { $attribute->setAttribute('size', Database::LENGTH_KEY); - $this->projectDB->updateDocument('attributes', $attribute->getId(), $attribute); + $this->dbForProject->updateDocument('attributes', $attribute->getId(), $attribute); $databaseInternalId = $attribute->getAttribute('databaseInternalId'); $collectionInternalId = $attribute->getAttribute('collectionInternalId'); - $this->projectDB->updateAttribute('database_' . $databaseInternalId . '_collection_' . $collectionInternalId, $attribute->getAttribute('key'), size: 255); + $this->dbForProject->updateAttribute('database_' . $databaseInternalId . '_collection_' . $collectionInternalId, $attribute->getAttribute('key'), size: 255); } } @@ -679,7 +679,7 @@ class V19 extends Migration break; case 'builds': $deploymentId = $document->getAttribute('deploymentId'); - $deployment = $this->projectDB->getDocument('deployments', $deploymentId); + $deployment = $this->dbForProject->getDocument('deployments', $deploymentId); $document->setAttribute('deploymentInternalId', $deployment->getInternalId()); $stdout = $document->getAttribute('stdout', ''); @@ -691,12 +691,12 @@ class V19 extends Migration break; case 'deployments': $resourceId = $document->getAttribute('resourceId'); - $function = $this->projectDB->getDocument('functions', $resourceId); + $function = $this->dbForProject->getDocument('functions', $resourceId); $document->setAttribute('resourceInternalId', $function->getInternalId()); $buildId = $document->getAttribute('buildId'); if (!empty($buildId)) { - $build = $this->projectDB->getDocument('builds', $buildId); + $build = $this->dbForProject->getDocument('builds', $buildId); $document->setAttribute('buildInternalId', $build->getInternalId()); } @@ -706,11 +706,11 @@ class V19 extends Migration break; case 'executions': $functionId = $document->getAttribute('functionId'); - $function = $this->projectDB->getDocument('functions', $functionId); + $function = $this->dbForProject->getDocument('functions', $functionId); $document->setAttribute('functionInternalId', $function->getInternalId()); $deploymentId = $document->getAttribute('deploymentId'); - $deployment = $this->projectDB->getDocument('deployments', $deploymentId); + $deployment = $this->dbForProject->getDocument('deployments', $deploymentId); $document->setAttribute('deploymentInternalId', $deployment->getInternalId()); break; case 'functions': @@ -720,7 +720,7 @@ class V19 extends Migration $deploymentId = $document->getAttribute('deployment'); if (!empty($deploymentId)) { - $deployment = $this->projectDB->getDocument('deployments', $deploymentId); + $deployment = $this->dbForProject->getDocument('deployments', $deploymentId); $document->setAttribute('deploymentInternalId', $deployment->getInternalId()); $document->setAttribute('entrypoint', $deployment->getAttribute('entrypoint')); } @@ -729,7 +729,7 @@ class V19 extends Migration $document->setAttribute('commands', $document->getAttribute('commands', $commands)); if (empty($document->getAttribute('scheduleId', null))) { - $schedule = $this->consoleDB->createDocument('schedules', new Document([ + $schedule = $this->dbForPlatform->createDocument('schedules', new Document([ 'region' => $project->getAttribute('region'), 'resourceType' => 'function', 'resourceId' => $document->getId(), @@ -769,26 +769,26 @@ class V19 extends Migration private function cleanCollections(): void { try { - $this->projectDB->deleteAttribute('projects', 'domains'); + $this->dbForProject->deleteAttribute('projects', 'domains'); } catch (\Throwable $th) { Console::warning("'domains' from projects: {$th->getMessage()}"); } - $this->projectDB->purgeCachedCollection('projects'); + $this->dbForProject->purgeCachedCollection('projects'); try { - $this->projectDB->deleteAttribute('builds', 'stderr'); + $this->dbForProject->deleteAttribute('builds', 'stderr'); } catch (\Throwable $th) { Console::warning("'stderr' from builds: {$th->getMessage()}"); } try { - $this->projectDB->deleteAttribute('builds', 'stdout'); + $this->dbForProject->deleteAttribute('builds', 'stdout'); } catch (\Throwable $th) { Console::warning("'stdout' from builds: {$th->getMessage()}"); } - $this->projectDB->purgeCachedCollection('builds'); + $this->dbForProject->purgeCachedCollection('builds'); } /** @@ -829,7 +829,7 @@ class V19 extends Migration } try { - $this->projectDB->updateDocument($document->getCollection(), $document->getId(), $document); + $this->dbForProject->updateDocument($document->getCollection(), $document->getId(), $document); } catch (\Throwable $th) { Console::error('Failed to update document: ' . $th->getMessage()); return; diff --git a/src/Appwrite/Migration/Version/V20.php b/src/Appwrite/Migration/Version/V20.php index 5a0807cedf..3a9bba6772 100644 --- a/src/Appwrite/Migration/Version/V20.php +++ b/src/Appwrite/Migration/Version/V20.php @@ -36,7 +36,7 @@ class V20 extends Migration } Console::log('Migrating Project: ' . $this->project->getAttribute('name') . ' (' . $this->project->getId() . ')'); - $this->projectDB->setNamespace("_{$this->project->getInternalId()}"); + $this->dbForProject->setNamespace("_{$this->project->getInternalId()}"); Console::info('Migrating Collections'); $this->migrateCollections(); @@ -94,19 +94,19 @@ class V20 extends Migration ) { if (\in_array($attribute->getAttribute('key'), $index->getAttribute('attributes'))) { try { - $this->projectDB->deleteIndex($collectionId, $index->getAttribute('key')); + $this->dbForProject->deleteIndex($collectionId, $index->getAttribute('key')); } catch (Throwable $th) { Console::warning("Failed to delete index: {$th->getMessage()}"); } try { - $this->projectDB->deleteDocument('indexes', $index->getId()); + $this->dbForProject->deleteDocument('indexes', $index->getId()); } catch (Throwable $th) { Console::warning("Failed to remove index: {$th->getMessage()}"); } } } - $this->projectDB->updateAttribute($collectionId, $attribute['key'], $attribute['type']); + $this->dbForProject->updateAttribute($collectionId, $attribute['key'], $attribute['type']); } } @@ -116,19 +116,19 @@ class V20 extends Migration Console::log("Migrating Collection \"{$id}\""); - $this->projectDB->setNamespace("_$internalProjectId"); + $this->dbForProject->setNamespace("_$internalProjectId"); // Support database array type migration foreach ($collection['attributes'] ?? [] as $attribute) { if ($attribute['array'] === true) { foreach ($collection['indexes'] ?? [] as $index) { if (\in_array($attribute['$id'], $index['attributes'])) { - $this->projectDB->deleteIndex($id, $index['$id']); + $this->dbForProject->deleteIndex($id, $index['$id']); } } try { - $this->projectDB->updateAttribute($id, $attribute['$id'], $attribute['type']); + $this->dbForProject->updateAttribute($id, $attribute['$id'], $attribute['type']); } catch (Throwable $th) { Console::warning("'{$attribute['$id']}' from {$id}: {$th->getMessage()}"); } @@ -151,19 +151,19 @@ class V20 extends Migration // Create resourceType attribute try { - $this->createAttributeFromCollection($this->projectDB, $id, 'resourceType'); + $this->createAttributeFromCollection($this->dbForProject, $id, 'resourceType'); } catch (Throwable $th) { Console::warning("'resourceType' from {$id}: {$th->getMessage()}"); } // Create mimeType attribute try { - $this->createAttributeFromCollection($this->projectDB, $id, 'mimeType'); + $this->createAttributeFromCollection($this->dbForProject, $id, 'mimeType'); } catch (Throwable $th) { Console::warning("'mimeType' from {$id}: {$th->getMessage()}"); } try { - $this->projectDB->purgeCachedCollection($id); + $this->dbForProject->purgeCachedCollection($id); } catch (Throwable $th) { Console::warning("Purge cache from {$id}: {$th->getMessage()}"); } @@ -174,11 +174,11 @@ class V20 extends Migration /** * Delete 'type' attribute */ - $this->projectDB->deleteAttribute($id, 'type'); + $this->dbForProject->deleteAttribute($id, 'type'); /** * Alter `signed` internal type on `value` attr */ - $this->projectDB->updateAttribute(collection: $id, id: 'value', signed: true); + $this->dbForProject->updateAttribute(collection: $id, id: 'value', signed: true); } catch (Throwable $th) { Console::warning("'type' from {$id}: {$th->getMessage()}"); } @@ -187,13 +187,13 @@ class V20 extends Migration /** * Ensure 'time' attribute is not required */ - $this->projectDB->updateAttribute($id, 'time', required: false); + $this->dbForProject->updateAttribute($id, 'time', required: false); } catch (Throwable $th) { Console::warning("'time' from {$id}: {$th->getMessage()}"); } try { - $this->projectDB->purgeCachedCollection($id); + $this->dbForProject->purgeCachedCollection($id); } catch (Throwable $th) { Console::warning("Purge cache from {$id}: {$th->getMessage()}"); } @@ -202,13 +202,13 @@ class V20 extends Migration $index = '_key_metric_period_time'; try { - $this->projectDB->deleteIndex($id, $index); + $this->dbForProject->deleteIndex($id, $index); } catch (\Throwable $th) { Console::warning("'$index' from {$id}: {$th->getMessage()}"); } try { - $this->createIndexFromCollection($this->projectDB, $id, $index); + $this->createIndexFromCollection($this->dbForProject, $id, $index); } catch (\Throwable $th) { Console::warning("'$index' from {$id}: {$th->getMessage()}"); } @@ -217,27 +217,27 @@ class V20 extends Migration case 'sessions': // Create expire attribute try { - $this->createAttributeFromCollection($this->projectDB, $id, 'expire'); + $this->createAttributeFromCollection($this->dbForProject, $id, 'expire'); } catch (Throwable $th) { Console::warning("'expire' from {$id}: {$th->getMessage()}"); } // Create factors attribute try { - $this->createAttributeFromCollection($this->projectDB, $id, 'factors'); + $this->createAttributeFromCollection($this->dbForProject, $id, 'factors'); } catch (Throwable $th) { Console::warning("'factors' from {$id}: {$th->getMessage()}"); } // Create mfaRecoveryCodes attribute try { - $this->createAttributeFromCollection($this->projectDB, $id, 'mfaUpdatedAt'); + $this->createAttributeFromCollection($this->dbForProject, $id, 'mfaUpdatedAt'); } catch (Throwable $th) { Console::warning("'mfaUpdatedAt' from {$id}: {$th->getMessage()}"); } try { - $this->projectDB->purgeCachedCollection($id); + $this->dbForProject->purgeCachedCollection($id); } catch (Throwable $th) { Console::warning("Purge cache from {$id}: {$th->getMessage()}"); } @@ -246,41 +246,41 @@ class V20 extends Migration case 'users': // Create targets attribute try { - $this->createAttributeFromCollection($this->projectDB, $id, 'targets'); + $this->createAttributeFromCollection($this->dbForProject, $id, 'targets'); } catch (Throwable $th) { Console::warning("'targets' from {$id}: {$th->getMessage()}"); } // Create mfa attribute try { - $this->createAttributeFromCollection($this->projectDB, $id, 'mfa'); + $this->createAttributeFromCollection($this->dbForProject, $id, 'mfa'); } catch (Throwable $th) { Console::warning("'mfa' from {$id}: {$th->getMessage()}"); } // Create mfaRecoveryCodes attribute try { - $this->createAttributeFromCollection($this->projectDB, $id, 'mfaRecoveryCodes'); + $this->createAttributeFromCollection($this->dbForProject, $id, 'mfaRecoveryCodes'); } catch (Throwable $th) { Console::warning("'mfaRecoveryCodes' from {$id}: {$th->getMessage()}"); } // Create challenges attribute try { - $this->createAttributeFromCollection($this->projectDB, $id, 'challenges'); + $this->createAttributeFromCollection($this->dbForProject, $id, 'challenges'); } catch (Throwable $th) { Console::warning("'challenges' from {$id}: {$th->getMessage()}"); } // Create authenticators attribute try { - $this->createAttributeFromCollection($this->projectDB, $id, 'authenticators'); + $this->createAttributeFromCollection($this->dbForProject, $id, 'authenticators'); } catch (Throwable $th) { Console::warning("'authenticators' from {$id}: {$th->getMessage()}"); } try { - $this->projectDB->purgeCachedCollection($id); + $this->dbForProject->purgeCachedCollection($id); } catch (Throwable $th) { Console::warning("Purge cache from {$id}: {$th->getMessage()}"); } @@ -289,20 +289,20 @@ class V20 extends Migration case 'projects': // Rename providers authProviders to oAuthProviders try { - $this->projectDB->renameAttribute($id, 'authProviders', 'oAuthProviders'); + $this->dbForProject->renameAttribute($id, 'authProviders', 'oAuthProviders'); } catch (Throwable $th) { Console::warning("'oAuthProviders' from {$id}: {$th->getMessage()}"); } // Create apis attribute try { - $this->createAttributeFromCollection($this->projectDB, $id, 'apis'); + $this->createAttributeFromCollection($this->dbForProject, $id, 'apis'); } catch (Throwable $th) { Console::warning("'apis' from {$id}: {$th->getMessage()}"); } try { - $this->projectDB->purgeCachedCollection($id); + $this->dbForProject->purgeCachedCollection($id); } catch (Throwable $th) { Console::warning("Purge cache from {$id}: {$th->getMessage()}"); } @@ -311,27 +311,27 @@ class V20 extends Migration case 'webhooks': // Create enabled attribute try { - $this->createAttributeFromCollection($this->projectDB, $id, 'enabled'); + $this->createAttributeFromCollection($this->dbForProject, $id, 'enabled'); } catch (Throwable $th) { Console::warning("'enabled' from {$id}: {$th->getMessage()}"); } // Create logs attribute try { - $this->createAttributeFromCollection($this->projectDB, $id, 'logs'); + $this->createAttributeFromCollection($this->dbForProject, $id, 'logs'); } catch (Throwable $th) { Console::warning("'logs' from {$id}: {$th->getMessage()}"); } // Create attempts attribute try { - $this->createAttributeFromCollection($this->projectDB, $id, 'attempts'); + $this->createAttributeFromCollection($this->dbForProject, $id, 'attempts'); } catch (Throwable $th) { Console::warning("'attempts' from {$id}: {$th->getMessage()}"); } try { - $this->projectDB->purgeCachedCollection($id); + $this->dbForProject->purgeCachedCollection($id); } catch (Throwable $th) { Console::warning("Purge cache from {$id}: {$th->getMessage()}"); } @@ -339,25 +339,25 @@ class V20 extends Migration break; case 'topics': try { - $this->projectDB->updateAttributeDefault($id, 'emailTotal', 0); + $this->dbForProject->updateAttributeDefault($id, 'emailTotal', 0); } catch (Throwable $th) { Console::warning("'topics' from {$id}: {$th->getMessage()}"); } try { - $this->projectDB->updateAttributeDefault($id, 'pushTotal', 0); + $this->dbForProject->updateAttributeDefault($id, 'pushTotal', 0); } catch (Throwable $th) { Console::warning("'topics' from {$id}: {$th->getMessage()}"); } try { - $this->projectDB->updateAttributeDefault($id, 'smsTotal', 0); + $this->dbForProject->updateAttributeDefault($id, 'smsTotal', 0); } catch (Throwable $th) { Console::warning("'topics' from {$id}: {$th->getMessage()}"); } try { - $this->projectDB->purgeCachedCollection($id); + $this->dbForProject->purgeCachedCollection($id); } catch (Throwable $th) { Console::warning("Purge cache from {$id}: {$th->getMessage()}"); } @@ -382,7 +382,7 @@ class V20 extends Migration */ Console::info('Migrating Sessions metric'); - $sessionsCreated = $this->projectDB->sum('stats', 'value', [ + $sessionsCreated = $this->dbForProject->sum('stats', 'value', [ Query::equal('metric', [ 'sessions.email-password.requests.create', 'sessions.magic-url.requests.create', @@ -394,7 +394,7 @@ class V20 extends Migration Query::equal('period', ['1d']), ]); - $query = $this->projectDB->findOne('stats', [ + $query = $this->dbForProject->findOne('stats', [ Query::equal('metric', ['sessions.$all.requests.delete']), Query::equal('period', ['1d']), ]); @@ -420,7 +420,7 @@ class V20 extends Migration */ Console::log("Creating inf metric to {$metric}"); $id = \md5("_inf_{$metric}"); - $this->projectDB->createDocument('stats', new Document([ + $this->dbForProject->createDocument('stats', new Document([ '$id' => $id, 'metric' => $metric, 'period' => 'inf', @@ -448,7 +448,7 @@ class V20 extends Migration str_contains($from, '$all') || str_contains($from, '.total') ) { - $query = $this->projectDB->sum('stats', 'value', [ + $query = $this->dbForProject->sum('stats', 'value', [ Query::equal('metric', [$from]), Query::equal('period', ['1d']), ]); @@ -470,7 +470,7 @@ class V20 extends Migration if ($latestDocument !== null) { $paginationQueries[] = Query::cursorAfter($latestDocument); } - $stats = $this->projectDB->find('stats', \array_merge($paginationQueries, [ + $stats = $this->dbForProject->find('stats', \array_merge($paginationQueries, [ Query::equal('metric', [$from]), ])); @@ -479,10 +479,10 @@ class V20 extends Migration foreach ($stats as $stat) { $format = $stat['period'] === '1d' ? 'Y-m-d 00:00' : 'Y-m-d H:00'; $time = date($format, strtotime($stat['time'])); - $this->projectDB->deleteDocument('stats', $stat->getId()); + $this->dbForProject->deleteDocument('stats', $stat->getId()); $stat->setAttribute('$id', \md5("{$time}_{$stat['period']}_{$to}")); $stat->setAttribute('metric', $to); - $this->projectDB->createDocument('stats', $stat); + $this->dbForProject->createDocument('stats', $stat); Console::log("deleting metric {$from} and creating {$to}"); } $latestDocument = !empty(array_key_last($stats)) ? $stats[array_key_last($stats)] : null; @@ -610,7 +610,7 @@ class V20 extends Migration 'identifier' => $document->getAttribute('email'), ]); try { - $this->projectDB->createDocument('targets', $target); + $this->dbForProject->createDocument('targets', $target); } catch (Duplicate $th) { Console::warning("Email target for user {$document->getId()} already exists."); } @@ -625,7 +625,7 @@ class V20 extends Migration 'identifier' => $document->getAttribute('phone'), ]); try { - $this->projectDB->createDocument('targets', $target); + $this->dbForProject->createDocument('targets', $target); } catch (Duplicate $th) { Console::warning("Email target for user {$document->getId()} already exists."); } diff --git a/src/Appwrite/Migration/Version/V21.php b/src/Appwrite/Migration/Version/V21.php index 46bd81a039..5a5a30bb6f 100644 --- a/src/Appwrite/Migration/Version/V21.php +++ b/src/Appwrite/Migration/Version/V21.php @@ -29,7 +29,7 @@ class V21 extends Migration } Console::log('Migrating Project: ' . $this->project->getAttribute('name') . ' (' . $this->project->getId() . ')'); - $this->projectDB->setNamespace("_{$this->project->getInternalId()}"); + $this->dbForProject->setNamespace("_{$this->project->getInternalId()}"); Console::info('Migrating Collections'); $this->migrateCollections(); @@ -63,13 +63,13 @@ class V21 extends Migration Console::log("Migrating Collection \"{$id}\""); - $this->projectDB->setNamespace("_$internalProjectId"); + $this->dbForProject->setNamespace("_$internalProjectId"); switch ($id) { case 'projects': // Create accessedAt attribute try { - $this->createAttributeFromCollection($this->projectDB, $id, 'accessedAt'); + $this->createAttributeFromCollection($this->dbForProject, $id, 'accessedAt'); } catch (Throwable $th) { Console::warning("'accessedAt' from {$id}: {$th->getMessage()}"); } @@ -77,7 +77,7 @@ class V21 extends Migration case 'platforms': // Increase 'type' length to 255 try { - $this->projectDB->updateAttribute($id, 'type', size: 255); + $this->dbForProject->updateAttribute($id, 'type', size: 255); } catch (Throwable $th) { Console::warning("'type' from {$id}: {$th->getMessage()}"); } @@ -85,7 +85,7 @@ class V21 extends Migration case 'migrations': // Create destination attribute try { - $this->createAttributeFromCollection($this->projectDB, $id, 'destination'); + $this->createAttributeFromCollection($this->dbForProject, $id, 'destination'); } catch (Throwable $th) { Console::warning("'destination' from {$id}: {$th->getMessage()}"); } @@ -93,7 +93,7 @@ class V21 extends Migration case 'schedules': // Create data attribute try { - $this->createAttributeFromCollection($this->projectDB, $id, 'data'); + $this->createAttributeFromCollection($this->dbForProject, $id, 'data'); } catch (Throwable $th) { Console::warning("'data' from {$id}: {$th->getMessage()}"); } @@ -102,7 +102,7 @@ class V21 extends Migration case 'databases': // Create originalId attribute try { - $this->createAttributeFromCollection($this->projectDB, $id, 'originalId'); + $this->createAttributeFromCollection($this->dbForProject, $id, 'originalId'); } catch (Throwable $th) { Console::warning("'originalId' from {$id}: {$th->getMessage()}"); } @@ -110,14 +110,14 @@ class V21 extends Migration case 'functions': // Create scopes attribute try { - $this->createAttributeFromCollection($this->projectDB, $id, 'scopes'); + $this->createAttributeFromCollection($this->dbForProject, $id, 'scopes'); } catch (Throwable $th) { Console::warning("'scopes' from {$id}: {$th->getMessage()}"); } // Create specification attribute try { - $this->createAttributeFromCollection($this->projectDB, $id, 'specification'); + $this->createAttributeFromCollection($this->dbForProject, $id, 'specification'); } catch (Throwable $th) { Console::warning("'specification' from {$id}: {$th->getMessage()}"); } @@ -126,21 +126,21 @@ class V21 extends Migration case 'executions': // Create requestMethod index try { - $this->createIndexFromCollection($this->projectDB, $id, '_key_requestMethod'); + $this->createIndexFromCollection($this->dbForProject, $id, '_key_requestMethod'); } catch (\Throwable $th) { Console::warning("'_key_requestMethod' from {$id}: {$th->getMessage()}"); } // Create requestPath index try { - $this->createIndexFromCollection($this->projectDB, $id, '_key_requestPath'); + $this->createIndexFromCollection($this->dbForProject, $id, '_key_requestPath'); } catch (\Throwable $th) { Console::warning("'_key_requestPath' from {$id}: {$th->getMessage()}"); } // Create deployment index try { - $this->createIndexFromCollection($this->projectDB, $id, '_key_deployment'); + $this->createIndexFromCollection($this->dbForProject, $id, '_key_deployment'); } catch (\Throwable $th) { Console::warning("'_key_deployment' from {$id}: {$th->getMessage()}"); } @@ -149,7 +149,7 @@ class V21 extends Migration /** * Create 'scheduledAt' attribute */ - $this->createAttributeFromCollection($this->projectDB, $id, 'scheduledAt'); + $this->createAttributeFromCollection($this->dbForProject, $id, 'scheduledAt'); } catch (\Throwable $th) { Console::warning("'scheduledAt' from {$id}: {$th->getMessage()}"); } @@ -158,7 +158,7 @@ class V21 extends Migration /** * Create 'scheduleInternalId' attribute */ - $this->createAttributeFromCollection($this->projectDB, $id, 'scheduleInternalId'); + $this->createAttributeFromCollection($this->dbForProject, $id, 'scheduleInternalId'); } catch (\Throwable $th) { Console::warning("'scheduleInternalId' from {$id}: {$th->getMessage()}"); } @@ -167,7 +167,7 @@ class V21 extends Migration /** * Create 'scheduleId' attribute */ - $this->createAttributeFromCollection($this->projectDB, $id, 'scheduleId'); + $this->createAttributeFromCollection($this->dbForProject, $id, 'scheduleId'); } catch (\Throwable $th) { Console::warning("'scheduleId' from {$id}: {$th->getMessage()}"); } @@ -218,8 +218,8 @@ class V21 extends Migration $bucketId = 'bucket_' . $bucket['$internalId']; try { - $this->projectDB->updateAttribute($bucketId, 'metadata', size: 65534); - $this->projectDB->purgeCachedCollection($bucketId); + $this->dbForProject->updateAttribute($bucketId, 'metadata', size: 65534); + $this->dbForProject->purgeCachedCollection($bucketId); } catch (\Throwable $th) { Console::warning("'bucketId' from {$bucketId}: {$th->getMessage()}"); } diff --git a/src/Appwrite/Migration/Version/V22.php b/src/Appwrite/Migration/Version/V22.php index 4d15662112..a5474ff80c 100644 --- a/src/Appwrite/Migration/Version/V22.php +++ b/src/Appwrite/Migration/Version/V22.php @@ -50,27 +50,27 @@ class V22 extends Migration Console::log("Migrating Collection \"{$id}\""); - $this->projectDB->setNamespace("_$internalProjectId"); + $this->dbForProject->setNamespace("_$internalProjectId"); switch ($id) { case 'installations': // Create personalAccessToken attribute try { - $this->createAttributeFromCollection($this->projectDB, $id, 'personalAccessToken'); + $this->createAttributeFromCollection($this->dbForProject, $id, 'personalAccessToken'); } catch (Throwable $th) { Console::warning("'personalAccessToken' from {$id}: {$th->getMessage()}"); } // Create personalAccessTokenExpiry attribute try { - $this->createAttributeFromCollection($this->projectDB, $id, 'personalAccessTokenExpiry'); + $this->createAttributeFromCollection($this->dbForProject, $id, 'personalAccessTokenExpiry'); } catch (Throwable $th) { Console::warning("'personalAccessTokenExpiry' from {$id}: {$th->getMessage()}"); } // Create personalRefreshToken attribute try { - $this->createAttributeFromCollection($this->projectDB, $id, 'personalRefreshToken'); + $this->createAttributeFromCollection($this->dbForProject, $id, 'personalRefreshToken'); } catch (Throwable $th) { Console::warning("'personalRefreshToken' from {$id}: {$th->getMessage()}"); } From 907d968a5f728af1e8bba9606a7ba69395484377 Mon Sep 17 00:00:00 2001 From: Jake Barnby Date: Fri, 16 May 2025 17:25:06 +1200 Subject: [PATCH 08/29] Remove redundant doc migration --- src/Appwrite/Migration/Version/V23.php | 89 +++---------- src/Appwrite/Platform/Tasks/Migrate.php | 163 +++++++++++------------- 2 files changed, 94 insertions(+), 158 deletions(-) diff --git a/src/Appwrite/Migration/Version/V23.php b/src/Appwrite/Migration/Version/V23.php index ab986cab55..39d8e1ff3f 100644 --- a/src/Appwrite/Migration/Version/V23.php +++ b/src/Appwrite/Migration/Version/V23.php @@ -404,89 +404,38 @@ class V23 extends Migration 17. Convert build's "path" to "buildPath" 18. Convert build's "logs" to "buildLogs" 19. Fill "totalSize" with "buildSize" plus "sourceSize" - --- Support for functions dual writing, if function's deploymentId is current deployment - 1. Fill function's "deploymentCreatedAt" with deployment's "$createdAt" - --- Support for functions dual writing, if this is most recent deployment - 2. Fill function's "latestDeploymentId" with deployment's "$id" - 3. Fill function's "latestDeploymentInternalId" with deployment's "$internalId" - 4. Fill function's "latestDeploymentCreatedAt" with deployment's "$createdAt" - 5. Fill function's "latestDeploymentStatus" with deployment's "$status" */ $document - ->setAttribute("buildCommands", $document->getAttribute("commands")) - ->setAttribute("sourcePath", $document->getAttribute("path")) - ->setAttribute("sourceSize", $document->getAttribute("size")) - ->setAttribute("sourceMetadata", $document->getAttribute("metadata")) - ->setAttribute("sourceChunksTotal", $document->getAttribute("chunksTotal")) - ->setAttribute("sourceChunksUploaded", $document->getAttribute("chunksUploaded")) - ; + ->setAttribute('buildCommands', $document->getAttribute('commands')) + ->setAttribute('sourcePath', $document->getAttribute('path')) + ->setAttribute('sourceSize', $document->getAttribute('size')) + ->setAttribute('sourceMetadata', $document->getAttribute('metadata')) + ->setAttribute('sourceChunksTotal', $document->getAttribute('chunksTotal')) + ->setAttribute('sourceChunksUploaded', $document->getAttribute('chunksUploaded')); $build = new Document(); - if (!empty($document->getAttribute('buildId'))) { - $build = Authorization::skip(fn () => $this->projectDB->getDocument('builds', $document->getAttribute('buildId'))); + $build = $this->dbForProject->getDocument('builds', $document->getAttribute('buildId')); } $document - ->setAttribute("buildStartedAt", $build->getAttribute("startTime", null)) - ->setAttribute("buildEndedAt", $build->getAttribute("endTime", null)) - ->setAttribute("buildDuration", $build->getAttribute("duration", 0)) - ->setAttribute("buildSize", $build->getAttribute("size", 0)) - ->setAttribute("status", $build->getAttribute("status", null)) - ->setAttribute("buildPath", $build->getAttribute("path", "")) - ->setAttribute("buildLogs", $build->getAttribute("logs", "")) - ; + ->setAttribute('buildStartedAt', $build->getAttribute('startTime')) + ->setAttribute('buildEndedAt', $build->getAttribute('endTime')) + ->setAttribute('buildDuration', $build->getAttribute('duration', 0)) + ->setAttribute('buildSize', $build->getAttribute('size', 0)) + ->setAttribute('status', $build->getAttribute('status')) + ->setAttribute('buildPath', $build->getAttribute('path', '')) + ->setAttribute('buildLogs', $build->getAttribute('logs', '')); - $totalSize = $document->getAttribute('buildSize', 0) + $document->getAttribute('sourceSize', 0); - $document->setAttribute("totalSize", $totalSize); + $totalSize = $document->getAttribute('buildSize', 0) + + $document->getAttribute('sourceSize', 0); - $function = Authorization::skip(fn () => $this->projectDB->getDocument('functions', $document->getAttribute('resourceId'))); - if (!$function->isEmpty()) { - $activeDeploymentId = $function->getAttribute('deployment', $function->getAttribute('deploymentId', '')); - if ($activeDeploymentId === $document->getId()) { - $function->setAttribute('deploymentCreatedAt', $document->getCreatedAt()); - - $function = Authorization::skip(fn () => $this->projectDB->updateDocument('functions', $function->getId(), $function)); - } else { - $latestDeployments = Authorization::skip(fn () => $this->projectDB->find('deployments', [ - Query::orderDesc(), - Query::limit(1), - Query::equal('resourceType', ['functions']), - Query::equal('resourceId', [$function->getId()]), - ])); - $latestDeployment = $latestDeployments[0] ? $latestDeployments[0] : new Document(); - - if (!$latestDeployment->isEmpty()) { - if ($latestDeployment->getId() === $document->getId()) { - $function - ->setAttribute("latestDeploymentId", $document->getId()) - ->setAttribute("latestDeploymentInternalId", $document->getInternalId()) - ->setAttribute("latestDeploymentCreatedAt", $document->getCreatedAt()) - ->setAttribute("latestDeploymentStatus", $document->getAttribute('status')) - ; - - $function = Authorization::skip(fn () => $this->projectDB->updateDocument('functions', $function->getId(), $function)); - } - } - } - } - break; - case 'builds': - /** - 1. Trigger deployments document update - */ - if (!empty($document->getAttribute('deploymentId'))) { - $deployment = Authorization::skip(fn () => $this->projectDB->getDocument('deployments', $document->getAttribute('deploymentId'))); - if (!$deployment->isEmpty()) { - $deployment = $this->fixDocument($deployment); - - Authorization::skip(fn () => $this->projectDB->updateDocument('deployments', $deployment->getId(), $deployment)); - } - } + $document->setAttribute('totalSize', $totalSize); break; + case 'migrations': /* - 1. Fill "options" with "[]" + 1. Fill "options" with "[]" */ $document->setAttribute('options', []); break; diff --git a/src/Appwrite/Platform/Tasks/Migrate.php b/src/Appwrite/Platform/Tasks/Migrate.php index e495ce1d3f..c2c19ec998 100644 --- a/src/Appwrite/Platform/Tasks/Migrate.php +++ b/src/Appwrite/Platform/Tasks/Migrate.php @@ -4,6 +4,7 @@ namespace Appwrite\Platform\Tasks; use Appwrite\Migration\Migration; use Redis; +use Swoole\Runtime; use Utopia\App; use Utopia\CLI\Console; use Utopia\Database\Database; @@ -26,9 +27,10 @@ class Migrate extends Action public function __construct() { + Runtime::enableCoroutine(); + $this ->desc('Migrate Appwrite to new version') - /** @TODO APP_VERSION_STABLE needs to be defined */ ->param('version', APP_VERSION_STABLE, new Text(8), 'Version to migrate to.', true) ->inject('dbForPlatform') ->inject('getProjectDB') @@ -36,12 +38,82 @@ class Migrate extends Action ->callback($this->action(...)); } - private function clearProjectsCache(Document $project) + /** + * @param string $version + * @param Database $dbForPlatform + * @param callable(Document): Database $getProjectDB + * @param Registry $register + * @return void + */ + public function action( + string $version, + Database $dbForPlatform, + callable $getProjectDB, + Registry $register, + ): void + { + Authorization::disable(); + + if (!\array_key_exists($version, Migration::$versions)) { + Console::error("Version {$version} not found."); + Console::exit(1); + return; + } + + \Co\run(function ( + string $version, + Database $dbForPlatform, + callable $getProjectDB, + Registry $register, + ) { + $this->redis = new Redis(); + $this->redis->connect( + System::getEnv('_APP_REDIS_HOST', ''), + System::getEnv('_APP_REDIS_PORT', 6379), + 3, + null, + 10 + ); + + Console::success('Starting Data Migration to version ' . $version); + + + $class = 'Appwrite\\Migration\\Version\\' . Migration::$versions[$version]; + + /** @var Migration $migration */ + $migration = new $class(); + + $count = 0; + $total = $dbForPlatform->count('projects'); + + $dbForPlatform->foreach('projects', function (Document $project) use ($dbForPlatform, $getProjectDB, $register, $migration, &$count, $total) { + /** @var Database $dbForProject */ + $dbForProject = $getProjectDB($project); + $dbForProject->disableValidation(); + + try { + $migration + ->setProject($project, $dbForProject, $dbForPlatform) + ->setPDO($register->get('db', true)) + ->execute(); + } catch (\Throwable $th) { + Console::error('Failed to migrate project "' . $project->getId() . '" with error: ' . $th->getMessage()); + throw $th; + } + + Console::log('Migrated ' . $count++ . '/' . $total . ' projects...'); + }); + + Console::success('Migration completed'); + }, [$version, $dbForPlatform, $getProjectDB, $register]); + } + + private function clearProjectsCache(Document $project): void { try { $iterator = null; do { - $pattern = "default-cache-_{$project->getInternalId()}:*"; + $pattern = "default-cache-mariadb:_{$project->getInternalId()}:*"; $keys = $this->redis->scan($iterator, $pattern, 1000); if ($keys !== false) { foreach ($keys as $key) { @@ -53,89 +125,4 @@ class Migrate extends Action Console::error('Failed to clear project ("' . $project->getId() . '") cache with error: ' . $th->getMessage()); } } - - public function action(string $version, Database $dbForPlatform, callable $getProjectDB, Registry $register) - { - Authorization::disable(); - if (!array_key_exists($version, Migration::$versions)) { - Console::error("Version {$version} not found."); - Console::exit(1); - - return; - } - - $this->redis = new Redis(); - $this->redis->connect( - System::getEnv('_APP_REDIS_HOST', null), - System::getEnv('_APP_REDIS_PORT', 6379), - 3, - null, - 10 - ); - - $app = new App('UTC'); - - Console::success('Starting Data Migration to version ' . $version); - - $console = $app->getResource('console'); - - $limit = 30; - $sum = 30; - $offset = 0; - /** - * @var \Utopia\Database\Document[] $projects - */ - $projects = [$console]; - $count = 0; - - try { - $totalProjects = $dbForPlatform->count('projects') + 1; - } catch (\Throwable $th) { - $dbForPlatform->setNamespace('_console'); - $totalProjects = $dbForPlatform->count('projects') + 1; - } - - $class = 'Appwrite\\Migration\\Version\\' . Migration::$versions[$version]; - /** @var Migration $migration */ - $migration = new $class(); - - while (!empty($projects)) { - foreach ($projects as $project) { - /** - * Skip user projects with id 'console' - */ - if ($project->getId() === 'console' && $project->getInternalId() !== 'console') { - continue; - } - - $this->clearProjectsCache($project); - - try { - // TODO: Iterate through all project DBs - /** @var Database $projectDB */ - $projectDB = $getProjectDB($project); - $projectDB->disableValidation(); - $migration - ->setProject($project, $projectDB, $dbForPlatform) - ->setPDO($register->get('db', true)) - ->execute(); - } catch (\Throwable $th) { - Console::error('Failed to update project ("' . $project->getId() . '") version with error: ' . $th->getMessage()); - throw $th; - } - - $this->clearProjectsCache($project); - } - - $sum = \count($projects); - $projects = $dbForPlatform->find('projects', [Query::limit($limit), Query::offset($offset)]); - - $offset = $offset + $limit; - $count = $count + $sum; - - Console::log('Migrated ' . $count . '/' . $totalProjects . ' projects...'); - } - - Console::success('Data Migration Completed'); - } } From 43fce76c9b78c6ecf74130210fa12d920b86182f Mon Sep 17 00:00:00 2001 From: Jake Barnby Date: Fri, 16 May 2025 17:35:36 +1200 Subject: [PATCH 09/29] Remove redundant namespace set --- src/Appwrite/Migration/Version/V23.php | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/src/Appwrite/Migration/Version/V23.php b/src/Appwrite/Migration/Version/V23.php index 39d8e1ff3f..0a2c632b3f 100644 --- a/src/Appwrite/Migration/Version/V23.php +++ b/src/Appwrite/Migration/Version/V23.php @@ -447,8 +447,9 @@ class V23 extends Migration private function cleanCollections(): void { - $internalProjectId = $this->project->getInternalId(); - $collectionType = match ($internalProjectId) { + $projectInternalId = $this->project->getInternalId(); + + $collectionType = match ($projectInternalId) { 'console' => 'console', default => 'projects', }; @@ -459,8 +460,6 @@ class V23 extends Migration Console::log("Migrating Collection \"{$id}\""); - $this->projectDB->setNamespace("_$internalProjectId"); - switch ($id) { case '_metadata': if ($this->projectDB->exists('builds')) { From 59ef8077daa4789aae4cf2e5fbddbd9094f4ebbc Mon Sep 17 00:00:00 2001 From: Jake Barnby Date: Fri, 16 May 2025 17:36:19 +1200 Subject: [PATCH 10/29] Skip devKeys subquery --- src/Appwrite/Migration/Version/V23.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Appwrite/Migration/Version/V23.php b/src/Appwrite/Migration/Version/V23.php index 0a2c632b3f..cb8969d010 100644 --- a/src/Appwrite/Migration/Version/V23.php +++ b/src/Appwrite/Migration/Version/V23.php @@ -21,7 +21,7 @@ class V23 extends Migration /** * Disable SubQueries for Performance. */ - foreach (['subQueryIndexes', 'subQueryPlatforms', 'subQueryDomains', 'subQueryKeys', 'subQueryWebhooks', 'subQuerySessions', 'subQueryTokens', 'subQueryMemberships', 'subQueryVariables', 'subQueryChallenges', 'subQueryProjectVariables', 'subQueryTargets', 'subQueryTopicTargets'] as $name) { + foreach (['subQueryIndexes', 'subQueryPlatforms', 'subQueryDomains', 'subQueryKeys', 'subQueryDevKeys', 'subQueryWebhooks', 'subQuerySessions', 'subQueryTokens', 'subQueryMemberships', 'subQueryVariables', 'subQueryChallenges', 'subQueryProjectVariables', 'subQueryTargets', 'subQueryTopicTargets'] as $name) { Database::addFilter( $name, fn () => null, From 2d6d79de7b961f18f52f55eb10b9ae8bb9d9b330 Mon Sep 17 00:00:00 2001 From: Jake Barnby Date: Fri, 16 May 2025 17:36:29 +1200 Subject: [PATCH 11/29] Fix names --- src/Appwrite/Migration/Version/V23.php | 291 +++++++++++++------------ 1 file changed, 155 insertions(+), 136 deletions(-) diff --git a/src/Appwrite/Migration/Version/V23.php b/src/Appwrite/Migration/Version/V23.php index cb8969d010..9c9d409838 100644 --- a/src/Appwrite/Migration/Version/V23.php +++ b/src/Appwrite/Migration/Version/V23.php @@ -8,6 +8,9 @@ use Throwable; use Utopia\CLI\Console; use Utopia\Database\Database; use Utopia\Database\Document; +use Utopia\Database\Exception\Conflict; +use Utopia\Database\Exception\Structure; +use Utopia\Database\Exception\Timeout; use Utopia\Database\Query; use Utopia\Database\Validator\Authorization; @@ -33,7 +36,7 @@ class V23 extends Migration $this->migrateCollections(); Console::info('Migrating Documents'); - $this->forEachDocument([$this, 'fixDocument']); + $this->forEachDocument($this->migrateDocument(...)); Console::log('Cleaning Up Collections'); $this->cleanCollections(); @@ -47,52 +50,57 @@ class V23 extends Migration */ private function migrateCollections(): void { - $internalProjectId = $this->project->getInternalId(); - $collectionType = match ($internalProjectId) { + $projectInternalId = $this->project->getInternalId(); + + if (empty($projectInternalId)) { + throw new Exception('Project ID is null'); + } + + $collectionType = match ($projectInternalId) { 'console' => 'console', default => 'projects', }; $collections = $this->collections[$collectionType]; + foreach ($collections as $collection) { $id = $collection['$id']; Console::log("Migrating Collection \"{$id}\""); - $this->projectDB->setNamespace("_$internalProjectId"); - switch ($id) { case '_metadata': $this->createCollection('sites'); $this->createCollection('resourceTokens'); - if ($internalProjectId === 'console') { + if ($projectInternalId === 'console') { $this->createCollection('devKeys'); } break; case 'identities': - $attributesToCreate = [ + $attributes = [ 'scopes', 'expire', ]; - foreach ($attributesToCreate as $attribute) { - try { - $this->createAttributeFromCollection($this->projectDB, $id, $attribute); - } catch (\Throwable $th) { - Console::warning("$attribute from {$id}: {$th->getMessage()}"); - } + try { + $this->createAttributesFromCollection($this->dbForProject, $id, $attributes); + } catch (\Throwable $th) { + Console::warning('Failed to create attributes "' . \implode(', ', $attributes) . "\" in collection {$id}: {$th->getMessage()}"); } - $this->projectDB->purgeCachedCollection($id); + $this->dbForProject->purgeCachedCollection($id); break; case 'projects': try { - $this->createAttributeFromCollection($this->projectDB, $id, 'devKeys'); - } catch (Throwable $th) { - Console::warning("'devKeys' from {$id}: {$th->getMessage()}"); + $attributes = [ + 'devKeys', + ]; + $this->createAttributesFromCollection($this->dbForProject, $id, $attributes); + } catch (\Throwable $th) { + Console::warning('Failed to create attributes "' . \implode(', ', $attributes) . "\" in collection {$id}: {$th->getMessage()}"); } - $this->projectDB->purgeCachedCollection($id); + $this->dbForProject->purgeCachedCollection($id); break; case 'rules': - $attributesToCreate = [ + $attributes = [ 'type', 'trigger', 'redirectUrl', @@ -105,15 +113,13 @@ class V23 extends Migration 'deploymentVcsProviderBranch', 'search' ]; - foreach ($attributesToCreate as $attribute) { - try { - $this->createAttributeFromCollection($this->projectDB, $id, $attribute); - } catch (\Throwable $th) { - Console::warning("$attribute from {$id}: {$th->getMessage()}"); - } + try { + $this->createAttributesFromCollection($this->dbForProject, $id, $attributes); + } catch (\Throwable $th) { + Console::warning('Failed to create attributes "' . \implode(', ', $attributes) . "\" in collection {$id}: {$th->getMessage()}"); } - $indexesToCreate = [ + $indexes = [ '_key_search', '_key_type', '_key_trigger', @@ -124,49 +130,57 @@ class V23 extends Migration '_key_deploymentInternalId', '_key_deploymentVcsProviderBranch', ]; - foreach ($indexesToCreate as $index) { + + foreach ($indexes as $index) { try { - $this->createIndexFromCollection($this->projectDB, $id, $index); + $this->createIndexFromCollection($this->dbForProject, $id, $index); } catch (\Throwable $th) { - Console::warning("'$index' from {$id}: {$th->getMessage()}"); + Console::warning("Failed to create \"$index\" from {$id}: {$th->getMessage()}"); } } - - $this->projectDB->purgeCachedCollection($id); - + $this->dbForProject->purgeCachedCollection($id); break; case 'memberships': - // Create roles index - try { - $this->createIndexFromCollection($this->projectDB, $id, '_key_roles'); - } catch (Throwable $th) { - Console::warning("'_key_roles' from {$id}: {$th->getMessage()}"); + $indexes = [ + '_key_roles', + ]; + foreach ($indexes as $index) { + try { + $this->createIndexFromCollection($this->dbForProject, $id, $index); + } catch (Throwable $th) { + Console::warning("Failed to create \"$index\" from {$id}: {$th->getMessage()}"); + } } + $this->dbForProject->purgeCachedCollection($id); break; case 'migrations': - $attributesToCreate = [ + $attributes = [ 'options', 'resourceId', 'resourceType' ]; - foreach ($attributesToCreate as $attribute) { + try { + $this->createAttributesFromCollection($this->dbForProject, $id, $attributes); + } catch (\Throwable $th) { + Console::warning('Failed to create attributes "' . \implode(', ', $attributes) . "\" in collection {$id}: {$th->getMessage()}"); + } + + $indexes = [ + '_key_resource_id', + ]; + + foreach ($indexes as $index) { try { - $this->createAttributeFromCollection($this->projectDB, $id, $attribute); - } catch (\Throwable $th) { - Console::warning("$attribute from {$id}: {$th->getMessage()}"); + $this->createIndexFromCollection($this->dbForProject, $id, $index); + } catch (Throwable $th) { + Console::warning("Failed to create \"$index\" from {$id}: {$th->getMessage()}"); } } - try { - $this->createIndexFromCollection($this->projectDB, $id, '_key_resource_id'); - } catch (Throwable $th) { - Console::warning("'_key_resource_id' from {$id}: {$th->getMessage()}"); - } - - $this->projectDB->purgeCachedCollection($id); + $this->dbForProject->purgeCachedCollection($id); break; case 'functions': - $attributesToCreate = [ + $attributes = [ 'deploymentId', 'deploymentCreatedAt', 'latestDeploymentId', @@ -174,24 +188,28 @@ class V23 extends Migration 'latestDeploymentCreatedAt', 'latestDeploymentStatus', ]; - foreach ($attributesToCreate as $attribute) { + try { + $this->createAttributesFromCollection($this->dbForProject, $id, $attributes); + } catch (\Throwable $th) { + Console::warning('Failed to create attributes "' . \implode(', ', $attributes) . "\" in collection {$id}: {$th->getMessage()}"); + } + + $indexes = [ + '_key_deploymentId', + ]; + + foreach ($indexes as $index) { try { - $this->createAttributeFromCollection($this->projectDB, $id, $attribute); - } catch (\Throwable $th) { - Console::warning("$attribute from {$id}: {$th->getMessage()}"); + $this->createIndexFromCollection($this->dbForProject, $id, $index); + } catch (Throwable $th) { + Console::warning("Failed to create \"$index\" from {$id}: {$th->getMessage()}"); } } - try { - $this->createIndexFromCollection($this->projectDB, $id, '_key_deploymentId'); - } catch (Throwable $th) { - Console::warning("'_key_deploymentId' from {$id}: {$th->getMessage()}"); - } - - $this->projectDB->purgeCachedCollection($id); + $this->dbForProject->purgeCachedCollection($id); break; case 'deployments': - $attributesToCreate = [ + $attributes = [ 'buildCommands', 'sourcePath', 'buildOutput', @@ -212,15 +230,15 @@ class V23 extends Migration 'buildLogs', 'totalSize', ]; - foreach ($attributesToCreate as $attribute) { + foreach ($attributes as $attribute) { try { - $this->createAttributeFromCollection($this->projectDB, $id, $attribute); + $this->createAttributeFromCollection($this->dbForProject, $id, $attribute); } catch (\Throwable $th) { - Console::warning("$attribute from {$id}: {$th->getMessage()}"); + Console::warning('Failed to create attributes "' . \implode(', ', $attributes) . "\" in collection {$id}: {$th->getMessage()}"); } } - $indexesToCreate = [ + $indexes = [ '_key_sourceSize', '_key_buildSize', '_key_totalSize', @@ -228,53 +246,57 @@ class V23 extends Migration '_key_type', '_key_status', ]; - foreach ($indexesToCreate as $index) { + + foreach ($indexes as $index) { try { - $this->createIndexFromCollection($this->projectDB, $id, $index); + $this->createIndexFromCollection($this->dbForProject, $id, $index); } catch (\Throwable $th) { - Console::warning("'$index' from {$id}: {$th->getMessage()}"); + Console::warning("Failed to create \"$index\" from {$id}: {$th->getMessage()}"); } } - $this->projectDB->purgeCachedCollection($id); + $this->dbForProject->purgeCachedCollection($id); break; case 'executions': - $attributesToCreate = [ + $attributes = [ 'resourceInternalId', 'resourceId', 'resourceType' ]; - foreach ($attributesToCreate as $attribute) { + try { + $this->createAttributesFromCollection($this->dbForProject, $id, $attributes); + } catch (\Throwable $th) { + Console::warning('Failed to create attributes "' . \implode(', ', $attributes) . "\" in collection {$id}: {$th->getMessage()}"); + } + + $indexes = [ + '_key_resource', + ]; + foreach ($indexes as $index) { try { - $this->createAttributeFromCollection($this->projectDB, $id, $attribute); + $this->createIndexFromCollection($this->dbForProject, $id, $index); } catch (\Throwable $th) { - Console::warning("$attribute from {$id}: {$th->getMessage()}"); + Console::warning("Failed to create \"$index\" from {$id}: {$th->getMessage()}"); } } - try { - $this->createIndexFromCollection($this->projectDB, $id, '_key_resource'); - } catch (Throwable $th) { - Console::warning("'_key_resource' from {$id}: {$th->getMessage()}"); - } - - $this->projectDB->purgeCachedCollection($id); + $this->dbForProject->purgeCachedCollection($id); break; case 'variables': + $attributes = [ + 'secret', + ]; try { - $this->createAttributeFromCollection($this->projectDB, $id, 'secret'); + $this->createAttributesFromCollection($this->dbForProject, $id, $attributes); } catch (\Throwable $th) { - Console::warning("'secret' from {$id}: {$th->getMessage()}"); + Console::warning('Failed to create attributes "' . \implode(', ', $attributes) . "\" in collection {$id}: {$th->getMessage()}"); } - $this->projectDB->purgeCachedCollection($id); - + $this->dbForProject->purgeCachedCollection($id); break; default: break; } - - usleep(50000); } } @@ -283,8 +305,14 @@ class V23 extends Migration * * @param Document $document * @return Document + * @throws Conflict + * @throws Structure + * @throws Timeout + * @throws \Utopia\Database\Exception + * @throws \Utopia\Database\Exception\Authorization + * @throws \Utopia\Database\Exception\Query */ - protected function fixDocument(Document $document): Document + protected function migrateDocument(Document $document): Document { switch ($document->getCollection()) { case 'rules': @@ -316,24 +344,23 @@ class V23 extends Migration ->setAttribute('deploymentResourceInternalId', $document->getAttribute('resourceInternalId')) ->setAttribute('trigger', 'manual') ->setAttribute('deploymentResourceType', $deploymentResourceType) - ->setAttribute('search', \implode(" ", [$document->getId(), $document->getAttribute('domain', '')])) + ->setAttribute('search', \implode(' ', [$document->getId(), $document->getAttribute('domain', '')])) ; if ($deploymentResourceType === 'function') { if ($this->project->getInternalId() !== 'console') { - $function = Authorization::skip(fn () => $this->projectDB->getDocument('functions', $resourceId)); + $function = $this->dbForProject->getDocument('functions', $resourceId); $document ->setAttribute('deploymentId', $function->getAttribute('deployment', $function->getAttribute('deploymentId', ''))) - ->setAttribute('deploymentInternalId', $function->getAttribute('deployment', $function->getAttribute('deploymentId', ''))) - ; + ->setAttribute('deploymentInternalId', $function->getAttribute('deployment', $function->getAttribute('deploymentId', ''))); } } break; case 'variables': /* - 1. Fill "secret" with "false" - */ + 1. Fill "secret" with "false" + */ $document->setAttribute('secret', false); break; case 'executions': @@ -347,12 +374,6 @@ class V23 extends Migration ->setAttribute('resourceId', $document->getAttribute('functionId')) ->setAttribute('resourceType', 'functions'); break; - case 'migrations': - /* - 1. Fill "options" with "[]" - */ - $document->setAttribute('options', []); - break; case 'functions': /* 1. Convert "deployment" to "deploymentId" @@ -364,23 +385,22 @@ class V23 extends Migration 5. Fill latestDeploymentCreatedAt with latestDeployment's "$createdAt" 6. Fill latestDeploymentStatus with latestDeployment's build's "status" */ - if ($document->getAttribute('deployment')) { $document->setAttribute('deploymentId', $document->getAttribute('deployment')); } $deploymentId = $document->getAttribute('deploymentId'); - $deployment = Authorization::skip(fn () => $this->projectDB->getDocument('deployments', $deploymentId)); + $deployment = $this->dbForProject->getDocument('deployments', $deploymentId); $document->setAttribute('deploymentCreatedAt', $deployment->getCreatedAt()); - $latestDeployments = Authorization::skip(fn () => $this->projectDB->find('deployments', [ + $latestDeployment = $this->dbForProject->findOne('deployments',[ Query::orderDesc(), - Query::limit(1), Query::equal('resourceId', [$document->getId()]), Query::equal('resourceType', ['functions']), - ])); - $latestDeployment = $latestDeployments[0] ?? new Document(); - $latestBuild = Authorization::skip(fn () => $this->projectDB->getDocument('builds', $latestDeployment->getAttribute('buildId', ''))); + ]); + + $latestBuild = $this->dbForProject->getDocument('builds', $latestDeployment->getAttribute('buildId', '')); + $document ->setAttribute('latestDeploymentId', $latestDeployment->getId()) ->setAttribute('latestDeploymentInternalId', $latestDeployment->getInternalId()) @@ -462,21 +482,21 @@ class V23 extends Migration switch ($id) { case '_metadata': - if ($this->projectDB->exists('builds')) { - $this->projectDB->deleteCollection('builds'); + if (!$this->dbForProject->getCollection('builds')->isEmpty()) { + $this->dbForProject->deleteCollection('builds'); } break; case 'rules': - $attributesToDelete = [ + $attributes = [ 'resourceId', 'resourceInternalId', 'resourceType', ]; - foreach ($attributesToDelete as $attribute) { + foreach ($attributes as $attribute) { try { - $this->projectDB->deleteAttribute($id, $attribute); + $this->dbForProject->deleteAttribute($id, $attribute); } catch (\Throwable $th) { - Console::warning("'$attribute' from {$id}: {$th->getMessage()}"); + Console::warning("Failed to delete attribute \"$attribute\" from collection {$id}: {$th->getMessage()}"); } } @@ -487,19 +507,19 @@ class V23 extends Migration ]; foreach ($indexesToDelete as $index) { try { - $this->projectDB->deleteIndex($id, $index); + $this->dbForProject->deleteIndex($id, $index); } catch (\Throwable $th) { - Console::warning("'$index' from {$id}: {$th->getMessage()}"); + Console::warning("Failed to delete index \"$index\" from collection {$id}: {$th->getMessage()}"); } } - $this->projectDB->purgeCachedCollection($id); + $this->dbForProject->purgeCachedCollection($id); break; case 'functions': try { - $this->projectDB->deleteAttribute($id, 'deployment'); + $this->dbForProject->deleteAttribute($id, 'deployment'); } catch (\Throwable $th) { - Console::warning("'deployment' from {$id}: {$th->getMessage()}"); + Console::warning("Failed to delete attribute \"deployment\" from collection {$id}: {$th->getMessage()}"); } $indexesToDelete = [ @@ -507,16 +527,16 @@ class V23 extends Migration ]; foreach ($indexesToDelete as $index) { try { - $this->projectDB->deleteIndex($id, $index); + $this->dbForProject->deleteIndex($id, $index); } catch (\Throwable $th) { - Console::warning("'$index' from {$id}: {$th->getMessage()}"); + Console::warning("Failed to delete index \"$index\" from collection {$id}: {$th->getMessage()}"); } } - $this->projectDB->purgeCachedCollection($id); + $this->dbForProject->purgeCachedCollection($id); break; case 'deployments': - $attributesToDelete = [ + $attributes = [ 'buildInternalId', 'buildId', 'commands', @@ -527,11 +547,11 @@ class V23 extends Migration 'chunksUploaded', 'search' ]; - foreach ($attributesToDelete as $attribute) { + foreach ($attributes as $attribute) { try { - $this->projectDB->deleteAttribute($id, $attribute); + $this->dbForProject->deleteAttribute($id, $attribute); } catch (\Throwable $th) { - Console::warning("'$attribute' from {$id}: {$th->getMessage()}"); + Console::warning("Failed to delete attribute \"$attribute\" from collection {$id}: {$th->getMessage()}"); } } @@ -542,25 +562,25 @@ class V23 extends Migration ]; foreach ($indexesToDelete as $index) { try { - $this->projectDB->deleteIndex($id, $index); + $this->dbForProject->deleteIndex($id, $index); } catch (\Throwable $th) { - Console::warning("'$index' from {$id}: {$th->getMessage()}"); + Console::warning("Failed to delete index \"$index\" from collection {$id}: {$th->getMessage()}"); } } - $this->projectDB->purgeCachedCollection($id); + $this->dbForProject->purgeCachedCollection($id); break; case 'executions': - $attributesToDelete = [ + $attributes = [ 'functionId', 'functionInternalId', 'search' ]; - foreach ($attributesToDelete as $attribute) { + foreach ($attributes as $attribute) { try { - $this->projectDB->deleteAttribute($id, $attribute); + $this->dbForProject->deleteAttribute($id, $attribute); } catch (\Throwable $th) { - Console::warning("'$attribute' from {$id}: {$th->getMessage()}"); + Console::warning("Failed to delete attribute \"$attribute\" from collection {$id}: {$th->getMessage()}"); } } @@ -570,18 +590,17 @@ class V23 extends Migration ]; foreach ($indexesToDelete as $index) { try { - $this->projectDB->deleteIndex($id, $index); + $this->dbForProject->deleteIndex($id, $index); } catch (\Throwable $th) { - Console::warning("'$index' from {$id}: {$th->getMessage()}"); + Console::warning("Failed to delete index \"$index\" from collection {$id}: {$th->getMessage()}"); } } - $this->projectDB->purgeCachedCollection($id); + $this->dbForProject->purgeCachedCollection($id); break; default: break; } - usleep(50000); } } } From 4d4cfef1ad664c4fae45f80e0feaf5ff0980475d Mon Sep 17 00:00:00 2001 From: Jake Barnby Date: Fri, 16 May 2025 20:29:52 +1200 Subject: [PATCH 12/29] Skip empty ID --- src/Appwrite/Migration/Version/V23.php | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/src/Appwrite/Migration/Version/V23.php b/src/Appwrite/Migration/Version/V23.php index 9c9d409838..b02ca20d1e 100644 --- a/src/Appwrite/Migration/Version/V23.php +++ b/src/Appwrite/Migration/Version/V23.php @@ -64,7 +64,11 @@ class V23 extends Migration $collections = $this->collections[$collectionType]; foreach ($collections as $collection) { - $id = $collection['$id']; + $id = $collection['$id'] ?? null; + + if (empty($id)) { + continue; + } Console::log("Migrating Collection \"{$id}\""); From 768d005f082c7b82e2318ef04fc79223180daeca Mon Sep 17 00:00:00 2001 From: Jake Barnby Date: Fri, 16 May 2025 20:30:04 +1200 Subject: [PATCH 13/29] Use create bulk attributes --- src/Appwrite/Migration/Version/V23.php | 10 ++++------ 1 file changed, 4 insertions(+), 6 deletions(-) diff --git a/src/Appwrite/Migration/Version/V23.php b/src/Appwrite/Migration/Version/V23.php index b02ca20d1e..daa5b03660 100644 --- a/src/Appwrite/Migration/Version/V23.php +++ b/src/Appwrite/Migration/Version/V23.php @@ -234,12 +234,10 @@ class V23 extends Migration 'buildLogs', 'totalSize', ]; - foreach ($attributes as $attribute) { - try { - $this->createAttributeFromCollection($this->dbForProject, $id, $attribute); - } catch (\Throwable $th) { - Console::warning('Failed to create attributes "' . \implode(', ', $attributes) . "\" in collection {$id}: {$th->getMessage()}"); - } + try { + $this->createAttributesFromCollection($this->dbForProject, $id, $attributes); + } catch (\Throwable $th) { + Console::warning('Failed to create attributes "' . \implode(', ', $attributes) . "\" in collection {$id}: {$th->getMessage()}"); } $indexes = [ From 4ce65876348203ce16f177f027c17a3c737db3cc Mon Sep 17 00:00:00 2001 From: Jake Barnby Date: Fri, 16 May 2025 20:30:16 +1200 Subject: [PATCH 14/29] Fix key matching --- src/Appwrite/Migration/Migration.php | 16 ++++++++++------ 1 file changed, 10 insertions(+), 6 deletions(-) diff --git a/src/Appwrite/Migration/Migration.php b/src/Appwrite/Migration/Migration.php index aa8254b0eb..1e6d53554e 100644 --- a/src/Appwrite/Migration/Migration.php +++ b/src/Appwrite/Migration/Migration.php @@ -261,26 +261,30 @@ abstract class Migration throw new Exception("Collection {$from} not found"); } - $attributes = []; - foreach ($attributeIds as $attributeId) { - $attribute = $collection['attributes'][$attributeId] ?? null; + $attributesToCreate = []; + $attributes = $collection['attributes']; + $attributeKeys = \array_column($collection['attributes'], '$id'); - if ($attribute === null) { + foreach ($attributeIds as $attributeId) { + $attributeKey = \array_search($attributeId, $attributeKeys); + + if ($attributeKey === false) { throw new Exception("Attribute {$attributeId} not found"); } + $attribute = $attributes[$attributeKey]; $attribute['filters'] ??= []; $attribute['default'] ??= null; $attribute['default'] = \in_array('json', $attribute['filters']) ? \json_encode($attribute['default']) : $attribute['default']; - $attributes[] = $attribute; + $attributesToCreate[] = $attribute; } $database->createAttributes( collection: $collectionId, - attributes: $attributes, + attributes: $attributesToCreate, ); } From 379ffd8eeb987831ad40852bd2798c6db419aa4c Mon Sep 17 00:00:00 2001 From: Jake Barnby Date: Fri, 16 May 2025 20:30:29 +1200 Subject: [PATCH 15/29] Disable coroutines --- src/Appwrite/Platform/Tasks/Migrate.php | 69 +++++++++++-------------- 1 file changed, 30 insertions(+), 39 deletions(-) diff --git a/src/Appwrite/Platform/Tasks/Migrate.php b/src/Appwrite/Platform/Tasks/Migrate.php index c2c19ec998..5e5920a1f7 100644 --- a/src/Appwrite/Platform/Tasks/Migrate.php +++ b/src/Appwrite/Platform/Tasks/Migrate.php @@ -27,8 +27,6 @@ class Migrate extends Action public function __construct() { - Runtime::enableCoroutine(); - $this ->desc('Migrate Appwrite to new version') ->param('version', APP_VERSION_STABLE, new Text(8), 'Version to migrate to.', true) @@ -60,52 +58,45 @@ class Migrate extends Action return; } - \Co\run(function ( - string $version, - Database $dbForPlatform, - callable $getProjectDB, - Registry $register, - ) { - $this->redis = new Redis(); - $this->redis->connect( - System::getEnv('_APP_REDIS_HOST', ''), - System::getEnv('_APP_REDIS_PORT', 6379), - 3, - null, - 10 - ); + $this->redis = new Redis(); + $this->redis->connect( + System::getEnv('_APP_REDIS_HOST', ''), + System::getEnv('_APP_REDIS_PORT', 6379), + 3, + null, + 10 + ); - Console::success('Starting Data Migration to version ' . $version); + Console::success('Starting Data Migration to version ' . $version); - $class = 'Appwrite\\Migration\\Version\\' . Migration::$versions[$version]; + $class = 'Appwrite\\Migration\\Version\\' . Migration::$versions[$version]; - /** @var Migration $migration */ - $migration = new $class(); + /** @var Migration $migration */ + $migration = new $class(); - $count = 0; - $total = $dbForPlatform->count('projects'); + $count = 0; + $total = $dbForPlatform->count('projects'); - $dbForPlatform->foreach('projects', function (Document $project) use ($dbForPlatform, $getProjectDB, $register, $migration, &$count, $total) { - /** @var Database $dbForProject */ - $dbForProject = $getProjectDB($project); - $dbForProject->disableValidation(); + $dbForPlatform->foreach('projects', function (Document $project) use ($dbForPlatform, $getProjectDB, $register, $migration, &$count, $total) { + /** @var Database $dbForProject */ + $dbForProject = $getProjectDB($project); + $dbForProject->disableValidation(); - try { - $migration - ->setProject($project, $dbForProject, $dbForPlatform) - ->setPDO($register->get('db', true)) - ->execute(); - } catch (\Throwable $th) { - Console::error('Failed to migrate project "' . $project->getId() . '" with error: ' . $th->getMessage()); - throw $th; - } + try { + $migration + ->setProject($project, $dbForProject, $dbForPlatform) + ->setPDO($register->get('db', true)) + ->execute(); + } catch (\Throwable $th) { + Console::error('Failed to migrate project "' . $project->getId() . '" with error: ' . $th->getMessage()); + throw $th; + } - Console::log('Migrated ' . $count++ . '/' . $total . ' projects...'); - }); + Console::log('Migrated ' . $count++ . '/' . $total . ' projects...'); + }); - Console::success('Migration completed'); - }, [$version, $dbForPlatform, $getProjectDB, $register]); + Console::success('Migration completed'); } private function clearProjectsCache(Document $project): void From 697d23e9a49ecd1b4d68512ec6370263c51da504 Mon Sep 17 00:00:00 2001 From: Jake Barnby Date: Fri, 16 May 2025 20:49:52 +1200 Subject: [PATCH 16/29] Update database --- composer.lock | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/composer.lock b/composer.lock index c68d6bf4d7..56c6e624ed 100644 --- a/composer.lock +++ b/composer.lock @@ -3499,16 +3499,16 @@ }, { "name": "utopia-php/database", - "version": "0.69.2", + "version": "0.69.3", "source": { "type": "git", "url": "https://github.com/utopia-php/database.git", - "reference": "60591ab073bb80bb9843338754b679bb8169e4ed" + "reference": "1f48ccc939199a9bf45c68d44dcfbc2b5dfdb5a7" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/utopia-php/database/zipball/60591ab073bb80bb9843338754b679bb8169e4ed", - "reference": "60591ab073bb80bb9843338754b679bb8169e4ed", + "url": "https://api.github.com/repos/utopia-php/database/zipball/1f48ccc939199a9bf45c68d44dcfbc2b5dfdb5a7", + "reference": "1f48ccc939199a9bf45c68d44dcfbc2b5dfdb5a7", "shasum": "" }, "require": { @@ -3549,9 +3549,9 @@ ], "support": { "issues": "https://github.com/utopia-php/database/issues", - "source": "https://github.com/utopia-php/database/tree/0.69.2" + "source": "https://github.com/utopia-php/database/tree/0.69.3" }, - "time": "2025-05-14T07:51:44+00:00" + "time": "2025-05-16T05:54:54+00:00" }, { "name": "utopia-php/detector", @@ -8240,7 +8240,7 @@ ], "aliases": [], "minimum-stability": "stable", - "stability-flags": [], + "stability-flags": {}, "prefer-stable": false, "prefer-lowest": false, "platform": { @@ -8264,5 +8264,5 @@ "platform-overrides": { "php": "8.3" }, - "plugin-api-version": "2.3.0" + "plugin-api-version": "2.6.0" } From 15c13aa0328528ddbe17584e3f252b81a9556d0c Mon Sep 17 00:00:00 2001 From: Jake Barnby Date: Fri, 16 May 2025 21:13:09 +1200 Subject: [PATCH 17/29] Remove duplicate attribute --- app/config/collections/projects.php | 11 ----------- 1 file changed, 11 deletions(-) diff --git a/app/config/collections/projects.php b/app/config/collections/projects.php index 3913fa8b00..48a0938a1c 100644 --- a/app/config/collections/projects.php +++ b/app/config/collections/projects.php @@ -2374,17 +2374,6 @@ return [ 'array' => false, 'filters' => [], ], - [ - '$id' => ID::custom('options'), - 'type' => Database::VAR_STRING, - 'format' => '', - 'size' => 65536, - 'signed' => true, - 'required' => false, - 'default' => [], - 'array' => false, - 'filters' => ['json'], - ] ], 'indexes' => [ [ From fa3894ef1c15d42d819fdd8796e91cc561eded2e Mon Sep 17 00:00:00 2001 From: Jake Barnby Date: Fri, 16 May 2025 22:06:37 +1200 Subject: [PATCH 18/29] Fix extra collection keys --- src/Appwrite/Migration/Migration.php | 16 ++++++---------- 1 file changed, 6 insertions(+), 10 deletions(-) diff --git a/src/Appwrite/Migration/Migration.php b/src/Appwrite/Migration/Migration.php index 1e6d53554e..a2ef038a2a 100644 --- a/src/Appwrite/Migration/Migration.php +++ b/src/Appwrite/Migration/Migration.php @@ -96,18 +96,14 @@ abstract class Migration $this->collections = Config::getParam('collections', []); - $this->collections['projects'][] = [ - '_metadata' => [ - '$id' => ID::custom('_metadata'), - '$collection' => Database::METADATA - ] + $this->collections['projects']['_metadata'] = [ + '$id' => ID::custom('_metadata'), + '$collection' => Database::METADATA, ]; - $this->collections['projects'][] = [ - 'audit' => [ - '$id' => ID::custom('audit'), - '$collection' => Database::METADATA - ], + $this->collections['projects']['audit'] = [ + '$id' => ID::custom('audit'), + '$collection' => Database::METADATA, ]; } From d6fd05866a4db1d76c682b7c28e8fc459e474df0 Mon Sep 17 00:00:00 2001 From: Jake Barnby Date: Fri, 16 May 2025 22:06:59 +1200 Subject: [PATCH 19/29] Ignore duplicate on create collection --- src/Appwrite/Migration/Migration.php | 14 ++++++++++---- 1 file changed, 10 insertions(+), 4 deletions(-) diff --git a/src/Appwrite/Migration/Migration.php b/src/Appwrite/Migration/Migration.php index a2ef038a2a..d7bef9ba93 100644 --- a/src/Appwrite/Migration/Migration.php +++ b/src/Appwrite/Migration/Migration.php @@ -158,7 +158,7 @@ abstract class Migration continue; } - Console::log('Migrating collection ' . $collection['$id'] . '...'); + Console::log('Migrating documents for collection "' . $collection['$id'] . '"'); $this->dbForProject->foreach($collection['$id'], function(Document $document) use ($collection, $callback) { if (empty($document->getId()) || empty($document->getCollection())) { @@ -204,17 +204,23 @@ abstract class Migration }; if (!$this->dbForProject->getCollection($id)->isEmpty()) { - $attributes = []; - $indexes = []; $collection = $this->collections[$collectionType][$id]; + + $attributes = []; foreach ($collection['attributes'] as $attribute) { $attributes[] = new Document($attribute); } + + $indexes = []; foreach ($collection['indexes'] as $index) { $indexes[] = new Document($index); } - $this->dbForProject->createCollection($name, $attributes, $indexes); + try { + $this->dbForProject->createCollection($name, $attributes, $indexes); + } catch (Duplicate ) { + Console::warning('Failed to create collection "' . $name . '": Collection already exists'); + } } } From 19d040d43d99948353091cac7d605c5eac5e5b6d Mon Sep 17 00:00:00 2001 From: Jake Barnby Date: Fri, 16 May 2025 22:07:17 +1200 Subject: [PATCH 20/29] Remove redundant method --- src/Appwrite/Platform/Tasks/Migrate.php | 29 +------------------------ 1 file changed, 1 insertion(+), 28 deletions(-) diff --git a/src/Appwrite/Platform/Tasks/Migrate.php b/src/Appwrite/Platform/Tasks/Migrate.php index 5e5920a1f7..0d7ce0be3e 100644 --- a/src/Appwrite/Platform/Tasks/Migrate.php +++ b/src/Appwrite/Platform/Tasks/Migrate.php @@ -42,6 +42,7 @@ class Migrate extends Action * @param callable(Document): Database $getProjectDB * @param Registry $register * @return void + * @throws Exception */ public function action( string $version, @@ -58,18 +59,8 @@ class Migrate extends Action return; } - $this->redis = new Redis(); - $this->redis->connect( - System::getEnv('_APP_REDIS_HOST', ''), - System::getEnv('_APP_REDIS_PORT', 6379), - 3, - null, - 10 - ); - Console::success('Starting Data Migration to version ' . $version); - $class = 'Appwrite\\Migration\\Version\\' . Migration::$versions[$version]; /** @var Migration $migration */ @@ -98,22 +89,4 @@ class Migrate extends Action Console::success('Migration completed'); } - - private function clearProjectsCache(Document $project): void - { - try { - $iterator = null; - do { - $pattern = "default-cache-mariadb:_{$project->getInternalId()}:*"; - $keys = $this->redis->scan($iterator, $pattern, 1000); - if ($keys !== false) { - foreach ($keys as $key) { - $this->redis->del($key); - } - } - } while ($iterator > 0); - } catch (\Throwable $th) { - Console::error('Failed to clear project ("' . $project->getId() . '") cache with error: ' . $th->getMessage()); - } - } } From 8ff4bc0f7bb87bfd951f2d9027acf697d030cd17 Mon Sep 17 00:00:00 2001 From: Jake Barnby Date: Fri, 16 May 2025 22:07:34 +1200 Subject: [PATCH 21/29] Fix count --- src/Appwrite/Platform/Tasks/Migrate.php | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) diff --git a/src/Appwrite/Platform/Tasks/Migrate.php b/src/Appwrite/Platform/Tasks/Migrate.php index 0d7ce0be3e..c8e9a73991 100644 --- a/src/Appwrite/Platform/Tasks/Migrate.php +++ b/src/Appwrite/Platform/Tasks/Migrate.php @@ -4,16 +4,13 @@ namespace Appwrite\Platform\Tasks; use Appwrite\Migration\Migration; use Redis; -use Swoole\Runtime; -use Utopia\App; use Utopia\CLI\Console; use Utopia\Database\Database; use Utopia\Database\Document; -use Utopia\Database\Query; +use Utopia\Database\Exception; use Utopia\Database\Validator\Authorization; use Utopia\Platform\Action; use Utopia\Registry\Registry; -use Utopia\System\System; use Utopia\Validator\Text; class Migrate extends Action @@ -84,7 +81,7 @@ class Migrate extends Action throw $th; } - Console::log('Migrated ' . $count++ . '/' . $total . ' projects...'); + Console::log('Migrated ' . ++$count . '/' . $total . ' projects...'); }); Console::success('Migration completed'); From ac384188127b0b02a43231c99df7d67f8ab6d504 Mon Sep 17 00:00:00 2001 From: Jake Barnby Date: Fri, 16 May 2025 22:07:43 +1200 Subject: [PATCH 22/29] Update logs --- src/Appwrite/Migration/Version/V23.php | 22 +++++++++++----------- 1 file changed, 11 insertions(+), 11 deletions(-) diff --git a/src/Appwrite/Migration/Version/V23.php b/src/Appwrite/Migration/Version/V23.php index daa5b03660..ba1816aec8 100644 --- a/src/Appwrite/Migration/Version/V23.php +++ b/src/Appwrite/Migration/Version/V23.php @@ -32,13 +32,13 @@ class V23 extends Migration ); } - Console::info('Migrating Collections'); + Console::info('Migrating collections'); $this->migrateCollections(); - Console::info('Migrating Documents'); + Console::info('Migrating documents'); $this->forEachDocument($this->migrateDocument(...)); - Console::log('Cleaning Up Collections'); + Console::info('Cleaning up collections'); $this->cleanCollections(); } @@ -70,7 +70,7 @@ class V23 extends Migration continue; } - Console::log("Migrating Collection \"{$id}\""); + Console::log("Migrating collection \"{$id}\""); switch ($id) { case '_metadata': @@ -139,7 +139,7 @@ class V23 extends Migration try { $this->createIndexFromCollection($this->dbForProject, $id, $index); } catch (\Throwable $th) { - Console::warning("Failed to create \"$index\" from {$id}: {$th->getMessage()}"); + Console::warning("Failed to create index \"$index\" from {$id}: {$th->getMessage()}"); } } $this->dbForProject->purgeCachedCollection($id); @@ -152,7 +152,7 @@ class V23 extends Migration try { $this->createIndexFromCollection($this->dbForProject, $id, $index); } catch (Throwable $th) { - Console::warning("Failed to create \"$index\" from {$id}: {$th->getMessage()}"); + Console::warning("Failed to create index \"$index\" from {$id}: {$th->getMessage()}"); } } $this->dbForProject->purgeCachedCollection($id); @@ -177,7 +177,7 @@ class V23 extends Migration try { $this->createIndexFromCollection($this->dbForProject, $id, $index); } catch (Throwable $th) { - Console::warning("Failed to create \"$index\" from {$id}: {$th->getMessage()}"); + Console::warning("Failed to create index \"$index\" from {$id}: {$th->getMessage()}"); } } @@ -206,7 +206,7 @@ class V23 extends Migration try { $this->createIndexFromCollection($this->dbForProject, $id, $index); } catch (Throwable $th) { - Console::warning("Failed to create \"$index\" from {$id}: {$th->getMessage()}"); + Console::warning("Failed to create index \"$index\" from {$id}: {$th->getMessage()}"); } } @@ -253,7 +253,7 @@ class V23 extends Migration try { $this->createIndexFromCollection($this->dbForProject, $id, $index); } catch (\Throwable $th) { - Console::warning("Failed to create \"$index\" from {$id}: {$th->getMessage()}"); + Console::warning("Failed to create index \"$index\" from {$id}: {$th->getMessage()}"); } } @@ -278,7 +278,7 @@ class V23 extends Migration try { $this->createIndexFromCollection($this->dbForProject, $id, $index); } catch (\Throwable $th) { - Console::warning("Failed to create \"$index\" from {$id}: {$th->getMessage()}"); + Console::warning("Failed to create index \"$index\" from {$id}: {$th->getMessage()}"); } } @@ -480,7 +480,7 @@ class V23 extends Migration foreach ($collections as $collection) { $id = $collection['$id']; - Console::log("Migrating Collection \"{$id}\""); + Console::log("Cleaning up collection \"{$id}\""); switch ($id) { case '_metadata': From 43493f71aa22a5ae9d36fab9c44e1cdaa03c33b8 Mon Sep 17 00:00:00 2001 From: Jake Barnby Date: Fri, 16 May 2025 22:10:13 +1200 Subject: [PATCH 23/29] Remove invalid collections --- app/config/collections/platform.php | 364 ---------------------------- 1 file changed, 364 deletions(-) diff --git a/app/config/collections/platform.php b/app/config/collections/platform.php index 4836f566aa..60f181df66 100644 --- a/app/config/collections/platform.php +++ b/app/config/collections/platform.php @@ -1891,368 +1891,4 @@ return [ 'attributes' => [], 'indexes' => [] ], - - 'domains' => [ - '$collection' => ID::custom(Database::METADATA), - '$id' => ID::custom('domains'), - 'name' => 'Domains', - 'attributes' => [ - [ - '$id' => ID::custom('teamInternalId'), - 'type' => Database::VAR_STRING, - 'format' => '', - 'size' => Database::LENGTH_KEY, - 'signed' => true, - 'required' => true, - 'default' => null, - 'array' => false, - 'filters' => [], - ], - [ - '$id' => ID::custom('teamId'), - 'type' => Database::VAR_STRING, - 'format' => '', - 'size' => Database::LENGTH_KEY, - 'signed' => true, - 'required' => false, - 'default' => null, - 'array' => false, - 'filters' => [], - ], - [ - '$id' => ID::custom('domain'), - 'type' => Database::VAR_STRING, - 'format' => '', - 'size' => 255, - 'signed' => true, - 'required' => true, - 'default' => null, - 'array' => false, - 'filters' => [], - ], - [ - '$id' => ID::custom('registrar'), - 'type' => Database::VAR_STRING, - 'format' => '', - 'size' => Database::LENGTH_KEY, - 'signed' => true, - 'required' => false, - 'default' => null, // e.g. "appwrite" or "third_party" - 'array' => false, - 'filters' => [], - ], - [ - '$id' => ID::custom('nameservers'), - 'type' => Database::VAR_STRING, - 'format' => '', - 'size' => 255, - 'signed' => true, - 'required' => false, - 'default' => '', // "Appwrite" or empty string - 'array' => false, - 'filters' => [], - ], - [ - '$id' => ID::custom('expire'), - 'type' => Database::VAR_DATETIME, - 'format' => '', - 'size' => 0, - 'signed' => false, - 'required' => false, - 'default' => null, - 'array' => false, - 'filters' => ['datetime'], - ], - [ - '$id' => ID::custom('renewal'), - 'type' => Database::VAR_DATETIME, - 'format' => '', - 'size' => 0, - 'signed' => false, - 'required' => false, - 'default' => null, - 'array' => false, - 'filters' => ['datetime'], - ], - [ - '$id' => ID::custom('autoRenewal'), - 'type' => Database::VAR_BOOLEAN, - 'signed' => true, - 'size' => 0, - 'format' => '', - 'filters' => [], - 'required' => false, - 'default' => false, - 'array' => false, - ], - [ - '$id' => ID::custom('renewalPrice'), - 'type' => Database::VAR_INTEGER, - 'format' => '', - 'size' => 0, - 'signed' => false, - 'required' => false, - 'default' => 0, - 'array' => false, - 'filters' => [], - ], - [ - '$id' => ID::custom('search'), - 'type' => Database::VAR_STRING, - 'format' => '', - 'size' => 16384, - 'signed' => true, - 'required' => false, - 'default' => null, - 'array' => false, - 'filters' => [], - ], - ], - 'indexes' => [ - [ - '$id' => ID::custom('_key_search'), - 'type' => Database::INDEX_FULLTEXT, - 'attributes' => ['search'], - 'lengths' => [], - 'orders' => [], - ], - [ - '$id' => ID::custom('_key_teamInternalId'), - 'type' => Database::INDEX_KEY, - 'attributes' => ['teamInternalId'], - 'lengths' => [Database::LENGTH_KEY], - 'orders' => [Database::ORDER_ASC], - ], - [ - '$id' => ID::custom('_key_domain'), - 'type' => Database::INDEX_KEY, - 'attributes' => ['domain'], - 'lengths' => [Database::LENGTH_KEY], - 'orders' => [Database::ORDER_ASC], - ], - [ - '$id' => ID::custom('_key_teamId_domain'), - 'type' => Database::INDEX_UNIQUE, - 'attributes' => ['teamId', 'domain'], - 'lengths' => [], - 'orders' => [], - ], - [ - '$id' => ID::custom('_key_expire'), - 'type' => Database::INDEX_KEY, - 'attributes' => ['expire'], - 'lengths' => [], - 'orders' => [], - ], - [ - '$id' => ID::custom('_key_registrar'), - 'type' => Database::INDEX_KEY, - 'attributes' => ['registrar'], - 'lengths' => [], - 'orders' => [], - ], - [ - '$id' => ID::custom('_key_nameservers'), - 'type' => Database::INDEX_KEY, - 'attributes' => ['nameservers'], - 'lengths' => [], - 'orders' => [], - ], - [ - '$id' => ID::custom('_key_renewalPrice'), - 'type' => Database::INDEX_KEY, - 'attributes' => ['renewalPrice'], - 'lengths' => [], - 'orders' => [], - ], - [ - '$id' => ID::custom('_key_renewal'), - 'type' => Database::INDEX_KEY, - 'attributes' => ['renewal'], - 'lengths' => [], - 'orders' => [], - ], - [ - '$id' => ID::custom('_key_autoRenewal'), - 'type' => Database::INDEX_KEY, - 'attributes' => ['autoRenewal'], - 'lengths' => [], - 'orders' => [], - ], - ], - ], - - 'dnsRecords' => [ - '$collection' => ID::custom(Database::METADATA), - '$id' => ID::custom('dnsRecords'), - 'name' => 'DNS Records', - 'attributes' => [ - [ - '$id' => ID::custom('domainInternalId'), - 'type' => Database::VAR_STRING, - 'format' => '', - 'size' => Database::LENGTH_KEY, - 'signed' => true, - 'required' => true, - 'default' => null, - 'array' => false, - 'filters' => [], - ], - [ - '$id' => ID::custom('domainId'), - 'type' => Database::VAR_STRING, - 'format' => '', - 'size' => Database::LENGTH_KEY, - 'signed' => true, - 'required' => false, - 'default' => null, - 'array' => false, - 'filters' => [], - ], - [ - '$id' => ID::custom('type'), - 'type' => Database::VAR_STRING, - 'format' => '', - 'size' => Database::LENGTH_KEY, - 'signed' => true, - 'required' => true, - 'default' => null, - 'array' => false, - 'filters' => [], - ], - [ - '$id' => ID::custom('name'), - 'type' => Database::VAR_STRING, - 'format' => '', - 'size' => 255, - 'signed' => true, - 'required' => true, - 'default' => null, - 'array' => false, - 'filters' => [], - ], - [ - '$id' => ID::custom('value'), - 'type' => Database::VAR_STRING, - 'format' => '', - 'size' => 16384, - 'signed' => true, - 'required' => true, - 'default' => null, - 'array' => false, - 'filters' => [], - ], - [ - '$id' => ID::custom('ttl'), - 'type' => Database::VAR_INTEGER, - 'format' => '', - 'size' => 0, - 'signed' => true, - 'required' => false, - 'default' => 3600, - 'array' => false, - 'filters' => [], - ], - [ - '$id' => ID::custom('priority'), - 'type' => Database::VAR_INTEGER, - 'format' => '', - 'size' => 0, - 'signed' => true, - 'required' => false, - 'default' => 0, - 'array' => false, - 'filters' => [], - ], - [ - '$id' => ID::custom('weight'), - 'type' => Database::VAR_INTEGER, - 'format' => '', - 'size' => 0, - 'signed' => true, - 'required' => false, - 'default' => 0, - 'array' => false, - 'filters' => [], - ], - [ - '$id' => ID::custom('port'), - 'type' => Database::VAR_INTEGER, - 'format' => '', - 'size' => 0, - 'signed' => false, // Port numbers are always positive - 'required' => false, - 'default' => 0, - 'array' => false, - 'filters' => [], - ], - [ - '$id' => ID::custom('lock'), - 'type' => Database::VAR_BOOLEAN, - 'signed' => true, - 'size' => 0, - 'format' => '', - 'filters' => [], - 'required' => false, - 'default' => false, - 'array' => false, - ], - [ - '$id' => ID::custom('comment'), - 'type' => Database::VAR_STRING, - 'format' => '', - 'size' => 16384, - 'signed' => true, - 'required' => true, - 'default' => null, - 'array' => false, - 'filters' => [], - ], - ], - 'indexes' => [ - [ - '$id' => ID::custom('_key_domainInternalId'), - 'type' => Database::INDEX_KEY, - 'attributes' => ['domainInternalId'], - 'lengths' => [Database::LENGTH_KEY], - 'orders' => [Database::ORDER_ASC], - ], - [ - '$id' => ID::custom('_key_domainId'), - 'type' => Database::INDEX_KEY, - 'attributes' => ['domainId'], - 'lengths' => [Database::LENGTH_KEY], - 'orders' => [Database::ORDER_ASC], - ], - // New indexes based on allowed query attributes - [ - '$id' => ID::custom('_key_type'), - 'type' => Database::INDEX_KEY, - 'attributes' => ['type'], - 'lengths' => [], - 'orders' => [], - ], - [ - '$id' => ID::custom('_key_name'), - 'type' => Database::INDEX_KEY, - 'attributes' => ['name'], - 'lengths' => [], - 'orders' => [], - ], - [ - '$id' => ID::custom('_key_lock'), - 'type' => Database::INDEX_KEY, - 'attributes' => ['lock'], - 'lengths' => [], - 'orders' => [], - ], - [ - '$id' => ID::custom('_key_priority'), - 'type' => Database::INDEX_KEY, - 'attributes' => ['priority'], - 'lengths' => [], - 'orders' => [], - ], - ], - ], ]; From be400681e721729e11232e808547e002821ba426 Mon Sep 17 00:00:00 2001 From: Jake Barnby Date: Sat, 17 May 2025 00:18:57 +1200 Subject: [PATCH 24/29] Fix collection exists fallbacks --- src/Appwrite/Migration/Migration.php | 30 +++++++++++++++------------- 1 file changed, 16 insertions(+), 14 deletions(-) diff --git a/src/Appwrite/Migration/Migration.php b/src/Appwrite/Migration/Migration.php index d7bef9ba93..5199368376 100644 --- a/src/Appwrite/Migration/Migration.php +++ b/src/Appwrite/Migration/Migration.php @@ -204,23 +204,25 @@ abstract class Migration }; if (!$this->dbForProject->getCollection($id)->isEmpty()) { - $collection = $this->collections[$collectionType][$id]; + return; + } - $attributes = []; - foreach ($collection['attributes'] as $attribute) { - $attributes[] = new Document($attribute); - } + $collection = $this->collections[$collectionType][$id]; - $indexes = []; - foreach ($collection['indexes'] as $index) { - $indexes[] = new Document($index); - } + $attributes = []; + foreach ($collection['attributes'] as $attribute) { + $attributes[] = new Document($attribute); + } - try { - $this->dbForProject->createCollection($name, $attributes, $indexes); - } catch (Duplicate ) { - Console::warning('Failed to create collection "' . $name . '": Collection already exists'); - } + $indexes = []; + foreach ($collection['indexes'] as $index) { + $indexes[] = new Document($index); + } + + try { + $this->dbForProject->createCollection($name, $attributes, $indexes); + } catch (Duplicate ) { + Console::warning('Failed to create collection "' . $name . '": Collection already exists'); } } From c56dba6b204c551db8054c0abfeb6c819bf1c7ac Mon Sep 17 00:00:00 2001 From: Jake Barnby Date: Sat, 17 May 2025 00:19:12 +1200 Subject: [PATCH 25/29] Add console --- src/Appwrite/Platform/Tasks/Migrate.php | 15 ++++++++++++++- 1 file changed, 14 insertions(+), 1 deletion(-) diff --git a/src/Appwrite/Platform/Tasks/Migrate.php b/src/Appwrite/Platform/Tasks/Migrate.php index c8e9a73991..6aa1f0da00 100644 --- a/src/Appwrite/Platform/Tasks/Migrate.php +++ b/src/Appwrite/Platform/Tasks/Migrate.php @@ -4,6 +4,7 @@ namespace Appwrite\Platform\Tasks; use Appwrite\Migration\Migration; use Redis; +use Utopia\App; use Utopia\CLI\Console; use Utopia\Database\Database; use Utopia\Database\Document; @@ -64,7 +65,7 @@ class Migrate extends Action $migration = new $class(); $count = 0; - $total = $dbForPlatform->count('projects'); + $total = $dbForPlatform->count('projects') + 1; $dbForPlatform->foreach('projects', function (Document $project) use ($dbForPlatform, $getProjectDB, $register, $migration, &$count, $total) { /** @var Database $dbForProject */ @@ -84,6 +85,18 @@ class Migrate extends Action Console::log('Migrated ' . ++$count . '/' . $total . ' projects...'); }); + $console = (new App('UTC'))->getResource('console'); + + try { + $migration + ->setProject($console, $getProjectDB($console), $dbForPlatform) + ->setPDO($register->get('db', true)) + ->execute(); + } catch (\Throwable $th) { + Console::error('Failed to migrate project "console" with error: ' . $th->getMessage()); + throw $th; + } + Console::success('Migration completed'); } } From e22ef821160e6eaeabc8f2c89c363ab0ce058338 Mon Sep 17 00:00:00 2001 From: Jake Barnby Date: Sat, 17 May 2025 00:49:59 +1200 Subject: [PATCH 26/29] Safe multi-run by self-fallback --- src/Appwrite/Migration/Version/V23.php | 67 +++++++++++++------------- 1 file changed, 34 insertions(+), 33 deletions(-) diff --git a/src/Appwrite/Migration/Version/V23.php b/src/Appwrite/Migration/Version/V23.php index ba1816aec8..57f3ee853b 100644 --- a/src/Appwrite/Migration/Version/V23.php +++ b/src/Appwrite/Migration/Version/V23.php @@ -64,7 +64,7 @@ class V23 extends Migration $collections = $this->collections[$collectionType]; foreach ($collections as $collection) { - $id = $collection['$id'] ?? null; + $id = $collection['$id']; if (empty($id)) { continue; @@ -314,7 +314,7 @@ class V23 extends Migration * @throws \Utopia\Database\Exception\Authorization * @throws \Utopia\Database\Exception\Query */ - protected function migrateDocument(Document $document): Document + private function migrateDocument(Document $document): Document { switch ($document->getCollection()) { case 'rules': @@ -328,34 +328,35 @@ class V23 extends Migration 7. Fill "deploymentId" and "deploymentInternalId". If "deploymentResourceType" is "function", get project DB, and find function with ID "resourceId". Then fill rule's "deploymentId" with function's "deployment", and "deploymentId" as backup */ + $deploymentResourceType = null; + $type = $document->getAttribute('resourceType'); if ($type === 'function') { $type = 'deployment'; - } - - $deploymentResourceType = null; - if ($document->getAttribute('resourceType') === 'function') { $deploymentResourceType = 'function'; } - $resourceId = $document->getAttribute('resourceId'); + $resourceId = $document->getAttribute('resourceId', $document->getAttribute('deploymentResourceId')); + $resourceInternalId = $document->getAttribute('resourceInternalId', $document->getAttribute('deploymentResourceInternalId')); $document ->setAttribute('type', $type) - ->setAttribute('deploymentResourceId', $resourceId) - ->setAttribute('deploymentResourceInternalId', $document->getAttribute('resourceInternalId')) ->setAttribute('trigger', 'manual') + ->setAttribute('deploymentResourceId', $resourceId) + ->setAttribute('deploymentResourceInternalId', $resourceInternalId) ->setAttribute('deploymentResourceType', $deploymentResourceType) - ->setAttribute('search', \implode(' ', [$document->getId(), $document->getAttribute('domain', '')])) - ; + ->setAttribute('search', \implode(' ', [$document->getId(), $document->getAttribute('domain', '')])); if ($deploymentResourceType === 'function') { if ($this->project->getInternalId() !== 'console') { $function = $this->dbForProject->getDocument('functions', $resourceId); + $deploymentId = $function->getAttribute('deployment', $document->getAttribute('deploymentId', '')); + $deploymentInternalId = $function->getAttribute('deploymentInternalId', $document->getAttribute('deploymentInternalId', '')); + $document - ->setAttribute('deploymentId', $function->getAttribute('deployment', $function->getAttribute('deploymentId', ''))) - ->setAttribute('deploymentInternalId', $function->getAttribute('deployment', $function->getAttribute('deploymentId', ''))); + ->setAttribute('deploymentId', $deploymentId) + ->setAttribute('deploymentInternalId', $deploymentInternalId); } } break; @@ -363,7 +364,7 @@ class V23 extends Migration /* 1. Fill "secret" with "false" */ - $document->setAttribute('secret', false); + $document->setAttribute('secret', $document->getAttribute('secret', false)); break; case 'executions': /* @@ -372,9 +373,9 @@ class V23 extends Migration 3. Fill "resourceType" with "functions" */ $document - ->setAttribute('resourceInternalId', $document->getAttribute('functionInternalId')) - ->setAttribute('resourceId', $document->getAttribute('functionId')) - ->setAttribute('resourceType', 'functions'); + ->setAttribute('resourceInternalId', $document->getAttribute('functionInternalId', $document->getAttribute('resourceInternalId'))) + ->setAttribute('resourceId', $document->getAttribute('functionId', $document->getAttribute('resourceId', ''))) + ->setAttribute('resourceType', $document->getAttribute('resourceType', 'functions')); break; case 'functions': /* @@ -388,7 +389,7 @@ class V23 extends Migration 6. Fill latestDeploymentStatus with latestDeployment's build's "status" */ if ($document->getAttribute('deployment')) { - $document->setAttribute('deploymentId', $document->getAttribute('deployment')); + $document->setAttribute('deploymentId', $document->getAttribute('deployment', $document->getAttribute('deploymentId', ''))); } $deploymentId = $document->getAttribute('deploymentId'); @@ -407,7 +408,7 @@ class V23 extends Migration ->setAttribute('latestDeploymentId', $latestDeployment->getId()) ->setAttribute('latestDeploymentInternalId', $latestDeployment->getInternalId()) ->setAttribute('latestDeploymentCreatedAt', $latestDeployment->getCreatedAt()) - ->setAttribute('latestDeploymentStatus', $latestBuild->getAttribute('status')); + ->setAttribute('latestDeploymentStatus', $latestBuild->getAttribute('status', $document->getAttribute('latestDeploymentStatus', ''))); break; case 'deployments': /* @@ -429,12 +430,12 @@ class V23 extends Migration */ $document - ->setAttribute('buildCommands', $document->getAttribute('commands')) - ->setAttribute('sourcePath', $document->getAttribute('path')) - ->setAttribute('sourceSize', $document->getAttribute('size')) - ->setAttribute('sourceMetadata', $document->getAttribute('metadata')) - ->setAttribute('sourceChunksTotal', $document->getAttribute('chunksTotal')) - ->setAttribute('sourceChunksUploaded', $document->getAttribute('chunksUploaded')); + ->setAttribute('buildCommands', $document->getAttribute('commands', $document->getAttribute('buildCommands', ''))) + ->setAttribute('sourcePath', $document->getAttribute('path', $document->getAttribute('sourcePath', ''))) + ->setAttribute('sourceSize', $document->getAttribute('size', $document->getAttribute('sourceSize', 0))) + ->setAttribute('sourceMetadata', $document->getAttribute('metadata', $document->getAttribute('sourceMetadata', []))) + ->setAttribute('sourceChunksTotal', $document->getAttribute('chunksTotal', $document->getAttribute('sourceChunksTotal', 0))) + ->setAttribute('sourceChunksUploaded', $document->getAttribute('chunksUploaded', $document->getAttribute('sourceChunksUploaded', 0))); $build = new Document(); if (!empty($document->getAttribute('buildId'))) { @@ -442,13 +443,13 @@ class V23 extends Migration } $document - ->setAttribute('buildStartedAt', $build->getAttribute('startTime')) - ->setAttribute('buildEndedAt', $build->getAttribute('endTime')) - ->setAttribute('buildDuration', $build->getAttribute('duration', 0)) - ->setAttribute('buildSize', $build->getAttribute('size', 0)) - ->setAttribute('status', $build->getAttribute('status')) - ->setAttribute('buildPath', $build->getAttribute('path', '')) - ->setAttribute('buildLogs', $build->getAttribute('logs', '')); + ->setAttribute('buildStartedAt', $build->getAttribute('startTime', $document->getAttribute('buildStartTime', ''))) + ->setAttribute('buildEndedAt', $build->getAttribute('endTime', $document->getAttribute('buildEndTime', ''))) + ->setAttribute('buildDuration', $build->getAttribute('duration', $document->getAttribute('buildDuration', 0))) + ->setAttribute('buildSize', $build->getAttribute('size', $document->getAttribute('buildSize', 0))) + ->setAttribute('status', $build->getAttribute('status', $document->getAttribute('status', ''))) + ->setAttribute('buildPath', $build->getAttribute('path', $document->getAttribute('buildPath', ''))) + ->setAttribute('buildLogs', $build->getAttribute('logs', $document->getAttribute('buildLogs', ''))); $totalSize = $document->getAttribute('buildSize', 0) + $document->getAttribute('sourceSize', 0); @@ -459,7 +460,7 @@ class V23 extends Migration /* 1. Fill "options" with "[]" */ - $document->setAttribute('options', []); + $document->setAttribute('options', $document->getAttribute('options', [])); break; default: break; From 04009699ebb6bf641c7a550a2fdc6b147ee9f7df Mon Sep 17 00:00:00 2001 From: Jake Barnby Date: Sat, 17 May 2025 01:37:20 +1200 Subject: [PATCH 27/29] Fix type + resourceType fallbacks --- src/Appwrite/Migration/Version/V23.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/Appwrite/Migration/Version/V23.php b/src/Appwrite/Migration/Version/V23.php index 57f3ee853b..f3b5746c89 100644 --- a/src/Appwrite/Migration/Version/V23.php +++ b/src/Appwrite/Migration/Version/V23.php @@ -330,7 +330,7 @@ class V23 extends Migration $deploymentResourceType = null; - $type = $document->getAttribute('resourceType'); + $type = $document->getAttribute('resourceType', $document->getAttribute('type', '')); if ($type === 'function') { $type = 'deployment'; $deploymentResourceType = 'function'; @@ -344,7 +344,7 @@ class V23 extends Migration ->setAttribute('trigger', 'manual') ->setAttribute('deploymentResourceId', $resourceId) ->setAttribute('deploymentResourceInternalId', $resourceInternalId) - ->setAttribute('deploymentResourceType', $deploymentResourceType) + ->setAttribute('deploymentResourceType', $document->getAttribute('deploymentResourceType', $deploymentResourceType)) ->setAttribute('search', \implode(' ', [$document->getId(), $document->getAttribute('domain', '')])); if ($deploymentResourceType === 'function') { From a3722f53a578905d20b5b5c207d33217d8f44a81 Mon Sep 17 00:00:00 2001 From: Jake Barnby Date: Sat, 17 May 2025 01:39:25 +1200 Subject: [PATCH 28/29] Fix getting function for rule --- src/Appwrite/Migration/Migration.php | 13 ++++++++++++- src/Appwrite/Migration/Version/V23.php | 17 ++++++++--------- src/Appwrite/Platform/Tasks/Migrate.php | 4 ++-- 3 files changed, 22 insertions(+), 12 deletions(-) diff --git a/src/Appwrite/Migration/Migration.php b/src/Appwrite/Migration/Migration.php index 5199368376..ffd2707097 100644 --- a/src/Appwrite/Migration/Migration.php +++ b/src/Appwrite/Migration/Migration.php @@ -28,6 +28,11 @@ abstract class Migration protected Database $dbForPlatform; + /** + * @var callable(Document): Database + */ + protected mixed $getProjectDB; + protected PDO $pdo; /** @@ -115,11 +120,17 @@ abstract class Migration * @param Database $dbForPlatform * @return self */ - public function setProject(Document $project, Database $dbForProject, Database $dbForPlatform): self + public function setProject( + Document $project, + Database $dbForProject, + Database $dbForPlatform, + ?callable $getProjectDB = null + ): self { $this->project = $project; $this->dbForProject = $dbForProject; $this->dbForPlatform = $dbForPlatform; + $this->getProjectDB = $getProjectDB; return $this; } diff --git a/src/Appwrite/Migration/Version/V23.php b/src/Appwrite/Migration/Version/V23.php index f3b5746c89..582b5fc36b 100644 --- a/src/Appwrite/Migration/Version/V23.php +++ b/src/Appwrite/Migration/Version/V23.php @@ -348,16 +348,15 @@ class V23 extends Migration ->setAttribute('search', \implode(' ', [$document->getId(), $document->getAttribute('domain', '')])); if ($deploymentResourceType === 'function') { - if ($this->project->getInternalId() !== 'console') { - $function = $this->dbForProject->getDocument('functions', $resourceId); + $project = $this->dbForProject->getDocument('projects', $document->getAttribute('projectId')); + $dbForOwnerProject = ($this->getProjectDB)($project); + $function = $dbForOwnerProject->getDocument('functions', $resourceId); + $deploymentId = $function->getAttribute('deployment', $function->getAttribute('deploymentId', $document->getAttribute('deploymentId'))); + $deploymentInternalId = $function->getAttribute('deploymentInternalId', $document->getAttribute('deploymentInternalId', '')); - $deploymentId = $function->getAttribute('deployment', $document->getAttribute('deploymentId', '')); - $deploymentInternalId = $function->getAttribute('deploymentInternalId', $document->getAttribute('deploymentInternalId', '')); - - $document - ->setAttribute('deploymentId', $deploymentId) - ->setAttribute('deploymentInternalId', $deploymentInternalId); - } + $document + ->setAttribute('deploymentId', $deploymentId) + ->setAttribute('deploymentInternalId', $deploymentInternalId); } break; case 'variables': diff --git a/src/Appwrite/Platform/Tasks/Migrate.php b/src/Appwrite/Platform/Tasks/Migrate.php index 6aa1f0da00..5d5cb2a407 100644 --- a/src/Appwrite/Platform/Tasks/Migrate.php +++ b/src/Appwrite/Platform/Tasks/Migrate.php @@ -74,7 +74,7 @@ class Migrate extends Action try { $migration - ->setProject($project, $dbForProject, $dbForPlatform) + ->setProject($project, $dbForProject, $dbForPlatform, $getProjectDB) ->setPDO($register->get('db', true)) ->execute(); } catch (\Throwable $th) { @@ -89,7 +89,7 @@ class Migrate extends Action try { $migration - ->setProject($console, $getProjectDB($console), $dbForPlatform) + ->setProject($console, $getProjectDB($console), $dbForPlatform, $getProjectDB) ->setPDO($register->get('db', true)) ->execute(); } catch (\Throwable $th) { From 91f8570801393c7009a4b288e446117ca7d66f7a Mon Sep 17 00:00:00 2001 From: Jake Barnby Date: Sat, 17 May 2025 01:57:57 +1200 Subject: [PATCH 29/29] Format --- composer.lock | 12 ++++++------ src/Appwrite/Migration/Migration.php | 16 +++++----------- src/Appwrite/Migration/Version/V23.php | 3 +-- src/Appwrite/Platform/Tasks/Migrate.php | 3 +-- .../Services/Sites/SitesConsoleClientTest.php | 3 +-- 5 files changed, 14 insertions(+), 23 deletions(-) diff --git a/composer.lock b/composer.lock index 56c6e624ed..65b04a8904 100644 --- a/composer.lock +++ b/composer.lock @@ -3499,16 +3499,16 @@ }, { "name": "utopia-php/database", - "version": "0.69.3", + "version": "0.69.4", "source": { "type": "git", "url": "https://github.com/utopia-php/database.git", - "reference": "1f48ccc939199a9bf45c68d44dcfbc2b5dfdb5a7" + "reference": "31f913a9c5c363e6427e69a0b8bbb9b8d901e061" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/utopia-php/database/zipball/1f48ccc939199a9bf45c68d44dcfbc2b5dfdb5a7", - "reference": "1f48ccc939199a9bf45c68d44dcfbc2b5dfdb5a7", + "url": "https://api.github.com/repos/utopia-php/database/zipball/31f913a9c5c363e6427e69a0b8bbb9b8d901e061", + "reference": "31f913a9c5c363e6427e69a0b8bbb9b8d901e061", "shasum": "" }, "require": { @@ -3549,9 +3549,9 @@ ], "support": { "issues": "https://github.com/utopia-php/database/issues", - "source": "https://github.com/utopia-php/database/tree/0.69.3" + "source": "https://github.com/utopia-php/database/tree/0.69.4" }, - "time": "2025-05-16T05:54:54+00:00" + "time": "2025-05-16T13:51:43+00:00" }, { "name": "utopia-php/detector", diff --git a/src/Appwrite/Migration/Migration.php b/src/Appwrite/Migration/Migration.php index ffd2707097..748e15413e 100644 --- a/src/Appwrite/Migration/Migration.php +++ b/src/Appwrite/Migration/Migration.php @@ -11,12 +11,9 @@ use Utopia\Database\Exception\Conflict; use Utopia\Database\Exception\Duplicate; use Utopia\Database\Exception\Limit; use Utopia\Database\Exception\Structure; -use Utopia\Database\Exception\Timeout; use Utopia\Database\Helpers\ID; use Utopia\Database\PDO; -use Utopia\Database\Query; use Utopia\Database\Validator\Authorization; -use Utopia\System\System; abstract class Migration { @@ -125,8 +122,7 @@ abstract class Migration Database $dbForProject, Database $dbForPlatform, ?callable $getProjectDB = null - ): self - { + ): self { $this->project = $project; $this->dbForProject = $dbForProject; $this->dbForPlatform = $dbForPlatform; @@ -171,7 +167,7 @@ abstract class Migration Console::log('Migrating documents for collection "' . $collection['$id'] . '"'); - $this->dbForProject->foreach($collection['$id'], function(Document $document) use ($collection, $callback) { + $this->dbForProject->foreach($collection['$id'], function (Document $document) use ($collection, $callback) { if (empty($document->getId()) || empty($document->getCollection())) { return; } @@ -232,7 +228,7 @@ abstract class Migration try { $this->dbForProject->createCollection($name, $attributes, $indexes); - } catch (Duplicate ) { + } catch (Duplicate) { Console::warning('Failed to create collection "' . $name . '": Collection already exists'); } } @@ -257,8 +253,7 @@ abstract class Migration string $collectionId, array $attributeIds, string $from = null - ): void - { + ): void { $from ??= $collectionId; $collectionType = match ($this->project->getInternalId()) { @@ -323,8 +318,7 @@ abstract class Migration string $collectionId, string $attributeId, string $from = null - ): void - { + ): void { $from ??= $collectionId; $collectionType = match ($this->project->getInternalId()) { diff --git a/src/Appwrite/Migration/Version/V23.php b/src/Appwrite/Migration/Version/V23.php index 582b5fc36b..400b223756 100644 --- a/src/Appwrite/Migration/Version/V23.php +++ b/src/Appwrite/Migration/Version/V23.php @@ -12,7 +12,6 @@ use Utopia\Database\Exception\Conflict; use Utopia\Database\Exception\Structure; use Utopia\Database\Exception\Timeout; use Utopia\Database\Query; -use Utopia\Database\Validator\Authorization; class V23 extends Migration { @@ -395,7 +394,7 @@ class V23 extends Migration $deployment = $this->dbForProject->getDocument('deployments', $deploymentId); $document->setAttribute('deploymentCreatedAt', $deployment->getCreatedAt()); - $latestDeployment = $this->dbForProject->findOne('deployments',[ + $latestDeployment = $this->dbForProject->findOne('deployments', [ Query::orderDesc(), Query::equal('resourceId', [$document->getId()]), Query::equal('resourceType', ['functions']), diff --git a/src/Appwrite/Platform/Tasks/Migrate.php b/src/Appwrite/Platform/Tasks/Migrate.php index 5d5cb2a407..9f3494c506 100644 --- a/src/Appwrite/Platform/Tasks/Migrate.php +++ b/src/Appwrite/Platform/Tasks/Migrate.php @@ -47,8 +47,7 @@ class Migrate extends Action Database $dbForPlatform, callable $getProjectDB, Registry $register, - ): void - { + ): void { Authorization::disable(); if (!\array_key_exists($version, Migration::$versions)) { diff --git a/tests/e2e/Services/Sites/SitesConsoleClientTest.php b/tests/e2e/Services/Sites/SitesConsoleClientTest.php index 3b9243ee77..1a84f46ed7 100644 --- a/tests/e2e/Services/Sites/SitesConsoleClientTest.php +++ b/tests/e2e/Services/Sites/SitesConsoleClientTest.php @@ -1,12 +1,11 @@