From c1cbdd95553538e3ad981551fc121a1c9cd4fa20 Mon Sep 17 00:00:00 2001 From: Chinmay Date: Thu, 26 Feb 2026 22:56:38 +0530 Subject: [PATCH 1/2] fix(frontend): update Dockerfile to Node 20, resolve strict build errors and configure 100MB payload limit for BIDS uploads --- apps/frontend/Dockerfile | 3 ++- apps/frontend/next.config.ts | 14 ++++++++++++++ apps/frontend/src/app/_home/UploadButtons.tsx | 5 +---- apps/frontend/src/app/_home/uploadHandlers.ts | 2 ++ apps/frontend/src/services/apiReport.ts | 2 +- 5 files changed, 20 insertions(+), 6 deletions(-) diff --git a/apps/frontend/Dockerfile b/apps/frontend/Dockerfile index a5be6be6..fe33f704 100644 --- a/apps/frontend/Dockerfile +++ b/apps/frontend/Dockerfile @@ -1,5 +1,5 @@ # 1. Install dependencies only when needed -FROM node:18-alpine AS deps +FROM node:20-alpine AS deps WORKDIR /app @@ -35,6 +35,7 @@ COPY --from=builder /app/public ./public COPY --from=builder /app/.next ./.next COPY --from=builder /app/node_modules ./node_modules COPY --from=builder /app/package.json ./package.json +COPY --from=builder /app/next.config.ts ./ # Expose the port Next.js runs on EXPOSE 3000 diff --git a/apps/frontend/next.config.ts b/apps/frontend/next.config.ts index e9ffa308..a726b9e3 100644 --- a/apps/frontend/next.config.ts +++ b/apps/frontend/next.config.ts @@ -2,6 +2,20 @@ import type { NextConfig } from "next"; const nextConfig: NextConfig = { /* config options here */ + experimental: { + serverActions: { + bodySizeLimit: '100mb', + }, + }, + + async rewrites() { + return [ + { + source: '/api/:path*', + destination: 'http://backend:8000/api/:path*' // Routes traffic safely inside the Docker network + } + ]; + } }; export default nextConfig; diff --git a/apps/frontend/src/app/_home/UploadButtons.tsx b/apps/frontend/src/app/_home/UploadButtons.tsx index 5c141393..466e700f 100644 --- a/apps/frontend/src/app/_home/UploadButtons.tsx +++ b/apps/frontend/src/app/_home/UploadButtons.tsx @@ -6,11 +6,8 @@ import { cn } from "@/lib/utils"; import { UploadDataType, UploadModalityType } from "@/enums"; import { Upload as UploadIcon } from "lucide-react"; import { useAppContext } from "@/providers/AppProvider"; -import { findNiftiFile, findRelevantFiles } from "@/utils"; -import { getReport } from "@/services/apiReport"; import { toast } from "sonner"; import { useRouter } from "next/navigation"; -import { IAllRelevantFilesType } from "@/types"; import { handleBidsUpload, handleDicomUpload } from "./uploadHandlers"; type TUploadDataOptions = (typeof UploadDataType)[keyof typeof UploadDataType]; @@ -62,7 +59,7 @@ const UploadButtons = () => { setApiData(data); if ( data.missing_required_parameters && - data.missing_required_parameters.length > 0 + Number(data.missing_required_parameters.length) > 0 ) { toast.info( "Report generated with missing parameters. Please provide the missing values." diff --git a/apps/frontend/src/app/_home/uploadHandlers.ts b/apps/frontend/src/app/_home/uploadHandlers.ts index 32008058..834df114 100644 --- a/apps/frontend/src/app/_home/uploadHandlers.ts +++ b/apps/frontend/src/app/_home/uploadHandlers.ts @@ -61,7 +61,9 @@ const handleBidsUpload = async ({ files: FileList; setIsLoading: (v: boolean) => void; setUploadedFiles: (files: IAllRelevantFilesType) => void; + // eslint-disable-next-line @typescript-eslint/no-explicit-any setUploadConfig: (config: any) => void; + // eslint-disable-next-line @typescript-eslint/no-explicit-any setUpdatedJsonContent: (content: any) => void; setUpdatedJsonFilename: (filename: string) => void; activeModalityTypeOption: UploadModalityType; diff --git a/apps/frontend/src/services/apiReport.ts b/apps/frontend/src/services/apiReport.ts index 1f74606c..4a7d95ea 100644 --- a/apps/frontend/src/services/apiReport.ts +++ b/apps/frontend/src/services/apiReport.ts @@ -2,7 +2,7 @@ import axios from 'axios'; import {IReportApiResponse} from '@/types'; -const API_BASE_URL = `${process.env.NEXT_PUBLIC_API_BASE_URL}/report`; +const API_BASE_URL = `/api/report`; const client = axios.create({ baseURL: API_BASE_URL, From 231d8f7cb4613269aae09929ee28f78de7410c43 Mon Sep 17 00:00:00 2001 From: Chinmay Date: Sun, 1 Mar 2026 22:01:27 +0530 Subject: [PATCH 2/2] perf: optimize DICOM header extraction to prevent O(N) disk I/O on larger datasets --- package/src/pyaslreport/main.py | 21 ++++++++------------- 1 file changed, 8 insertions(+), 13 deletions(-) diff --git a/package/src/pyaslreport/main.py b/package/src/pyaslreport/main.py index 553e7e5e..b9fc3e9c 100644 --- a/package/src/pyaslreport/main.py +++ b/package/src/pyaslreport/main.py @@ -40,6 +40,8 @@ def get_bids_metadata(data): def get_dicom_header(dicom_dir: str): """ Extracts the DICOM header from the provided DICOM files. + Optimized to return immediately upon finding the first valid DICOM file, preventing unnecessary O(N) disk I/O on large medical datasets. + :param dicom_dir: Directory containing DICOM files. :return: DICOM header from the first valid DICOM file found. """ @@ -47,23 +49,16 @@ def get_dicom_header(dicom_dir: str): all_files = [f for f in os.listdir(dicom_dir) if os.path.isfile(os.path.join(dicom_dir, f))] # Try to find DICOM files by attempting to read them with pydicom - dcm_files = [] for file in all_files: file_path = os.path.join(dicom_dir, file) try: - # Try to read the file as DICOM - pydicom.dcmread(file_path, stop_before_pixels=True) - dcm_files.append(file) + # Try to read the file as DICOM and return immediately if successful + dcm_header = pydicom.dcmread(file_path, stop_before_pixels=True) + log.info(f"Successfully extracted DICOM header from {file}") + return dcm_header except (InvalidDicomError, OSError, PermissionError): # File is not a valid DICOM file or cannot be read continue - - log.info(f"Found {len(dcm_files)} DICOM files in {dicom_dir}") - - if not dcm_files: - raise ValueError(f"No DICOM files found in directory: {dicom_dir}") - - # Read the first valid DICOM file - dcm_header = pydicom.dcmread(os.path.join(dicom_dir, dcm_files[0])) - return dcm_header \ No newline at end of file + log.error(f"No valid DICOM files found in directory: {dicom_dir}") + raise ValueError(f"No DICOM files found in directory: {dicom_dir}") \ No newline at end of file