appwrite/src/Appwrite/Migration/Version/V21.php

284 lines
11 KiB
PHP
Raw Normal View History

2024-07-17 05:52:17 +00:00
<?php
namespace Appwrite\Migration\Version;
use Appwrite\Migration\Migration;
use Exception;
use Throwable;
use Utopia\CLI\Console;
use Utopia\Database\Database;
2024-07-17 06:20:34 +00:00
use Utopia\Database\DateTime;
2024-07-17 05:52:17 +00:00
use Utopia\Database\Document;
2024-07-17 05:54:37 +00:00
class V21 extends Migration
2024-07-17 05:52:17 +00:00
{
/**
* @throws Throwable
*/
public function execute(): void
{
/**
* Disable SubQueries for Performance.
*/
foreach (['subQueryIndexes', 'subQueryPlatforms', 'subQueryDomains', 'subQueryKeys', 'subQueryWebhooks', 'subQuerySessions', 'subQueryTokens', 'subQueryMemberships', 'subQueryVariables', 'subQueryChallenges', 'subQueryProjectVariables', 'subQueryTargets', 'subQueryTopicTargets'] as $name) {
Database::addFilter(
$name,
fn () => null,
fn () => []
);
}
Console::log('Migrating Project: ' . $this->project->getAttribute('name') . ' (' . $this->project->getId() . ')');
2025-05-16 05:24:11 +00:00
$this->dbForProject->setNamespace("_{$this->project->getInternalId()}");
2024-07-17 05:52:17 +00:00
Console::info('Migrating Collections');
$this->migrateCollections();
2024-07-30 20:53:18 +00:00
if ($this->project->getInternalId() !== 'console') {
Console::info('Migrating Buckets');
$this->migrateBuckets();
}
2024-07-30 21:39:32 +00:00
Console::info('Migrating Documents');
$this->forEachDocument([$this, 'fixDocument']);
2024-07-17 05:52:17 +00:00
}
/**
* Migrate Collections.
*
* @return void
* @throws Exception|Throwable
*/
private function migrateCollections(): 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}\"");
2025-05-16 05:24:11 +00:00
$this->dbForProject->setNamespace("_$internalProjectId");
2024-07-17 05:52:17 +00:00
switch ($id) {
case 'projects':
// Create accessedAt attribute
try {
2025-05-16 05:24:11 +00:00
$this->createAttributeFromCollection($this->dbForProject, $id, 'accessedAt');
2024-07-17 05:52:17 +00:00
} catch (Throwable $th) {
Console::warning("'accessedAt' from {$id}: {$th->getMessage()}");
}
2024-07-24 07:00:20 +00:00
break;
case 'rules':
$attributesToCreate = ['owner', 'region'];
foreach ($attributesToCreate as $attribute) {
// Create attribute
try {
$this->createAttributeFromCollection($this->dbForProject, $id, $attribute);
} catch (Throwable $th) {
Console::warning("'$attribute' from {$id}: {$th->getMessage()}");
}
}
$indexesToCreate = ['_key_owner', '_key_region'];
foreach ($indexesToCreate as $index) {
// Create index
try {
$this->createIndexFromCollection($this->dbForProject, $id, $index);
} catch (Throwable $th) {
Console::warning("'$index' from {$id}: {$th->getMessage()}");
}
}
break;
case 'platforms':
// Increase 'type' length to 255
try {
2025-05-16 05:24:11 +00:00
$this->dbForProject->updateAttribute($id, 'type', size: 255);
} catch (Throwable $th) {
Console::warning("'type' from {$id}: {$th->getMessage()}");
}
break;
case 'installations':
$attributesToCreate = ['personalAccessToken', 'personalAccessTokenExpiry', 'personalRefreshToken'];
foreach ($attributesToCreate as $attribute) {
// Create attribute
try {
$this->createAttributeFromCollection($this->dbForProject, $id, $attribute);
} catch (Throwable $th) {
Console::warning("'$attribute' from {$id}: {$th->getMessage()}");
}
}
break;
case 'migrations':
// Create destination attribute
try {
2025-05-16 05:24:11 +00:00
$this->createAttributeFromCollection($this->dbForProject, $id, 'destination');
} catch (Throwable $th) {
Console::warning("'destination' from {$id}: {$th->getMessage()}");
}
break;
2024-07-17 05:52:17 +00:00
case 'schedules':
// Create data attribute
try {
2025-05-16 05:24:11 +00:00
$this->createAttributeFromCollection($this->dbForProject, $id, 'data');
2024-07-17 05:52:17 +00:00
} catch (Throwable $th) {
Console::warning("'data' from {$id}: {$th->getMessage()}");
}
break;
case 'databases':
// Create originalId attribute
try {
2025-05-16 05:24:11 +00:00
$this->createAttributeFromCollection($this->dbForProject, $id, 'originalId');
} catch (Throwable $th) {
Console::warning("'originalId' from {$id}: {$th->getMessage()}");
}
break;
2024-07-17 05:52:17 +00:00
case 'functions':
// Create scopes attribute
try {
2025-05-16 05:24:11 +00:00
$this->createAttributeFromCollection($this->dbForProject, $id, 'scopes');
2024-07-17 05:52:17 +00:00
} catch (Throwable $th) {
Console::warning("'scopes' from {$id}: {$th->getMessage()}");
}
// Create specification attribute
2024-07-22 10:40:05 +00:00
try {
2025-05-16 05:24:11 +00:00
$this->createAttributeFromCollection($this->dbForProject, $id, 'specification');
2024-07-22 10:40:05 +00:00
} catch (Throwable $th) {
Console::warning("'specification' from {$id}: {$th->getMessage()}");
2024-07-22 10:40:05 +00:00
}
2024-07-17 05:52:17 +00:00
break;
case 'executions':
// Create requestMethod index
try {
2025-05-16 05:24:11 +00:00
$this->createIndexFromCollection($this->dbForProject, $id, '_key_requestMethod');
2024-07-17 05:52:17 +00:00
} catch (\Throwable $th) {
Console::warning("'_key_requestMethod' from {$id}: {$th->getMessage()}");
}
// Create requestPath index
try {
2025-05-16 05:24:11 +00:00
$this->createIndexFromCollection($this->dbForProject, $id, '_key_requestPath');
2024-07-17 05:52:17 +00:00
} catch (\Throwable $th) {
Console::warning("'_key_requestPath' from {$id}: {$th->getMessage()}");
}
// Create deployment index
try {
2025-05-16 05:24:11 +00:00
$this->createIndexFromCollection($this->dbForProject, $id, '_key_deployment');
2024-07-17 05:52:17 +00:00
} catch (\Throwable $th) {
Console::warning("'_key_deployment' from {$id}: {$th->getMessage()}");
}
2024-07-24 07:11:48 +00:00
try {
/**
* Create 'scheduledAt' attribute
*/
2025-05-16 05:24:11 +00:00
$this->createAttributeFromCollection($this->dbForProject, $id, 'scheduledAt');
2024-07-24 07:11:48 +00:00
} catch (\Throwable $th) {
Console::warning("'scheduledAt' from {$id}: {$th->getMessage()}");
}
try {
/**
* Create 'scheduleInternalId' attribute
*/
2025-05-16 05:24:11 +00:00
$this->createAttributeFromCollection($this->dbForProject, $id, 'scheduleInternalId');
2024-07-24 07:11:48 +00:00
} catch (\Throwable $th) {
Console::warning("'scheduleInternalId' from {$id}: {$th->getMessage()}");
}
try {
/**
* Create 'scheduleId' attribute
*/
2025-05-16 05:24:11 +00:00
$this->createAttributeFromCollection($this->dbForProject, $id, 'scheduleId');
2024-07-24 07:11:48 +00:00
} catch (\Throwable $th) {
Console::warning("'scheduleId' from {$id}: {$th->getMessage()}");
}
break;
2024-07-17 05:52:17 +00:00
}
usleep(50000);
}
}
/**
* Fix run on each document
*
* @param Document $document
* @return Document
*/
protected function fixDocument(Document $document): Document
{
switch ($document->getCollection()) {
case 'projects':
/**
* Bump version number.
*/
$document->setAttribute('version', '1.6.0');
// Add accessedAt attribute
2024-07-17 06:20:42 +00:00
$document->setAttribute('accessedAt', DateTime::now());
2024-07-17 05:52:17 +00:00
break;
2024-07-22 10:40:05 +00:00
case 'functions':
// Set scopes attribute
if (empty($document->getAttribute('scopes', []))) {
$document->setAttribute('scopes', []);
}
2024-07-22 10:40:05 +00:00
// Set specification attribute
if (empty($document->getAttribute('specification'))) {
$document->setAttribute('specification', APP_COMPUTE_SPECIFICATION_DEFAULT);
}
2024-07-17 05:52:17 +00:00
}
2024-07-22 10:40:05 +00:00
2024-07-17 05:52:17 +00:00
return $document;
}
2024-07-30 20:53:18 +00:00
/**
* Migrating Buckets.
*
* @return void
*/
private function migrateBuckets(): void
2024-07-30 20:53:18 +00:00
{
$this->dbForProject->forEach('buckets', function (Document $bucket) {
2024-07-30 20:53:18 +00:00
$bucketId = 'bucket_' . $bucket['$internalId'];
Console::log("Migrating Bucket {$bucketId} {$bucket->getId()} ({$bucket->getAttribute('name')})");
2024-07-30 21:39:32 +00:00
try {
2025-05-16 05:24:11 +00:00
$this->dbForProject->updateAttribute($bucketId, 'metadata', size: 65534);
} catch (\Throwable $th) {
Console::warning("'metadata' from {$bucketId}: {$th->getMessage()}");
}
try {
$this->createAttributeFromCollection($this->dbForProject, $bucketId, 'transformedAt', 'files');
} catch (\Throwable $th) {
Console::warning("'transformedAt' from {$bucketId}: {$th->getMessage()}");
}
try {
$this->createIndexFromCollection($this->dbForProject, $bucketId, '_key_transformedAt', 'files');
} catch (\Throwable $th) {
Console::warning("'_key_transformedAt' from {$bucketId}: {$th->getMessage()}");
}
try {
2025-05-16 05:24:11 +00:00
$this->dbForProject->purgeCachedCollection($bucketId);
2024-07-30 21:39:32 +00:00
} catch (\Throwable $th) {
Console::warning("purging {$bucketId}: {$th->getMessage()}");
2024-07-30 21:39:32 +00:00
}
});
2024-07-30 20:53:18 +00:00
}
2024-07-17 05:52:17 +00:00
}