fix: #3563399 prevent data loss when updating index schema

Saving a search_api_index entity fired updateIndex(), which always reindexed, dropped and recreated the Typesense collection, losing all indexed documents even when nothing relevant changed (for example a processor toggle imported with drush cim). A second latent bug: schema changes imported via configuration never rebuilt the collection at all, because the rebuild was only triggered by the schema admin form.

Introduce a CollectionManager service that converges the live collection toward the typesense_schema config entity, the single source of truth:

  • SchemaComparator produces an attribute-level SchemaDiff classified as NONE (no-op), COMPATIBLE (field add/drop/attribute change, applied in place with the new TypesenseClient::updateCollectionSchema() PATCH method, preserving all documents) or BREAKING (top-level attributes, field type changes: full rebuild).
  • TypesenseSchema::postSave() compares the original and saved schema via isEquals() and reconciles on real changes, for every save channel.
  • SearchApiTypesenseBackend::updateIndex() becomes a pure reconciliation pass (ensure collection exists, diff, apply), which also repairs drift no entity save announced. Errors are logged, never re-thrown, so a Typesense failure cannot abort a configuration import.
  • SchemaForm no longer saves the index to force a rebuild.
  • The collection rebuild moved to a dedicated rebuildCollection() method, used only for breaking changes.

Includes unit coverage for the comparator (server-added defaults, module only attributes, add/drop/modify, id field protection, type and default_sorting_field changes, embed redaction).

Assisted-by: claude-code/claude-fable-5

Closes #3563399

Merge request reports

Loading