fix: Enhance DB queries with async pagination and improve test reliability (#8040)

Co-authored-by: Lucas Oliveira <lucas.edu.oli@hotmail.com>
Co-authored-by: autofix-ci[bot] <114827586+autofix-ci[bot]@users.noreply.github.com>
This commit is contained in:
Cristhian Zanforlin Lousa 2025-05-14 06:19:34 -07:00 • committed by GitHub
commit 183a8c28d9
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
3 changed files with 16 additions and 15 deletions

View file

@ -10,7 +10,7 @@ from fastapi import APIRouter, Depends, File, HTTPException, Response, UploadFil
from fastapi.encoders import jsonable_encoder from fastapi.encoders import jsonable_encoder
from fastapi.responses import StreamingResponse from fastapi.responses import StreamingResponse
from fastapi_pagination import Params from fastapi_pagination import Params
from fastapi_pagination.ext.sqlmodel import paginate from fastapi_pagination.ext.sqlmodel import apaginate
from sqlalchemy import or_, update from sqlalchemy import or_, update
from sqlalchemy.orm import selectinload from sqlalchemy.orm import selectinload
from sqlmodel import select from sqlmodel import select
@ -152,7 +152,7 @@ async def read_project(
stmt = stmt.where(Flow.is_component == False) # noqa: E712 stmt = stmt.where(Flow.is_component == False) # noqa: E712
if search: if search:
stmt = stmt.where(Flow.name.like(f"%{search}%")) # type: ignore[attr-defined] stmt = stmt.where(Flow.name.like(f"%{search}%")) # type: ignore[attr-defined]
paginated_flows = await paginate(session, stmt, params=params) paginated_flows = await apaginate(session, stmt, params=params)
return FolderWithPaginatedFlows(folder=FolderRead.model_validate(project), flows=paginated_flows) return FolderWithPaginatedFlows(folder=FolderRead.model_validate(project), flows=paginated_flows)

View file

@ -11,7 +11,7 @@ from zoneinfo import ZoneInfo
from fastapi import APIRouter, Depends, File, HTTPException, UploadFile from fastapi import APIRouter, Depends, File, HTTPException, UploadFile
from fastapi.responses import StreamingResponse from fastapi.responses import StreamingResponse
from sqlmodel import String, cast, select from sqlmodel import String, cast, col, select
from langflow.api.schemas import UploadFileResponse from langflow.api.schemas import UploadFileResponse
from langflow.api.utils import CurrentActiveUser, DbSession from langflow.api.utils import CurrentActiveUser, DbSession
@ -173,7 +173,7 @@ async def delete_files_batch(
"""Delete multiple files by their IDs.""" """Delete multiple files by their IDs."""
try: try:
# Fetch all files from the DB # Fetch all files from the DB
stmt = select(UserFile).where(UserFile.id in file_ids, UserFile.user_id == current_user.id) stmt = select(UserFile).where(col(UserFile.id).in_(file_ids), col(UserFile.user_id) == current_user.id)
results = await session.exec(stmt) results = await session.exec(stmt)
files = results.all() files = results.all()
@ -206,7 +206,7 @@ async def download_files_batch(
"""Download multiple files as a zip file by their IDs.""" """Download multiple files as a zip file by their IDs."""
try: try:
# Fetch all files from the DB # Fetch all files from the DB
stmt = select(UserFile).where(UserFile.id in file_ids, UserFile.user_id == current_user.id) stmt = select(UserFile).where(col(UserFile.id).in_(file_ids), col(UserFile.user_id) == current_user.id)
results = await session.exec(stmt) results = await session.exec(stmt)
files = results.all() files = results.all()

View file

@ -8,7 +8,7 @@ import { generateRandomFilename } from "../../utils/generate-filename";
// Configure tests to run serially with a delay between each test // Configure tests to run serially with a delay between each test
test( test(
"should navigate to files page and show empty state", "should navigate to files page and show empty state",
{ tag: ["@release", "@files"] }, { tag: ["@release", "@components"] },
async ({ page }) => { async ({ page }) => {
await awaitBootstrapTest(page, { skipModal: true }); await awaitBootstrapTest(page, { skipModal: true });
@ -49,7 +49,7 @@ test(
test( test(
"should upload file using upload button", "should upload file using upload button",
{ tag: ["@release", "@files"] }, { tag: ["@release", "@components"] },
async ({ page }) => { async ({ page }) => {
const fileName = generateRandomFilename(); const fileName = generateRandomFilename();
const testFilePath = path.join(__dirname, "../../assets/test-file.txt"); const testFilePath = path.join(__dirname, "../../assets/test-file.txt");
@ -94,7 +94,7 @@ test(
test( test(
"should upload file using drag and drop", "should upload file using drag and drop",
{ tag: ["@release", "@files"] }, { tag: ["@release", "@components"] },
async ({ page }) => { async ({ page }) => {
const fileName = generateRandomFilename(); const fileName = generateRandomFilename();
@ -150,7 +150,7 @@ test(
test( test(
"should upload multiple files with different types", "should upload multiple files with different types",
{ tag: ["@release", "@files"] }, { tag: ["@release", "@components"] },
async ({ page }) => { async ({ page }) => {
const fileNames = { const fileNames = {
txt: generateRandomFilename(), txt: generateRandomFilename(),
@ -222,7 +222,7 @@ test(
test( test(
"should search uploaded files", "should search uploaded files",
{ tag: ["@release", "@files"] }, { tag: ["@release", "@components"] },
async ({ page }) => { async ({ page }) => {
const fileNames = { const fileNames = {
txt: generateRandomFilename(), txt: generateRandomFilename(),
@ -321,7 +321,7 @@ test(
test( test(
"should handle bulk actions for multiple files", "should handle bulk actions for multiple files",
{ tag: ["@release", "@files"] }, { tag: ["@release", "@components"] },
async ({ page }) => { async ({ page }) => {
const fileNames = { const fileNames = {
txt: generateRandomFilename(), txt: generateRandomFilename(),
@ -421,13 +421,13 @@ test(
const download = await downloadPromise; const download = await downloadPromise;
// Verify the download was initiated // Verify the download was initiated
expect(download).toBeTruthy(); await expect(download).toBeTruthy();
// Check for success message // Check for success message
const downloadSuccessMessage = await page.getByText( const downloadSuccessMessage = await page.getByText(
/Files? downloaded successfully/, /Files? downloaded successfully/,
); );
expect(downloadSuccessMessage).toBeTruthy(); await expect(downloadSuccessMessage).toBeTruthy();
// Select both files (checkbox on the grid) // Select both files (checkbox on the grid)
@ -453,13 +453,14 @@ test(
const deleteSuccessMessage = await page.getByText( const deleteSuccessMessage = await page.getByText(
"Files deleted successfully", "Files deleted successfully",
); );
expect(deleteSuccessMessage).toBeTruthy(); await expect(deleteSuccessMessage).toBeTruthy();
await page.waitForTimeout(500);
// Verify the deleted files are no longer visible // Verify the deleted files are no longer visible
const remainingFileCount = const remainingFileCount =
(await page.getByText(fileNames.py + ".py").count()) + (await page.getByText(fileNames.py + ".py").count()) +
(await page.getByText(fileNames.txt + ".txt").count()) + (await page.getByText(fileNames.txt + ".txt").count()) +
(await page.getByText(fileNames.json + ".json").count()); (await page.getByText(fileNames.json + ".json").count());
expect(remainingFileCount).toBe(1); await expect(remainingFileCount).toBe(1);
}, },
); );