Problem/Motivation

An infinite loop occurs when a custom datasource deriver interacts with Search API Solr's dynamic data types.
The loop is triggered by calling $this->entityFieldManager->getFieldMapByFieldType() while
search_api_solr is enabled, which leads to recursive datasource plugin loading.

Steps to Reproduce:

  1. Enable both search_api and search_api_solr.
  2. Implement a datasource deriver that uses $this->entityFieldManager->getFieldMapByFieldType().
  3. Observe the infinite recursion caused by:
    • Custom deriver → getFieldMapByFieldType()
    • Triggers SolrDocumentDeriver::getDerivativeDefinitions()
    • Calls Utility::hasIndexSolrDatasources() → Index::getDatasourceIds()
    • Reloads datasource plugins, re-triggering the custom deriver

Fixing this could also lead to a potential performance improvement.

Steps to reproduce

Proposed resolution

array_keys($this->datasource_settings) could be used to return the data source plugin ids with initialization - this value is also used by \Drupal\search_api\Entity\Index::getDatasources() which leads to data source plugin initializations.

Remaining tasks

CommentFileSizeAuthor
#2 stack_trace.txt7.1 KBmxr576

Issue fork search_api-3519499

Command icon Show commands

Start within a Git clone of the project using the version control instructions.

Or, if you do not have SSH keys set up on git.drupalcode.org:

Comments

mxr576 created an issue. See original summary.

mxr576’s picture

StatusFileSize
new7.1 KB

mxr576’s picture

Status: Active » Needs review

drunken monkey made their first commit to this issue’s fork.

drunken monkey’s picture

Thanks for reporting this problem!

As you already saw by the test failure, the Index class uses $this->datasourceInstances as the “source of truth” for its datasources. Keeping this consistent helps avoid a lot of thorny problems when changing index settings (see #2638116: Clean up caching of Index class method results (especially fields) for background on this decision). For instance, a similar change as the one for removeDatasource() would have to be made to addDatasource() or getDatasourceIds() would return incorrect data when called after adding a datasource.

However, I guess this doesn’t really apply when the datasource plugins aren’t loaded yet, so maybe using either $datasourceInstances or $datasource_settings based on whether the former is initialized would work in all cases. The only “break” in functionality would now be that Index::getDatasourceIds() will never throw an exception, and since that exception wasn’t even documented I guess this is acceptable. As you say, it might even improve performance in rare cases.

Please give the new code in the MR a try!

mxr576’s picture

Status: Needs review » Reviewed & tested by the community

Good thinking! I can confirm that the changes you made still mitigates the reported issue. Should I just RTBC this then? :thinking-face:

drunken monkey’s picture

Status: Reviewed & tested by the community » Fixed

Good to hear, thanks for reporting back!
Merged.

Status: Fixed » Closed (fixed)

Automatically closed - issue fixed for 2 weeks with no activity.