From 0ff00c8443f7096423a0c286b7a8ae586480c222 Mon Sep 17 00:00:00 2001 From: "Michael E. Karpeles" Date: Fri, 22 May 2026 19:11:06 -0600 Subject: [PATCH 1/2] fix(solr): detect version mismatch at startup and add make check-solr Adds a 60s timeout around the temp Solr start in ol-local-solr-start.sh so the container fails fast with an actionable message instead of hanging when the data volume is incompatible with the current Solr major version (e.g. after the Solr 9 -> 10 upgrade in #12786). Also adds `make check-solr` to detect the mismatch while containers are already running, by comparing the live Solr version API against the image tag in compose.yaml. Closes #12792 --- Makefile | 17 ++++++++++++++++- docker/ol-local-solr-start.sh | 20 +++++++++++++++----- 2 files changed, 31 insertions(+), 6 deletions(-) diff --git a/Makefile b/Makefile index fb69b124e9e..050b2b6b2f1 100644 --- a/Makefile +++ b/Makefile @@ -9,7 +9,7 @@ COMPONENTS_DIR=openlibrary/components OSP_DUMP_LOCATION=/solr-updater-data/osp_totals.db -.PHONY: all clean distclean git css js components lit-components i18n lint frontend +.PHONY: all clean distclean git css js components lit-components i18n lint frontend check-solr all: git css js components lit-components i18n @@ -75,6 +75,21 @@ reindex-solr: PYTHONPATH=$(PWD) python ./scripts/solr_builder/solr_builder/index_subjects.py place PYTHONPATH=$(PWD) python ./scripts/solr_builder/solr_builder/index_subjects.py time +check-solr: + @RUNNING=$$(curl -sf http://localhost:8983/solr/admin/info/system 2>/dev/null | python3 -c "import json,sys; print(json.load(sys.stdin)['lucene']['solr-spec-version'])" 2>/dev/null) || { echo "Solr is not running or not reachable at http://localhost:8983"; exit 1; }; \ + EXPECTED=$$(grep 'image: solr:' compose.yaml | grep -oE '[0-9]+\.[0-9]+\.[0-9]+' | head -1); \ + RUNNING_MAJOR=$$(echo "$$RUNNING" | cut -d. -f1); \ + EXPECTED_MAJOR=$$(echo "$$EXPECTED" | cut -d. -f1); \ + if [ "$$RUNNING_MAJOR" != "$$EXPECTED_MAJOR" ]; then \ + echo "⚠️ Solr version mismatch:"; \ + echo " Running: $$RUNNING"; \ + echo " Expected: $$EXPECTED (from compose.yaml)"; \ + echo " Fix: docker compose down -v && docker compose up -d"; \ + exit 1; \ + else \ + echo "✓ Solr version OK ($$RUNNING)"; \ + fi + lint: # See the pyproject.toml file for ruff's settings python -m ruff check . diff --git a/docker/ol-local-solr-start.sh b/docker/ol-local-solr-start.sh index 65e81c087e9..b946c67bf45 100755 --- a/docker/ol-local-solr-start.sh +++ b/docker/ol-local-solr-start.sh @@ -31,12 +31,22 @@ if [ -f "$OL_SCHEMA_FILE" ] && [ -f "$SOLR_SCHEMA_FILE" ]; then echo "${PREFIX} Schema files has been updated. Attempting to resolve by deleting and recreating Solr core..." # Start Solr in background (on tmp port 8989) + # Use timeout to avoid hanging if the data volume is incompatible with the current Solr major version TMP_SOLR_PORT=8989 - solr start -p $TMP_SOLR_PORT - # Wait for solr core to be ready for searching - until curl -s -o /dev/null -w "%{http_code}" "http://localhost:${TMP_SOLR_PORT}/solr/${CORE_NAME}/select?q=*:*&rows=0&wt=json" | grep -q "200"; do - sleep 1; - done + SOLR_VERSION=$(solr --version 2>/dev/null | grep -oE '[0-9]+\.[0-9]+\.[0-9]+' | head -1 || echo "unknown") + if ! timeout 60 bash -c " + solr start -p $TMP_SOLR_PORT + until curl -s -o /dev/null -w '%{http_code}' \ + 'http://localhost:${TMP_SOLR_PORT}/solr/${CORE_NAME}/select?q=*:*&rows=0&wt=json' \ + | grep -q '200'; do sleep 1; done + "; then + echo "${PREFIX} ERROR: Solr ${SOLR_VERSION} failed to start with the existing data volume." + echo "${PREFIX} This usually means the data volume was written by an older Solr major version." + echo "${PREFIX} Action required: docker compose down -v && docker compose up -d" + echo "${PREFIX} See: https://docs.openlibrary.org/advanced/solr.html#making-changes-to-solr-config" + solr stop -p $TMP_SOLR_PORT 2>/dev/null || true + exit 1 + fi TOTAL_SOLR_DOCS=$(curl -s "http://localhost:${TMP_SOLR_PORT}/solr/${CORE_NAME}/select?q=*:*&rows=0&wt=json" | grep -oE '"numFound":[0-9]+' | grep -oE '[0-9]+') echo "${PREFIX} Current Solr core has $TOTAL_SOLR_DOCS documents" From c291698101fb13fcb5dd1019df705f245d1175a7 Mon Sep 17 00:00:00 2001 From: "Michael E. Karpeles" Date: Sun, 24 May 2026 16:31:54 -0600 Subject: [PATCH 2/2] fix(make): use python not python3 in check-solr; guard empty EXPECTED --- Makefile | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/Makefile b/Makefile index 050b2b6b2f1..a7298b16472 100644 --- a/Makefile +++ b/Makefile @@ -76,8 +76,11 @@ reindex-solr: PYTHONPATH=$(PWD) python ./scripts/solr_builder/solr_builder/index_subjects.py time check-solr: - @RUNNING=$$(curl -sf http://localhost:8983/solr/admin/info/system 2>/dev/null | python3 -c "import json,sys; print(json.load(sys.stdin)['lucene']['solr-spec-version'])" 2>/dev/null) || { echo "Solr is not running or not reachable at http://localhost:8983"; exit 1; }; \ + @RUNNING=$$(curl -sf http://localhost:8983/solr/admin/info/system 2>/dev/null | python -c "import json,sys; print(json.load(sys.stdin)['lucene']['solr-spec-version'])" 2>/dev/null) || { echo "Solr is not running or not reachable at http://localhost:8983"; exit 1; }; \ EXPECTED=$$(grep 'image: solr:' compose.yaml | grep -oE '[0-9]+\.[0-9]+\.[0-9]+' | head -1); \ + if [ -z "$$EXPECTED" ]; then \ + echo "Could not determine expected Solr version from compose.yaml"; exit 1; \ + fi; \ RUNNING_MAJOR=$$(echo "$$RUNNING" | cut -d. -f1); \ EXPECTED_MAJOR=$$(echo "$$EXPECTED" | cut -d. -f1); \ if [ "$$RUNNING_MAJOR" != "$$EXPECTED_MAJOR" ]; then \