diff --git a/data/model/legacy.py b/data/model/legacy.py index 311d566ad..94f799992 100644 --- a/data/model/legacy.py +++ b/data/model/legacy.py @@ -1668,6 +1668,7 @@ def _garbage_collect_storage(storage_id_whitelist): logger.debug('Garbage collecting derived storage from candidates: %s', storage_id_whitelist) with config.app_config['DB_TRANSACTION_FACTORY'](db): # Find out which derived storages will be removed, and add them to the whitelist + # The comma after ImageStorage.id is VERY important, it makes it a tuple, which is a sequence orphaned_from_candidates = list(orphaned_storage_query(ImageStorage.select(ImageStorage.id), storage_id_whitelist, (ImageStorage.id,))) @@ -1707,22 +1708,32 @@ def _garbage_collect_storage(storage_id_whitelist): paths_to_remove = placements_query_to_paths_set(placements_to_remove.clone()) # Remove the placements for orphaned storages - placements_subquery = list(placements_to_remove.clone().select(ImageStoragePlacement.id)) - if len(placements_subquery) > 0: - (ImageStoragePlacement - .delete() - .where(ImageStoragePlacement.id << list(placements_subquery)) - .execute()) + placements_subquery = (placements_to_remove + .clone() + .select(ImageStoragePlacement.id) + .alias('ps')) + inner = (ImageStoragePlacement + .select(placements_subquery.c.id) + .from_(placements_subquery)) + placements_removed = (ImageStoragePlacement + .delete() + .where(ImageStoragePlacement.id << inner) + .execute()) + logger.debug('Removed %s image storage placements', placements_removed) - # Remove the all orphaned storages - orphaned_storages = list(orphaned_storage_query(ImageStorage.select(ImageStorage.id), - storage_id_whitelist, - (ImageStorage.id,))) - if len(orphaned_storages) > 0: - (ImageStorage - .delete() - .where(ImageStorage.id << orphaned_storages) - .execute()) + # Remove all orphaned storages + # The comma after ImageStorage.id is VERY important, it makes it a tuple, which is a sequence + orphaned_storages = orphaned_storage_query(ImageStorage.select(ImageStorage.id), + storage_id_whitelist, + (ImageStorage.id,)).alias('osq') + orphaned_storage_inner = (ImageStorage + .select(orphaned_storages.c.id) + .from_(orphaned_storages)) + storages_removed = (ImageStorage + .delete() + .where(ImageStorage.id << orphaned_storage_inner) + .execute()) + logger.debug('Removed %s image storage records', storages_removed) # We are going to make the conscious decision to not delete image storage blobs inside # transactions.