Skip to content

Commit 1aef610

Browse files
committed
batch delete folders
1 parent fa58e81 commit 1aef610

File tree

3 files changed

+53
-5
lines changed

3 files changed

+53
-5
lines changed

services/web/server/src/simcore_service_webserver/folders/_folders_repository.py

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -266,7 +266,7 @@ async def list_trashed_folders(
266266
*,
267267
# filter
268268
trashed_explicitly: bool | UnSet = UnSet.VALUE,
269-
trashed_until: datetime | UnSet = UnSet.VALUE,
269+
trashed_before: datetime | UnSet = UnSet.VALUE,
270270
# pagination
271271
offset: NonNegativeInt,
272272
limit: int,
@@ -285,9 +285,9 @@ async def list_trashed_folders(
285285
folders_v2.c.trashed_explicitly.is_(trashed_explicitly)
286286
)
287287

288-
if is_set(trashed_until):
289-
assert isinstance(trashed_until, datetime) # nosec
290-
base_query = base_query.where(folders_v2.c.trashed < trashed_until)
288+
if is_set(trashed_before):
289+
assert isinstance(trashed_before, datetime) # nosec
290+
base_query = base_query.where(folders_v2.c.trashed < trashed_before)
291291

292292
# Select total count from base_query
293293
count_query = select(func.count()).select_from(base_query.subquery())

services/web/server/src/simcore_service_webserver/folders/_trash_service.py

Lines changed: 45 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@
1919
from ..projects._trash_service import trash_project, untrash_project
2020
from ..workspaces.api import check_user_workspace_access
2121
from . import _folders_repository, _folders_service
22-
from .errors import FolderNotTrashedError
22+
from .errors import FolderBatchDeleteError, FolderNotTrashedError
2323

2424
_logger = logging.getLogger(__name__)
2525

@@ -278,3 +278,47 @@ async def delete_trashed_folder(
278278
await _folders_service.delete_folder(
279279
app, user_id=user_id, folder_id=folder_id, product_name=product_name
280280
)
281+
282+
283+
async def batch_delete_trashed_folders_as_admin(
284+
app: web.Application,
285+
trashed_before: datetime,
286+
*,
287+
product_name: ProductName,
288+
fail_fast: bool,
289+
) -> None:
290+
"""
291+
Raises:
292+
FolderBatchDeleteError: if error and fail_fast=False
293+
Exception: any other exception during delete_recursively
294+
"""
295+
296+
for page_params in iter_pagination_params(limit=MAXIMUM_NUMBER_OF_ITEMS_PER_PAGE):
297+
(
298+
page_params.total_number_of_items,
299+
expired_trashed_folders,
300+
) = await _folders_repository.list_trashed_folders(
301+
app,
302+
trashed_explicitly=True,
303+
trashed_before=trashed_before,
304+
offset=page_params.offset,
305+
limit=page_params.limit,
306+
order_by=OrderBy(field=IDStr("trashed"), direction=OrderDirection.ASC),
307+
)
308+
309+
# batch delete
310+
errors: list[tuple[FolderID, Exception]] = []
311+
for folder in expired_trashed_folders:
312+
try:
313+
await _folders_repository.delete_recursively(
314+
app, folder_id=folder.folder_id, product_name=product_name
315+
)
316+
except Exception as err: # pylint: disable=broad-exception-caught
317+
if fail_fast:
318+
raise
319+
errors.append((folder.folder_id, err))
320+
321+
if errors:
322+
raise FolderBatchDeleteError(
323+
errors=errors, trashed_before=trashed_before, product_name=product_name
324+
)

services/web/server/src/simcore_service_webserver/folders/errors.py

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,3 +29,7 @@ class FolderNotTrashedError(FoldersRuntimeError):
2929
msg_template = (
3030
"Cannot delete folder {folder_id} since it was not trashed first: {reason}"
3131
)
32+
33+
34+
class FolderBatchDeleteError(FoldersRuntimeError):
35+
msg_template = "One or more folders could not be deleted: {errors}"

0 commit comments

Comments
 (0)