@@ -17,6 +17,8 @@ $RootDir = Resolve-Path "$PSScriptRoot\.."
1717$FrontendDir = Join-Path $RootDir " frontend"
1818$BackendDir = Join-Path $RootDir " backend"
1919$ComposeFile = Join-Path $RootDir " docker-compose.yml"
20+ $LogLevel = if ([string ]::IsNullOrWhiteSpace($env: LOG_LEVEL )) { " info" } else { $env: LOG_LEVEL }
21+ $WorkerConcurrency = if ([string ]::IsNullOrWhiteSpace($env: WORKER_CONCURRENCY )) { [Environment ]::ProcessorCount } else { $env: WORKER_CONCURRENCY }
2022
2123function Write-Info { param ($Message ) Write-Host " [info] $Message " - ForegroundColor Cyan }
2224function Write-Warn { param ($Message ) Write-Host " [warn] $Message " - ForegroundColor Yellow }
@@ -26,43 +28,20 @@ function Write-Error { param($Message) Write-Host "[error] $Message" -Foreground
2628if (Get-Command docker - ErrorAction SilentlyContinue) {
2729 Write-Info " Starting postgres/redis via docker compose..."
2830 docker compose -f " $ComposeFile " up - d postgres redis
29-
30- Write-Info " Ensuring notes table exists..."
31- $SqlScript = @"
32- CREATE TABLE IF NOT EXISTS notes (
33- id SERIAL PRIMARY KEY,
34- user_id INTEGER NOT NULL REFERENCES users(id) ON DELETE CASCADE,
35- uploaded_paper_id INTEGER REFERENCES uploaded_papers(id) ON DELETE SET NULL,
36- title VARCHAR(255) NOT NULL,
37- content TEXT,
38- tags JSONB,
39- created_at TIMESTAMP NOT NULL DEFAULT NOW(),
40- updated_at TIMESTAMP NOT NULL DEFAULT NOW()
41- );
42- CREATE INDEX IF NOT EXISTS idx_notes_user_id ON notes(user_id);
43- CREATE INDEX IF NOT EXISTS idx_notes_updated_at ON notes(updated_at DESC);
44- CREATE TABLE IF NOT EXISTS library_folders (
45- id SERIAL PRIMARY KEY,
46- user_id INTEGER NOT NULL REFERENCES users(id) ON DELETE CASCADE,
47- name VARCHAR(120) NOT NULL,
48- color VARCHAR(32),
49- created_at TIMESTAMP NOT NULL DEFAULT NOW(),
50- updated_at TIMESTAMP NOT NULL DEFAULT NOW()
51- );
52- CREATE INDEX IF NOT EXISTS idx_library_folders_user_id ON library_folders(user_id);
53- ALTER TABLE uploaded_papers ADD COLUMN IF NOT EXISTS folder_id INTEGER;
54- DO `$`$
55- BEGIN
56- IF NOT EXISTS (SELECT 1 FROM pg_constraint WHERE conname = 'uploaded_papers_folder_id_fkey') THEN
57- ALTER TABLE uploaded_papers
58- ADD CONSTRAINT uploaded_papers_folder_id_fkey
59- FOREIGN KEY (folder_id) REFERENCES library_folders(id) ON DELETE SET NULL;
60- END IF;
61- END`$`$ ;
62- CREATE INDEX IF NOT EXISTS idx_uploaded_papers_folder_id ON uploaded_papers(folder_id);
63- "@
64-
65- $SqlScript | docker compose -f " $ComposeFile " exec - T postgres psql - U postgres - d papers | Out-Null
31+ Write-Info " Waiting for postgres to become ready..."
32+ $pgReady = $false
33+ for ($i = 1 ; $i -le 30 ; $i ++ ) {
34+ $result = docker compose -f " $ComposeFile " exec - T postgres pg_isready - U postgres - d papers 2> $null
35+ if ($LASTEXITCODE -eq 0 ) {
36+ $pgReady = $true
37+ Write-Info " Postgres is ready."
38+ break
39+ }
40+ Start-Sleep - Seconds 1
41+ }
42+ if (-not $pgReady ) {
43+ Write-Warn " Postgres did not become ready in time; migrations may fail."
44+ }
6645} else {
6746 Write-Warn " docker not found; skipping postgres/redis startup"
6847}
@@ -103,25 +82,30 @@ Write-Info "Starting FastAPI backend on :8000 (New Window)..."
10382$BackendCmd = "
10483 Write-Host 'Starting FastAPI Backend...' -ForegroundColor Cyan;
10584 cd '$BackendDir ';
106- `$ env:POSTGRES_HOST='127.0.0.1 ';
107- `$ env:REDIS_HOST='127.0.0.1 ';
85+ `$ env:POSTGRES_HOST='localhost ';
86+ `$ env:REDIS_HOST='localhost ';
10887 `$ env:PYTHONPATH='$BackendDir ';
88+ `$ env:LOG_LEVEL='$LogLevel ';
10989 uv run alembic upgrade head;
110- uv run uvicorn app.main:app --host 0.0.0.0 --port 8000 --reload;
90+ uv run uvicorn app.main:app --host 0.0.0.0 --port 8000 --reload --log-level `$ env:LOG_LEVEL ;
11191 if (`$ LastExitCode -ne 0) { Read-Host 'Backend exited with error. Press Enter to close...' }
11292"
11393Start-Process powershell - ArgumentList " -NoExit" , " -Command" , " $BackendCmd "
11494
11595# 3.2) Celery Worker
11696Write-Info " Starting Celery worker (MinerU queue) (New Window)..."
117- # Note: Windows requires -P solo (or threads) and we must listen to 'default' queue
97+ # Align with dev.sh: threads pool, concurrency=CPU cores (Windows-safe)
11898$CeleryCmd = "
11999 Write-Host 'Starting Celery Worker...' -ForegroundColor Cyan;
120100 cd '$BackendDir ';
121- `$ env:POSTGRES_HOST='127.0.0.1 ';
122- `$ env:REDIS_HOST='127.0.0.1 ';
101+ `$ env:POSTGRES_HOST='localhost ';
102+ `$ env:REDIS_HOST='localhost ';
123103 `$ env:PYTHONPATH='$BackendDir ';
124- uv run celery -A app.workers.celery_app worker --loglevel=info -P solo -Q default;
104+ `$ env:OBJC_DISABLE_INITIALIZE_FORK_SAFETY='YES';
105+ `$ env:CPU_CORES=[Environment]::ProcessorCount;
106+ `$ env:WORKER_POOL='threads';
107+ `$ env:WORKER_CONCURRENCY='$WorkerConcurrency ';
108+ uv run celery -A app.workers.celery_app worker --loglevel=info --queues default --pool `$ env:WORKER_POOL --concurrency `$ env:WORKER_CONCURRENCY;
125109 if (`$ LastExitCode -ne 0) { Read-Host 'Celery exited with error. Press Enter to close...' }
126110"
127111Start-Process powershell - ArgumentList " -NoExit" , " -Command" , " $CeleryCmd "
0 commit comments