mirror of
https://github.com/comfyanonymous/ComfyUI.git
synced 2025-12-24 05:20:48 +08:00
rework + add test for concurrent AssetInfo delete
This commit is contained in:
parent
cdd8d16075
commit
47f7c7ee8c
@ -379,11 +379,12 @@ async def touch_asset_info_by_id(
|
|||||||
|
|
||||||
|
|
||||||
async def delete_asset_info_by_id(session: AsyncSession, *, asset_info_id: str, owner_id: str) -> bool:
|
async def delete_asset_info_by_id(session: AsyncSession, *, asset_info_id: str, owner_id: str) -> bool:
|
||||||
res = await session.execute(delete(AssetInfo).where(
|
return (
|
||||||
AssetInfo.id == asset_info_id,
|
await session.execute(delete(AssetInfo).where(
|
||||||
visible_owner_clause(owner_id),
|
AssetInfo.id == asset_info_id,
|
||||||
))
|
visible_owner_clause(owner_id),
|
||||||
return bool(res.rowcount)
|
).returning(AssetInfo.id))
|
||||||
|
).scalar_one_or_none() is not None
|
||||||
|
|
||||||
|
|
||||||
async def add_tags_to_asset_info(
|
async def add_tags_to_asset_info(
|
||||||
|
|||||||
@ -1,3 +1,4 @@
|
|||||||
|
import asyncio
|
||||||
import uuid
|
import uuid
|
||||||
|
|
||||||
import aiohttp
|
import aiohttp
|
||||||
@ -177,3 +178,43 @@ async def test_update_requires_at_least_one_field(http: aiohttp.ClientSession, a
|
|||||||
body = await r.json()
|
body = await r.json()
|
||||||
assert r.status == 400
|
assert r.status == 400
|
||||||
assert body["error"]["code"] == "INVALID_BODY"
|
assert body["error"]["code"] == "INVALID_BODY"
|
||||||
|
|
||||||
|
|
||||||
|
@pytest.mark.asyncio
|
||||||
|
@pytest.mark.parametrize("root", ["input", "output"])
|
||||||
|
async def test_concurrent_delete_same_asset_info_single_204(
|
||||||
|
root: str,
|
||||||
|
http: aiohttp.ClientSession,
|
||||||
|
api_base: str,
|
||||||
|
asset_factory,
|
||||||
|
make_asset_bytes,
|
||||||
|
):
|
||||||
|
"""
|
||||||
|
Many concurrent DELETE for the same AssetInfo should result in:
|
||||||
|
- exactly one 204 No Content (the one that actually deleted)
|
||||||
|
- all others 404 Not Found (row already gone)
|
||||||
|
"""
|
||||||
|
scope = f"conc-del-{uuid.uuid4().hex[:6]}"
|
||||||
|
name = "to_delete.bin"
|
||||||
|
data = make_asset_bytes(name, 1536)
|
||||||
|
|
||||||
|
created = await asset_factory(name, [root, "unit-tests", scope], {}, data)
|
||||||
|
aid = created["id"]
|
||||||
|
|
||||||
|
# Hit the same endpoint N times in parallel.
|
||||||
|
n_tests = 4
|
||||||
|
url = f"{api_base}/api/assets/{aid}?delete_content=false"
|
||||||
|
tasks = [asyncio.create_task(http.delete(url)) for _ in range(n_tests)]
|
||||||
|
responses = await asyncio.gather(*tasks)
|
||||||
|
|
||||||
|
statuses = [r.status for r in responses]
|
||||||
|
# Drain bodies to close connections (optional but avoids warnings).
|
||||||
|
await asyncio.gather(*[r.read() for r in responses])
|
||||||
|
|
||||||
|
# Exactly one actual delete, the rest must be 404
|
||||||
|
assert statuses.count(204) == 1, f"Expected exactly one 204; got: {statuses}"
|
||||||
|
assert statuses.count(404) == n_tests - 1, f"Expected {n_tests-1} 404; got: {statuses}"
|
||||||
|
|
||||||
|
# The resource must be gone.
|
||||||
|
async with http.get(f"{api_base}/api/assets/{aid}") as rg:
|
||||||
|
assert rg.status == 404
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user