chore(search): warn on additive opensearch changes and name the exact delete step

Addresses the two Copilot review comments on the PR: the additive
opensearch log now matches the bleve warning (level and re-index hint),
and the refuse message spells out how to delete the index per engine
(DELETE /<name> vs removing the bleve directory).
This commit is contained in:
Dominik Schmidt committed 2026-08-18 18:07:50 +02:00
1 parent aca8f9d2b8
commit c595a53818
3 files changed
+10 -8

No files matched your search

+1 -1
View File
@@ -63,7 +63,7 @@ func NewIndex(root string) (bleve.Index, searchmapping.Classification, error) {
switch classification.Verdict {
case searchmapping.VerdictBreaking:
_ = index.Close()
return nil, classification, searchmapping.ManualActionRequiredError(destination, classification.Reasons)
return nil, classification, searchmapping.ManualActionRequiredError(destination, "delete the index directory "+destination, classification.Reasons)
case searchmapping.VerdictAdditive:
// The classifier guarantees everything else is identical and the new
// fields hold no data yet, so storing the code mapping only adds
+6 -4
View File
@@ -15,18 +15,20 @@ var ErrManualActionRequired = errors.New("manual action required")
// ManualActionRequiredError builds the operator-facing error for a breaking
// schema change, shared by both engines. index is the index name (OpenSearch)
// or path (bleve).
func ManualActionRequiredError(index string, reasons []string) error {
// or path (bleve); deleteStep is the engine-specific instruction to remove the
// index, e.g. "delete the index (DELETE /name)" or "delete the index
// directory /path".
func ManualActionRequiredError(index, deleteStep string, reasons []string) error {
return fmt.Errorf(
"%w: search index %s was built with a different schema (%s). "+
"There is no in-place migration: stop the service, delete %s, "+
"There is no in-place migration: stop the service, %s, "+
"start the service (an empty index with the new schema is created), "+
"then rebuild the content by running: opencloud search index --all-spaces. "+
"To bring the instance up without search until a maintenance window, "+
"set OC_EXCLUDE_RUN_SERVICES=search; until the service is back, search "+
"and features built on it (e.g. the search bar and the tag list) are "+
"unavailable",
ErrManualActionRequired, index, strings.Join(reasons, "; "), index,
ErrManualActionRequired, index, strings.Join(reasons, "; "), deleteStep,
)
}
+3 -3
View File
@@ -166,7 +166,7 @@ func (m IndexManager) Apply(ctx context.Context, name string, client *opensearch
)
reasons = append(reasons, classification.Reasons...)
if len(reasons) > 0 {
return searchmapping.ManualActionRequiredError(name, reasons)
return searchmapping.ManualActionRequiredError(name, fmt.Sprintf("delete the index (DELETE /%s)", name), reasons)
}
if len(classification.NewFields) == 0 {
return nil // schema is up to date
@@ -183,14 +183,14 @@ func (m IndexManager) Apply(ctx context.Context, name string, client *opensearch
case err != nil && errors.As(err, &putErr) && putErr.Err.Type == "illegal_argument_exception" &&
(strings.Contains(putErr.Err.Reason, "cannot be changed") || strings.Contains(putErr.Err.Reason, "Cannot update parameter")):
// backstop, should be unreachable after the classification above
return searchmapping.ManualActionRequiredError(name, []string{putErr.Err.Reason})
return searchmapping.ManualActionRequiredError(name, fmt.Sprintf("delete the index (DELETE /%s)", name), []string{putErr.Err.Reason})
case err != nil:
return fmt.Errorf("failed to update mapping of index %s: %w", name, err)
case !putResp.Acknowledged:
return fmt.Errorf("failed to update mapping of index %s: not acknowledged", name)
}
logger.Info().Strs("fields", classification.NewFields).Str("index", name).Msg("extended the search index mapping with new fields")
logger.Warn().Strs("fields", classification.NewFields).Str("index", name).Msg("extended the search index mapping with new fields; documents indexed before the upgrade do not contain them and queries on these fields will miss those documents until they are re-indexed; to re-index everything run: opencloud search index --all-spaces")
return nil
}