Skip to content

Replace Solr with Elasticsearch 8 and add candidate-based deployment - #216

Open
asuworks wants to merge 22 commits into
comses:mainfrom
asuworks:release/candidate-deployment
Open

asuworks wants to merge 22 commits into
comses:mainfrom
asuworks:release/candidate-deployment

Conversation

@asuworks

@asuworks asuworks commented Sep 27, 2026 •

Copy link
Copy Markdown

Summary

  • replace Solr and Haystack with Elasticsearch 8, using generation indexes and alias swaps for rebuilds;
  • add a candidate-centered deployment controller (scripts/catalogctl.py) for independent staging and production hosts: digest-pinned candidates, fresh-host restore, verified on-host backups, gated schema migration and search rebuild, transactional deploy, rollback, and recovery;
  • fail closed on hosts whose Python lacks tarfile extraction filters, on restores over a populated database, and on HTTP binds without an explicit address;
  • test pull requests without publishing; each main build publishes an immutable image and release-handoff.json, and a stable vYYYY.MM tag creates the GitHub Release without rebuilding;
  • pin Citation to the Fix Citation behavior required by Catalog citation#74 merge commit fbce715;
  • fix the curator tag filter, curator contribution labels, publication years in the visualization charts, the top-10 charts, and the unpinned plotly.js on the home page.

Operator procedure: docs/deployment-runbook.md.
Disposable-host validation: docs/deployment-acceptance-testing.md.
Design and deferred work: docs/proposals/candidate-centered-multi-host-deployment.md.

Closes #193.
Closes #194.

Verification

  • make check, migrations-check, cite-check, cite-migrations-check, test-all (Catalog 76 and Citation 79 tests), and deploy-controller-test (31 tests) pass.
  • Two fresh throwaway VMs with staging and production identities ran a first deployment from the production dump, a subsequent release without restore, a B to A to B rollback, backups, the scheduler, and fail-closed checks.
    Counts were preserved (290,922 publications, 9,538 primary), and both hosts validated every search alias.
    That rehearsal pinned Citation a59d379.
  • The Citation changes since then, including migrations 0037 and 0038, were rehearsed locally on the same production dump.
    Migration 0038 filled 289,278 publication years in about 41 s with a peak of about 1 GiB of memory; Address #74 review: export coverage, CSV safety, and backfill memory citation#76 reduces that to 100 MiB.
    Browser checks passed for search, the curator export (9,538 rows), merges, visualization, and the reviewed and unreviewed status round trip.

Deployment notes

Separate routine operations from disposable acceptance testing. Prevent controller subprocesses from consuming later pasted commands and document the verified backup, transfer, scheduler, and recovery behavior.
make bootstrap failed on any workstation that already had credentials, although the runbook runs it first. Rotation still requires FORCE=1 and an incomplete configuration is still an error.
Citation now stores year_published. Deriving it again with dateutil dropped 100 of 7673 public publications, such as "SEP-OCT 2007", from the year charts.
The tags widget bound an undefined SelectedTags observable, so knockout aborted and the filter never loaded options.
Show "curator (66%)" instead of "curator (66)%".
Long sponsor and journal names squeezed the vertical charts and were clipped by the footer.
plotly-latest is frozen at 1.58.5 and logs a console error; use the version the visualization page already pins.

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copilot review overview

🟡 Changes recommended

Four critical and two moderate one-vote findings remain unresolved.

Review effort: Lite
Findings: 4 High severity

Open (4)
What changed in this PR

Replaces Solr/Haystack with Elasticsearch 8 and adds digest-pinned, candidate-based deployment with restore, rollback, recovery, CI release handoffs, and visualization fixes.

Changes:

  • Adds generation-based Elasticsearch indexes, aliases, synchronization, and validation.
  • Adds deployment orchestration, backups, restores, migrations, rollback, and recovery.
  • Updates Compose, CI, dependencies, documentation, templates, and tests while removing Solr assets.

Four critical and two moderate findings remain unresolved, each with one vote, covering Elasticsearch security, host compatibility and safety, search consistency, rollback retention, and bind validation.

File Summary
uv.lock Removes legacy Solr/Haystack dependencies.
tasks.py Removes legacy deployment tasks and updates Elasticsearch usage.
staging.yml Adds candidate services and scheduler configuration.
scripts/​dev-restore.sh Adds validated local database restore.
scripts/​database.sh Wraps backup and restore operations.
scripts/​config.sh Adds safer configuration regeneration.
scripts/​compose.sh Protects deployment state during rendering.
scripts/​citation-config.sh Validates generated Citation configuration.
scripts/​checkout-citation.sh Checks out the pinned Citation revision.
README.md Documents development and deployment workflows.
pyproject.toml Replaces Solr dependencies with Elasticsearch clients.
prod.yml Updates production services and scheduler settings.
Makefile Adds deployment, migration, rebuild, and recovery commands.
docs/​proposals/​candidate-centered-multi-host-deployment.md Documents the deployment design.
dev.yml Updates local PostgreSQL and Elasticsearch services.
deploy/​travis/​travis-solr.sh Removes obsolete Solr tooling.
deploy/​travis/​solrconfig.xml Removes obsolete Solr configuration.
deploy/​solr/​init.d/​solr.in.sh Removes obsolete Solr configuration.
deploy/​solr/​init.d/​set-heap.sh Removes obsolete Solr tooling.
deploy/​solr/​conf/​synonyms.txt Removes obsolete Solr configuration.
deploy/​solr/​conf/​stopwords.txt Removes obsolete Solr configuration.
deploy/​solr/​conf/​solrconfig.xml Removes obsolete Solr configuration.
deploy/​solr/​conf/​schema.xml Removes the obsolete Solr schema.
deploy/​solr/​conf/​protwords.txt Removes obsolete Solr configuration.
deploy/​solr/​conf/​managed-schema Removes the obsolete Solr schema.
deploy/​solr/​conf/​lang/​stopwords_en.txt Removes obsolete Solr configuration.
deploy/​solr/​conf/​currency.xml Removes obsolete Solr configuration.
deploy/​solr/​conf/​_rest_managed.json Removes obsolete Solr configuration.
deploy/​images/​solr.Dockerfile Removes the Solr image.
deploy/​images/​django.Dockerfile Pins the application image and adds scheduler tooling.
deploy/​elasticsearch.conf.d/​log4j2.properties Removes obsolete configuration.
deploy/​elasticsearch.conf.d/​elasticsearch8.yml Updates Elasticsearch 8 configuration.
deploy/​elasticsearch.conf.d/​elasticsearch-dev.yml Removes obsolete development configuration.
deploy/​docker/​test.sh Switches readiness checks to Elasticsearch.
deploy/​docker/​scheduler.sh Adds the scheduler entrypoint.
deploy/​docker/​prod.sh Removes Solr startup and uses Elasticsearch.
deploy/​docker/​dev.sh Updates local startup and readiness checks.
deploy/​cron/​monthly_catalog_tasks Runs monthly tasks through the scheduler.
deploy/​cron/​daily_catalog_tasks Runs daily tasks with failure propagation.
deploy/​conf/​config.template.ini Removes Solr configuration.
deploy.sh Redirects operators to the Make workflow.
core.properties Removes obsolete Solr metadata.
catalog/​settings/​staging.py Adds staging email configuration.
catalog/​settings/​base.py Removes Haystack and adds environment-based settings.
catalog/​core/​visualization/​plots.py Fixes publication years and top-ten charts.
catalog/​core/​visualization/​data_access.py Preserves dataframe columns and Citation years.
catalog/​core/​views.py Replaces Haystack views with Elasticsearch queries.
catalog/​core/​tests/​test_visualization_plots.py Tests chart and year behavior.
catalog/​core/​tests/​test_visualization_cache_command.py Tests visualization cache rebuilding.
catalog/​core/​tests/​test_views.py Updates search and response tests.
catalog/​core/​tests/​test_suggested_merge_views.py Tests autocomplete validation.
catalog/​core/​tests/​test_search_sync.py Tests Elasticsearch synchronization and curator labels.
catalog/​core/​tests/​test_search_indexes.py Tests generation indexes and aliases.
catalog/​core/​tests/​test_rebuild_es_index_command.py Tests rebuild and validation commands.
catalog/​core/​tests/​test_public_layout.py Tests footer rendering.
catalog/​core/​tests/​test_export.py Tests CSV export behavior.
catalog/​core/​tests/​test_citation_integration.py Tests Citation integration.
catalog/​core/​tests/​common.py Fixes status comparison assertions.
catalog/​core/​templates/​search/​indexes/​citation/​publication_text.txt Removes the obsolete Haystack template.
catalog/​core/​templates/​public/​search.html Updates search documentation rendering.
catalog/​core/​templates/​public/​home.html Pins Plotly and centralizes the footer.
catalog/​core/​templates/​public/​base.html Adds the shared footer.
catalog/​core/​search_sync.py Synchronizes publication changes to Elasticsearch.
catalog/​core/​management/​commands/​validate_search_indexes.py Adds search-index validation.
catalog/​core/​management/​commands/​rebuild_es_index.py Rebuilds public and curator indexes.
catalog/​core/​management/​commands/​populate_visualization_cache.py Adds cache-clearing support.
catalog/​core/​forms.py Reimplements curator search filters.
catalog/​core/​apps.py Registers search synchronization signals.
base.yml Replaces Solr with pinned Elasticsearch and PostgreSQL services.
.gitignore Ignores dumps and private deployment data.
.github/​workflows/​release-tag.yml Publishes stable releases without rebuilding.
.github/​workflows/​docker-build.yml Adds testing, image publication, and handoff generation.
.dockerignore Excludes dumps and private data from builds.

💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.

Comment thread base.yml
Comment thread scripts/catalogctl.py
Comment thread scripts/catalogctl.py
Comment thread scripts/catalogctl.py
Candidate extraction uses filter="data", which Python 3.10.0-3.10.11 and 3.11.0-3.11.3 lack. host-check now tests for the feature, as the tarfile documentation recommends.
A missing active.json alone does not prove the host is fresh. Restore now fails closed when the current database already contains publications.
A bare port in CATALOG_HTTP_BIND published nginx on every interface. The documented override now needs an explicit address, and make status shows the bind.
@asuworks asuworks self-assigned this Sep 27, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

replace solr with elasticsearch add Makefile deployment

2 participants