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:
- Enable both
search_apiandsearch_api_solr. - Implement a datasource deriver that uses
$this->entityFieldManager->getFieldMapByFieldType(). -
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
- 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
| Comment | File | Size | Author |
|---|---|---|---|
| #2 | stack_trace.txt | 7.1 KB | mxr576 |
Issue fork search_api-3519499
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
Comment #2
mxr576Comment #4
mxr576Comment #6
drunken monkeyThanks for reporting this problem!
As you already saw by the test failure, the
Indexclass uses$this->datasourceInstancesas 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 forremoveDatasource()would have to be made toaddDatasource()orgetDatasourceIds()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
$datasourceInstancesor$datasource_settingsbased on whether the former is initialized would work in all cases. The only “break” in functionality would now be thatIndex::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!
Comment #7
mxr576Good thinking! I can confirm that the changes you made still mitigates the reported issue. Should I just RTBC this then? :thinking-face:
Comment #9
drunken monkeyGood to hear, thanks for reporting back!
Merged.