@@ -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