From a5f0f1b74d248bbbbe63edb4500147abb17f22b8 Mon Sep 17 00:00:00 2001 From: Anas Rashid Date: Mon, 5 Oct 2026 01:03:44 +0200 Subject: [PATCH] Fix poet image placeholder: null RImageId cast threw 500 (#4); run-local waits via HTTP - GetPoetImageIdByUrl: missing portrait -> Guid.Empty (placeholder) instead of a null cast - run-local.sh: wait for SQL Server with a query and for API/site via HTTP (pipefail+grep -q never matched; API log level hides 'Now listening' outside Development) Co-Authored-By: Claude Opus 5.5 --- RMuseum/Services/Implementation/DivanService.cs | 2 +- run-local.sh | 12 +++++++----- 2 files changed, 8 insertions(+), 6 deletions(-) diff --git a/RMuseum/Services/Implementation/DivanService.cs b/RMuseum/Services/Implementation/DivanService.cs index 41a5c894..ced87876 100644 --- a/RMuseum/Services/Implementation/DivanService.cs +++ b/RMuseum/Services/Implementation/DivanService.cs @@ -152,7 +152,7 @@ namespace RMuseum.Services.Implementation if (cat == null) return new RServiceResult(Guid.Empty); var poet = await _context.DivanPoets.Where(p => p.Id == cat.PoetId).AsNoTracking().SingleOrDefaultAsync(); - return new RServiceResult((Guid)poet.RImageId); + return new RServiceResult(poet?.RImageId ?? Guid.Empty); // divan: no portrait -> placeholder (was a null cast -> 500) } /// diff --git a/run-local.sh b/run-local.sh index cddbdf66..50129bd3 100755 --- a/run-local.sh +++ b/run-local.sh @@ -18,12 +18,14 @@ stop() { pkill -f "dotnet RMuseum.dll" || true; pkill -f "dotnet DivanRazor.dll" if [ "${1:-}" = stop ]; then stop; echo stopped; exit 0; fi # 1. SQL Server (x86-64 image; runs under Rosetta on Apple Silicon) -if ! docker ps --format '{{.Names}}' | grep -qx divan-mssql; then +if [ -z "$(docker ps -q -f name=^divan-mssql$)" ]; then docker start divan-mssql 2>/dev/null || docker run -d --name divan-mssql --platform linux/amd64 \ -e ACCEPT_EULA=Y -e MSSQL_PID=Express -e "MSSQL_SA_PASSWORD=$SA_PASSWORD" -p 1433:1433 \ -v divan-mssql:/var/opt/mssql --restart unless-stopped mcr.microsoft.com/mssql/server:2022-latest - echo "waiting for SQL Server..."; until docker logs divan-mssql 2>&1 | grep -q "ready for client connections"; do sleep 3; done fi +# wait until SQL Server accepts queries (also covers a container auto-started by Docker/Colima a moment ago) +echo "waiting for SQL Server..." +until docker exec divan-mssql /opt/mssql-tools18/bin/sqlcmd -C -S localhost -U sa -P "$SA_PASSWORD" -Q "SELECT 1" >/dev/null 2>&1; do sleep 3; done # 2. publish (from RMuseum/: its global.json pins the SDK newer Razor compilers can't build with) stop @@ -49,14 +51,14 @@ d['RSecurityBackend']['FirstUserEmail'] = os.environ['RSecurityBackend__FirstUse json.dump(d, open(f, 'w', encoding='utf-8'), ensure_ascii=False, indent=2) PY ASPNETCORE_URLS=http://localhost:5100 nohup dotnet RMuseum.dll > "$RUN/logs/api.log" 2>&1 &) -until grep -q "Now listening" "$RUN/logs/api.log" 2>/dev/null; do sleep 2; done -curl -s -o /dev/null http://localhost:5100/api/divan/poets # first request creates/migrates the database +# wait for the API (its log level hides "Now listening" outside Development); the first request creates/migrates the database +until curl -s -o /dev/null --max-time 300 http://localhost:5100/api/divan/poets; do sleep 2; done # 4. site (cd "$RUN/site" && APIRoot=http://localhost:5100 GlobalAPIRoot=http://localhost:5100 SiteUrl=http://localhost:5200 \ DataProtectionPersistPath=$RUN/keys TrackingScript="" SemanticSearchAPIRoot="" ASPNETCORE_URLS=http://localhost:5200 \ nohup dotnet DivanRazor.dll > "$RUN/logs/site.log" 2>&1 &) -until grep -q "Now listening" "$RUN/logs/site.log" 2>/dev/null; do sleep 2; done +until curl -s -o /dev/null http://localhost:5200/; do sleep 2; done # 5. optional data import (background job; ~1 hour for all 11k poems; re-running only adds what's missing) if [ "${1:-}" = import ]; then