spacexerq 1 тиждень тому
батько
коміт
8ce57f5c79
4 змінених файлів з 45 додано та 17 видалено
  1. 5 1
      services/orchestrator/Dockerfile
  2. 18 1
      services/orchestrator/orchestrator/main.py
  3. 3 3
      start.bat
  4. 19 12
      start.ps1

+ 5 - 1
services/orchestrator/Dockerfile

@@ -3,7 +3,11 @@ FROM python:3.12-slim
 WORKDIR /app
 WORKDIR /app
 
 
 ENV PYTHONDONTWRITEBYTECODE=1 \
 ENV PYTHONDONTWRITEBYTECODE=1 \
-    PYTHONUNBUFFERED=1
+    PYTHONUNBUFFERED=1 \
+    PYTHONIOENCODING=utf-8 \
+    PYTHONUTF8=1 \
+    LANG=C.UTF-8 \
+    LC_ALL=C.UTF-8
 
 
 RUN apt-get update && apt-get install -y --no-install-recommends curl \
 RUN apt-get update && apt-get install -y --no-install-recommends curl \
     && rm -rf /var/lib/apt/lists/*
     && rm -rf /var/lib/apt/lists/*

+ 18 - 1
services/orchestrator/orchestrator/main.py

@@ -4,7 +4,23 @@ import os
 import threading
 import threading
 from typing import Any, Dict, Optional
 from typing import Any, Dict, Optional
 from fastapi import FastAPI, File, Form, HTTPException, Query, UploadFile
 from fastapi import FastAPI, File, Form, HTTPException, Query, UploadFile
+from fastapi.responses import JSONResponse
 from pydantic import BaseModel
 from pydantic import BaseModel
+
+
+class _UTF8JSONResponse(JSONResponse):
+    """FastAPI's default JSONResponse uses ensure_ascii=True, which escapes
+    Cyrillic and other non-ASCII characters to \\uXXXX sequences.
+    This subclass disables that so error messages stay human-readable."""
+
+    def render(self, content: Any) -> bytes:
+        return json.dumps(
+            content,
+            ensure_ascii=False,
+            allow_nan=False,
+            indent=None,
+            separators=(",", ":"),
+        ).encode("utf-8")
 from .scenario import Scenario, Step, StepStatus
 from .scenario import Scenario, Step, StepStatus
 from .docstore import JobDoc
 from .docstore import JobDoc
 from .scenario_loader import load_scenarios
 from .scenario_loader import load_scenarios
@@ -42,7 +58,8 @@ TASK_REGISTRY = tasks.TASK_REGISTRY
 _current_mode: str = "real" if mode == "real" else "plug"
 _current_mode: str = "real" if mode == "real" else "plug"
 _mode_lock = threading.Lock()
 _mode_lock = threading.Lock()
 
 
-app = FastAPI(title="Orchestrator with Templates")
+app = FastAPI(title="Orchestrator with Templates",
+              default_response_class=_UTF8JSONResponse)
 
 
 
 
 @app.get("/health")
 @app.get("/health")

+ 3 - 3
start.bat

@@ -1,5 +1,5 @@
 @echo off
 @echo off
-REM LF-MRI Platform -- double-click to start in plug mode
-REM For real hardware mode run:  powershell -File start.ps1 -Mode real
-powershell -ExecutionPolicy Bypass -File "%~dp0start.ps1"
+REM LF-MRI Platform -- double-click to start (real hardware mode)
+REM Plug mode (no hardware):  powershell -File start.ps1 -Mode plug -SkipSpectrometer
+powershell -ExecutionPolicy Bypass -File "%~dp0start.ps1" -Mode real
 pause
 pause

+ 19 - 12
start.ps1

@@ -116,8 +116,8 @@ if (-not $GuiOnly) {
     if ($LASTEXITCODE -ne 0) { Write-Fail "docker compose up failed" }
     if ($LASTEXITCODE -ne 0) { Write-Fail "docker compose up failed" }
     Write-OK "Containers started"
     Write-OK "Containers started"
 
 
-    # -- 5. Native spectrometer (real mode only) --------------------------------
-    if ($Mode -eq "real" -and -not $SkipSpectrometer) {
+    # -- 5. Native spectrometer ------------------------------------------------
+    if (-not $SkipSpectrometer) {
         Write-Step "Starting native spectrometer"
         Write-Step "Starting native spectrometer"
         $SpecDir  = Join-Path $Root "services\spectrometer"
         $SpecDir  = Join-Path $Root "services\spectrometer"
         $SpecVenv = Join-Path $SpecDir "mvenv\Scripts\python.exe"
         $SpecVenv = Join-Path $SpecDir "mvenv\Scripts\python.exe"
@@ -146,28 +146,35 @@ if (-not $GuiOnly) {
         Write-OK "Migrations applied"
         Write-OK "Migrations applied"
 
 
         if (Test-Path $PicoExe) {
         if (Test-Path $PicoExe) {
-            Start-Process $PicoExe -WindowStyle Hidden
-            Write-OK "pico-tcp.exe started"
+            Start-Process $PicoExe -WindowStyle Normal
+            Write-OK "pico-tcp.exe started (visible window)"
         } else {
         } else {
             Write-Warn "bin\pico-tcp.exe not found -- ADC proxy not started"
             Write-Warn "bin\pico-tcp.exe not found -- ADC proxy not started"
         }
         }
 
 
-        $running = Get-Process -Name python* -ErrorAction SilentlyContinue |
-                   Where-Object { $_.CommandLine -like "*manage.py*runserver*" }
-        if ($running) {
-            Write-OK "Spectrometer already running (PID $($running.Id))"
+        # Check if runserver is already up by probing port 8000
+        $specPort = Get-EnvPort "SPECTROMETER_PORT" "8000"
+        $alreadyUp = $false
+        try {
+            $r = Invoke-WebRequest "http://localhost:$specPort/api/" `
+                     -UseBasicParsing -TimeoutSec 2 -ErrorAction Stop
+            $alreadyUp = ($r.StatusCode -lt 400)
+        } catch {}
+
+        if ($alreadyUp) {
+            Write-OK "Spectrometer already responding on port $specPort"
         } else {
         } else {
             Start-Process $SpecVenv `
             Start-Process $SpecVenv `
-                -ArgumentList "manage.py runserver 0.0.0.0:8000" `
+                -ArgumentList "manage.py runserver 0.0.0.0:$specPort" `
                 -WorkingDirectory $SpecDir `
                 -WorkingDirectory $SpecDir `
                 -WindowStyle Normal
                 -WindowStyle Normal
-            Write-OK "Spectrometer started in new window"
+            Write-OK "Spectrometer started in new window (port $specPort)"
         }
         }
     }
     }
 
 
     # -- 6. Health check -------------------------------------------------------
     # -- 6. Health check -------------------------------------------------------
     Write-Step "Waiting for services to become healthy"
     Write-Step "Waiting for services to become healthy"
-    $checkSpec = ($Mode -eq "real") -and (-not $SkipSpectrometer)
+    $checkSpec = -not $SkipSpectrometer
     $services = @(
     $services = @(
         @{ Name = "Orchestrator";  Url = "http://localhost:$(Get-EnvPort 'ORCHESTRATOR_PORT'  '1717')/health"; Required = $true      },
         @{ Name = "Orchestrator";  Url = "http://localhost:$(Get-EnvPort 'ORCHESTRATOR_PORT'  '1717')/health"; Required = $true      },
         @{ Name = "Seq-Interp";    Url = "http://localhost:$(Get-EnvPort 'SEQ_INTERP_PORT'    '7475')/health"; Required = $true      },
         @{ Name = "Seq-Interp";    Url = "http://localhost:$(Get-EnvPort 'SEQ_INTERP_PORT'    '7475')/health"; Required = $true      },
@@ -252,7 +259,7 @@ Write-Host "============================================================" -Foreg
 Write-Host ("  LF-MRI platform is running  [{0} mode]" -f $Mode.ToUpper()) -ForegroundColor Green
 Write-Host ("  LF-MRI platform is running  [{0} mode]" -f $Mode.ToUpper()) -ForegroundColor Green
 Write-Host "============================================================" -ForegroundColor Green
 Write-Host "============================================================" -ForegroundColor Green
 Write-Host ""
 Write-Host ""
-if ($Mode -eq "real") {
+if (-not $SkipSpectrometer) {
     Write-Host "  Stop spectrometer:  close the spectrometer terminal window"
     Write-Host "  Stop spectrometer:  close the spectrometer terminal window"
     Write-Host "  Stop pico-tcp:      services\spectrometer\autokill.bat"
     Write-Host "  Stop pico-tcp:      services\spectrometer\autokill.bat"
 }
 }