Skip to content
Merged
182 changes: 117 additions & 65 deletions src/Migration/Destinations/Appwrite.php
Original file line number Diff line number Diff line change
Expand Up @@ -481,12 +481,14 @@ protected function createDatabase(Database $resource): bool
$validator = new UID();

if (!$validator->isValid($resource->getId())) {
throw new Exception(
$resource->setStatus(Resource::STATUS_ERROR, $validator->getDescription());
$this->addError(new Exception(
resourceName: $resource->getName(),
resourceGroup: $resource->getGroup(),
resourceId: $resource->getId(),
message: $validator->getDescription(),
);
));
return false;
}

$createdAt = $this->normalizeDateTime($resource->getCreatedAt());
Expand Down Expand Up @@ -579,12 +581,14 @@ protected function createEntity(Table $resource): bool
$validator = new UID();

if (!$validator->isValid($resource->getId())) {
throw new Exception(
$resource->setStatus(Resource::STATUS_ERROR, $validator->getDescription());
$this->addError(new Exception(
resourceName: $resource->getName(),
resourceGroup: $resource->getGroup(),
resourceId: $resource->getId(),
message: $validator->getDescription(),
);
));
return false;
}

$database = $this->dbForProject->getDocument(
Expand All @@ -593,12 +597,14 @@ protected function createEntity(Table $resource): bool
);

if ($database->isEmpty()) {
throw new Exception(
$resource->setStatus(Resource::STATUS_ERROR, 'Database not found');
$this->addError(new Exception(
resourceName: $resource->getName(),
resourceGroup: $resource->getGroup(),
resourceId: $resource->getId(),
message: 'Database not found',
);
));
return false;
}

$createdAt = $this->normalizeDateTime($resource->getCreatedAt());
Expand Down Expand Up @@ -724,12 +730,14 @@ protected function createField(Column|Attribute $resource): bool
);

if ($database->isEmpty()) {
throw new Exception(
$resource->setStatus(Resource::STATUS_ERROR, 'Database not found');
$this->addError(new Exception(
resourceName: $resource->getName(),
resourceGroup: $resource->getGroup(),
resourceId: $resource->getId(),
message: 'Database not found',
);
));
return false;
}

$table = $this->dbForProject->getDocument(
Expand All @@ -738,41 +746,49 @@ protected function createField(Column|Attribute $resource): bool
);

if ($table->isEmpty()) {
throw new Exception(
$resource->setStatus(Resource::STATUS_ERROR, 'Table not found');
$this->addError(new Exception(
resourceName: $resource->getName(),
resourceGroup: $resource->getGroup(),
resourceId: $resource->getId(),
message: 'Table not found',
);
));
return false;
}

if (!empty($resource->getFormat())) {
if (!Structure::hasFormat($resource->getFormat(), $type)) {
throw new Exception(
$resource->setStatus(Resource::STATUS_ERROR, "Format {$resource->getFormat()} not available for column type {$type}");
$this->addError(new Exception(
resourceName: $resource->getName(),
resourceGroup: $resource->getGroup(),
resourceId: $resource->getId(),
message: "Format {$resource->getFormat()} not available for column type {$type}",
);
));
return false;
}
}

if ($resource->isRequired() && $resource->getDefault() !== null) {
throw new Exception(
$resource->setStatus(Resource::STATUS_ERROR, 'Cannot set default value for required column');
$this->addError(new Exception(
resourceName: $resource->getName(),
resourceGroup: $resource->getGroup(),
resourceId: $resource->getId(),
message: 'Cannot set default value for required column',
);
));
return false;
}

if ($resource->isArray() && $resource->getDefault() !== null) {
throw new Exception(
$resource->setStatus(Resource::STATUS_ERROR, 'Cannot set default value for array column');
$this->addError(new Exception(
resourceName: $resource->getName(),
resourceGroup: $resource->getGroup(),
resourceId: $resource->getId(),
message: 'Cannot set default value for array column',
);
));
return false;
}

if ($type === UtopiaDatabase::VAR_RELATIONSHIP) {
Expand All @@ -782,12 +798,14 @@ protected function createField(Column|Attribute $resource): bool
$resource->getOptions()['relatedCollection']
);
if ($relatedTable->isEmpty()) {
throw new Exception(
$resource->setStatus(Resource::STATUS_ERROR, 'Related table not found');
$this->addError(new Exception(
resourceName: $resource->getName(),
resourceGroup: $resource->getGroup(),
resourceId: $resource->getId(),
message: 'Related table not found',
);
));
return false;
}
}

Expand Down Expand Up @@ -872,20 +890,26 @@ protected function createField(Column|Attribute $resource): bool
$this->dbForProject->checkAttribute($table, $column);

$column = $this->dbForProject->createDocument(self::META_ATTRIBUTES, $column);
} catch (DuplicateException) {
throw new Exception(
} catch (DuplicateException $e) {
$resource->setStatus(Resource::STATUS_ERROR, 'Attribute already exists');
$this->addError(new Exception(
resourceName: $resource->getName(),
resourceGroup: $resource->getGroup(),
resourceId: $resource->getId(),
message: 'Attribute already exists',
);
} catch (LimitException) {
throw new Exception(
previous: $e,
));
return false;
} catch (LimitException $e) {
$resource->setStatus(Resource::STATUS_ERROR, 'Attribute limit exceeded');
$this->addError(new Exception(
resourceName: $resource->getName(),
resourceGroup: $resource->getGroup(),
resourceId: $resource->getId(),
message: 'Attribute limit exceeded',
);
previous: $e,
));
return false;
} catch (\Throwable $e) {
$this->purgeTableCaches($database, $table, $dbForDatabases);
throw $e;
Expand Down Expand Up @@ -927,24 +951,30 @@ protected function createField(Column|Attribute $resource): bool

$this->dbForProject->createDocument(self::META_ATTRIBUTES, $twoWayAttribute);
$this->trackOrphanCandidate($database, $relatedTable, 'attributeKeys', $twoWayKey, $dbForDatabases);
} catch (DuplicateException) {
} catch (DuplicateException $e) {
$this->dbForProject->deleteDocument(self::META_ATTRIBUTES, $column->getId());

throw new Exception(
$resource->setStatus(Resource::STATUS_ERROR, 'Attribute already exists');
$this->addError(new Exception(
resourceName: $resource->getName(),
resourceGroup: $resource->getGroup(),
resourceId: $resource->getId(),
message: 'Attribute already exists',
);
} catch (LimitException) {
previous: $e,
));
return false;
} catch (LimitException $e) {
$this->dbForProject->deleteDocument(self::META_ATTRIBUTES, $column->getId());

throw new Exception(
$resource->setStatus(Resource::STATUS_ERROR, 'Attribute limit exceeded');
$this->addError(new Exception(
resourceName: $resource->getName(),
resourceGroup: $resource->getGroup(),
resourceId: $resource->getId(),
message: 'Attribute limit exceeded',
);
previous: $e,
));
return false;
} catch (\Throwable $e) {
$this->purgeTableCaches($database, $relatedTable, $dbForDatabases);
throw $e;
Expand Down Expand Up @@ -989,19 +1019,14 @@ protected function createField(Column|Attribute $resource): bool
throw new \Exception('Failed to create Column', Exception::CODE_INTERNAL);
}
}
} catch (\Throwable) {
} catch (\Throwable $e) {
$this->dbForProject->deleteDocument(self::META_ATTRIBUTES, $column->getId());

if (isset($twoWayAttribute)) {
$this->dbForProject->deleteDocument(self::META_ATTRIBUTES, $twoWayAttribute->getId());
}

throw new Exception(
resourceName: $resource->getName(),
resourceGroup: $resource->getGroup(),
resourceId: $resource->getId(),
message: 'Failed to create column',
);
throw $e;
}

if ($type === UtopiaDatabase::VAR_RELATIONSHIP && $options['twoWay']) {
Expand Down Expand Up @@ -1029,25 +1054,29 @@ protected function createIndex(Index $resource): bool
$resource->getTable()->getDatabase()->getId(),
);
if ($database->isEmpty()) {
throw new Exception(
$resource->setStatus(Resource::STATUS_ERROR, 'Database not found');
$this->addError(new Exception(
resourceName: $resource->getName(),
resourceGroup: $resource->getGroup(),
resourceId: $resource->getId(),
message: 'Database not found',
);
));
return false;
}

$table = $this->dbForProject->getDocument(
$this->databaseCollectionId($database),
$resource->getTable()->getId(),
);
if ($table->isEmpty()) {
throw new Exception(
$resource->setStatus(Resource::STATUS_ERROR, 'Table not found');
$this->addError(new Exception(
resourceName: $resource->getName(),
resourceGroup: $resource->getGroup(),
resourceId: $resource->getId(),
message: 'Table not found',
);
));
return false;
}
$dbForDatabases = ($this->getDatabasesDB)($database);

Expand Down Expand Up @@ -1101,12 +1130,14 @@ protected function createIndex(Index $resource): bool
], $dbForDatabases->getLimitForIndexes());

if ($count >= $dbForDatabases->getLimitForIndexes()) {
throw new Exception(
$resource->setStatus(Resource::STATUS_ERROR, 'Index limit reached for table');
$this->addError(new Exception(
resourceName: $resource->getName(),
resourceGroup: $resource->getGroup(),
resourceId: $resource->getId(),
message: 'Index limit reached for table',
);
));
return false;
}

// Lengths hidden by default
Expand Down Expand Up @@ -1159,12 +1190,14 @@ protected function createIndex(Index $resource): bool
);

if (!$validator->isValid($index)) {
throw new Exception(
$resource->setStatus(Resource::STATUS_ERROR, 'Invalid index: ' . $validator->getDescription());
$this->addError(new Exception(
resourceName: $resource->getName(),
resourceGroup: $resource->getGroup(),
resourceId: $resource->getId(),
message: 'Invalid index: ' . $validator->getDescription(),
);
));
return false;
}

$index = $this->dbForProject->createDocument(self::META_INDEXES, $index);
Expand All @@ -1190,12 +1223,7 @@ protected function createIndex(Index $resource): bool
} catch (\Throwable $th) {
$this->dbForProject->deleteDocument(self::META_INDEXES, $index->getId());

throw new Exception(
resourceName: $resource->getName(),
resourceGroup: $resource->getGroup(),
resourceId: $resource->getId(),
message: 'Failed to create index',
);
throw $th;
}
Comment thread
premtsd-code marked this conversation as resolved.

$this->dbForProject->purgeCachedDocument($this->databaseCollectionId($database), $table->getId());
Expand All @@ -1218,12 +1246,14 @@ protected function createRecord(Row $resource, bool $isLast): bool
$validator = new UID();

if (!$validator->isValid($resource->getId())) {
throw new Exception(
$resource->setStatus(Resource::STATUS_ERROR, $validator->getDescription());
$this->addError(new Exception(
resourceName: $resource->getName(),
resourceGroup: $resource->getGroup(),
resourceId: $resource->getId(),
message: $validator->getDescription(),
);
));
return false;
}

// Check if document has already been created
Expand Down Expand Up @@ -1318,19 +1348,41 @@ protected function createRecord(Row $resource, bool $isLast): bool
}
$collectionId = $this->tableCollectionId($database, $table);

match ($this->onDuplicate) {
OnDuplicate::Overwrite => $dbForDatabases->skipRelationshipsExistCheck(
fn () => $dbForDatabases->upsertDocuments($collectionId, $this->rowBuffer)
),
OnDuplicate::Skip => $dbForDatabases->skipDuplicates(
fn () => $dbForDatabases->skipRelationshipsExistCheck(
try {
match ($this->onDuplicate) {
OnDuplicate::Overwrite => $dbForDatabases->skipRelationshipsExistCheck(
fn () => $dbForDatabases->upsertDocuments($collectionId, $this->rowBuffer)
),
OnDuplicate::Skip => $dbForDatabases->skipDuplicates(
fn () => $dbForDatabases->skipRelationshipsExistCheck(
fn () => $dbForDatabases->createDocuments($collectionId, $this->rowBuffer)
)
),
OnDuplicate::Fail => $dbForDatabases->skipRelationshipsExistCheck(
fn () => $dbForDatabases->createDocuments($collectionId, $this->rowBuffer)
)
),
OnDuplicate::Fail => $dbForDatabases->skipRelationshipsExistCheck(
fn () => $dbForDatabases->createDocuments($collectionId, $this->rowBuffer)
),
};
),
};
} catch (DuplicateException $e) {
$resource->setStatus(Resource::STATUS_ERROR, 'Document already exists');
$this->addError(new Exception(
resourceName: $resource->getName(),
resourceGroup: $resource->getGroup(),
resourceId: $resource->getId(),
message: 'Document already exists',
previous: $e,
));
return false;
} catch (StructureException $e) {
$resource->setStatus(Resource::STATUS_ERROR, $e->getMessage());
$this->addError(new Exception(
resourceName: $resource->getName(),
resourceGroup: $resource->getGroup(),
resourceId: $resource->getId(),
message: $e->getMessage(),
previous: $e,
));
return false;
Comment thread
greptile-apps[bot] marked this conversation as resolved.
}
} finally {
$this->rowBuffer = [];
}
Expand Down
Loading