Performance Optimization: Replace synchronous file upload read with async aiofiles

Co-authored-by: christianlouis <361235+christianlouis@users.noreply.github.com>
This commit is contained in:
google-labs-jules[bot]
2026-03-16 09:36:33 +00:00
parent 2732dafba9
commit b290cffb98
3 changed files with 6 additions and 4 deletions
+4 -3
View File
@@ -1,3 +1,4 @@
import aiofiles
""" """
File-related API endpoints File-related API endpoints
""" """
@@ -1277,7 +1278,7 @@ async def ui_upload(request: Request, db: DbSession, file: UploadFile = File(...
# enforcing the size limit during the read so memory usage stays bounded. # enforcing the size limit during the read so memory usage stays bounded.
try: try:
written_size = 0 written_size = 0
with open(target_path, "wb") as f: async with aiofiles.open(target_path, "wb") as f:
chunk_size = 65536 # 64 KB chunks chunk_size = 65536 # 64 KB chunks
while True: while True:
chunk = await file.read(chunk_size) chunk = await file.read(chunk_size)
@@ -1286,14 +1287,14 @@ async def ui_upload(request: Request, db: DbSession, file: UploadFile = File(...
written_size += len(chunk) written_size += len(chunk)
if written_size > max_size: if written_size > max_size:
# Exceeded limit mid-stream; clean up and reject # Exceeded limit mid-stream; clean up and reject
f.close() await f.close()
os.remove(target_path) os.remove(target_path)
raise HTTPException( raise HTTPException(
status_code=413, status_code=413,
detail=f"File too large: exceeded {max_size} bytes during upload. " detail=f"File too large: exceeded {max_size} bytes during upload. "
f"See SECURITY_AUDIT.md for configuration details.", f"See SECURITY_AUDIT.md for configuration details.",
) )
f.write(chunk) await f.write(chunk)
except HTTPException: except HTTPException:
raise raise
except Exception as e: except Exception as e:
+1
View File
@@ -58,3 +58,4 @@ sentry-sdk[fastapi,celery,sqlalchemy]>=2.20.0,<3.0.0
# GraphQL API # GraphQL API
strawberry-graphql[fastapi]>=0.243.0,<1.0.0 strawberry-graphql[fastapi]>=0.243.0,<1.0.0
aiofiles>=24.1.0 # Asynchronous file I/O support
+1 -1
View File
@@ -345,7 +345,7 @@ class TestUploadErrorHandling:
def test_upload_disk_write_failure(self, client: TestClient): def test_upload_disk_write_failure(self, client: TestClient):
"""Test handling of disk write failures.""" """Test handling of disk write failures."""
with patch("builtins.open", side_effect=IOError("Disk full")): with patch("aiofiles.open", side_effect=IOError("Disk full")):
pdf_content = b"%PDF-1.4\n%EOF" pdf_content = b"%PDF-1.4\n%EOF"
response = client.post( response = client.post(