Skip to content

Commit b561d0f

Browse files
committed
Improve delete flows
1 parent 4a9535e commit b561d0f

1 file changed

Lines changed: 87 additions & 59 deletions

File tree

src/Database/Database.php

Lines changed: 87 additions & 59 deletions
Original file line numberDiff line numberDiff line change
@@ -1599,9 +1599,9 @@ public function createCollection(string $id, array $attributes = [], array $inde
15991599
} catch (\Throwable $e) {
16001600
if ($created) {
16011601
try {
1602-
$this->adapter->deleteCollection($id);
1603-
} catch (\Throwable $e) {
1604-
// Ignore
1602+
$this->cleanupCollection($id);
1603+
} catch (\Throwable $rollbackError) {
1604+
Console::error("Failed to rollback collection '{$id}': " . $rollbackError->getMessage());
16051605
}
16061606
}
16071607
throw new DatabaseException("Failed to create collection metadata for '{$id}': " . $e->getMessage(), previous: $e);
@@ -2928,18 +2928,9 @@ public function deleteAttribute(string $collection, string $id): bool
29282928

29292929
$this->updateMetadata(
29302930
collection: $collection,
2931-
rollbackOperation: fn () => $this->adapter->createAttribute(
2932-
$collection->getId(),
2933-
$id,
2934-
$attribute['type'],
2935-
$attribute['size'],
2936-
$attribute['signed'] ?? false,
2937-
$attribute['array'] ?? false,
2938-
$attribute['required'] ?? false
2939-
),
2940-
shouldRollback: $shouldRollback,
2941-
operationDescription: "attribute deletion '{$id}'",
2942-
silentRollback: true
2931+
rollbackOperation: null,
2932+
shouldRollback: false,
2933+
operationDescription: "attribute deletion '{$id}'"
29432934
);
29442935

29452936
$this->withRetries(fn () => $this->purgeCachedCollection($collection->getId()));
@@ -3106,6 +3097,66 @@ private function cleanupAttributes(
31063097
return $errors;
31073098
}
31083099

3100+
/**
3101+
* Cleanup (delete) a collection with retry logic
3102+
*
3103+
* @param string $collectionId The collection ID
3104+
* @param int $maxAttempts Maximum retry attempts
3105+
* @return void
3106+
* @throws DatabaseException If cleanup fails after all retries
3107+
*/
3108+
private function cleanupCollection(
3109+
string $collectionId,
3110+
int $maxAttempts = 3
3111+
): void {
3112+
$this->cleanup(
3113+
fn () => $this->adapter->deleteCollection($collectionId),
3114+
'collection',
3115+
$collectionId,
3116+
$maxAttempts
3117+
);
3118+
}
3119+
3120+
/**
3121+
* Cleanup (delete) a relationship with retry logic
3122+
*
3123+
* @param string $collectionId The collection ID
3124+
* @param string $relatedCollectionId The related collection ID
3125+
* @param string $type The relationship type
3126+
* @param bool $twoWay Whether the relationship is two-way
3127+
* @param string $key The relationship key
3128+
* @param string $twoWayKey The two-way relationship key
3129+
* @param string $side The relationship side
3130+
* @param int $maxAttempts Maximum retry attempts
3131+
* @return void
3132+
* @throws DatabaseException If cleanup fails after all retries
3133+
*/
3134+
private function cleanupRelationship(
3135+
string $collectionId,
3136+
string $relatedCollectionId,
3137+
string $type,
3138+
bool $twoWay,
3139+
string $key,
3140+
string $twoWayKey,
3141+
string $side = Database::RELATION_SIDE_PARENT,
3142+
int $maxAttempts = 3
3143+
): void {
3144+
$this->cleanup(
3145+
fn () => $this->adapter->deleteRelationship(
3146+
$collectionId,
3147+
$relatedCollectionId,
3148+
$type,
3149+
$twoWay,
3150+
$key,
3151+
$twoWayKey,
3152+
$side
3153+
),
3154+
'relationship',
3155+
$key,
3156+
$maxAttempts
3157+
);
3158+
}
3159+
31093160
/**
31103161
* Create a relationship attribute
31113162
*
@@ -3199,9 +3250,7 @@ public function createRelationship(
31993250

32003251
$this->checkAttribute($collection, $relationship);
32013252
$this->checkAttribute($relatedCollection, $twoWayRelationship);
3202-
3203-
3204-
// Track junction collection name for rollback
3253+
32053254
$junctionCollection = null;
32063255
if ($type === self::RELATION_MANY_TO_MANY) {
32073256
$junctionCollection = '_' . $collection->getSequence() . '_' . $relatedCollection->getSequence();
@@ -3252,12 +3301,11 @@ public function createRelationship(
32523301
);
32533302

32543303
if (!$created) {
3255-
// Rollback junction table if it was created
32563304
if ($junctionCollection !== null) {
32573305
try {
3258-
$this->silent(fn () => $this->deleteCollection($junctionCollection));
3306+
$this->silent(fn () => $this->cleanupCollection($junctionCollection));
32593307
} catch (\Throwable $e) {
3260-
// Continue to throw the main error
3308+
Console::error("Failed to cleanup junction collection '{$junctionCollection}': " . $e->getMessage());
32613309
}
32623310
}
32633311
throw new DatabaseException('Failed to create relationship');
@@ -3278,7 +3326,7 @@ public function createRelationship(
32783326
$this->rollbackAttributeMetadata($relatedCollection, [$twoWayKey]);
32793327

32803328
try {
3281-
$this->adapter->deleteRelationship(
3329+
$this->cleanupRelationship(
32823330
$collection->getId(),
32833331
$relatedCollection->getId(),
32843332
$type,
@@ -3288,15 +3336,14 @@ public function createRelationship(
32883336
Database::RELATION_SIDE_PARENT
32893337
);
32903338
} catch (\Throwable $e) {
3291-
// Continue to rollback junction table
3339+
Console::error("Failed to cleanup relationship '{$id}': " . $e->getMessage());
32923340
}
32933341

3294-
// Rollback junction table if it was created
32953342
if ($junctionCollection !== null) {
32963343
try {
3297-
$this->deleteCollection($junctionCollection);
3344+
$this->cleanupCollection($junctionCollection);
32983345
} catch (\Throwable $e) {
3299-
// Continue to throw original error
3346+
Console::error("Failed to cleanup junction collection '{$junctionCollection}': " . $e->getMessage());
33003347
}
33013348
}
33023349

@@ -3335,8 +3382,8 @@ public function createRelationship(
33353382
foreach ($indexesCreated as $indexInfo) {
33363383
try {
33373384
$this->deleteIndex($indexInfo['collection'], $indexInfo['index']);
3338-
} catch (\Throwable $e) {
3339-
// Continue rollback
3385+
} catch (\Throwable $cleanupError) {
3386+
Console::error("Failed to cleanup index '{$indexInfo['index']}': " . $cleanupError->getMessage());
33403387
}
33413388
}
33423389

@@ -3350,12 +3397,13 @@ public function createRelationship(
33503397
$relatedCollection->setAttribute('attributes', array_filter($relatedAttributes, fn ($attr) => $attr->getId() !== $twoWayKey));
33513398
$this->updateDocument(self::METADATA, $relatedCollection->getId(), $relatedCollection);
33523399
});
3353-
} catch (\Throwable $e) {
3354-
// Continue rollback
3400+
} catch (\Throwable $cleanupError) {
3401+
Console::error("Failed to cleanup metadata for relationship '{$id}': " . $cleanupError->getMessage());
33553402
}
33563403

3404+
// Cleanup relationship
33573405
try {
3358-
$this->adapter->deleteRelationship(
3406+
$this->cleanupRelationship(
33593407
$collection->getId(),
33603408
$relatedCollection->getId(),
33613409
$type,
@@ -3364,15 +3412,15 @@ public function createRelationship(
33643412
$twoWayKey,
33653413
Database::RELATION_SIDE_PARENT
33663414
);
3367-
} catch (\Throwable $e) {
3368-
// Continue rollback
3415+
} catch (\Throwable $cleanupError) {
3416+
Console::error("Failed to cleanup relationship '{$id}': " . $cleanupError->getMessage());
33693417
}
33703418

33713419
if ($junctionCollection !== null) {
33723420
try {
3373-
$this->deleteCollection($junctionCollection);
3374-
} catch (\Throwable $e) {
3375-
// Continue to throw original error
3421+
$this->cleanupCollection($junctionCollection);
3422+
} catch (\Throwable $cleanupError) {
3423+
Console::error("Failed to cleanup junction collection '{$junctionCollection}': " . $cleanupError->getMessage());
33763424
}
33773425
}
33783426

@@ -3739,18 +3787,6 @@ public function deleteRelationship(string $collection, string $id): bool
37393787
});
37403788
});
37413789
} catch (\Throwable $e) {
3742-
try {
3743-
$this->adapter->createRelationship(
3744-
$collection->getId(),
3745-
$relatedCollection->getId(),
3746-
$type,
3747-
$twoWay,
3748-
$id,
3749-
$twoWayKey
3750-
);
3751-
} catch (\Throwable $e) {
3752-
// Log rollback failure but don't throw - we're already handling an error
3753-
}
37543790
throw new DatabaseException('Failed to persist metadata after retries: ' . $e->getMessage());
37553791
}
37563792

@@ -4043,17 +4079,9 @@ public function deleteIndex(string $collection, string $id): bool
40434079

40444080
$this->updateMetadata(
40454081
collection: $collection,
4046-
rollbackOperation: fn () => $this->adapter->createIndex(
4047-
$collection->getId(),
4048-
$id,
4049-
$indexDeleted['type'],
4050-
$indexDeleted['attributes'],
4051-
$indexDeleted['lengths'] ?? [],
4052-
$indexDeleted['orders'] ?? []
4053-
),
4054-
shouldRollback: $deleted,
4055-
operationDescription: "index deletion '{$id}'",
4056-
silentRollback: true
4082+
rollbackOperation: null,
4083+
shouldRollback: false,
4084+
operationDescription: "index deletion '{$id}'"
40574085
);
40584086

40594087

0 commit comments

Comments
 (0)