|
| 1 | +import asyncio |
1 | 2 | import logging |
2 | 3 |
|
3 | 4 | from aiohttp import web |
4 | 5 | from servicelib.aiohttp import status |
| 6 | +from servicelib.aiohttp.application_keys import APP_FIRE_AND_FORGET_TASKS_KEY |
| 7 | +from servicelib.utils import fire_and_forget_task |
5 | 8 |
|
6 | 9 | from .._meta import API_VTAG as VTAG |
7 | 10 | from ..exception_handling import ( |
@@ -47,12 +50,23 @@ async def empty_trash(request: web.Request): |
47 | 50 | user_id = get_user_id(request) |
48 | 51 | product_name = products_web.get_product_name(request) |
49 | 52 |
|
50 | | - # NOTE: This handler waits for all deletions to complete before returning. |
51 | | - # We chose this over hiding the project, as that approach is both costlier to implement |
52 | | - # and duplicates the deletion logic. In the worst case, if deletion is too slow, |
53 | | - # the frontend can disconnect sand retry the request. |
54 | | - await _service.safe_empty_trash( |
55 | | - request.app, product_name=product_name, user_id=user_id |
| 53 | + is_fired = asyncio.Event() |
| 54 | + |
| 55 | + fire_and_forget_task( |
| 56 | + _service.safe_empty_trash( |
| 57 | + request.app, |
| 58 | + product_name=product_name, |
| 59 | + user_id=user_id, |
| 60 | + notify_explicit_projects_deleted=is_fired, |
| 61 | + ), |
| 62 | + task_suffix_name="rest.empty_trash", |
| 63 | + fire_and_forget_tasks_collection=request.app[APP_FIRE_AND_FORGET_TASKS_KEY], |
56 | 64 | ) |
57 | 65 |
|
| 66 | + # NOTE: Ensures `fire_and_forget_task` is triggered and deletes explicit projects; |
| 67 | + # otherwise, when the front-end requests the trash item list, |
| 68 | + # it may still display items, misleading the user into |
| 69 | + # thinking the `empty trash` operation failed. |
| 70 | + await is_fired.wait() |
| 71 | + |
58 | 72 | return web.json_response(status=status.HTTP_204_NO_CONTENT) |
0 commit comments