@echo off rem ============================================================ rem dsh-sync resident worker: PostgreSQL + uvicorn with restart rem loop. Launched detached by start-server.bat, stopped by rem stop-server.bat (stop.flag). rem NOTE: keep this file pure ASCII - cmd.exe misparses UTF-8. rem rem Two rules keep this loop sane (both were learned the hard way): rem 1. Never start uvicorn while :8020 is already served. A second rem worker used to spin, each iteration failing to bind and rem writing two log lines, ~20/s. rem 2. Never use `timeout /t N` here. Detached (no console input) rem it returns after ~1s instead of N seconds, so the loop has rem no real delay. Start-Sleep is used instead. rem ============================================================ cd /d C:\Users\12914\Desktop\dsh set DSH_DATA_DIR=C:\Users\12914\Desktop\dsh\data set DSH_DATABASE_URL=postgresql://dsh@127.0.0.1:15433/postgres set DSH_BOOTSTRAP_ADMIN_TOKEN=74020d5458c05a43e6abca0ddea020b5 set DSH_INVITE_CODE=d4977f261a7e set PYTHONPATH=C:\Users\12914\Desktop\dsh\server set PY=C:\Users\12914\Desktop\dsh\server\.venv\Scripts\python.exe set PGBIN=C:\Users\12914\Desktop\dsh\.pg\bin set PGDATA=C:\Users\12914\Desktop\dsh\.pg\data set DSH_HOST=192.168.5.2 set DSH_PORT=8020 set FAILS=0 if not exist logs mkdir logs rem --- rotate logs so a failing loop cannot fill the disk --- for %%f in (logs\server.log logs\uvicorn.log) do ( if exist %%f if %%~zf GTR 5242880 move /y %%f %%~nf.1%%~xf >nul 2>&1 ) rem --- make sure PostgreSQL is up (once per worker, not per loop) --- if not exist %PGDATA%\base ( echo [%date% %time%] initdb... >> logs\server.log %PGBIN%\initdb.exe -D %PGDATA% -U dsh -A trust -E UTF8 --no-instructions >nul 2>&1 ) %PGBIN%\pg_ctl.exe -D %PGDATA% -o "-p 15433 -c listen_addresses=127.0.0.1" status >nul 2>&1 if errorlevel 1 ( echo [%date% %time%] starting PostgreSQL >> logs\server.log %PGBIN%\pg_ctl.exe -D %PGDATA% -o "-p 15433 -c listen_addresses=127.0.0.1" -l logs\pg.log start >nul 2>&1 powershell -NoProfile -Command "Start-Sleep -Seconds 2" ) :loop if exist stop.flag ( del stop.flag echo [%date% %time%] stop flag received, worker exiting >> logs\server.log goto :eof ) rem --- singleton guard: an already-served port means another worker owns it. rem Match "%DSH_HOST%:%DSH_PORT%" - a bare ":8020" also matches the local Django rem dev stack on 127.0.0.1, which would make this worker idle forever. netstat -ano | findstr /C:"LISTENING" | findstr /C:"%DSH_HOST%:%DSH_PORT% " >nul if not errorlevel 1 ( echo [%date% %time%] port %DSH_PORT% already served, idling >> logs\server.log set FAILS=0 powershell -NoProfile -Command "Start-Sleep -Seconds 20" goto :loop ) echo [%date% %time%] starting uvicorn %DSH_HOST%:%DSH_PORT% >> logs\server.log %PY% -m uvicorn dsh_sync.main:app --host %DSH_HOST% --port %DSH_PORT% >> logs\uvicorn.log 2>&1 echo [%date% %time%] uvicorn exited (code %errorlevel%), restarting >> logs\server.log set /a FAILS+=1 if %FAILS% GEQ 5 ( echo [%date% %time%] %FAILS% consecutive exits, backing off 60s >> logs\server.log powershell -NoProfile -Command "Start-Sleep -Seconds 60" ) else ( powershell -NoProfile -Command "Start-Sleep -Seconds 3" ) goto :loop