File size: 5,490 Bytes
371efe0
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
@echo off
setlocal EnableExtensions DisableDelayedExpansion

set "SCRIPT_DIR=%~dp0"
if "%SCRIPT_DIR:~-1%"=="\" set "SCRIPT_DIR=%SCRIPT_DIR:~0,-1%"
set "REPO_ROOT=%SCRIPT_DIR%"
set "FRONTEND_DIR=%REPO_ROOT%\frontend"

set "DEFAULT_BACKEND_PORT=8000"
set "DEFAULT_FRONTEND_PORT=3001"
set "MAX_FRONTEND_SCAN=25"
set "BACKEND_HEALTH_PATH=/health"

set "MODE=%~1"
if /I "%MODE%"=="backend" goto :backend_mode
if /I "%MODE%"=="frontend" goto :frontend_mode
if /I "%MODE%"=="help" goto :usage
if /I "%MODE%"=="-h" goto :usage
if /I "%MODE%"=="--help" goto :usage

set "BACKEND_PORT=%DEFAULT_BACKEND_PORT%"
set "FRONTEND_PORT=%DEFAULT_FRONTEND_PORT%"
if not "%~1"=="" set "BACKEND_PORT=%~1"
if not "%~2"=="" set "FRONTEND_PORT=%~2"

if not exist "%REPO_ROOT%\api.py" (
  echo [ERROR] api.py not found. Run this script from the repository root.
  exit /b 1
)

if not exist "%FRONTEND_DIR%\package.json" (
  echo [ERROR] frontend\package.json not found.
  exit /b 1
)

set "BACKEND_ALREADY_RUNNING=0"
call :is_port_in_use %BACKEND_PORT%
if errorlevel 1 (
  echo [INFO] Starting backend API window...
  start "openLLMbenchmark API" "%ComSpec%" /k call "%~f0" backend %BACKEND_PORT%
  call :wait_for_backend_healthy %BACKEND_PORT%
  if errorlevel 1 (
    echo [WARN] Backend did not become healthy on port %BACKEND_PORT%.
    echo [WARN] Check backend window logs. Missing deps/env can cause startup failures.
  )
) else (
  set "BACKEND_ALREADY_RUNNING=1"
  echo [INFO] Backend port %BACKEND_PORT% is already in use. Reusing existing backend.
  call :is_backend_healthy %BACKEND_PORT%
  if errorlevel 1 (
    echo [WARN] Port %BACKEND_PORT% is listening but %BACKEND_HEALTH_PATH% did not return API health.
    echo [WARN] If this is not the benchmark API, stop that process or use another backend port.
  )
)

set /a "SCAN_COUNT=0"
:find_frontend_port
call :is_port_in_use %FRONTEND_PORT%
if not errorlevel 1 (
  set /a "SCAN_COUNT+=1"
  if %SCAN_COUNT% GTR %MAX_FRONTEND_SCAN% (
    echo [ERROR] Could not find a free frontend port after %MAX_FRONTEND_SCAN% attempts.
    echo [INFO] Try: run_local_stack.bat %BACKEND_PORT% 3100
    exit /b 1
  )
  set /a "FRONTEND_PORT+=1"
  goto :find_frontend_port
)

echo [INFO] Starting frontend UI window...
start "openLLMbenchmark UI" "%ComSpec%" /k call "%~f0" frontend %BACKEND_PORT% %FRONTEND_PORT%
timeout /t 2 /nobreak >nul
call :is_port_in_use %FRONTEND_PORT%
if errorlevel 1 (
  echo [WARN] Frontend did not open port %FRONTEND_PORT% yet. Check the frontend window for errors.
)

echo [OK] Services launched.
if "%BACKEND_ALREADY_RUNNING%"=="1" (
  echo [OK] Backend: reused existing instance on port %BACKEND_PORT%.
)
echo [OK] API docs: http://localhost:%BACKEND_PORT%/docs
echo [OK] API health: http://localhost:%BACKEND_PORT%%BACKEND_HEALTH_PATH%
echo [OK] UI:       http://localhost:%FRONTEND_PORT%
echo.
echo Optional usage:
echo   run_local_stack.bat                     ^(defaults: 8000 / 3001^)
echo   run_local_stack.bat 8001 3002           ^(custom ports^)
echo   run_local_stack.bat backend 8000        ^(backend only^)
echo   run_local_stack.bat frontend 8000 3001  ^(frontend only^)
exit /b 0

:backend_mode
set "BACKEND_PORT=%DEFAULT_BACKEND_PORT%"
if not "%~2"=="" set "BACKEND_PORT=%~2"

cd /d "%REPO_ROOT%"

where python >nul 2>&1
if errorlevel 1 (
  echo [ERROR] python is not available on PATH.
  exit /b 1
)

echo [INFO] Backend starting on port %BACKEND_PORT%...
python -m uvicorn api:app --host 0.0.0.0 --port %BACKEND_PORT%
exit /b %ERRORLEVEL%

:frontend_mode
set "BACKEND_PORT=%DEFAULT_BACKEND_PORT%"
set "FRONTEND_PORT=%DEFAULT_FRONTEND_PORT%"
if not "%~2"=="" set "BACKEND_PORT=%~2"
if not "%~3"=="" set "FRONTEND_PORT=%~3"
set "NEXT_PUBLIC_API_BASE_URL=http://127.0.0.1:%BACKEND_PORT%"

if not exist "%FRONTEND_DIR%\package.json" (
  echo [ERROR] frontend\package.json not found.
  exit /b 1
)

where npm >nul 2>&1
if errorlevel 1 (
  echo [ERROR] npm is not available on PATH.
  exit /b 1
)

cd /d "%FRONTEND_DIR%"

if not exist "node_modules" (
  echo [INFO] Installing frontend dependencies...
  if exist "package-lock.json" (
    call npm ci
  ) else (
    call npm install
  )
  if errorlevel 1 (
    echo [ERROR] Frontend dependency installation failed.
    exit /b 1
  )
)

echo [INFO] Frontend starting on port %FRONTEND_PORT%...
echo [INFO] API base URL: %NEXT_PUBLIC_API_BASE_URL%
call npm run dev -- -p %FRONTEND_PORT%
exit /b %ERRORLEVEL%

:usage
echo Usage:
echo   run_local_stack.bat
echo   run_local_stack.bat [backend_port] [frontend_port]
echo   run_local_stack.bat backend [backend_port]
echo   run_local_stack.bat frontend [backend_port] [frontend_port]
exit /b 0

:is_port_in_use
set "PORT_TO_CHECK=%~1"
powershell -NoProfile -Command ^
  "$p=%PORT_TO_CHECK%; if (Get-NetTCPConnection -State Listen -LocalPort $p -ErrorAction SilentlyContinue) { exit 0 } else { exit 1 }" >nul 2>&1
exit /b %ERRORLEVEL%

:is_backend_healthy
set "PORT_TO_CHECK=%~1"
powershell -NoProfile -Command ^
  "$url='http://127.0.0.1:%PORT_TO_CHECK%%BACKEND_HEALTH_PATH%'; try { $r=Invoke-RestMethod -Uri $url -TimeoutSec 2; if ($r.status -eq 'ok') { exit 0 } } catch {}; exit 1" >nul 2>&1
exit /b %ERRORLEVEL%

:wait_for_backend_healthy
set "PORT_TO_CHECK=%~1"
set /a "HEALTH_CHECK_COUNT=0"
:wait_for_backend_healthy_loop
call :is_backend_healthy %PORT_TO_CHECK%
if not errorlevel 1 exit /b 0
set /a "HEALTH_CHECK_COUNT+=1"
if %HEALTH_CHECK_COUNT% GEQ 20 exit /b 1
timeout /t 1 /nobreak >nul
goto :wait_for_backend_healthy_loop