@@ -279,7 +279,7 @@ public static void deleteCategorySyncTestData(@Nonnull final ProjectApiRoot ctpC
279279 * @param ctpClient defines the CTP project to delete the categories from.
280280 */
281281 public static void deleteAllCategories (@ Nonnull final ProjectApiRoot ctpClient ) {
282- final Set <String > keys = new HashSet <>();
282+ final Set <String > deletedIds = new HashSet <>();
283283 final List <Category > categories =
284284 QueryUtils .queryAll (
285285 ctpClient .categories ().get ().addExpand ("ancestors[*]" ), categories1 -> categories1 )
@@ -291,31 +291,28 @@ public static void deleteAllCategories(@Nonnull final ProjectApiRoot ctpClient)
291291 .join ();
292292 categories .forEach (
293293 category -> {
294- final String categoryKey = category .getKey ();
295- if (!hasADeletedAncestor (category , keys )) {
296- ctpClient
297- .categories ()
298- .delete (category )
299- .execute ()
300- .thenAccept (deletedCategory -> keys .add (categoryKey ))
301- .handle (
302- (result , throwable ) -> {
303- if (throwable != null && !(throwable instanceof NotFoundException )) {
304- return throwable ;
305- }
306- return result ;
307- })
308- .toCompletableFuture ()
309- .join ();
294+ final String categoryId = category .getId ();
295+ if (!hasADeletedAncestor (category , deletedIds )) {
296+ try {
297+ ctpClient .categories ().delete (category ).execute ().toCompletableFuture ().join ();
298+ deletedIds .add (categoryId );
299+ } catch (NotFoundException e ) {
300+ // Already deleted, mark as deleted
301+ deletedIds .add (categoryId );
302+ } catch (Exception e ) {
303+ // Ignore - may have been deleted by parent cascade
304+ }
310305 }
311306 });
312307 }
313308
314309 /**
315310 * Deletes categories from CTP projects defined by the {@code ctpClient} that match any of the
316- * supplied slugs in the specified locale. This method is useful for cleaning up categories that
317- * may not have keys set (which prevents them from being properly tracked by {@link
318- * #deleteAllCategories(ProjectApiRoot)}).
311+ * supplied slugs in the specified locale. This method is useful for cleaning up specific
312+ * categories by slug, especially those without keys.
313+ *
314+ * <p>This method handles errors gracefully and will not throw exceptions if categories don't
315+ * exist or have already been deleted.
319316 *
320317 * @param ctpClient defines the CTP project to delete the categories from.
321318 * @param locale the locale to use when matching slugs.
@@ -325,29 +322,37 @@ public static void deleteCategoriesBySlug(
325322 @ Nonnull final ProjectApiRoot ctpClient ,
326323 @ Nonnull final Locale locale ,
327324 @ Nonnull final List <String > slugs ) {
328- slugs .forEach (
329- slug -> {
330- ctpClient
331- .categories ()
332- .get ()
333- .addWhere ("slug(" + locale .getLanguage () + "=:slug)" )
334- .addPredicateVar ("slug" , slug )
335- .execute ()
336- .toCompletableFuture ()
337- .join ()
338- .getBody ()
339- .getResults ()
340- .forEach (
341- category ->
342- ctpClient
343- .categories ()
344- .withId (category .getId ())
345- .delete ()
346- .withVersion (category .getVersion ())
347- .execute ()
348- .toCompletableFuture ()
349- .join ());
350- });
325+ for (String slug : slugs ) {
326+ try {
327+ ctpClient
328+ .categories ()
329+ .get ()
330+ .addWhere ("slug(" + locale .getLanguage () + "=:slug)" )
331+ .addPredicateVar ("slug" , slug )
332+ .execute ()
333+ .toCompletableFuture ()
334+ .join ()
335+ .getBody ()
336+ .getResults ()
337+ .forEach (
338+ cat -> {
339+ try {
340+ ctpClient
341+ .categories ()
342+ .withId (cat .getId ())
343+ .delete ()
344+ .withVersion (cat .getVersion ())
345+ .execute ()
346+ .toCompletableFuture ()
347+ .join ();
348+ } catch (Exception e ) {
349+ // Ignore - already deleted or cascade deleted
350+ }
351+ });
352+ } catch (Exception e ) {
353+ // Ignore - slug doesn't exist
354+ }
355+ }
351356 }
352357
353358 private static List <Category > sortCategoriesByLeastAncestors (
@@ -357,14 +362,14 @@ private static List<Category> sortCategoriesByLeastAncestors(
357362 }
358363
359364 private static boolean hasADeletedAncestor (
360- @ Nonnull final Category category , @ Nonnull final Set <String > keysOfDeletedAncestors ) {
365+ @ Nonnull final Category category , @ Nonnull final Set <String > idsOfDeletedAncestors ) {
361366 final List <CategoryReference > categoryAncestors = category .getAncestors ();
362367 return categoryAncestors .stream ()
363368 .filter (Objects ::nonNull )
364369 .anyMatch (
365370 ancestor ->
366371 ancestor .getObj () != null
367- && keysOfDeletedAncestors .contains (ancestor .getObj ().getKey ()));
372+ && idsOfDeletedAncestors .contains (ancestor .getObj ().getId ()));
368373 }
369374
370375 /**
0 commit comments